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