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