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