linux/drivers/platform/x86/hp-wmi.c
<<
>>
Prefs
   1/*
   2 * HP WMI hotkeys
   3 *
   4 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
   5 * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
   6 *
   7 * Portions based on wistron_btns.c:
   8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
   9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
  10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
  11 *
  12 *  This program is free software; you can redistribute it and/or modify
  13 *  it under the terms of the GNU General Public License as published by
  14 *  the Free Software Foundation; either version 2 of the License, or
  15 *  (at your option) any later version.
  16 *
  17 *  This program is distributed in the hope that it will be useful,
  18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 *  GNU General Public License for more details.
  21 *
  22 *  You should have received a copy of the GNU General Public License
  23 *  along with this program; if not, write to the Free Software
  24 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25 */
  26
  27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  28
  29#include <linux/kernel.h>
  30#include <linux/module.h>
  31#include <linux/init.h>
  32#include <linux/slab.h>
  33#include <linux/types.h>
  34#include <linux/input.h>
  35#include <linux/input/sparse-keymap.h>
  36#include <linux/platform_device.h>
  37#include <linux/acpi.h>
  38#include <linux/rfkill.h>
  39#include <linux/string.h>
  40
  41MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
  42MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
  43MODULE_LICENSE("GPL");
  44
  45MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
  46MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
  47
  48#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
  49#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
  50
  51enum hp_wmi_radio {
  52        HPWMI_WIFI      = 0x0,
  53        HPWMI_BLUETOOTH = 0x1,
  54        HPWMI_WWAN      = 0x2,
  55        HPWMI_GPS       = 0x3,
  56};
  57
  58enum hp_wmi_event_ids {
  59        HPWMI_DOCK_EVENT                = 0x01,
  60        HPWMI_PARK_HDD                  = 0x02,
  61        HPWMI_SMART_ADAPTER             = 0x03,
  62        HPWMI_BEZEL_BUTTON              = 0x04,
  63        HPWMI_WIRELESS                  = 0x05,
  64        HPWMI_CPU_BATTERY_THROTTLE      = 0x06,
  65        HPWMI_LOCK_SWITCH               = 0x07,
  66        HPWMI_LID_SWITCH                = 0x08,
  67        HPWMI_SCREEN_ROTATION           = 0x09,
  68        HPWMI_COOLSENSE_SYSTEM_MOBILE   = 0x0A,
  69        HPWMI_COOLSENSE_SYSTEM_HOT      = 0x0B,
  70        HPWMI_PROXIMITY_SENSOR          = 0x0C,
  71        HPWMI_BACKLIT_KB_BRIGHTNESS     = 0x0D,
  72        HPWMI_PEAKSHIFT_PERIOD          = 0x0F,
  73        HPWMI_BATTERY_CHARGE_PERIOD     = 0x10,
  74};
  75
  76struct bios_args {
  77        u32 signature;
  78        u32 command;
  79        u32 commandtype;
  80        u32 datasize;
  81        u32 data;
  82};
  83
  84enum hp_wmi_commandtype {
  85        HPWMI_DISPLAY_QUERY             = 0x01,
  86        HPWMI_HDDTEMP_QUERY             = 0x02,
  87        HPWMI_ALS_QUERY                 = 0x03,
  88        HPWMI_HARDWARE_QUERY            = 0x04,
  89        HPWMI_WIRELESS_QUERY            = 0x05,
  90        HPWMI_BATTERY_QUERY             = 0x07,
  91        HPWMI_BIOS_QUERY                = 0x09,
  92        HPWMI_FEATURE_QUERY             = 0x0b,
  93        HPWMI_HOTKEY_QUERY              = 0x0c,
  94        HPWMI_FEATURE2_QUERY            = 0x0d,
  95        HPWMI_WIRELESS2_QUERY           = 0x1b,
  96        HPWMI_POSTCODEERROR_QUERY       = 0x2a,
  97};
  98
  99enum hp_wmi_command {
 100        HPWMI_READ      = 0x01,
 101        HPWMI_WRITE     = 0x02,
 102        HPWMI_ODM       = 0x03,
 103};
 104
 105enum hp_wmi_hardware_mask {
 106        HPWMI_DOCK_MASK         = 0x01,
 107        HPWMI_TABLET_MASK       = 0x04,
 108};
 109
 110#define BIOS_ARGS_INIT(write, ctype, size)                              \
 111        (struct bios_args)      {       .signature = 0x55434553,        \
 112                                        .command = (write) ? 0x2 : 0x1, \
 113                                        .commandtype = (ctype),         \
 114                                        .datasize = (size),             \
 115                                        .data = 0 }
 116
 117struct bios_return {
 118        u32 sigpass;
 119        u32 return_code;
 120};
 121
 122enum hp_return_value {
 123        HPWMI_RET_WRONG_SIGNATURE       = 0x02,
 124        HPWMI_RET_UNKNOWN_COMMAND       = 0x03,
 125        HPWMI_RET_UNKNOWN_CMDTYPE       = 0x04,
 126        HPWMI_RET_INVALID_PARAMETERS    = 0x05,
 127};
 128
 129enum hp_wireless2_bits {
 130        HPWMI_POWER_STATE       = 0x01,
 131        HPWMI_POWER_SOFT        = 0x02,
 132        HPWMI_POWER_BIOS        = 0x04,
 133        HPWMI_POWER_HARD        = 0x08,
 134};
 135
 136#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \
 137                         != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD))
 138#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
 139
 140struct bios_rfkill2_device_state {
 141        u8 radio_type;
 142        u8 bus_type;
 143        u16 vendor_id;
 144        u16 product_id;
 145        u16 subsys_vendor_id;
 146        u16 subsys_product_id;
 147        u8 rfkill_id;
 148        u8 power;
 149        u8 unknown[4];
 150};
 151
 152/* 7 devices fit into the 128 byte buffer */
 153#define HPWMI_MAX_RFKILL2_DEVICES       7
 154
 155struct bios_rfkill2_state {
 156        u8 unknown[7];
 157        u8 count;
 158        u8 pad[8];
 159        struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
 160};
 161
 162static const struct key_entry hp_wmi_keymap[] = {
 163        { KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
 164        { KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
 165        { KE_KEY, 0x20e6, { KEY_PROG1 } },
 166        { KE_KEY, 0x20e8, { KEY_MEDIA } },
 167        { KE_KEY, 0x2142, { KEY_MEDIA } },
 168        { KE_KEY, 0x213b, { KEY_INFO } },
 169        { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } },
 170        { KE_KEY, 0x216a, { KEY_SETUP } },
 171        { KE_KEY, 0x231b, { KEY_HELP } },
 172        { KE_END, 0 }
 173};
 174
 175static struct input_dev *hp_wmi_input_dev;
 176static struct platform_device *hp_wmi_platform_dev;
 177
 178static struct rfkill *wifi_rfkill;
 179static struct rfkill *bluetooth_rfkill;
 180static struct rfkill *wwan_rfkill;
 181
 182struct rfkill2_device {
 183        u8 id;
 184        int num;
 185        struct rfkill *rfkill;
 186};
 187
 188static int rfkill2_count;
 189static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
 190
 191/*
 192 * hp_wmi_perform_query
 193 *
 194 * query:       The commandtype (enum hp_wmi_commandtype)
 195 * write:       The command (enum hp_wmi_command)
 196 * buffer:      Buffer used as input and/or output
 197 * insize:      Size of input buffer
 198 * outsize:     Size of output buffer
 199 *
 200 * returns zero on success
 201 *         an HP WMI query specific error code (which is positive)
 202 *         -EINVAL if the query was not successful at all
 203 *         -EINVAL if the output buffer size exceeds buffersize
 204 *
 205 * Note: The buffersize must at least be the maximum of the input and output
 206 *       size. E.g. Battery info query is defined to have 1 byte input
 207 *       and 128 byte output. The caller would do:
 208 *       buffer = kzalloc(128, GFP_KERNEL);
 209 *       ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
 210 */
 211static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
 212                                void *buffer, int insize, int outsize)
 213{
 214        struct bios_return *bios_return;
 215        int actual_outsize;
 216        union acpi_object *obj;
 217        struct bios_args args = {
 218                .signature = 0x55434553,
 219                .command = command,
 220                .commandtype = query,
 221                .datasize = insize,
 222                .data = 0,
 223        };
 224        struct acpi_buffer input = { sizeof(struct bios_args), &args };
 225        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 226        int ret = 0;
 227
 228        if (WARN_ON(insize > sizeof(args.data)))
 229                return -EINVAL;
 230        memcpy(&args.data, buffer, insize);
 231
 232        wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
 233
 234        obj = output.pointer;
 235
 236        if (!obj)
 237                return -EINVAL;
 238
 239        if (obj->type != ACPI_TYPE_BUFFER) {
 240                ret = -EINVAL;
 241                goto out_free;
 242        }
 243
 244        bios_return = (struct bios_return *)obj->buffer.pointer;
 245        ret = bios_return->return_code;
 246
 247        if (ret) {
 248                if (ret != HPWMI_RET_UNKNOWN_CMDTYPE)
 249                        pr_warn("query 0x%x returned error 0x%x\n", query, ret);
 250                goto out_free;
 251        }
 252
 253        /* Ignore output data of zero size */
 254        if (!outsize)
 255                goto out_free;
 256
 257        actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
 258        memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
 259        memset(buffer + actual_outsize, 0, outsize - actual_outsize);
 260
 261out_free:
 262        kfree(obj);
 263        return ret;
 264}
 265
 266static int hp_wmi_read_int(int query)
 267{
 268        int val = 0, ret;
 269
 270        ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
 271                                   sizeof(val), sizeof(val));
 272
 273        if (ret)
 274                return ret < 0 ? ret : -EINVAL;
 275
 276        return val;
 277}
 278
 279static int hp_wmi_hw_state(int mask)
 280{
 281        int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
 282
 283        if (state < 0)
 284                return state;
 285
 286        return state & 0x1;
 287}
 288
 289static int __init hp_wmi_bios_2008_later(void)
 290{
 291        int state = 0;
 292        int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
 293                                       sizeof(state), sizeof(state));
 294        if (!ret)
 295                return 1;
 296
 297        return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 298}
 299
 300static int __init hp_wmi_bios_2009_later(void)
 301{
 302        int state = 0;
 303        int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
 304                                       sizeof(state), sizeof(state));
 305        if (!ret)
 306                return 1;
 307
 308        return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 309}
 310
 311static int __init hp_wmi_enable_hotkeys(void)
 312{
 313        int value = 0x6e;
 314        int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
 315                                       sizeof(value), 0);
 316
 317        return ret <= 0 ? ret : -EINVAL;
 318}
 319
 320static int hp_wmi_set_block(void *data, bool blocked)
 321{
 322        enum hp_wmi_radio r = (enum hp_wmi_radio) data;
 323        int query = BIT(r + 8) | ((!blocked) << r);
 324        int ret;
 325
 326        ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
 327                                   &query, sizeof(query), 0);
 328
 329        return ret <= 0 ? ret : -EINVAL;
 330}
 331
 332static const struct rfkill_ops hp_wmi_rfkill_ops = {
 333        .set_block = hp_wmi_set_block,
 334};
 335
 336static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 337{
 338        int mask = 0x200 << (r * 8);
 339
 340        int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 341
 342        /* TBD: Pass error */
 343        WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 344
 345        return !(wireless & mask);
 346}
 347
 348static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
 349{
 350        int mask = 0x800 << (r * 8);
 351
 352        int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 353
 354        /* TBD: Pass error */
 355        WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 356
 357        return !(wireless & mask);
 358}
 359
 360static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
 361{
 362        int rfkill_id = (int)(long)data;
 363        char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
 364        int ret;
 365
 366        ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
 367                                   buffer, sizeof(buffer), 0);
 368
 369        return ret <= 0 ? ret : -EINVAL;
 370}
 371
 372static const struct rfkill_ops hp_wmi_rfkill2_ops = {
 373        .set_block = hp_wmi_rfkill2_set_block,
 374};
 375
 376static int hp_wmi_rfkill2_refresh(void)
 377{
 378        struct bios_rfkill2_state state;
 379        int err, i;
 380
 381        err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
 382                                   0, sizeof(state));
 383        if (err)
 384                return err;
 385
 386        for (i = 0; i < rfkill2_count; i++) {
 387                int num = rfkill2[i].num;
 388                struct bios_rfkill2_device_state *devstate;
 389                devstate = &state.device[num];
 390
 391                if (num >= state.count ||
 392                    devstate->rfkill_id != rfkill2[i].id) {
 393                        pr_warn("power configuration of the wireless devices unexpectedly changed\n");
 394                        continue;
 395                }
 396
 397                rfkill_set_states(rfkill2[i].rfkill,
 398                                  IS_SWBLOCKED(devstate->power),
 399                                  IS_HWBLOCKED(devstate->power));
 400        }
 401
 402        return 0;
 403}
 404
 405static ssize_t display_show(struct device *dev, struct device_attribute *attr,
 406                            char *buf)
 407{
 408        int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
 409        if (value < 0)
 410                return value;
 411        return sprintf(buf, "%d\n", value);
 412}
 413
 414static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
 415                            char *buf)
 416{
 417        int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
 418        if (value < 0)
 419                return value;
 420        return sprintf(buf, "%d\n", value);
 421}
 422
 423static ssize_t als_show(struct device *dev, struct device_attribute *attr,
 424                        char *buf)
 425{
 426        int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
 427        if (value < 0)
 428                return value;
 429        return sprintf(buf, "%d\n", value);
 430}
 431
 432static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
 433                         char *buf)
 434{
 435        int value = hp_wmi_hw_state(HPWMI_DOCK_MASK);
 436        if (value < 0)
 437                return value;
 438        return sprintf(buf, "%d\n", value);
 439}
 440
 441static ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
 442                           char *buf)
 443{
 444        int value = hp_wmi_hw_state(HPWMI_TABLET_MASK);
 445        if (value < 0)
 446                return value;
 447        return sprintf(buf, "%d\n", value);
 448}
 449
 450static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
 451                             char *buf)
 452{
 453        /* Get the POST error code of previous boot failure. */
 454        int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
 455        if (value < 0)
 456                return value;
 457        return sprintf(buf, "0x%x\n", value);
 458}
 459
 460static ssize_t als_store(struct device *dev, struct device_attribute *attr,
 461                         const char *buf, size_t count)
 462{
 463        u32 tmp = simple_strtoul(buf, NULL, 10);
 464        int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
 465                                       sizeof(tmp), sizeof(tmp));
 466        if (ret)
 467                return ret < 0 ? ret : -EINVAL;
 468
 469        return count;
 470}
 471
 472static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
 473                              const char *buf, size_t count)
 474{
 475        long unsigned int tmp2;
 476        int ret;
 477        u32 tmp;
 478
 479        ret = kstrtoul(buf, 10, &tmp2);
 480        if (!ret && tmp2 != 1)
 481                ret = -EINVAL;
 482        if (ret)
 483                goto out;
 484
 485        /* Clear the POST error code. It is kept until until cleared. */
 486        tmp = (u32) tmp2;
 487        ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
 488                                       sizeof(tmp), sizeof(tmp));
 489
 490out:
 491        if (ret)
 492                return ret < 0 ? ret : -EINVAL;
 493
 494        return count;
 495}
 496
 497static DEVICE_ATTR_RO(display);
 498static DEVICE_ATTR_RO(hddtemp);
 499static DEVICE_ATTR_RW(als);
 500static DEVICE_ATTR_RO(dock);
 501static DEVICE_ATTR_RO(tablet);
 502static DEVICE_ATTR_RW(postcode);
 503
 504static void hp_wmi_notify(u32 value, void *context)
 505{
 506        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
 507        u32 event_id, event_data;
 508        union acpi_object *obj;
 509        acpi_status status;
 510        u32 *location;
 511        int key_code;
 512
 513        status = wmi_get_event_data(value, &response);
 514        if (status != AE_OK) {
 515                pr_info("bad event status 0x%x\n", status);
 516                return;
 517        }
 518
 519        obj = (union acpi_object *)response.pointer;
 520
 521        if (!obj)
 522                return;
 523        if (obj->type != ACPI_TYPE_BUFFER) {
 524                pr_info("Unknown response received %d\n", obj->type);
 525                kfree(obj);
 526                return;
 527        }
 528
 529        /*
 530         * Depending on ACPI version the concatenation of id and event data
 531         * inside _WED function will result in a 8 or 16 byte buffer.
 532         */
 533        location = (u32 *)obj->buffer.pointer;
 534        if (obj->buffer.length == 8) {
 535                event_id = *location;
 536                event_data = *(location + 1);
 537        } else if (obj->buffer.length == 16) {
 538                event_id = *location;
 539                event_data = *(location + 2);
 540        } else {
 541                pr_info("Unknown buffer length %d\n", obj->buffer.length);
 542                kfree(obj);
 543                return;
 544        }
 545        kfree(obj);
 546
 547        switch (event_id) {
 548        case HPWMI_DOCK_EVENT:
 549                if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
 550                        input_report_switch(hp_wmi_input_dev, SW_DOCK,
 551                                            hp_wmi_hw_state(HPWMI_DOCK_MASK));
 552                if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
 553                        input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
 554                                            hp_wmi_hw_state(HPWMI_TABLET_MASK));
 555                input_sync(hp_wmi_input_dev);
 556                break;
 557        case HPWMI_PARK_HDD:
 558                break;
 559        case HPWMI_SMART_ADAPTER:
 560                break;
 561        case HPWMI_BEZEL_BUTTON:
 562                key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
 563                if (key_code < 0)
 564                        break;
 565
 566                if (!sparse_keymap_report_event(hp_wmi_input_dev,
 567                                                key_code, 1, true))
 568                        pr_info("Unknown key code - 0x%x\n", key_code);
 569                break;
 570        case HPWMI_WIRELESS:
 571                if (rfkill2_count) {
 572                        hp_wmi_rfkill2_refresh();
 573                        break;
 574                }
 575
 576                if (wifi_rfkill)
 577                        rfkill_set_states(wifi_rfkill,
 578                                          hp_wmi_get_sw_state(HPWMI_WIFI),
 579                                          hp_wmi_get_hw_state(HPWMI_WIFI));
 580                if (bluetooth_rfkill)
 581                        rfkill_set_states(bluetooth_rfkill,
 582                                          hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
 583                                          hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
 584                if (wwan_rfkill)
 585                        rfkill_set_states(wwan_rfkill,
 586                                          hp_wmi_get_sw_state(HPWMI_WWAN),
 587                                          hp_wmi_get_hw_state(HPWMI_WWAN));
 588                break;
 589        case HPWMI_CPU_BATTERY_THROTTLE:
 590                pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
 591                break;
 592        case HPWMI_LOCK_SWITCH:
 593                break;
 594        case HPWMI_LID_SWITCH:
 595                break;
 596        case HPWMI_SCREEN_ROTATION:
 597                break;
 598        case HPWMI_COOLSENSE_SYSTEM_MOBILE:
 599                break;
 600        case HPWMI_COOLSENSE_SYSTEM_HOT:
 601                break;
 602        case HPWMI_PROXIMITY_SENSOR:
 603                break;
 604        case HPWMI_BACKLIT_KB_BRIGHTNESS:
 605                break;
 606        case HPWMI_PEAKSHIFT_PERIOD:
 607                break;
 608        case HPWMI_BATTERY_CHARGE_PERIOD:
 609                break;
 610        default:
 611                pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
 612                break;
 613        }
 614}
 615
 616static int __init hp_wmi_input_setup(void)
 617{
 618        acpi_status status;
 619        int err, val;
 620
 621        hp_wmi_input_dev = input_allocate_device();
 622        if (!hp_wmi_input_dev)
 623                return -ENOMEM;
 624
 625        hp_wmi_input_dev->name = "HP WMI hotkeys";
 626        hp_wmi_input_dev->phys = "wmi/input0";
 627        hp_wmi_input_dev->id.bustype = BUS_HOST;
 628
 629        __set_bit(EV_SW, hp_wmi_input_dev->evbit);
 630
 631        /* Dock */
 632        val = hp_wmi_hw_state(HPWMI_DOCK_MASK);
 633        if (!(val < 0)) {
 634                __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
 635                input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
 636        }
 637
 638        /* Tablet mode */
 639        val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
 640        if (!(val < 0)) {
 641                __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
 642                input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
 643        }
 644
 645        err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
 646        if (err)
 647                goto err_free_dev;
 648
 649        /* Set initial hardware state */
 650        input_sync(hp_wmi_input_dev);
 651
 652        if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
 653                hp_wmi_enable_hotkeys();
 654
 655        status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
 656        if (ACPI_FAILURE(status)) {
 657                err = -EIO;
 658                goto err_free_dev;
 659        }
 660
 661        err = input_register_device(hp_wmi_input_dev);
 662        if (err)
 663                goto err_uninstall_notifier;
 664
 665        return 0;
 666
 667 err_uninstall_notifier:
 668        wmi_remove_notify_handler(HPWMI_EVENT_GUID);
 669 err_free_dev:
 670        input_free_device(hp_wmi_input_dev);
 671        return err;
 672}
 673
 674static void hp_wmi_input_destroy(void)
 675{
 676        wmi_remove_notify_handler(HPWMI_EVENT_GUID);
 677        input_unregister_device(hp_wmi_input_dev);
 678}
 679
 680static void cleanup_sysfs(struct platform_device *device)
 681{
 682        device_remove_file(&device->dev, &dev_attr_display);
 683        device_remove_file(&device->dev, &dev_attr_hddtemp);
 684        device_remove_file(&device->dev, &dev_attr_als);
 685        device_remove_file(&device->dev, &dev_attr_dock);
 686        device_remove_file(&device->dev, &dev_attr_tablet);
 687        device_remove_file(&device->dev, &dev_attr_postcode);
 688}
 689
 690static int __init hp_wmi_rfkill_setup(struct platform_device *device)
 691{
 692        int err, wireless;
 693
 694        wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 695        if (wireless < 0)
 696                return wireless;
 697
 698        err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
 699                                   sizeof(wireless), 0);
 700        if (err)
 701                return err;
 702
 703        if (wireless & 0x1) {
 704                wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
 705                                           RFKILL_TYPE_WLAN,
 706                                           &hp_wmi_rfkill_ops,
 707                                           (void *) HPWMI_WIFI);
 708                if (!wifi_rfkill)
 709                        return -ENOMEM;
 710                rfkill_init_sw_state(wifi_rfkill,
 711                                     hp_wmi_get_sw_state(HPWMI_WIFI));
 712                rfkill_set_hw_state(wifi_rfkill,
 713                                    hp_wmi_get_hw_state(HPWMI_WIFI));
 714                err = rfkill_register(wifi_rfkill);
 715                if (err)
 716                        goto register_wifi_error;
 717        }
 718
 719        if (wireless & 0x2) {
 720                bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
 721                                                RFKILL_TYPE_BLUETOOTH,
 722                                                &hp_wmi_rfkill_ops,
 723                                                (void *) HPWMI_BLUETOOTH);
 724                if (!bluetooth_rfkill) {
 725                        err = -ENOMEM;
 726                        goto register_bluetooth_error;
 727                }
 728                rfkill_init_sw_state(bluetooth_rfkill,
 729                                     hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
 730                rfkill_set_hw_state(bluetooth_rfkill,
 731                                    hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
 732                err = rfkill_register(bluetooth_rfkill);
 733                if (err)
 734                        goto register_bluetooth_error;
 735        }
 736
 737        if (wireless & 0x4) {
 738                wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
 739                                           RFKILL_TYPE_WWAN,
 740                                           &hp_wmi_rfkill_ops,
 741                                           (void *) HPWMI_WWAN);
 742                if (!wwan_rfkill) {
 743                        err = -ENOMEM;
 744                        goto register_wwan_error;
 745                }
 746                rfkill_init_sw_state(wwan_rfkill,
 747                                     hp_wmi_get_sw_state(HPWMI_WWAN));
 748                rfkill_set_hw_state(wwan_rfkill,
 749                                    hp_wmi_get_hw_state(HPWMI_WWAN));
 750                err = rfkill_register(wwan_rfkill);
 751                if (err)
 752                        goto register_wwan_error;
 753        }
 754
 755        return 0;
 756
 757register_wwan_error:
 758        rfkill_destroy(wwan_rfkill);
 759        wwan_rfkill = NULL;
 760        if (bluetooth_rfkill)
 761                rfkill_unregister(bluetooth_rfkill);
 762register_bluetooth_error:
 763        rfkill_destroy(bluetooth_rfkill);
 764        bluetooth_rfkill = NULL;
 765        if (wifi_rfkill)
 766                rfkill_unregister(wifi_rfkill);
 767register_wifi_error:
 768        rfkill_destroy(wifi_rfkill);
 769        wifi_rfkill = NULL;
 770        return err;
 771}
 772
 773static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
 774{
 775        struct bios_rfkill2_state state;
 776        int err, i;
 777
 778        err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
 779                                   0, sizeof(state));
 780        if (err)
 781                return err < 0 ? err : -EINVAL;
 782
 783        if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
 784                pr_warn("unable to parse 0x1b query output\n");
 785                return -EINVAL;
 786        }
 787
 788        for (i = 0; i < state.count; i++) {
 789                struct rfkill *rfkill;
 790                enum rfkill_type type;
 791                char *name;
 792                switch (state.device[i].radio_type) {
 793                case HPWMI_WIFI:
 794                        type = RFKILL_TYPE_WLAN;
 795                        name = "hp-wifi";
 796                        break;
 797                case HPWMI_BLUETOOTH:
 798                        type = RFKILL_TYPE_BLUETOOTH;
 799                        name = "hp-bluetooth";
 800                        break;
 801                case HPWMI_WWAN:
 802                        type = RFKILL_TYPE_WWAN;
 803                        name = "hp-wwan";
 804                        break;
 805                case HPWMI_GPS:
 806                        type = RFKILL_TYPE_GPS;
 807                        name = "hp-gps";
 808                        break;
 809                default:
 810                        pr_warn("unknown device type 0x%x\n",
 811                                state.device[i].radio_type);
 812                        continue;
 813                }
 814
 815                if (!state.device[i].vendor_id) {
 816                        pr_warn("zero device %d while %d reported\n",
 817                                i, state.count);
 818                        continue;
 819                }
 820
 821                rfkill = rfkill_alloc(name, &device->dev, type,
 822                                      &hp_wmi_rfkill2_ops, (void *)(long)i);
 823                if (!rfkill) {
 824                        err = -ENOMEM;
 825                        goto fail;
 826                }
 827
 828                rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
 829                rfkill2[rfkill2_count].num = i;
 830                rfkill2[rfkill2_count].rfkill = rfkill;
 831
 832                rfkill_init_sw_state(rfkill,
 833                                     IS_SWBLOCKED(state.device[i].power));
 834                rfkill_set_hw_state(rfkill,
 835                                    IS_HWBLOCKED(state.device[i].power));
 836
 837                if (!(state.device[i].power & HPWMI_POWER_BIOS))
 838                        pr_info("device %s blocked by BIOS\n", name);
 839
 840                err = rfkill_register(rfkill);
 841                if (err) {
 842                        rfkill_destroy(rfkill);
 843                        goto fail;
 844                }
 845
 846                rfkill2_count++;
 847        }
 848
 849        return 0;
 850fail:
 851        for (; rfkill2_count > 0; rfkill2_count--) {
 852                rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
 853                rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
 854        }
 855        return err;
 856}
 857
 858static int __init hp_wmi_bios_setup(struct platform_device *device)
 859{
 860        int err;
 861
 862        /* clear detected rfkill devices */
 863        wifi_rfkill = NULL;
 864        bluetooth_rfkill = NULL;
 865        wwan_rfkill = NULL;
 866        rfkill2_count = 0;
 867
 868        if (hp_wmi_rfkill_setup(device))
 869                hp_wmi_rfkill2_setup(device);
 870
 871        err = device_create_file(&device->dev, &dev_attr_display);
 872        if (err)
 873                goto add_sysfs_error;
 874        err = device_create_file(&device->dev, &dev_attr_hddtemp);
 875        if (err)
 876                goto add_sysfs_error;
 877        err = device_create_file(&device->dev, &dev_attr_als);
 878        if (err)
 879                goto add_sysfs_error;
 880        err = device_create_file(&device->dev, &dev_attr_dock);
 881        if (err)
 882                goto add_sysfs_error;
 883        err = device_create_file(&device->dev, &dev_attr_tablet);
 884        if (err)
 885                goto add_sysfs_error;
 886        err = device_create_file(&device->dev, &dev_attr_postcode);
 887        if (err)
 888                goto add_sysfs_error;
 889        return 0;
 890
 891add_sysfs_error:
 892        cleanup_sysfs(device);
 893        return err;
 894}
 895
 896static int __exit hp_wmi_bios_remove(struct platform_device *device)
 897{
 898        int i;
 899        cleanup_sysfs(device);
 900
 901        for (i = 0; i < rfkill2_count; i++) {
 902                rfkill_unregister(rfkill2[i].rfkill);
 903                rfkill_destroy(rfkill2[i].rfkill);
 904        }
 905
 906        if (wifi_rfkill) {
 907                rfkill_unregister(wifi_rfkill);
 908                rfkill_destroy(wifi_rfkill);
 909        }
 910        if (bluetooth_rfkill) {
 911                rfkill_unregister(bluetooth_rfkill);
 912                rfkill_destroy(bluetooth_rfkill);
 913        }
 914        if (wwan_rfkill) {
 915                rfkill_unregister(wwan_rfkill);
 916                rfkill_destroy(wwan_rfkill);
 917        }
 918
 919        return 0;
 920}
 921
 922static int hp_wmi_resume_handler(struct device *device)
 923{
 924        /*
 925         * Hardware state may have changed while suspended, so trigger
 926         * input events for the current state. As this is a switch,
 927         * the input layer will only actually pass it on if the state
 928         * changed.
 929         */
 930        if (hp_wmi_input_dev) {
 931                if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
 932                        input_report_switch(hp_wmi_input_dev, SW_DOCK,
 933                                            hp_wmi_hw_state(HPWMI_DOCK_MASK));
 934                if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
 935                        input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
 936                                            hp_wmi_hw_state(HPWMI_TABLET_MASK));
 937                input_sync(hp_wmi_input_dev);
 938        }
 939
 940        if (rfkill2_count)
 941                hp_wmi_rfkill2_refresh();
 942
 943        if (wifi_rfkill)
 944                rfkill_set_states(wifi_rfkill,
 945                                  hp_wmi_get_sw_state(HPWMI_WIFI),
 946                                  hp_wmi_get_hw_state(HPWMI_WIFI));
 947        if (bluetooth_rfkill)
 948                rfkill_set_states(bluetooth_rfkill,
 949                                  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
 950                                  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
 951        if (wwan_rfkill)
 952                rfkill_set_states(wwan_rfkill,
 953                                  hp_wmi_get_sw_state(HPWMI_WWAN),
 954                                  hp_wmi_get_hw_state(HPWMI_WWAN));
 955
 956        return 0;
 957}
 958
 959static const struct dev_pm_ops hp_wmi_pm_ops = {
 960        .resume  = hp_wmi_resume_handler,
 961        .restore  = hp_wmi_resume_handler,
 962};
 963
 964static struct platform_driver hp_wmi_driver = {
 965        .driver = {
 966                .name = "hp-wmi",
 967                .pm = &hp_wmi_pm_ops,
 968        },
 969        .remove = __exit_p(hp_wmi_bios_remove),
 970};
 971
 972static int __init hp_wmi_init(void)
 973{
 974        int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
 975        int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
 976        int err;
 977
 978        if (!bios_capable && !event_capable)
 979                return -ENODEV;
 980
 981        if (event_capable) {
 982                err = hp_wmi_input_setup();
 983                if (err)
 984                        return err;
 985        }
 986
 987        if (bios_capable) {
 988                hp_wmi_platform_dev =
 989                        platform_device_register_simple("hp-wmi", -1, NULL, 0);
 990                if (IS_ERR(hp_wmi_platform_dev)) {
 991                        err = PTR_ERR(hp_wmi_platform_dev);
 992                        goto err_destroy_input;
 993                }
 994
 995                err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup);
 996                if (err)
 997                        goto err_unregister_device;
 998        }
 999
1000        return 0;
1001
1002err_unregister_device:
1003        platform_device_unregister(hp_wmi_platform_dev);
1004err_destroy_input:
1005        if (event_capable)
1006                hp_wmi_input_destroy();
1007
1008        return err;
1009}
1010module_init(hp_wmi_init);
1011
1012static void __exit hp_wmi_exit(void)
1013{
1014        if (wmi_has_guid(HPWMI_EVENT_GUID))
1015                hp_wmi_input_destroy();
1016
1017        if (hp_wmi_platform_dev) {
1018                platform_device_unregister(hp_wmi_platform_dev);
1019                platform_driver_unregister(&hp_wmi_driver);
1020        }
1021}
1022module_exit(hp_wmi_exit);
1023