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