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