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