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