xref: /linux/drivers/platform/x86/hp/hp-wmi.c (revision c2d4b76458c9ebf81eae2916970320f1f61ad002)
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 
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 
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 */
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  */
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  */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
1628 static int thermal_profile_get(void)
1629 {
1630 	return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY);
1631 }
1632 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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(&current_ctgp_state,
1805 					       &current_ppab_state,
1806 					       &current_dstate,
1807 					       &current_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 */
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 
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(&current_ctgp_state,
1887 						       &current_ppab_state,
1888 						       &current_dstate,
1889 						       &current_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 
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 
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 
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 
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 
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 
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 
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 
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 
2141 static inline void omen_unregister_powersource_event_handler(void)
2142 {
2143 	unregister_acpi_notifier(&platform_power_source_nb);
2144 }
2145 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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