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