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(¤t_ctgp_state,
1778 ¤t_ppab_state,
1779 ¤t_dstate,
1780 ¤t_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(¤t_ctgp_state,
1859 ¤t_ppab_state,
1860 ¤t_dstate,
1861 ¤t_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