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