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