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