Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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