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