FILE
hp-wmi.c
File preview with syntax highlighting.
linux-6.19.14/drivers/platform/x86/hp/hp-wmi.c
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/hwmon.h> 26#include <linux/acpi.h> 27#include <linux/mutex.h> 28#include <linux/cleanup.h> 29#include <linux/power_supply.h> 30#include <linux/rfkill.h> 31#include <linux/string.h> 32#include <linux/dmi.h> 33 34MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>"); 35MODULE_DESCRIPTION("HP laptop WMI driver"); 36MODULE_LICENSE("GPL"); 37 38MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C"); 39MODULE_ALIAS("wmi:5FB7F034-2C63-45E9-BE91-3D44E2C707E4"); 40 41#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" 42#define HPWMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4" 43 44#define HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET 0x62 45#define HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET 0x63 46#define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 47 48#define HP_FAN_SPEED_AUTOMATIC 0x00 49#define HP_POWER_LIMIT_DEFAULT 0x00 50#define HP_POWER_LIMIT_NO_CHANGE 0xFF 51 52#define ACPI_AC_CLASS "ac_adapter" 53 54#define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required 55 56enum hp_thermal_profile_omen_v0 { 57 HP_OMEN_V0_THERMAL_PROFILE_DEFAULT = 0x00, 58 HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE = 0x01, 59 HP_OMEN_V0_THERMAL_PROFILE_COOL = 0x02, 60}; 61 62enum hp_thermal_profile_omen_v1 { 63 HP_OMEN_V1_THERMAL_PROFILE_DEFAULT = 0x30, 64 HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE = 0x31, 65 HP_OMEN_V1_THERMAL_PROFILE_COOL = 0x50, 66}; 67 68enum hp_thermal_profile_omen_flags { 69 HP_OMEN_EC_FLAGS_TURBO = 0x04, 70 HP_OMEN_EC_FLAGS_NOTIMER = 0x02, 71 HP_OMEN_EC_FLAGS_JUSTSET = 0x01, 72}; 73 74enum hp_thermal_profile_victus { 75 HP_VICTUS_THERMAL_PROFILE_DEFAULT = 0x00, 76 HP_VICTUS_THERMAL_PROFILE_PERFORMANCE = 0x01, 77 HP_VICTUS_THERMAL_PROFILE_QUIET = 0x03, 78}; 79 80enum hp_thermal_profile_victus_s { 81 HP_VICTUS_S_THERMAL_PROFILE_DEFAULT = 0x00, 82 HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE = 0x01, 83}; 84 85enum hp_thermal_profile { 86 HP_THERMAL_PROFILE_PERFORMANCE = 0x00, 87 HP_THERMAL_PROFILE_DEFAULT = 0x01, 88 HP_THERMAL_PROFILE_COOL = 0x02, 89 HP_THERMAL_PROFILE_QUIET = 0x03, 90}; 91 92struct thermal_profile_params { 93 u8 performance; 94 u8 balanced; 95 u8 low_power; 96}; 97 98static const struct thermal_profile_params victus_s_thermal_params = { 99 .performance = HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE, 100 .balanced = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT, 101 .low_power = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT, 102}; 103 104static const struct thermal_profile_params omen_v1_thermal_params = { 105 .performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE, 106 .balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT, 107 .low_power = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT, 108}; 109 110/* 111 * A generic pointer for the currently-active board's thermal profile 112 * parameters. 113 */ 114static struct thermal_profile_params *active_thermal_profile_params; 115 116/* DMI board names of devices that should use the omen specific path for 117 * thermal profiles. 118 * This was obtained by taking a look in the windows omen command center 119 * app and parsing a json file that they use to figure out what capabilities 120 * the device should have. 121 * A device is considered an omen if the DisplayName in that list contains 122 * "OMEN", and it can use the thermal profile stuff if the "Feature" array 123 * contains "PerformanceControl". 124 */ 125static const char * const omen_thermal_profile_boards[] = { 126 "84DA", "84DB", "84DC", 127 "8572", "8573", "8574", "8575", 128 "8600", "8601", "8602", "8603", "8604", "8605", "8606", "8607", "860A", 129 "8746", "8747", "8748", "8749", "874A", "8786", "8787", "8788", "878A", 130 "878B", "878C", "87B5", 131 "886B", "886C", "88C8", "88CB", "88D1", "88D2", "88F4", "88F5", "88F6", 132 "88F7", "88FD", "88FE", "88FF", 133 "8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB", 134 "8A15", "8A42", 135 "8BAD", 136 "8E41", 137}; 138 139/* DMI Board names of Omen laptops that are specifically set to be thermal 140 * profile version 0 by the Omen Command Center app, regardless of what 141 * the get system design information WMI call returns 142 */ 143static const char * const omen_thermal_profile_force_v0_boards[] = { 144 "8607", 145 "8746", "8747", "8748", "8749", "874A", 146}; 147 148/* DMI board names of Omen laptops that have a thermal profile timer which will 149 * cause the embedded controller to set the thermal profile back to 150 * "balanced" when reaching zero. 151 */ 152static const char * const omen_timed_thermal_profile_boards[] = { 153 "8A15", "8A42", 154 "8BAD", 155}; 156 157/* DMI Board names of Victus 16-d laptops */ 158static const char * const victus_thermal_profile_boards[] = { 159 "88F8", 160 "8A25", 161}; 162 163/* DMI Board names of Victus 16-r and Victus 16-s laptops */ 164static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { 165 { 166 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") }, 167 .driver_data = (void *)&omen_v1_thermal_params, 168 }, 169 { 170 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") }, 171 .driver_data = (void *)&victus_s_thermal_params, 172 }, 173 { 174 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") }, 175 .driver_data = (void *)&omen_v1_thermal_params, 176 }, 177 { 178 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") }, 179 .driver_data = (void *)&victus_s_thermal_params, 180 }, 181 { 182 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") }, 183 .driver_data = (void *)&victus_s_thermal_params, 184 }, 185 { 186 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") }, 187 .driver_data = (void *)&omen_v1_thermal_params, 188 }, 189 { 190 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") }, 191 .driver_data = (void *)&omen_v1_thermal_params, 192 }, 193 { 194 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") }, 195 .driver_data = (void *)&victus_s_thermal_params, 196 }, 197 { 198 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") }, 199 .driver_data = (void *)&victus_s_thermal_params, 200 }, 201 { 202 .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") }, 203 .driver_data = (void *)&victus_s_thermal_params, 204 }, 205 {}, 206}; 207 208static bool is_victus_s_board; 209 210enum hp_wmi_radio { 211 HPWMI_WIFI = 0x0, 212 HPWMI_BLUETOOTH = 0x1, 213 HPWMI_WWAN = 0x2, 214 HPWMI_GPS = 0x3, 215}; 216 217enum hp_wmi_event_ids { 218 HPWMI_DOCK_EVENT = 0x01, 219 HPWMI_PARK_HDD = 0x02, 220 HPWMI_SMART_ADAPTER = 0x03, 221 HPWMI_BEZEL_BUTTON = 0x04, 222 HPWMI_WIRELESS = 0x05, 223 HPWMI_CPU_BATTERY_THROTTLE = 0x06, 224 HPWMI_LOCK_SWITCH = 0x07, 225 HPWMI_LID_SWITCH = 0x08, 226 HPWMI_SCREEN_ROTATION = 0x09, 227 HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A, 228 HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B, 229 HPWMI_PROXIMITY_SENSOR = 0x0C, 230 HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, 231 HPWMI_PEAKSHIFT_PERIOD = 0x0F, 232 HPWMI_BATTERY_CHARGE_PERIOD = 0x10, 233 HPWMI_SANITIZATION_MODE = 0x17, 234 HPWMI_CAMERA_TOGGLE = 0x1A, 235 HPWMI_FN_P_HOTKEY = 0x1B, 236 HPWMI_OMEN_KEY = 0x1D, 237 HPWMI_SMART_EXPERIENCE_APP = 0x21, 238}; 239 240/* 241 * struct bios_args buffer is dynamically allocated. New WMI command types 242 * were introduced that exceeds 128-byte data size. Changes to handle 243 * the data size allocation scheme were kept in hp_wmi_perform_qurey function. 244 */ 245struct bios_args { 246 u32 signature; 247 u32 command; 248 u32 commandtype; 249 u32 datasize; 250 u8 data[]; 251}; 252 253enum hp_wmi_commandtype { 254 HPWMI_DISPLAY_QUERY = 0x01, 255 HPWMI_HDDTEMP_QUERY = 0x02, 256 HPWMI_ALS_QUERY = 0x03, 257 HPWMI_HARDWARE_QUERY = 0x04, 258 HPWMI_WIRELESS_QUERY = 0x05, 259 HPWMI_BATTERY_QUERY = 0x07, 260 HPWMI_BIOS_QUERY = 0x09, 261 HPWMI_FEATURE_QUERY = 0x0b, 262 HPWMI_HOTKEY_QUERY = 0x0c, 263 HPWMI_FEATURE2_QUERY = 0x0d, 264 HPWMI_WIRELESS2_QUERY = 0x1b, 265 HPWMI_POSTCODEERROR_QUERY = 0x2a, 266 HPWMI_SYSTEM_DEVICE_MODE = 0x40, 267 HPWMI_THERMAL_PROFILE_QUERY = 0x4c, 268}; 269 270struct victus_power_limits { 271 u8 pl1; 272 u8 pl2; 273 u8 pl4; 274 u8 cpu_gpu_concurrent_limit; 275}; 276 277struct victus_gpu_power_modes { 278 u8 ctgp_enable; 279 u8 ppab_enable; 280 u8 dstate; 281 u8 gpu_slowdown_temp; 282}; 283 284enum hp_wmi_gm_commandtype { 285 HPWMI_FAN_SPEED_GET_QUERY = 0x11, 286 HPWMI_SET_PERFORMANCE_MODE = 0x1A, 287 HPWMI_FAN_SPEED_MAX_GET_QUERY = 0x26, 288 HPWMI_FAN_SPEED_MAX_SET_QUERY = 0x27, 289 HPWMI_GET_SYSTEM_DESIGN_DATA = 0x28, 290 HPWMI_FAN_COUNT_GET_QUERY = 0x10, 291 HPWMI_GET_GPU_THERMAL_MODES_QUERY = 0x21, 292 HPWMI_SET_GPU_THERMAL_MODES_QUERY = 0x22, 293 HPWMI_SET_POWER_LIMITS_QUERY = 0x29, 294 HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY = 0x2D, 295 HPWMI_FAN_SPEED_SET_QUERY = 0x2E, 296}; 297 298enum hp_wmi_command { 299 HPWMI_READ = 0x01, 300 HPWMI_WRITE = 0x02, 301 HPWMI_ODM = 0x03, 302 HPWMI_GM = 0x20008, 303}; 304 305enum hp_wmi_hardware_mask { 306 HPWMI_DOCK_MASK = 0x01, 307 HPWMI_TABLET_MASK = 0x04, 308}; 309 310struct bios_return { 311 u32 sigpass; 312 u32 return_code; 313}; 314 315enum hp_return_value { 316 HPWMI_RET_WRONG_SIGNATURE = 0x02, 317 HPWMI_RET_UNKNOWN_COMMAND = 0x03, 318 HPWMI_RET_UNKNOWN_CMDTYPE = 0x04, 319 HPWMI_RET_INVALID_PARAMETERS = 0x05, 320}; 321 322enum hp_wireless2_bits { 323 HPWMI_POWER_STATE = 0x01, 324 HPWMI_POWER_SOFT = 0x02, 325 HPWMI_POWER_BIOS = 0x04, 326 HPWMI_POWER_HARD = 0x08, 327 HPWMI_POWER_FW_OR_HW = HPWMI_POWER_BIOS | HPWMI_POWER_HARD, 328}; 329 330#define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW) 331#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) 332 333struct bios_rfkill2_device_state { 334 u8 radio_type; 335 u8 bus_type; 336 u16 vendor_id; 337 u16 product_id; 338 u16 subsys_vendor_id; 339 u16 subsys_product_id; 340 u8 rfkill_id; 341 u8 power; 342 u8 unknown[4]; 343}; 344 345/* 7 devices fit into the 128 byte buffer */ 346#define HPWMI_MAX_RFKILL2_DEVICES 7 347 348struct bios_rfkill2_state { 349 u8 unknown[7]; 350 u8 count; 351 u8 pad[8]; 352 struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES]; 353}; 354 355static const struct key_entry hp_wmi_keymap[] = { 356 { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } }, 357 { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } }, 358 { KE_KEY, 0x270, { KEY_MICMUTE } }, 359 { KE_KEY, 0x20e6, { KEY_PROG1 } }, 360 { KE_KEY, 0x20e8, { KEY_MEDIA } }, 361 { KE_KEY, 0x2142, { KEY_MEDIA } }, 362 { KE_KEY, 0x213b, { KEY_INFO } }, 363 { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } }, 364 { KE_KEY, 0x216a, { KEY_SETUP } }, 365 { KE_IGNORE, 0x21a4, }, /* Win Lock On */ 366 { KE_IGNORE, 0x121a4, }, /* Win Lock Off */ 367 { KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */ 368 { KE_KEY, 0x21a7, { KEY_FN_ESC } }, 369 { KE_KEY, 0x21a8, { KEY_PROG2 } }, /* HP Envy x360 programmable key */ 370 { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, 371 { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, 372 { KE_KEY, 0x231b, { KEY_HELP } }, 373 { KE_END, 0 } 374}; 375 376/* 377 * Mutex for the active_platform_profile variable, 378 * see omen_powersource_event. 379 */ 380static DEFINE_MUTEX(active_platform_profile_lock); 381 382static struct input_dev *hp_wmi_input_dev; 383static struct input_dev *camera_shutter_input_dev; 384static struct platform_device *hp_wmi_platform_dev; 385static struct device *platform_profile_device; 386static struct notifier_block platform_power_source_nb; 387static enum platform_profile_option active_platform_profile; 388static bool platform_profile_support; 389static bool zero_insize_support; 390 391static struct rfkill *wifi_rfkill; 392static struct rfkill *bluetooth_rfkill; 393static struct rfkill *wwan_rfkill; 394 395struct rfkill2_device { 396 u8 id; 397 int num; 398 struct rfkill *rfkill; 399}; 400 401static int rfkill2_count; 402static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; 403 404/* 405 * Chassis Types values were obtained from SMBIOS reference 406 * specification version 3.00. A complete list of system enclosures 407 * and chassis types is available on Table 17. 408 */ 409static const char * const tablet_chassis_types[] = { 410 "30", /* Tablet*/ 411 "31", /* Convertible */ 412 "32" /* Detachable */ 413}; 414 415#define DEVICE_MODE_TABLET 0x06 416 417/* map output size to the corresponding WMI method id */ 418static inline int encode_outsize_for_pvsz(int outsize) 419{ 420 if (outsize > 4096) 421 return -EINVAL; 422 if (outsize > 1024) 423 return 5; 424 if (outsize > 128) 425 return 4; 426 if (outsize > 4) 427 return 3; 428 if (outsize > 0) 429 return 2; 430 return 1; 431} 432 433/* 434 * hp_wmi_perform_query 435 * 436 * query: The commandtype (enum hp_wmi_commandtype) 437 * write: The command (enum hp_wmi_command) 438 * buffer: Buffer used as input and/or output 439 * insize: Size of input buffer 440 * outsize: Size of output buffer 441 * 442 * returns zero on success 443 * an HP WMI query specific error code (which is positive) 444 * -EINVAL if the query was not successful at all 445 * -EINVAL if the output buffer size exceeds buffersize 446 * 447 * Note: The buffersize must at least be the maximum of the input and output 448 * size. E.g. Battery info query is defined to have 1 byte input 449 * and 128 byte output. The caller would do: 450 * buffer = kzalloc(128, GFP_KERNEL); 451 * ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128) 452 */ 453static int hp_wmi_perform_query(int query, enum hp_wmi_command command, 454 void *buffer, int insize, int outsize) 455{ 456 struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; 457 struct bios_return *bios_return; 458 union acpi_object *obj = NULL; 459 struct bios_args *args = NULL; 460 int mid, actual_insize, actual_outsize; 461 size_t bios_args_size; 462 int ret; 463 464 mid = encode_outsize_for_pvsz(outsize); 465 if (WARN_ON(mid < 0)) 466 return mid; 467 468 actual_insize = max(insize, 128); 469 bios_args_size = struct_size(args, data, actual_insize); 470 args = kmalloc(bios_args_size, GFP_KERNEL); 471 if (!args) 472 return -ENOMEM; 473 474 input.length = bios_args_size; 475 input.pointer = args; 476 477 args->signature = 0x55434553; 478 args->command = command; 479 args->commandtype = query; 480 args->datasize = insize; 481 memcpy(args->data, buffer, flex_array_size(args, data, insize)); 482 483 ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); 484 if (ret) 485 goto out_free; 486 487 obj = output.pointer; 488 if (!obj) { 489 ret = -EINVAL; 490 goto out_free; 491 } 492 493 if (obj->type != ACPI_TYPE_BUFFER) { 494 pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); 495 ret = -EINVAL; 496 goto out_free; 497 } 498 499 bios_return = (struct bios_return *)obj->buffer.pointer; 500 ret = bios_return->return_code; 501 502 if (ret) { 503 if (ret != HPWMI_RET_UNKNOWN_COMMAND && 504 ret != HPWMI_RET_UNKNOWN_CMDTYPE) 505 pr_warn("query 0x%x returned error 0x%x\n", query, ret); 506 goto out_free; 507 } 508 509 /* Ignore output data of zero size */ 510 if (!outsize) 511 goto out_free; 512 513 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); 514 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); 515 memset(buffer + actual_outsize, 0, outsize - actual_outsize); 516 517out_free: 518 kfree(obj); 519 kfree(args); 520 return ret; 521} 522 523/* 524 * Calling this hp_wmi_get_fan_count_userdefine_trigger function also enables 525 * and/or maintains the laptop in user defined thermal and fan states, instead 526 * of using a fallback state. After a 120 seconds timeout however, the laptop 527 * goes back to its fallback state. 528 */ 529static int hp_wmi_get_fan_count_userdefine_trigger(void) 530{ 531 u8 fan_data[4] = {}; 532 int ret; 533 534 ret = hp_wmi_perform_query(HPWMI_FAN_COUNT_GET_QUERY, HPWMI_GM, 535 &fan_data, sizeof(u8), 536 sizeof(fan_data)); 537 if (ret != 0) 538 return -EINVAL; 539 540 return fan_data[0]; /* Others bytes aren't providing fan count */ 541} 542 543static int hp_wmi_get_fan_speed(int fan) 544{ 545 u8 fsh, fsl; 546 char fan_data[4] = { fan, 0, 0, 0 }; 547 548 int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM, 549 &fan_data, sizeof(char), 550 sizeof(fan_data)); 551 552 if (ret != 0) 553 return -EINVAL; 554 555 fsh = fan_data[2]; 556 fsl = fan_data[3]; 557 558 return (fsh << 8) | fsl; 559} 560 561static int hp_wmi_get_fan_speed_victus_s(int fan) 562{ 563 u8 fan_data[128] = {}; 564 int ret; 565 566 if (fan < 0 || fan >= sizeof(fan_data)) 567 return -EINVAL; 568 569 ret = hp_wmi_perform_query(HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY, 570 HPWMI_GM, &fan_data, sizeof(u8), 571 sizeof(fan_data)); 572 if (ret != 0) 573 return -EINVAL; 574 575 return fan_data[fan] * 100; 576} 577 578static int hp_wmi_read_int(int query) 579{ 580 int val = 0, ret; 581 582 ret = hp_wmi_perform_query(query, HPWMI_READ, &val, 583 zero_if_sup(val), sizeof(val)); 584 585 if (ret) 586 return ret < 0 ? ret : -EINVAL; 587 588 return val; 589} 590 591static int hp_wmi_get_dock_state(void) 592{ 593 int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); 594 595 if (state < 0) 596 return state; 597 598 return !!(state & HPWMI_DOCK_MASK); 599} 600 601static int hp_wmi_get_tablet_mode(void) 602{ 603 char system_device_mode[4] = { 0 }; 604 const char *chassis_type; 605 bool tablet_found; 606 int ret; 607 608 chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); 609 if (!chassis_type) 610 return -ENODEV; 611 612 tablet_found = match_string(tablet_chassis_types, 613 ARRAY_SIZE(tablet_chassis_types), 614 chassis_type) >= 0; 615 if (!tablet_found) 616 return -ENODEV; 617 618 ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, 619 system_device_mode, zero_if_sup(system_device_mode), 620 sizeof(system_device_mode)); 621 if (ret < 0) 622 return ret; 623 624 return system_device_mode[0] == DEVICE_MODE_TABLET; 625} 626 627static int omen_thermal_profile_set(int mode) 628{ 629 /* The Omen Control Center actively sets the first byte of the buffer to 630 * 255, so let's mimic this behaviour to be as close as possible to 631 * the original software. 632 */ 633 char buffer[2] = {-1, mode}; 634 int ret; 635 636 ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM, 637 &buffer, sizeof(buffer), 0); 638 639 if (ret) 640 return ret < 0 ? ret : -EINVAL; 641 642 return mode; 643} 644 645static bool is_omen_thermal_profile(void) 646{ 647 const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); 648 649 if (!board_name) 650 return false; 651 652 return match_string(omen_thermal_profile_boards, 653 ARRAY_SIZE(omen_thermal_profile_boards), 654 board_name) >= 0; 655} 656 657static int omen_get_thermal_policy_version(void) 658{ 659 unsigned char buffer[8] = { 0 }; 660 int ret; 661 662 const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); 663 664 if (board_name) { 665 int matches = match_string(omen_thermal_profile_force_v0_boards, 666 ARRAY_SIZE(omen_thermal_profile_force_v0_boards), 667 board_name); 668 if (matches >= 0) 669 return 0; 670 } 671 672 ret = hp_wmi_perform_query(HPWMI_GET_SYSTEM_DESIGN_DATA, HPWMI_GM, 673 &buffer, sizeof(buffer), sizeof(buffer)); 674 675 if (ret) 676 return ret < 0 ? ret : -EINVAL; 677 678 return buffer[3]; 679} 680 681static int omen_thermal_profile_get(void) 682{ 683 u8 data; 684 685 int ret = ec_read(HP_OMEN_EC_THERMAL_PROFILE_OFFSET, &data); 686 687 if (ret) 688 return ret; 689 690 return data; 691} 692 693static int hp_wmi_fan_speed_max_set(int enabled) 694{ 695 int ret; 696 697 ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM, 698 &enabled, sizeof(enabled), 0); 699 700 if (ret) 701 return ret < 0 ? ret : -EINVAL; 702 703 return enabled; 704} 705 706static int hp_wmi_fan_speed_reset(void) 707{ 708 u8 fan_speed[2] = { HP_FAN_SPEED_AUTOMATIC, HP_FAN_SPEED_AUTOMATIC }; 709 int ret; 710 711 ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_SET_QUERY, HPWMI_GM, 712 &fan_speed, sizeof(fan_speed), 0); 713 714 return ret; 715} 716 717static int hp_wmi_fan_speed_max_reset(void) 718{ 719 int ret; 720 721 ret = hp_wmi_fan_speed_max_set(0); 722 if (ret) 723 return ret; 724 725 /* Disabling max fan speed on Victus s1xxx laptops needs a 2nd step: */ 726 ret = hp_wmi_fan_speed_reset(); 727 return ret; 728} 729 730static int hp_wmi_fan_speed_max_get(void) 731{ 732 int val = 0, ret; 733 734 ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM, 735 &val, zero_if_sup(val), sizeof(val)); 736 737 if (ret) 738 return ret < 0 ? ret : -EINVAL; 739 740 return val; 741} 742 743static int __init hp_wmi_bios_2008_later(void) 744{ 745 int state = 0; 746 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state, 747 zero_if_sup(state), sizeof(state)); 748 if (!ret) 749 return 1; 750 751 return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; 752} 753 754static int __init hp_wmi_bios_2009_later(void) 755{ 756 u8 state[128]; 757 int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state, 758 zero_if_sup(state), sizeof(state)); 759 if (!ret) 760 return 1; 761 762 return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; 763} 764 765static int __init hp_wmi_enable_hotkeys(void) 766{ 767 int value = 0x6e; 768 int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value, 769 sizeof(value), 0); 770 771 return ret <= 0 ? ret : -EINVAL; 772} 773 774static int hp_wmi_set_block(void *data, bool blocked) 775{ 776 enum hp_wmi_radio r = (long)data; 777 int query = BIT(r + 8) | ((!blocked) << r); 778 int ret; 779 780 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, 781 &query, sizeof(query), 0); 782 783 return ret <= 0 ? ret : -EINVAL; 784} 785 786static const struct rfkill_ops hp_wmi_rfkill_ops = { 787 .set_block = hp_wmi_set_block, 788}; 789 790static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 791{ 792 int mask = 0x200 << (r * 8); 793 794 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 795 796 /* TBD: Pass error */ 797 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 798 799 return !(wireless & mask); 800} 801 802static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 803{ 804 int mask = 0x800 << (r * 8); 805 806 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 807 808 /* TBD: Pass error */ 809 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 810 811 return !(wireless & mask); 812} 813 814static int hp_wmi_rfkill2_set_block(void *data, bool blocked) 815{ 816 int rfkill_id = (int)(long)data; 817 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; 818 int ret; 819 820 ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE, 821 buffer, sizeof(buffer), 0); 822 823 return ret <= 0 ? ret : -EINVAL; 824} 825 826static const struct rfkill_ops hp_wmi_rfkill2_ops = { 827 .set_block = hp_wmi_rfkill2_set_block, 828}; 829 830static int hp_wmi_rfkill2_refresh(void) 831{ 832 struct bios_rfkill2_state state; 833 int err, i; 834 835 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 836 zero_if_sup(state), sizeof(state)); 837 if (err) 838 return err; 839 840 for (i = 0; i < rfkill2_count; i++) { 841 int num = rfkill2[i].num; 842 struct bios_rfkill2_device_state *devstate; 843 844 devstate = &state.device[num]; 845 846 if (num >= state.count || 847 devstate->rfkill_id != rfkill2[i].id) { 848 pr_warn("power configuration of the wireless devices unexpectedly changed\n"); 849 continue; 850 } 851 852 rfkill_set_states(rfkill2[i].rfkill, 853 IS_SWBLOCKED(devstate->power), 854 IS_HWBLOCKED(devstate->power)); 855 } 856 857 return 0; 858} 859 860static ssize_t display_show(struct device *dev, struct device_attribute *attr, 861 char *buf) 862{ 863 int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY); 864 865 if (value < 0) 866 return value; 867 return sysfs_emit(buf, "%d\n", value); 868} 869 870static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr, 871 char *buf) 872{ 873 int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY); 874 875 if (value < 0) 876 return value; 877 return sysfs_emit(buf, "%d\n", value); 878} 879 880static ssize_t als_show(struct device *dev, struct device_attribute *attr, 881 char *buf) 882{ 883 int value = hp_wmi_read_int(HPWMI_ALS_QUERY); 884 885 if (value < 0) 886 return value; 887 return sysfs_emit(buf, "%d\n", value); 888} 889 890static ssize_t dock_show(struct device *dev, struct device_attribute *attr, 891 char *buf) 892{ 893 int value = hp_wmi_get_dock_state(); 894 895 if (value < 0) 896 return value; 897 return sysfs_emit(buf, "%d\n", value); 898} 899 900static ssize_t tablet_show(struct device *dev, struct device_attribute *attr, 901 char *buf) 902{ 903 int value = hp_wmi_get_tablet_mode(); 904 905 if (value < 0) 906 return value; 907 return sysfs_emit(buf, "%d\n", value); 908} 909 910static ssize_t postcode_show(struct device *dev, struct device_attribute *attr, 911 char *buf) 912{ 913 /* Get the POST error code of previous boot failure. */ 914 int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY); 915 916 if (value < 0) 917 return value; 918 return sysfs_emit(buf, "0x%x\n", value); 919} 920 921static ssize_t als_store(struct device *dev, struct device_attribute *attr, 922 const char *buf, size_t count) 923{ 924 u32 tmp; 925 int ret; 926 927 ret = kstrtou32(buf, 10, &tmp); 928 if (ret) 929 return ret; 930 931 ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp, 932 sizeof(tmp), 0); 933 if (ret) 934 return ret < 0 ? ret : -EINVAL; 935 936 return count; 937} 938 939static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, 940 const char *buf, size_t count) 941{ 942 u32 tmp = 1; 943 bool clear; 944 int ret; 945 946 ret = kstrtobool(buf, &clear); 947 if (ret) 948 return ret; 949 950 if (clear == false) 951 return -EINVAL; 952 953 /* Clear the POST error code. It is kept until cleared. */ 954 ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, 955 sizeof(tmp), 0); 956 if (ret) 957 return ret < 0 ? ret : -EINVAL; 958 959 return count; 960} 961 962static int camera_shutter_input_setup(void) 963{ 964 int err; 965 966 camera_shutter_input_dev = input_allocate_device(); 967 if (!camera_shutter_input_dev) 968 return -ENOMEM; 969 970 camera_shutter_input_dev->name = "HP WMI camera shutter"; 971 camera_shutter_input_dev->phys = "wmi/input1"; 972 camera_shutter_input_dev->id.bustype = BUS_HOST; 973 974 __set_bit(EV_SW, camera_shutter_input_dev->evbit); 975 __set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit); 976 977 err = input_register_device(camera_shutter_input_dev); 978 if (err) 979 goto err_free_dev; 980 981 return 0; 982 983 err_free_dev: 984 input_free_device(camera_shutter_input_dev); 985 camera_shutter_input_dev = NULL; 986 return err; 987} 988 989static DEVICE_ATTR_RO(display); 990static DEVICE_ATTR_RO(hddtemp); 991static DEVICE_ATTR_RW(als); 992static DEVICE_ATTR_RO(dock); 993static DEVICE_ATTR_RO(tablet); 994static DEVICE_ATTR_RW(postcode); 995 996static struct attribute *hp_wmi_attrs[] = { 997 &dev_attr_display.attr, 998 &dev_attr_hddtemp.attr, 999 &dev_attr_als.attr, 1000 &dev_attr_dock.attr, 1001 &dev_attr_tablet.attr, 1002 &dev_attr_postcode.attr, 1003 NULL, 1004}; 1005ATTRIBUTE_GROUPS(hp_wmi); 1006 1007static void hp_wmi_notify(union acpi_object *obj, void *context) 1008{ 1009 u32 event_id, event_data; 1010 u32 *location; 1011 int key_code; 1012 1013 if (!obj) 1014 return; 1015 if (obj->type != ACPI_TYPE_BUFFER) { 1016 pr_info("Unknown response received %d\n", obj->type); 1017 return; 1018 } 1019 1020 /* 1021 * Depending on ACPI version the concatenation of id and event data 1022 * inside _WED function will result in a 8 or 16 byte buffer. 1023 */ 1024 location = (u32 *)obj->buffer.pointer; 1025 if (obj->buffer.length == 8) { 1026 event_id = *location; 1027 event_data = *(location + 1); 1028 } else if (obj->buffer.length == 16) { 1029 event_id = *location; 1030 event_data = *(location + 2); 1031 } else { 1032 pr_info("Unknown buffer length %d\n", obj->buffer.length); 1033 return; 1034 } 1035 1036 switch (event_id) { 1037 case HPWMI_DOCK_EVENT: 1038 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 1039 input_report_switch(hp_wmi_input_dev, SW_DOCK, 1040 hp_wmi_get_dock_state()); 1041 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 1042 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 1043 hp_wmi_get_tablet_mode()); 1044 input_sync(hp_wmi_input_dev); 1045 break; 1046 case HPWMI_PARK_HDD: 1047 break; 1048 case HPWMI_SMART_ADAPTER: 1049 break; 1050 case HPWMI_BEZEL_BUTTON: 1051 key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); 1052 if (key_code < 0) 1053 break; 1054 1055 if (!sparse_keymap_report_event(hp_wmi_input_dev, 1056 key_code, 1, true)) 1057 pr_info("Unknown key code - 0x%x\n", key_code); 1058 break; 1059 case HPWMI_FN_P_HOTKEY: 1060 platform_profile_cycle(); 1061 break; 1062 case HPWMI_OMEN_KEY: 1063 if (event_data) /* Only should be true for HP Omen */ 1064 key_code = event_data; 1065 else 1066 key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); 1067 1068 if (!sparse_keymap_report_event(hp_wmi_input_dev, 1069 key_code, 1, true)) 1070 pr_info("Unknown key code - 0x%x\n", key_code); 1071 break; 1072 case HPWMI_WIRELESS: 1073 if (rfkill2_count) { 1074 hp_wmi_rfkill2_refresh(); 1075 break; 1076 } 1077 1078 if (wifi_rfkill) 1079 rfkill_set_states(wifi_rfkill, 1080 hp_wmi_get_sw_state(HPWMI_WIFI), 1081 hp_wmi_get_hw_state(HPWMI_WIFI)); 1082 if (bluetooth_rfkill) 1083 rfkill_set_states(bluetooth_rfkill, 1084 hp_wmi_get_sw_state(HPWMI_BLUETOOTH), 1085 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 1086 if (wwan_rfkill) 1087 rfkill_set_states(wwan_rfkill, 1088 hp_wmi_get_sw_state(HPWMI_WWAN), 1089 hp_wmi_get_hw_state(HPWMI_WWAN)); 1090 break; 1091 case HPWMI_CPU_BATTERY_THROTTLE: 1092 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n"); 1093 break; 1094 case HPWMI_LOCK_SWITCH: 1095 break; 1096 case HPWMI_LID_SWITCH: 1097 break; 1098 case HPWMI_SCREEN_ROTATION: 1099 break; 1100 case HPWMI_COOLSENSE_SYSTEM_MOBILE: 1101 break; 1102 case HPWMI_COOLSENSE_SYSTEM_HOT: 1103 break; 1104 case HPWMI_PROXIMITY_SENSOR: 1105 break; 1106 case HPWMI_BACKLIT_KB_BRIGHTNESS: 1107 break; 1108 case HPWMI_PEAKSHIFT_PERIOD: 1109 break; 1110 case HPWMI_BATTERY_CHARGE_PERIOD: 1111 break; 1112 case HPWMI_SANITIZATION_MODE: 1113 break; 1114 case HPWMI_CAMERA_TOGGLE: 1115 if (!camera_shutter_input_dev) 1116 if (camera_shutter_input_setup()) { 1117 pr_err("Failed to setup camera shutter input device\n"); 1118 break; 1119 } 1120 if (event_data == 0xff) 1121 input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1); 1122 else if (event_data == 0xfe) 1123 input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0); 1124 else 1125 pr_warn("Unknown camera shutter state - 0x%x\n", event_data); 1126 input_sync(camera_shutter_input_dev); 1127 break; 1128 case HPWMI_SMART_EXPERIENCE_APP: 1129 break; 1130 default: 1131 pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data); 1132 break; 1133 } 1134} 1135 1136static int __init hp_wmi_input_setup(void) 1137{ 1138 acpi_status status; 1139 int err, val; 1140 1141 hp_wmi_input_dev = input_allocate_device(); 1142 if (!hp_wmi_input_dev) 1143 return -ENOMEM; 1144 1145 hp_wmi_input_dev->name = "HP WMI hotkeys"; 1146 hp_wmi_input_dev->phys = "wmi/input0"; 1147 hp_wmi_input_dev->id.bustype = BUS_HOST; 1148 1149 __set_bit(EV_SW, hp_wmi_input_dev->evbit); 1150 1151 /* Dock */ 1152 val = hp_wmi_get_dock_state(); 1153 if (!(val < 0)) { 1154 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 1155 input_report_switch(hp_wmi_input_dev, SW_DOCK, val); 1156 } 1157 1158 /* Tablet mode */ 1159 val = hp_wmi_get_tablet_mode(); 1160 if (!(val < 0)) { 1161 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 1162 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); 1163 } 1164 1165 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); 1166 if (err) 1167 goto err_free_dev; 1168 1169 /* Set initial hardware state */ 1170 input_sync(hp_wmi_input_dev); 1171 1172 if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) 1173 hp_wmi_enable_hotkeys(); 1174 1175 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); 1176 if (ACPI_FAILURE(status)) { 1177 err = -EIO; 1178 goto err_free_dev; 1179 } 1180 1181 err = input_register_device(hp_wmi_input_dev); 1182 if (err) 1183 goto err_uninstall_notifier; 1184 1185 return 0; 1186 1187 err_uninstall_notifier: 1188 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 1189 err_free_dev: 1190 input_free_device(hp_wmi_input_dev); 1191 return err; 1192} 1193 1194static void hp_wmi_input_destroy(void) 1195{ 1196 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 1197 input_unregister_device(hp_wmi_input_dev); 1198} 1199 1200static int __init hp_wmi_rfkill_setup(struct platform_device *device) 1201{ 1202 int err, wireless; 1203 1204 wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 1205 if (wireless < 0) 1206 return wireless; 1207 1208 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless, 1209 sizeof(wireless), 0); 1210 if (err) 1211 return err; 1212 1213 if (wireless & 0x1) { 1214 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 1215 RFKILL_TYPE_WLAN, 1216 &hp_wmi_rfkill_ops, 1217 (void *) HPWMI_WIFI); 1218 if (!wifi_rfkill) 1219 return -ENOMEM; 1220 rfkill_init_sw_state(wifi_rfkill, 1221 hp_wmi_get_sw_state(HPWMI_WIFI)); 1222 rfkill_set_hw_state(wifi_rfkill, 1223 hp_wmi_get_hw_state(HPWMI_WIFI)); 1224 err = rfkill_register(wifi_rfkill); 1225 if (err) 1226 goto register_wifi_error; 1227 } 1228 1229 if (wireless & 0x2) { 1230 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 1231 RFKILL_TYPE_BLUETOOTH, 1232 &hp_wmi_rfkill_ops, 1233 (void *) HPWMI_BLUETOOTH); 1234 if (!bluetooth_rfkill) { 1235 err = -ENOMEM; 1236 goto register_bluetooth_error; 1237 } 1238 rfkill_init_sw_state(bluetooth_rfkill, 1239 hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); 1240 rfkill_set_hw_state(bluetooth_rfkill, 1241 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 1242 err = rfkill_register(bluetooth_rfkill); 1243 if (err) 1244 goto register_bluetooth_error; 1245 } 1246 1247 if (wireless & 0x4) { 1248 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 1249 RFKILL_TYPE_WWAN, 1250 &hp_wmi_rfkill_ops, 1251 (void *) HPWMI_WWAN); 1252 if (!wwan_rfkill) { 1253 err = -ENOMEM; 1254 goto register_wwan_error; 1255 } 1256 rfkill_init_sw_state(wwan_rfkill, 1257 hp_wmi_get_sw_state(HPWMI_WWAN)); 1258 rfkill_set_hw_state(wwan_rfkill, 1259 hp_wmi_get_hw_state(HPWMI_WWAN)); 1260 err = rfkill_register(wwan_rfkill); 1261 if (err) 1262 goto register_wwan_error; 1263 } 1264 1265 return 0; 1266 1267register_wwan_error: 1268 rfkill_destroy(wwan_rfkill); 1269 wwan_rfkill = NULL; 1270 if (bluetooth_rfkill) 1271 rfkill_unregister(bluetooth_rfkill); 1272register_bluetooth_error: 1273 rfkill_destroy(bluetooth_rfkill); 1274 bluetooth_rfkill = NULL; 1275 if (wifi_rfkill) 1276 rfkill_unregister(wifi_rfkill); 1277register_wifi_error: 1278 rfkill_destroy(wifi_rfkill); 1279 wifi_rfkill = NULL; 1280 return err; 1281} 1282 1283static int __init hp_wmi_rfkill2_setup(struct platform_device *device) 1284{ 1285 struct bios_rfkill2_state state; 1286 int err, i; 1287 1288 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 1289 zero_if_sup(state), sizeof(state)); 1290 if (err) 1291 return err < 0 ? err : -EINVAL; 1292 1293 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { 1294 pr_warn("unable to parse 0x1b query output\n"); 1295 return -EINVAL; 1296 } 1297 1298 for (i = 0; i < state.count; i++) { 1299 struct rfkill *rfkill; 1300 enum rfkill_type type; 1301 char *name; 1302 1303 switch (state.device[i].radio_type) { 1304 case HPWMI_WIFI: 1305 type = RFKILL_TYPE_WLAN; 1306 name = "hp-wifi"; 1307 break; 1308 case HPWMI_BLUETOOTH: 1309 type = RFKILL_TYPE_BLUETOOTH; 1310 name = "hp-bluetooth"; 1311 break; 1312 case HPWMI_WWAN: 1313 type = RFKILL_TYPE_WWAN; 1314 name = "hp-wwan"; 1315 break; 1316 case HPWMI_GPS: 1317 type = RFKILL_TYPE_GPS; 1318 name = "hp-gps"; 1319 break; 1320 default: 1321 pr_warn("unknown device type 0x%x\n", 1322 state.device[i].radio_type); 1323 continue; 1324 } 1325 1326 if (!state.device[i].vendor_id) { 1327 pr_warn("zero device %d while %d reported\n", 1328 i, state.count); 1329 continue; 1330 } 1331 1332 rfkill = rfkill_alloc(name, &device->dev, type, 1333 &hp_wmi_rfkill2_ops, (void *)(long)i); 1334 if (!rfkill) { 1335 err = -ENOMEM; 1336 goto fail; 1337 } 1338 1339 rfkill2[rfkill2_count].id = state.device[i].rfkill_id; 1340 rfkill2[rfkill2_count].num = i; 1341 rfkill2[rfkill2_count].rfkill = rfkill; 1342 1343 rfkill_init_sw_state(rfkill, 1344 IS_SWBLOCKED(state.device[i].power)); 1345 rfkill_set_hw_state(rfkill, 1346 IS_HWBLOCKED(state.device[i].power)); 1347 1348 if (!(state.device[i].power & HPWMI_POWER_BIOS)) 1349 pr_info("device %s blocked by BIOS\n", name); 1350 1351 err = rfkill_register(rfkill); 1352 if (err) { 1353 rfkill_destroy(rfkill); 1354 goto fail; 1355 } 1356 1357 rfkill2_count++; 1358 } 1359 1360 return 0; 1361fail: 1362 for (; rfkill2_count > 0; rfkill2_count--) { 1363 rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill); 1364 rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill); 1365 } 1366 return err; 1367} 1368 1369static int platform_profile_omen_get_ec(enum platform_profile_option *profile) 1370{ 1371 int tp; 1372 1373 tp = omen_thermal_profile_get(); 1374 if (tp < 0) 1375 return tp; 1376 1377 switch (tp) { 1378 case HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE: 1379 case HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE: 1380 *profile = PLATFORM_PROFILE_PERFORMANCE; 1381 break; 1382 case HP_OMEN_V0_THERMAL_PROFILE_DEFAULT: 1383 case HP_OMEN_V1_THERMAL_PROFILE_DEFAULT: 1384 *profile = PLATFORM_PROFILE_BALANCED; 1385 break; 1386 case HP_OMEN_V0_THERMAL_PROFILE_COOL: 1387 case HP_OMEN_V1_THERMAL_PROFILE_COOL: 1388 *profile = PLATFORM_PROFILE_COOL; 1389 break; 1390 default: 1391 return -EINVAL; 1392 } 1393 1394 return 0; 1395} 1396 1397static int platform_profile_omen_get(struct device *dev, 1398 enum platform_profile_option *profile) 1399{ 1400 /* 1401 * We directly return the stored platform profile, as the embedded 1402 * controller will not accept switching to the performance option when 1403 * the conditions are not met (e.g. the laptop is not plugged in). 1404 * 1405 * If we directly return what the EC reports, the platform profile will 1406 * immediately "switch back" to normal mode, which is against the 1407 * expected behaviour from a userspace point of view, as described in 1408 * the Platform Profile Section page of the kernel documentation. 1409 * 1410 * See also omen_powersource_event. 1411 */ 1412 guard(mutex)(&active_platform_profile_lock); 1413 *profile = active_platform_profile; 1414 1415 return 0; 1416} 1417 1418static bool has_omen_thermal_profile_ec_timer(void) 1419{ 1420 const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); 1421 1422 if (!board_name) 1423 return false; 1424 1425 return match_string(omen_timed_thermal_profile_boards, 1426 ARRAY_SIZE(omen_timed_thermal_profile_boards), 1427 board_name) >= 0; 1428} 1429 1430inline int omen_thermal_profile_ec_flags_set(enum hp_thermal_profile_omen_flags flags) 1431{ 1432 return ec_write(HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET, flags); 1433} 1434 1435inline int omen_thermal_profile_ec_timer_set(u8 value) 1436{ 1437 return ec_write(HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET, value); 1438} 1439 1440static int platform_profile_omen_set_ec(enum platform_profile_option profile) 1441{ 1442 int err, tp, tp_version; 1443 enum hp_thermal_profile_omen_flags flags = 0; 1444 1445 tp_version = omen_get_thermal_policy_version(); 1446 1447 if (tp_version < 0 || tp_version > 1) 1448 return -EOPNOTSUPP; 1449 1450 switch (profile) { 1451 case PLATFORM_PROFILE_PERFORMANCE: 1452 if (tp_version == 0) 1453 tp = HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE; 1454 else 1455 tp = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE; 1456 break; 1457 case PLATFORM_PROFILE_BALANCED: 1458 if (tp_version == 0) 1459 tp = HP_OMEN_V0_THERMAL_PROFILE_DEFAULT; 1460 else 1461 tp = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT; 1462 break; 1463 case PLATFORM_PROFILE_COOL: 1464 if (tp_version == 0) 1465 tp = HP_OMEN_V0_THERMAL_PROFILE_COOL; 1466 else 1467 tp = HP_OMEN_V1_THERMAL_PROFILE_COOL; 1468 break; 1469 default: 1470 return -EOPNOTSUPP; 1471 } 1472 1473 err = omen_thermal_profile_set(tp); 1474 if (err < 0) 1475 return err; 1476 1477 if (has_omen_thermal_profile_ec_timer()) { 1478 err = omen_thermal_profile_ec_timer_set(0); 1479 if (err < 0) 1480 return err; 1481 1482 if (profile == PLATFORM_PROFILE_PERFORMANCE) 1483 flags = HP_OMEN_EC_FLAGS_NOTIMER | 1484 HP_OMEN_EC_FLAGS_TURBO; 1485 1486 err = omen_thermal_profile_ec_flags_set(flags); 1487 if (err < 0) 1488 return err; 1489 } 1490 1491 return 0; 1492} 1493 1494static int platform_profile_omen_set(struct device *dev, 1495 enum platform_profile_option profile) 1496{ 1497 int err; 1498 1499 guard(mutex)(&active_platform_profile_lock); 1500 1501 err = platform_profile_omen_set_ec(profile); 1502 if (err < 0) 1503 return err; 1504 1505 active_platform_profile = profile; 1506 1507 return 0; 1508} 1509 1510static int thermal_profile_get(void) 1511{ 1512 return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY); 1513} 1514 1515static int thermal_profile_set(int thermal_profile) 1516{ 1517 return hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY, HPWMI_WRITE, &thermal_profile, 1518 sizeof(thermal_profile), 0); 1519} 1520 1521static int hp_wmi_platform_profile_get(struct device *dev, 1522 enum platform_profile_option *profile) 1523{ 1524 int tp; 1525 1526 tp = thermal_profile_get(); 1527 if (tp < 0) 1528 return tp; 1529 1530 switch (tp) { 1531 case HP_THERMAL_PROFILE_PERFORMANCE: 1532 *profile = PLATFORM_PROFILE_PERFORMANCE; 1533 break; 1534 case HP_THERMAL_PROFILE_DEFAULT: 1535 *profile = PLATFORM_PROFILE_BALANCED; 1536 break; 1537 case HP_THERMAL_PROFILE_COOL: 1538 *profile = PLATFORM_PROFILE_COOL; 1539 break; 1540 case HP_THERMAL_PROFILE_QUIET: 1541 *profile = PLATFORM_PROFILE_QUIET; 1542 break; 1543 default: 1544 return -EINVAL; 1545 } 1546 1547 return 0; 1548} 1549 1550static int hp_wmi_platform_profile_set(struct device *dev, 1551 enum platform_profile_option profile) 1552{ 1553 int err, tp; 1554 1555 switch (profile) { 1556 case PLATFORM_PROFILE_PERFORMANCE: 1557 tp = HP_THERMAL_PROFILE_PERFORMANCE; 1558 break; 1559 case PLATFORM_PROFILE_BALANCED: 1560 tp = HP_THERMAL_PROFILE_DEFAULT; 1561 break; 1562 case PLATFORM_PROFILE_COOL: 1563 tp = HP_THERMAL_PROFILE_COOL; 1564 break; 1565 case PLATFORM_PROFILE_QUIET: 1566 tp = HP_THERMAL_PROFILE_QUIET; 1567 break; 1568 default: 1569 return -EOPNOTSUPP; 1570 } 1571 1572 err = thermal_profile_set(tp); 1573 if (err) 1574 return err; 1575 1576 return 0; 1577} 1578 1579static bool is_victus_thermal_profile(void) 1580{ 1581 const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); 1582 1583 if (!board_name) 1584 return false; 1585 1586 return match_string(victus_thermal_profile_boards, 1587 ARRAY_SIZE(victus_thermal_profile_boards), 1588 board_name) >= 0; 1589} 1590 1591static int platform_profile_victus_get_ec(enum platform_profile_option *profile) 1592{ 1593 int tp; 1594 1595 tp = omen_thermal_profile_get(); 1596 if (tp < 0) 1597 return tp; 1598 1599 switch (tp) { 1600 case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE: 1601 *profile = PLATFORM_PROFILE_PERFORMANCE; 1602 break; 1603 case HP_VICTUS_THERMAL_PROFILE_DEFAULT: 1604 *profile = PLATFORM_PROFILE_BALANCED; 1605 break; 1606 case HP_VICTUS_THERMAL_PROFILE_QUIET: 1607 *profile = PLATFORM_PROFILE_QUIET; 1608 break; 1609 default: 1610 return -EOPNOTSUPP; 1611 } 1612 1613 return 0; 1614} 1615 1616static int platform_profile_victus_get(struct device *dev, 1617 enum platform_profile_option *profile) 1618{ 1619 /* Same behaviour as platform_profile_omen_get */ 1620 return platform_profile_omen_get(dev, profile); 1621} 1622 1623static int platform_profile_victus_set_ec(enum platform_profile_option profile) 1624{ 1625 int err, tp; 1626 1627 switch (profile) { 1628 case PLATFORM_PROFILE_PERFORMANCE: 1629 tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE; 1630 break; 1631 case PLATFORM_PROFILE_BALANCED: 1632 tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT; 1633 break; 1634 case PLATFORM_PROFILE_QUIET: 1635 tp = HP_VICTUS_THERMAL_PROFILE_QUIET; 1636 break; 1637 default: 1638 return -EOPNOTSUPP; 1639 } 1640 1641 err = omen_thermal_profile_set(tp); 1642 if (err < 0) 1643 return err; 1644 1645 return 0; 1646} 1647 1648static bool is_victus_s_thermal_profile(void) 1649{ 1650 /* Initialised in driver init, hence safe to use here */ 1651 return is_victus_s_board; 1652} 1653 1654static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, 1655 bool *ppab_enable, 1656 u8 *dstate, 1657 u8 *gpu_slowdown_temp) 1658{ 1659 struct victus_gpu_power_modes gpu_power_modes; 1660 int ret; 1661 1662 ret = hp_wmi_perform_query(HPWMI_GET_GPU_THERMAL_MODES_QUERY, HPWMI_GM, 1663 &gpu_power_modes, sizeof(gpu_power_modes), 1664 sizeof(gpu_power_modes)); 1665 if (ret == 0) { 1666 *ctgp_enable = gpu_power_modes.ctgp_enable ? true : false; 1667 *ppab_enable = gpu_power_modes.ppab_enable ? true : false; 1668 *dstate = gpu_power_modes.dstate; 1669 *gpu_slowdown_temp = gpu_power_modes.gpu_slowdown_temp; 1670 } 1671 1672 return ret; 1673} 1674 1675static int victus_s_gpu_thermal_profile_set(bool ctgp_enable, 1676 bool ppab_enable, 1677 u8 dstate) 1678{ 1679 struct victus_gpu_power_modes gpu_power_modes; 1680 int ret; 1681 1682 bool current_ctgp_state, current_ppab_state; 1683 u8 current_dstate, current_gpu_slowdown_temp; 1684 1685 /* Retrieving GPU slowdown temperature, in order to keep it unchanged */ 1686 ret = victus_s_gpu_thermal_profile_get(¤t_ctgp_state, 1687 ¤t_ppab_state, 1688 ¤t_dstate, 1689 ¤t_gpu_slowdown_temp); 1690 if (ret < 0) { 1691 pr_warn("GPU modes not updated, unable to get slowdown temp\n"); 1692 return ret; 1693 } 1694 1695 gpu_power_modes.ctgp_enable = ctgp_enable ? 0x01 : 0x00; 1696 gpu_power_modes.ppab_enable = ppab_enable ? 0x01 : 0x00; 1697 gpu_power_modes.dstate = dstate; 1698 gpu_power_modes.gpu_slowdown_temp = current_gpu_slowdown_temp; 1699 1700 1701 ret = hp_wmi_perform_query(HPWMI_SET_GPU_THERMAL_MODES_QUERY, HPWMI_GM, 1702 &gpu_power_modes, sizeof(gpu_power_modes), 0); 1703 1704 return ret; 1705} 1706 1707/* Note: HP_POWER_LIMIT_DEFAULT can be used to restore default PL1 and PL2 */ 1708static int victus_s_set_cpu_pl1_pl2(u8 pl1, u8 pl2) 1709{ 1710 struct victus_power_limits power_limits; 1711 int ret; 1712 1713 /* We need to know both PL1 and PL2 values in order to check them */ 1714 if (pl1 == HP_POWER_LIMIT_NO_CHANGE || pl2 == HP_POWER_LIMIT_NO_CHANGE) 1715 return -EINVAL; 1716 1717 /* PL2 is not supposed to be lower than PL1 */ 1718 if (pl2 < pl1) 1719 return -EINVAL; 1720 1721 power_limits.pl1 = pl1; 1722 power_limits.pl2 = pl2; 1723 power_limits.pl4 = HP_POWER_LIMIT_NO_CHANGE; 1724 power_limits.cpu_gpu_concurrent_limit = HP_POWER_LIMIT_NO_CHANGE; 1725 1726 ret = hp_wmi_perform_query(HPWMI_SET_POWER_LIMITS_QUERY, HPWMI_GM, 1727 &power_limits, sizeof(power_limits), 0); 1728 1729 return ret; 1730} 1731 1732static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) 1733{ 1734 struct thermal_profile_params *params; 1735 bool gpu_ctgp_enable, gpu_ppab_enable; 1736 u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ 1737 int err, tp; 1738 1739 params = active_thermal_profile_params; 1740 if (!params) 1741 return -ENODEV; 1742 1743 switch (profile) { 1744 case PLATFORM_PROFILE_PERFORMANCE: 1745 tp = params->performance; 1746 gpu_ctgp_enable = true; 1747 gpu_ppab_enable = true; 1748 gpu_dstate = 1; 1749 break; 1750 case PLATFORM_PROFILE_BALANCED: 1751 tp = params->balanced; 1752 gpu_ctgp_enable = false; 1753 gpu_ppab_enable = true; 1754 gpu_dstate = 1; 1755 break; 1756 case PLATFORM_PROFILE_LOW_POWER: 1757 tp = params->low_power; 1758 gpu_ctgp_enable = false; 1759 gpu_ppab_enable = false; 1760 gpu_dstate = 1; 1761 break; 1762 default: 1763 return -EOPNOTSUPP; 1764 } 1765 1766 hp_wmi_get_fan_count_userdefine_trigger(); 1767 1768 err = omen_thermal_profile_set(tp); 1769 if (err < 0) { 1770 pr_err("Failed to set platform profile %d: %d\n", profile, err); 1771 return err; 1772 } 1773 1774 err = victus_s_gpu_thermal_profile_set(gpu_ctgp_enable, 1775 gpu_ppab_enable, 1776 gpu_dstate); 1777 if (err < 0) { 1778 pr_err("Failed to set GPU profile %d: %d\n", profile, err); 1779 return err; 1780 } 1781 1782 return 0; 1783} 1784 1785static int platform_profile_victus_s_set(struct device *dev, 1786 enum platform_profile_option profile) 1787{ 1788 int err; 1789 1790 guard(mutex)(&active_platform_profile_lock); 1791 1792 err = platform_profile_victus_s_set_ec(profile); 1793 if (err < 0) 1794 return err; 1795 1796 active_platform_profile = profile; 1797 1798 return 0; 1799} 1800 1801static int platform_profile_victus_set(struct device *dev, 1802 enum platform_profile_option profile) 1803{ 1804 int err; 1805 1806 guard(mutex)(&active_platform_profile_lock); 1807 1808 err = platform_profile_victus_set_ec(profile); 1809 if (err < 0) 1810 return err; 1811 1812 active_platform_profile = profile; 1813 1814 return 0; 1815} 1816 1817static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices) 1818{ 1819 if (is_omen_thermal_profile()) { 1820 set_bit(PLATFORM_PROFILE_COOL, choices); 1821 } else if (is_victus_thermal_profile()) { 1822 set_bit(PLATFORM_PROFILE_QUIET, choices); 1823 } else if (is_victus_s_thermal_profile()) { 1824 /* Adding an equivalent to HP Omen software ECO mode: */ 1825 set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1826 } else { 1827 set_bit(PLATFORM_PROFILE_QUIET, choices); 1828 set_bit(PLATFORM_PROFILE_COOL, choices); 1829 } 1830 1831 set_bit(PLATFORM_PROFILE_BALANCED, choices); 1832 set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1833 1834 return 0; 1835} 1836 1837static int omen_powersource_event(struct notifier_block *nb, 1838 unsigned long value, 1839 void *data) 1840{ 1841 struct acpi_bus_event *event_entry = data; 1842 enum platform_profile_option actual_profile; 1843 int err; 1844 1845 if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0) 1846 return NOTIFY_DONE; 1847 1848 pr_debug("Received power source device event\n"); 1849 1850 guard(mutex)(&active_platform_profile_lock); 1851 1852 /* 1853 * This handler can only be called on Omen and Victus models, so 1854 * there's no need to call is_victus_thermal_profile() here. 1855 */ 1856 if (is_omen_thermal_profile()) 1857 err = platform_profile_omen_get_ec(&actual_profile); 1858 else 1859 err = platform_profile_victus_get_ec(&actual_profile); 1860 1861 if (err < 0) { 1862 /* 1863 * Although we failed to get the current platform profile, we 1864 * still want the other event consumers to process it. 1865 */ 1866 pr_warn("Failed to read current platform profile (%d)\n", err); 1867 return NOTIFY_DONE; 1868 } 1869 1870 /* 1871 * If we're back on AC and that the user-chosen power profile is 1872 * different from what the EC reports, we restore the user-chosen 1873 * one. 1874 */ 1875 if (power_supply_is_system_supplied() <= 0 || 1876 active_platform_profile == actual_profile) { 1877 pr_debug("Platform profile update skipped, conditions unmet\n"); 1878 return NOTIFY_DONE; 1879 } 1880 1881 if (is_omen_thermal_profile()) 1882 err = platform_profile_omen_set_ec(active_platform_profile); 1883 else 1884 err = platform_profile_victus_set_ec(active_platform_profile); 1885 1886 if (err < 0) { 1887 pr_warn("Failed to restore platform profile (%d)\n", err); 1888 return NOTIFY_DONE; 1889 } 1890 1891 return NOTIFY_OK; 1892} 1893 1894static int victus_s_powersource_event(struct notifier_block *nb, 1895 unsigned long value, 1896 void *data) 1897{ 1898 struct acpi_bus_event *event_entry = data; 1899 int err; 1900 1901 if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0) 1902 return NOTIFY_DONE; 1903 1904 pr_debug("Received power source device event\n"); 1905 1906 /* 1907 * Switching to battery power source while Performance mode is active 1908 * needs manual triggering of CPU power limits. Same goes when switching 1909 * to AC power source while Performance mode is active. Other modes 1910 * however are automatically behaving without any manual action. 1911 * Seen on HP 16-s1034nf (board 8C9C) with F.11 and F.13 BIOS versions. 1912 */ 1913 1914 if (active_platform_profile == PLATFORM_PROFILE_PERFORMANCE) { 1915 pr_debug("Triggering CPU PL1/PL2 actualization\n"); 1916 err = victus_s_set_cpu_pl1_pl2(HP_POWER_LIMIT_DEFAULT, 1917 HP_POWER_LIMIT_DEFAULT); 1918 if (err) 1919 pr_warn("Failed to actualize power limits: %d\n", err); 1920 1921 return NOTIFY_DONE; 1922 } 1923 1924 return NOTIFY_OK; 1925} 1926 1927static int omen_register_powersource_event_handler(void) 1928{ 1929 int err; 1930 1931 platform_power_source_nb.notifier_call = omen_powersource_event; 1932 err = register_acpi_notifier(&platform_power_source_nb); 1933 1934 if (err < 0) { 1935 pr_warn("Failed to install ACPI power source notify handler\n"); 1936 return err; 1937 } 1938 1939 return 0; 1940} 1941 1942static int victus_s_register_powersource_event_handler(void) 1943{ 1944 int err; 1945 1946 platform_power_source_nb.notifier_call = victus_s_powersource_event; 1947 err = register_acpi_notifier(&platform_power_source_nb); 1948 if (err < 0) { 1949 pr_warn("Failed to install ACPI power source notify handler\n"); 1950 return err; 1951 } 1952 1953 return 0; 1954} 1955 1956static inline void omen_unregister_powersource_event_handler(void) 1957{ 1958 unregister_acpi_notifier(&platform_power_source_nb); 1959} 1960 1961static inline void victus_s_unregister_powersource_event_handler(void) 1962{ 1963 unregister_acpi_notifier(&platform_power_source_nb); 1964} 1965 1966static const struct platform_profile_ops platform_profile_omen_ops = { 1967 .probe = hp_wmi_platform_profile_probe, 1968 .profile_get = platform_profile_omen_get, 1969 .profile_set = platform_profile_omen_set, 1970}; 1971 1972static const struct platform_profile_ops platform_profile_victus_ops = { 1973 .probe = hp_wmi_platform_profile_probe, 1974 .profile_get = platform_profile_victus_get, 1975 .profile_set = platform_profile_victus_set, 1976}; 1977 1978static const struct platform_profile_ops platform_profile_victus_s_ops = { 1979 .probe = hp_wmi_platform_profile_probe, 1980 .profile_get = platform_profile_omen_get, 1981 .profile_set = platform_profile_victus_s_set, 1982}; 1983 1984static const struct platform_profile_ops hp_wmi_platform_profile_ops = { 1985 .probe = hp_wmi_platform_profile_probe, 1986 .profile_get = hp_wmi_platform_profile_get, 1987 .profile_set = hp_wmi_platform_profile_set, 1988}; 1989 1990static int thermal_profile_setup(struct platform_device *device) 1991{ 1992 const struct platform_profile_ops *ops; 1993 int err, tp; 1994 1995 if (is_omen_thermal_profile()) { 1996 err = platform_profile_omen_get_ec(&active_platform_profile); 1997 if (err < 0) 1998 return err; 1999 2000 /* 2001 * call thermal profile write command to ensure that the 2002 * firmware correctly sets the OEM variables 2003 */ 2004 err = platform_profile_omen_set_ec(active_platform_profile); 2005 if (err < 0) 2006 return err; 2007 2008 ops = &platform_profile_omen_ops; 2009 } else if (is_victus_thermal_profile()) { 2010 err = platform_profile_victus_get_ec(&active_platform_profile); 2011 if (err < 0) 2012 return err; 2013 2014 /* 2015 * call thermal profile write command to ensure that the 2016 * firmware correctly sets the OEM variables 2017 */ 2018 err = platform_profile_victus_set_ec(active_platform_profile); 2019 if (err < 0) 2020 return err; 2021 2022 ops = &platform_profile_victus_ops; 2023 } else if (is_victus_s_thermal_profile()) { 2024 /* 2025 * Being unable to retrieve laptop's current thermal profile, 2026 * during this setup, we set it to Balanced by default. 2027 */ 2028 active_platform_profile = PLATFORM_PROFILE_BALANCED; 2029 2030 err = platform_profile_victus_s_set_ec(active_platform_profile); 2031 if (err < 0) 2032 return err; 2033 2034 ops = &platform_profile_victus_s_ops; 2035 } else { 2036 tp = thermal_profile_get(); 2037 2038 if (tp < 0) 2039 return tp; 2040 2041 /* 2042 * call thermal profile write command to ensure that the 2043 * firmware correctly sets the OEM variables for the DPTF 2044 */ 2045 err = thermal_profile_set(tp); 2046 if (err) 2047 return err; 2048 2049 ops = &hp_wmi_platform_profile_ops; 2050 } 2051 2052 platform_profile_device = devm_platform_profile_register(&device->dev, "hp-wmi", 2053 NULL, ops); 2054 if (IS_ERR(platform_profile_device)) 2055 return PTR_ERR(platform_profile_device); 2056 2057 pr_info("Registered as platform profile handler\n"); 2058 platform_profile_support = true; 2059 2060 return 0; 2061} 2062 2063static int hp_wmi_hwmon_init(void); 2064 2065static int __init hp_wmi_bios_setup(struct platform_device *device) 2066{ 2067 int err; 2068 /* clear detected rfkill devices */ 2069 wifi_rfkill = NULL; 2070 bluetooth_rfkill = NULL; 2071 wwan_rfkill = NULL; 2072 rfkill2_count = 0; 2073 2074 /* 2075 * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that 2076 * BIOS no longer controls the power for the wireless 2077 * devices. All features supported by this command will no 2078 * longer be supported. 2079 */ 2080 if (!hp_wmi_bios_2009_later()) { 2081 if (hp_wmi_rfkill_setup(device)) 2082 hp_wmi_rfkill2_setup(device); 2083 } 2084 2085 err = hp_wmi_hwmon_init(); 2086 2087 if (err < 0) 2088 return err; 2089 2090 thermal_profile_setup(device); 2091 2092 return 0; 2093} 2094 2095static void __exit hp_wmi_bios_remove(struct platform_device *device) 2096{ 2097 int i; 2098 2099 for (i = 0; i < rfkill2_count; i++) { 2100 rfkill_unregister(rfkill2[i].rfkill); 2101 rfkill_destroy(rfkill2[i].rfkill); 2102 } 2103 2104 if (wifi_rfkill) { 2105 rfkill_unregister(wifi_rfkill); 2106 rfkill_destroy(wifi_rfkill); 2107 } 2108 if (bluetooth_rfkill) { 2109 rfkill_unregister(bluetooth_rfkill); 2110 rfkill_destroy(bluetooth_rfkill); 2111 } 2112 if (wwan_rfkill) { 2113 rfkill_unregister(wwan_rfkill); 2114 rfkill_destroy(wwan_rfkill); 2115 } 2116} 2117 2118static int hp_wmi_resume_handler(struct device *device) 2119{ 2120 /* 2121 * Hardware state may have changed while suspended, so trigger 2122 * input events for the current state. As this is a switch, 2123 * the input layer will only actually pass it on if the state 2124 * changed. 2125 */ 2126 if (hp_wmi_input_dev) { 2127 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 2128 input_report_switch(hp_wmi_input_dev, SW_DOCK, 2129 hp_wmi_get_dock_state()); 2130 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 2131 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 2132 hp_wmi_get_tablet_mode()); 2133 input_sync(hp_wmi_input_dev); 2134 } 2135 2136 if (rfkill2_count) 2137 hp_wmi_rfkill2_refresh(); 2138 2139 if (wifi_rfkill) 2140 rfkill_set_states(wifi_rfkill, 2141 hp_wmi_get_sw_state(HPWMI_WIFI), 2142 hp_wmi_get_hw_state(HPWMI_WIFI)); 2143 if (bluetooth_rfkill) 2144 rfkill_set_states(bluetooth_rfkill, 2145 hp_wmi_get_sw_state(HPWMI_BLUETOOTH), 2146 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 2147 if (wwan_rfkill) 2148 rfkill_set_states(wwan_rfkill, 2149 hp_wmi_get_sw_state(HPWMI_WWAN), 2150 hp_wmi_get_hw_state(HPWMI_WWAN)); 2151 2152 return 0; 2153} 2154 2155static const struct dev_pm_ops hp_wmi_pm_ops = { 2156 .resume = hp_wmi_resume_handler, 2157 .restore = hp_wmi_resume_handler, 2158}; 2159 2160/* 2161 * hp_wmi_bios_remove() lives in .exit.text. For drivers registered via 2162 * module_platform_driver_probe() this is ok because they cannot get unbound at 2163 * runtime. So mark the driver struct with __refdata to prevent modpost 2164 * triggering a section mismatch warning. 2165 */ 2166static struct platform_driver hp_wmi_driver __refdata = { 2167 .driver = { 2168 .name = "hp-wmi", 2169 .pm = &hp_wmi_pm_ops, 2170 .dev_groups = hp_wmi_groups, 2171 }, 2172 .remove = __exit_p(hp_wmi_bios_remove), 2173}; 2174 2175static umode_t hp_wmi_hwmon_is_visible(const void *data, 2176 enum hwmon_sensor_types type, 2177 u32 attr, int channel) 2178{ 2179 switch (type) { 2180 case hwmon_pwm: 2181 return 0644; 2182 case hwmon_fan: 2183 if (is_victus_s_thermal_profile()) { 2184 if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) 2185 return 0444; 2186 } else { 2187 if (hp_wmi_get_fan_speed(channel) >= 0) 2188 return 0444; 2189 } 2190 break; 2191 default: 2192 return 0; 2193 } 2194 2195 return 0; 2196} 2197 2198static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 2199 u32 attr, int channel, long *val) 2200{ 2201 int ret; 2202 2203 switch (type) { 2204 case hwmon_fan: 2205 if (is_victus_s_thermal_profile()) 2206 ret = hp_wmi_get_fan_speed_victus_s(channel); 2207 else 2208 ret = hp_wmi_get_fan_speed(channel); 2209 if (ret < 0) 2210 return ret; 2211 *val = ret; 2212 return 0; 2213 case hwmon_pwm: 2214 switch (hp_wmi_fan_speed_max_get()) { 2215 case 0: 2216 /* 0 is automatic fan, which is 2 for hwmon */ 2217 *val = 2; 2218 return 0; 2219 case 1: 2220 /* 1 is max fan, which is 0 2221 * (no fan speed control) for hwmon 2222 */ 2223 *val = 0; 2224 return 0; 2225 default: 2226 /* shouldn't happen */ 2227 return -ENODATA; 2228 } 2229 default: 2230 return -EINVAL; 2231 } 2232} 2233 2234static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, 2235 u32 attr, int channel, long val) 2236{ 2237 switch (type) { 2238 case hwmon_pwm: 2239 switch (val) { 2240 case 0: 2241 if (is_victus_s_thermal_profile()) 2242 hp_wmi_get_fan_count_userdefine_trigger(); 2243 /* 0 is no fan speed control (max), which is 1 for us */ 2244 return hp_wmi_fan_speed_max_set(1); 2245 case 2: 2246 /* 2 is automatic speed control, which is 0 for us */ 2247 if (is_victus_s_thermal_profile()) { 2248 hp_wmi_get_fan_count_userdefine_trigger(); 2249 return hp_wmi_fan_speed_max_reset(); 2250 } else 2251 return hp_wmi_fan_speed_max_set(0); 2252 default: 2253 /* we don't support manual fan speed control */ 2254 return -EINVAL; 2255 } 2256 default: 2257 return -EOPNOTSUPP; 2258 } 2259} 2260 2261static const struct hwmon_channel_info * const info[] = { 2262 HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), 2263 HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE), 2264 NULL 2265}; 2266 2267static const struct hwmon_ops ops = { 2268 .is_visible = hp_wmi_hwmon_is_visible, 2269 .read = hp_wmi_hwmon_read, 2270 .write = hp_wmi_hwmon_write, 2271}; 2272 2273static const struct hwmon_chip_info chip_info = { 2274 .ops = &ops, 2275 .info = info, 2276}; 2277 2278static int hp_wmi_hwmon_init(void) 2279{ 2280 struct device *dev = &hp_wmi_platform_dev->dev; 2281 struct device *hwmon; 2282 2283 hwmon = devm_hwmon_device_register_with_info(dev, "hp", &hp_wmi_driver, 2284 &chip_info, NULL); 2285 2286 if (IS_ERR(hwmon)) { 2287 dev_err(dev, "Could not register hp hwmon device\n"); 2288 return PTR_ERR(hwmon); 2289 } 2290 2291 return 0; 2292} 2293 2294static void __init setup_active_thermal_profile_params(void) 2295{ 2296 const struct dmi_system_id *id; 2297 2298 /* 2299 * Currently only victus_s devices use the 2300 * active_thermal_profile_params 2301 */ 2302 id = dmi_first_match(victus_s_thermal_profile_boards); 2303 if (id) { 2304 /* 2305 * Marking this boolean is required to ensure that 2306 * is_victus_s_thermal_profile() behaves like a valid 2307 * wrapper. 2308 */ 2309 is_victus_s_board = true; 2310 active_thermal_profile_params = id->driver_data; 2311 } 2312} 2313 2314static int __init hp_wmi_init(void) 2315{ 2316 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); 2317 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 2318 int err, tmp = 0; 2319 2320 if (!bios_capable && !event_capable) 2321 return -ENODEV; 2322 2323 if (hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &tmp, 2324 sizeof(tmp), sizeof(tmp)) == HPWMI_RET_INVALID_PARAMETERS) 2325 zero_insize_support = true; 2326 2327 if (event_capable) { 2328 err = hp_wmi_input_setup(); 2329 if (err) 2330 return err; 2331 } 2332 2333 if (bios_capable) { 2334 hp_wmi_platform_dev = 2335 platform_device_register_simple("hp-wmi", PLATFORM_DEVID_NONE, NULL, 0); 2336 if (IS_ERR(hp_wmi_platform_dev)) { 2337 err = PTR_ERR(hp_wmi_platform_dev); 2338 goto err_destroy_input; 2339 } 2340 2341 /* 2342 * Setup active board's thermal profile parameters before 2343 * starting platform driver probe. 2344 */ 2345 setup_active_thermal_profile_params(); 2346 err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); 2347 if (err) 2348 goto err_unregister_device; 2349 } 2350 2351 if (is_omen_thermal_profile() || is_victus_thermal_profile()) { 2352 err = omen_register_powersource_event_handler(); 2353 if (err) 2354 goto err_unregister_device; 2355 } else if (is_victus_s_thermal_profile()) { 2356 err = victus_s_register_powersource_event_handler(); 2357 if (err) 2358 goto err_unregister_device; 2359 } 2360 2361 return 0; 2362 2363err_unregister_device: 2364 platform_device_unregister(hp_wmi_platform_dev); 2365err_destroy_input: 2366 if (event_capable) 2367 hp_wmi_input_destroy(); 2368 2369 return err; 2370} 2371module_init(hp_wmi_init); 2372 2373static void __exit hp_wmi_exit(void) 2374{ 2375 if (is_omen_thermal_profile() || is_victus_thermal_profile()) 2376 omen_unregister_powersource_event_handler(); 2377 2378 if (is_victus_s_thermal_profile()) 2379 victus_s_unregister_powersource_event_handler(); 2380 2381 if (wmi_has_guid(HPWMI_EVENT_GUID)) 2382 hp_wmi_input_destroy(); 2383 2384 if (camera_shutter_input_dev) 2385 input_unregister_device(camera_shutter_input_dev); 2386 2387 if (hp_wmi_platform_dev) { 2388 platform_device_unregister(hp_wmi_platform_dev); 2389 platform_driver_unregister(&hp_wmi_driver); 2390 } 2391} 2392module_exit(hp_wmi_exit);
~/
Read-only file preview.