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