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