1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Alienware WMAX WMI device driver
4 *
5 * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
6 * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
7 */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/array_size.h>
12 #include <linux/bitfield.h>
13 #include <linux/bitmap.h>
14 #include <linux/bits.h>
15 #include <linux/debugfs.h>
16 #include <linux/dmi.h>
17 #include <linux/hwmon.h>
18 #include <linux/hwmon-sysfs.h>
19 #include <linux/kstrtox.h>
20 #include <linux/minmax.h>
21 #include <linux/moduleparam.h>
22 #include <linux/platform_profile.h>
23 #include <linux/pm.h>
24 #include <linux/seq_file.h>
25 #include <linux/units.h>
26 #include <linux/wmi.h>
27 #include "alienware-wmi.h"
28
29 #define WMAX_METHOD_HDMI_SOURCE 0x1
30 #define WMAX_METHOD_HDMI_STATUS 0x2
31 #define WMAX_METHOD_HDMI_CABLE 0x5
32 #define WMAX_METHOD_AMPLIFIER_CABLE 0x6
33 #define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
34 #define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
35 #define WMAX_METHOD_BRIGHTNESS 0x3
36 #define WMAX_METHOD_ZONE_CONTROL 0x4
37
38 #define AWCC_METHOD_GET_FAN_SENSORS 0x13
39 #define AWCC_METHOD_THERMAL_INFORMATION 0x14
40 #define AWCC_METHOD_THERMAL_CONTROL 0x15
41 #define AWCC_METHOD_FWUP_GPIO_CONTROL 0x20
42 #define AWCC_METHOD_READ_TOTAL_GPIOS 0x21
43 #define AWCC_METHOD_READ_GPIO_STATUS 0x22
44 #define AWCC_METHOD_GAME_SHIFT_STATUS 0x25
45
46 #define AWCC_FAILURE_CODE 0xFFFFFFFF
47 #define AWCC_FAILURE_CODE_2 0xFFFFFFFE
48
49 #define AWCC_SENSOR_ID_FLAG BIT(8)
50 #define AWCC_THERMAL_MODE_MASK GENMASK(3, 0)
51 #define AWCC_THERMAL_TABLE_MASK GENMASK(7, 4)
52 #define AWCC_RESOURCE_ID_MASK GENMASK(7, 0)
53
54 /* Arbitrary limit based on supported models */
55 #define AWCC_MAX_RES_COUNT 16
56 #define AWCC_ID_BITMAP_SIZE (U8_MAX + 1)
57 #define AWCC_ID_BITMAP_LONGS BITS_TO_LONGS(AWCC_ID_BITMAP_SIZE)
58
59 static bool force_hwmon;
60 module_param_unsafe(force_hwmon, bool, 0);
61 MODULE_PARM_DESC(force_hwmon, "Force probing for HWMON support without checking if the WMI backend is available");
62
63 static bool force_platform_profile;
64 module_param_unsafe(force_platform_profile, bool, 0);
65 MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available");
66
67 static bool force_gmode;
68 module_param_unsafe(force_gmode, bool, 0);
69 MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
70
71 struct awcc_quirks {
72 bool hwmon;
73 bool pprof;
74 bool gmode;
75 };
76
77 static struct awcc_quirks g_series_quirks = {
78 .hwmon = true,
79 .pprof = true,
80 .gmode = true,
81 };
82
83 static struct awcc_quirks generic_quirks = {
84 .hwmon = true,
85 .pprof = true,
86 .gmode = false,
87 };
88
89 static struct awcc_quirks empty_quirks;
90
91 static const struct dmi_system_id awcc_dmi_table[] __initconst = {
92 {
93 .ident = "Alienware Area-51m",
94 .matches = {
95 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
96 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m"),
97 },
98 .driver_data = &generic_quirks,
99 },
100 {
101 .ident = "Alienware Area-51m R2",
102 .matches = {
103 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
104 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m R2"),
105 },
106 .driver_data = &generic_quirks,
107 },
108 {
109 .ident = "Alienware m15 R5",
110 .matches = {
111 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
112 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R5"),
113 },
114 .driver_data = &generic_quirks,
115 },
116 {
117 .ident = "Alienware m15 R7",
118 .matches = {
119 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
120 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R7"),
121 },
122 .driver_data = &generic_quirks,
123 },
124 {
125 .ident = "Alienware m16 R1",
126 .matches = {
127 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
128 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1"),
129 },
130 .driver_data = &g_series_quirks,
131 },
132 {
133 .ident = "Alienware m16 R1 AMD",
134 .matches = {
135 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
136 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
137 },
138 .driver_data = &generic_quirks,
139 },
140 {
141 .ident = "Alienware m16 R2",
142 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R2"),
145 },
146 .driver_data = &generic_quirks,
147 },
148 {
149 .ident = "Alienware m17 R5",
150 .matches = {
151 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
152 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
153 },
154 .driver_data = &generic_quirks,
155 },
156 {
157 .ident = "Alienware m18 R2",
158 .matches = {
159 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
160 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
161 },
162 .driver_data = &generic_quirks,
163 },
164 {
165 .ident = "Alienware x15 R1",
166 .matches = {
167 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
168 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
169 },
170 .driver_data = &generic_quirks,
171 },
172 {
173 .ident = "Alienware x15 R2",
174 .matches = {
175 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
176 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R2"),
177 },
178 .driver_data = &generic_quirks,
179 },
180 {
181 .ident = "Alienware x17 R2",
182 .matches = {
183 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
184 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
185 },
186 .driver_data = &generic_quirks,
187 },
188 {
189 .ident = "Dell Inc. G15 5510",
190 .matches = {
191 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
192 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
193 },
194 .driver_data = &g_series_quirks,
195 },
196 {
197 .ident = "Dell Inc. G15 5511",
198 .matches = {
199 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
200 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
201 },
202 .driver_data = &g_series_quirks,
203 },
204 {
205 .ident = "Dell Inc. G15 5515",
206 .matches = {
207 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
209 },
210 .driver_data = &g_series_quirks,
211 },
212 {
213 .ident = "Dell Inc. G15 5530",
214 .matches = {
215 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
216 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5530"),
217 },
218 .driver_data = &g_series_quirks,
219 },
220 {
221 .ident = "Dell Inc. G16 7630",
222 .matches = {
223 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
224 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G16 7630"),
225 },
226 .driver_data = &g_series_quirks,
227 },
228 {
229 .ident = "Dell Inc. G3 3500",
230 .matches = {
231 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
232 DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
233 },
234 .driver_data = &g_series_quirks,
235 },
236 {
237 .ident = "Dell Inc. G3 3590",
238 .matches = {
239 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
240 DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
241 },
242 .driver_data = &g_series_quirks,
243 },
244 {
245 .ident = "Dell Inc. G5 5500",
246 .matches = {
247 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
248 DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
249 },
250 .driver_data = &g_series_quirks,
251 },
252 {
253 .ident = "Dell Inc. G5 5505",
254 .matches = {
255 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
256 DMI_MATCH(DMI_PRODUCT_NAME, "G5 5505"),
257 },
258 .driver_data = &g_series_quirks,
259 },
260 {}
261 };
262
263 enum AWCC_GET_FAN_SENSORS_OPERATIONS {
264 AWCC_OP_GET_TOTAL_FAN_TEMPS = 0x01,
265 AWCC_OP_GET_FAN_TEMP_ID = 0x02,
266 };
267
268 enum AWCC_THERMAL_INFORMATION_OPERATIONS {
269 AWCC_OP_GET_SYSTEM_DESCRIPTION = 0x02,
270 AWCC_OP_GET_RESOURCE_ID = 0x03,
271 AWCC_OP_GET_TEMPERATURE = 0x04,
272 AWCC_OP_GET_FAN_RPM = 0x05,
273 AWCC_OP_GET_FAN_MIN_RPM = 0x08,
274 AWCC_OP_GET_FAN_MAX_RPM = 0x09,
275 AWCC_OP_GET_CURRENT_PROFILE = 0x0B,
276 AWCC_OP_GET_FAN_BOOST = 0x0C,
277 };
278
279 enum AWCC_THERMAL_CONTROL_OPERATIONS {
280 AWCC_OP_ACTIVATE_PROFILE = 0x01,
281 AWCC_OP_SET_FAN_BOOST = 0x02,
282 };
283
284 enum AWCC_GAME_SHIFT_STATUS_OPERATIONS {
285 AWCC_OP_TOGGLE_GAME_SHIFT = 0x01,
286 AWCC_OP_GET_GAME_SHIFT_STATUS = 0x02,
287 };
288
289 enum AWCC_THERMAL_TABLES {
290 AWCC_THERMAL_TABLE_LEGACY = 0x9,
291 AWCC_THERMAL_TABLE_USTT = 0xA,
292 };
293
294 enum AWCC_SPECIAL_THERMAL_CODES {
295 AWCC_SPECIAL_PROFILE_CUSTOM = 0x00,
296 AWCC_SPECIAL_PROFILE_GMODE = 0xAB,
297 };
298
299 enum AWCC_TEMP_SENSOR_TYPES {
300 AWCC_TEMP_SENSOR_CPU = 0x01,
301 AWCC_TEMP_SENSOR_FRONT = 0x03,
302 AWCC_TEMP_SENSOR_GPU = 0x06,
303 };
304
305 enum AWCC_FAN_TYPES {
306 AWCC_FAN_CPU_1 = 0x32,
307 AWCC_FAN_GPU_1 = 0x33,
308 AWCC_FAN_PCI = 0x34,
309 AWCC_FAN_MID = 0x35,
310 AWCC_FAN_TOP_1 = 0x36,
311 AWCC_FAN_SIDE = 0x37,
312 AWCC_FAN_U2_1 = 0x38,
313 AWCC_FAN_U2_2 = 0x39,
314 AWCC_FAN_FRONT_1 = 0x3A,
315 AWCC_FAN_CPU_2 = 0x3B,
316 AWCC_FAN_GPU_2 = 0x3C,
317 AWCC_FAN_TOP_2 = 0x3D,
318 AWCC_FAN_TOP_3 = 0x3E,
319 AWCC_FAN_FRONT_2 = 0x3F,
320 AWCC_FAN_BOTTOM_1 = 0x40,
321 AWCC_FAN_BOTTOM_2 = 0x41,
322 };
323
324 enum awcc_thermal_profile {
325 AWCC_PROFILE_USTT_BALANCED,
326 AWCC_PROFILE_USTT_BALANCED_PERFORMANCE,
327 AWCC_PROFILE_USTT_COOL,
328 AWCC_PROFILE_USTT_QUIET,
329 AWCC_PROFILE_USTT_PERFORMANCE,
330 AWCC_PROFILE_USTT_LOW_POWER,
331 AWCC_PROFILE_LEGACY_QUIET,
332 AWCC_PROFILE_LEGACY_BALANCED,
333 AWCC_PROFILE_LEGACY_BALANCED_PERFORMANCE,
334 AWCC_PROFILE_LEGACY_PERFORMANCE,
335 AWCC_PROFILE_LAST,
336 };
337
338 struct wmax_led_args {
339 u32 led_mask;
340 struct color_platform colors;
341 u8 state;
342 } __packed;
343
344 struct wmax_brightness_args {
345 u32 led_mask;
346 u32 percentage;
347 };
348
349 struct wmax_basic_args {
350 u8 arg;
351 };
352
353 struct wmax_u32_args {
354 u8 operation;
355 u8 arg1;
356 u8 arg2;
357 u8 arg3;
358 };
359
360 struct awcc_fan_data {
361 unsigned long auto_channels_temp;
362 u32 min_rpm;
363 u32 max_rpm;
364 u8 suspend_cache;
365 u8 id;
366 };
367
368 struct awcc_priv {
369 struct wmi_device *wdev;
370 union {
371 u32 system_description;
372 struct {
373 u8 fan_count;
374 u8 temp_count;
375 u8 unknown_count;
376 u8 profile_count;
377 };
378 u8 res_count[4];
379 };
380
381 struct device *ppdev;
382 u8 supported_profiles[PLATFORM_PROFILE_LAST];
383
384 struct device *hwdev;
385 struct awcc_fan_data **fan_data;
386 unsigned long temp_sensors[AWCC_ID_BITMAP_LONGS];
387
388 u32 gpio_count;
389 };
390
391 static const enum platform_profile_option awcc_mode_to_platform_profile[AWCC_PROFILE_LAST] = {
392 [AWCC_PROFILE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED,
393 [AWCC_PROFILE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
394 [AWCC_PROFILE_USTT_COOL] = PLATFORM_PROFILE_COOL,
395 [AWCC_PROFILE_USTT_QUIET] = PLATFORM_PROFILE_QUIET,
396 [AWCC_PROFILE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
397 [AWCC_PROFILE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER,
398 [AWCC_PROFILE_LEGACY_QUIET] = PLATFORM_PROFILE_QUIET,
399 [AWCC_PROFILE_LEGACY_BALANCED] = PLATFORM_PROFILE_BALANCED,
400 [AWCC_PROFILE_LEGACY_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
401 [AWCC_PROFILE_LEGACY_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
402 };
403
404 static struct awcc_quirks *awcc;
405
406 /*
407 * The HDMI mux sysfs node indicates the status of the HDMI input mux.
408 * It can toggle between standard system GPU output and HDMI input.
409 */
cable_show(struct device * dev,struct device_attribute * attr,char * buf)410 static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
411 char *buf)
412 {
413 struct alienfx_platdata *pdata = dev_get_platdata(dev);
414 struct wmax_basic_args in_args = {
415 .arg = 0,
416 };
417 u32 out_data;
418 int ret;
419
420 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
421 &in_args, sizeof(in_args), &out_data);
422 if (!ret) {
423 if (out_data == 0)
424 return sysfs_emit(buf, "[unconnected] connected unknown\n");
425 else if (out_data == 1)
426 return sysfs_emit(buf, "unconnected [connected] unknown\n");
427 }
428
429 pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
430 return sysfs_emit(buf, "unconnected connected [unknown]\n");
431 }
432
source_show(struct device * dev,struct device_attribute * attr,char * buf)433 static ssize_t source_show(struct device *dev, struct device_attribute *attr,
434 char *buf)
435 {
436 struct alienfx_platdata *pdata = dev_get_platdata(dev);
437 struct wmax_basic_args in_args = {
438 .arg = 0,
439 };
440 u32 out_data;
441 int ret;
442
443 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
444 &in_args, sizeof(in_args), &out_data);
445 if (!ret) {
446 if (out_data == 1)
447 return sysfs_emit(buf, "[input] gpu unknown\n");
448 else if (out_data == 2)
449 return sysfs_emit(buf, "input [gpu] unknown\n");
450 }
451
452 pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
453 return sysfs_emit(buf, "input gpu [unknown]\n");
454 }
455
source_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)456 static ssize_t source_store(struct device *dev, struct device_attribute *attr,
457 const char *buf, size_t count)
458 {
459 struct alienfx_platdata *pdata = dev_get_platdata(dev);
460 struct wmax_basic_args args;
461 int ret;
462
463 if (strcmp(buf, "gpu\n") == 0)
464 args.arg = 1;
465 else if (strcmp(buf, "input\n") == 0)
466 args.arg = 2;
467 else
468 args.arg = 3;
469 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
470
471 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
472 sizeof(args), NULL);
473 if (ret < 0)
474 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
475
476 return count;
477 }
478
479 static DEVICE_ATTR_RO(cable);
480 static DEVICE_ATTR_RW(source);
481
hdmi_group_visible(struct kobject * kobj)482 static bool hdmi_group_visible(struct kobject *kobj)
483 {
484 return alienware_interface == WMAX && alienfx->hdmi_mux;
485 }
486 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
487
488 static struct attribute *hdmi_attrs[] = {
489 &dev_attr_cable.attr,
490 &dev_attr_source.attr,
491 NULL,
492 };
493
494 const struct attribute_group wmax_hdmi_attribute_group = {
495 .name = "hdmi",
496 .is_visible = SYSFS_GROUP_VISIBLE(hdmi),
497 .attrs = hdmi_attrs,
498 };
499
500 /*
501 * Alienware GFX amplifier support
502 * - Currently supports reading cable status
503 * - Leaving expansion room to possibly support dock/undock events later
504 */
status_show(struct device * dev,struct device_attribute * attr,char * buf)505 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
506 char *buf)
507 {
508 struct alienfx_platdata *pdata = dev_get_platdata(dev);
509 struct wmax_basic_args in_args = {
510 .arg = 0,
511 };
512 u32 out_data;
513 int ret;
514
515 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
516 &in_args, sizeof(in_args), &out_data);
517 if (!ret) {
518 if (out_data == 0)
519 return sysfs_emit(buf, "[unconnected] connected unknown\n");
520 else if (out_data == 1)
521 return sysfs_emit(buf, "unconnected [connected] unknown\n");
522 }
523
524 pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
525 return sysfs_emit(buf, "unconnected connected [unknown]\n");
526 }
527
528 static DEVICE_ATTR_RO(status);
529
amplifier_group_visible(struct kobject * kobj)530 static bool amplifier_group_visible(struct kobject *kobj)
531 {
532 return alienware_interface == WMAX && alienfx->amplifier;
533 }
534 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
535
536 static struct attribute *amplifier_attrs[] = {
537 &dev_attr_status.attr,
538 NULL,
539 };
540
541 const struct attribute_group wmax_amplifier_attribute_group = {
542 .name = "amplifier",
543 .is_visible = SYSFS_GROUP_VISIBLE(amplifier),
544 .attrs = amplifier_attrs,
545 };
546
547 /*
548 * Deep Sleep Control support
549 * - Modifies BIOS setting for deep sleep control allowing extra wakeup events
550 */
deepsleep_show(struct device * dev,struct device_attribute * attr,char * buf)551 static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
552 char *buf)
553 {
554 struct alienfx_platdata *pdata = dev_get_platdata(dev);
555 struct wmax_basic_args in_args = {
556 .arg = 0,
557 };
558 u32 out_data;
559 int ret;
560
561 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
562 &in_args, sizeof(in_args), &out_data);
563 if (!ret) {
564 if (out_data == 0)
565 return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
566 else if (out_data == 1)
567 return sysfs_emit(buf, "disabled [s5] s5_s4\n");
568 else if (out_data == 2)
569 return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
570 }
571
572 pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
573 return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
574 }
575
deepsleep_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)576 static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
577 const char *buf, size_t count)
578 {
579 struct alienfx_platdata *pdata = dev_get_platdata(dev);
580 struct wmax_basic_args args;
581 int ret;
582
583 if (strcmp(buf, "disabled\n") == 0)
584 args.arg = 0;
585 else if (strcmp(buf, "s5\n") == 0)
586 args.arg = 1;
587 else
588 args.arg = 2;
589 pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
590
591 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
592 &args, sizeof(args), NULL);
593 if (!ret)
594 pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
595
596 return count;
597 }
598
599 static DEVICE_ATTR_RW(deepsleep);
600
deepsleep_group_visible(struct kobject * kobj)601 static bool deepsleep_group_visible(struct kobject *kobj)
602 {
603 return alienware_interface == WMAX && alienfx->deepslp;
604 }
605 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
606
607 static struct attribute *deepsleep_attrs[] = {
608 &dev_attr_deepsleep.attr,
609 NULL,
610 };
611
612 const struct attribute_group wmax_deepsleep_attribute_group = {
613 .name = "deepsleep",
614 .is_visible = SYSFS_GROUP_VISIBLE(deepsleep),
615 .attrs = deepsleep_attrs,
616 };
617
618 /*
619 * AWCC Helpers
620 */
is_awcc_thermal_profile_id(u8 code)621 static bool is_awcc_thermal_profile_id(u8 code)
622 {
623 u8 table = FIELD_GET(AWCC_THERMAL_TABLE_MASK, code);
624 u8 mode = FIELD_GET(AWCC_THERMAL_MODE_MASK, code);
625
626 if (mode >= AWCC_PROFILE_LAST)
627 return false;
628
629 if (table == AWCC_THERMAL_TABLE_LEGACY && mode >= AWCC_PROFILE_LEGACY_QUIET)
630 return true;
631
632 if (table == AWCC_THERMAL_TABLE_USTT && mode <= AWCC_PROFILE_USTT_LOW_POWER)
633 return true;
634
635 return false;
636 }
637
awcc_wmi_command(struct wmi_device * wdev,u32 method_id,struct wmax_u32_args * args,u32 * out)638 static int awcc_wmi_command(struct wmi_device *wdev, u32 method_id,
639 struct wmax_u32_args *args, u32 *out)
640 {
641 int ret;
642
643 ret = alienware_wmi_command(wdev, method_id, args, sizeof(*args), out);
644 if (ret)
645 return ret;
646
647 if (*out == AWCC_FAILURE_CODE || *out == AWCC_FAILURE_CODE_2)
648 return -EBADRQC;
649
650 return 0;
651 }
652
awcc_get_fan_sensors(struct wmi_device * wdev,u8 operation,u8 fan_id,u8 index,u32 * out)653 static int awcc_get_fan_sensors(struct wmi_device *wdev, u8 operation,
654 u8 fan_id, u8 index, u32 *out)
655 {
656 struct wmax_u32_args args = {
657 .operation = operation,
658 .arg1 = fan_id,
659 .arg2 = index,
660 .arg3 = 0,
661 };
662
663 return awcc_wmi_command(wdev, AWCC_METHOD_GET_FAN_SENSORS, &args, out);
664 }
665
awcc_thermal_information(struct wmi_device * wdev,u8 operation,u8 arg,u32 * out)666 static int awcc_thermal_information(struct wmi_device *wdev, u8 operation, u8 arg,
667 u32 *out)
668 {
669 struct wmax_u32_args args = {
670 .operation = operation,
671 .arg1 = arg,
672 .arg2 = 0,
673 .arg3 = 0,
674 };
675
676 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out);
677 }
678
awcc_fwup_gpio_control(struct wmi_device * wdev,u8 pin,u8 status)679 static int awcc_fwup_gpio_control(struct wmi_device *wdev, u8 pin, u8 status)
680 {
681 struct wmax_u32_args args = {
682 .operation = pin,
683 .arg1 = status,
684 .arg2 = 0,
685 .arg3 = 0,
686 };
687 u32 out;
688
689 return awcc_wmi_command(wdev, AWCC_METHOD_FWUP_GPIO_CONTROL, &args, &out);
690 }
691
awcc_read_total_gpios(struct wmi_device * wdev,u32 * count)692 static int awcc_read_total_gpios(struct wmi_device *wdev, u32 *count)
693 {
694 struct wmax_u32_args args = {};
695
696 return awcc_wmi_command(wdev, AWCC_METHOD_READ_TOTAL_GPIOS, &args, count);
697 }
698
awcc_read_gpio_status(struct wmi_device * wdev,u8 pin,u32 * status)699 static int awcc_read_gpio_status(struct wmi_device *wdev, u8 pin, u32 *status)
700 {
701 struct wmax_u32_args args = {
702 .operation = pin,
703 .arg1 = 0,
704 .arg2 = 0,
705 .arg3 = 0,
706 };
707
708 return awcc_wmi_command(wdev, AWCC_METHOD_READ_GPIO_STATUS, &args, status);
709 }
710
awcc_game_shift_status(struct wmi_device * wdev,u8 operation,u32 * out)711 static int awcc_game_shift_status(struct wmi_device *wdev, u8 operation,
712 u32 *out)
713 {
714 struct wmax_u32_args args = {
715 .operation = operation,
716 .arg1 = 0,
717 .arg2 = 0,
718 .arg3 = 0,
719 };
720
721 return awcc_wmi_command(wdev, AWCC_METHOD_GAME_SHIFT_STATUS, &args, out);
722 }
723
724 /**
725 * awcc_op_get_resource_id - Get the resource ID at a given index
726 * @wdev: AWCC WMI device
727 * @index: Index
728 * @out: Value returned by the WMI call
729 *
730 * Get the resource ID at a given @index. Resource IDs are listed in the
731 * following order:
732 *
733 * - Fan IDs
734 * - Sensor IDs
735 * - Unknown IDs
736 * - Thermal Profile IDs
737 *
738 * The total number of IDs of a given type can be obtained with
739 * AWCC_OP_GET_SYSTEM_DESCRIPTION.
740 *
741 * Return: 0 on success, -errno on failure
742 */
awcc_op_get_resource_id(struct wmi_device * wdev,u8 index,u8 * out)743 static int awcc_op_get_resource_id(struct wmi_device *wdev, u8 index, u8 *out)
744 {
745 struct wmax_u32_args args = {
746 .operation = AWCC_OP_GET_RESOURCE_ID,
747 .arg1 = index,
748 .arg2 = 0,
749 .arg3 = 0,
750 };
751 u32 out_data;
752 int ret;
753
754 ret = awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, &out_data);
755 if (ret)
756 return ret;
757
758 *out = FIELD_GET(AWCC_RESOURCE_ID_MASK, out_data);
759
760 return 0;
761 }
762
awcc_op_get_fan_rpm(struct wmi_device * wdev,u8 fan_id,u32 * out)763 static int awcc_op_get_fan_rpm(struct wmi_device *wdev, u8 fan_id, u32 *out)
764 {
765 struct wmax_u32_args args = {
766 .operation = AWCC_OP_GET_FAN_RPM,
767 .arg1 = fan_id,
768 .arg2 = 0,
769 .arg3 = 0,
770 };
771
772 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out);
773 }
774
awcc_op_get_temperature(struct wmi_device * wdev,u8 temp_id,u32 * out)775 static int awcc_op_get_temperature(struct wmi_device *wdev, u8 temp_id, u32 *out)
776 {
777 struct wmax_u32_args args = {
778 .operation = AWCC_OP_GET_TEMPERATURE,
779 .arg1 = temp_id,
780 .arg2 = 0,
781 .arg3 = 0,
782 };
783
784 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out);
785 }
786
awcc_op_get_fan_boost(struct wmi_device * wdev,u8 fan_id,u32 * out)787 static int awcc_op_get_fan_boost(struct wmi_device *wdev, u8 fan_id, u32 *out)
788 {
789 struct wmax_u32_args args = {
790 .operation = AWCC_OP_GET_FAN_BOOST,
791 .arg1 = fan_id,
792 .arg2 = 0,
793 .arg3 = 0,
794 };
795
796 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out);
797 }
798
awcc_op_get_current_profile(struct wmi_device * wdev,u32 * out)799 static int awcc_op_get_current_profile(struct wmi_device *wdev, u32 *out)
800 {
801 struct wmax_u32_args args = {
802 .operation = AWCC_OP_GET_CURRENT_PROFILE,
803 .arg1 = 0,
804 .arg2 = 0,
805 .arg3 = 0,
806 };
807
808 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out);
809 }
810
awcc_op_activate_profile(struct wmi_device * wdev,u8 profile)811 static int awcc_op_activate_profile(struct wmi_device *wdev, u8 profile)
812 {
813 struct wmax_u32_args args = {
814 .operation = AWCC_OP_ACTIVATE_PROFILE,
815 .arg1 = profile,
816 .arg2 = 0,
817 .arg3 = 0,
818 };
819 u32 out;
820
821 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_CONTROL, &args, &out);
822 }
823
awcc_op_set_fan_boost(struct wmi_device * wdev,u8 fan_id,u8 boost)824 static int awcc_op_set_fan_boost(struct wmi_device *wdev, u8 fan_id, u8 boost)
825 {
826 struct wmax_u32_args args = {
827 .operation = AWCC_OP_SET_FAN_BOOST,
828 .arg1 = fan_id,
829 .arg2 = boost,
830 .arg3 = 0,
831 };
832 u32 out;
833
834 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_CONTROL, &args, &out);
835 }
836
837 /*
838 * HWMON
839 * - Provides temperature and fan speed monitoring as well as manual fan
840 * control
841 */
awcc_hwmon_is_visible(const void * drvdata,enum hwmon_sensor_types type,u32 attr,int channel)842 static umode_t awcc_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
843 u32 attr, int channel)
844 {
845 const struct awcc_priv *priv = drvdata;
846 unsigned int temp_count;
847
848 switch (type) {
849 case hwmon_temp:
850 temp_count = bitmap_weight(priv->temp_sensors, AWCC_ID_BITMAP_SIZE);
851
852 return channel < temp_count ? 0444 : 0;
853 case hwmon_fan:
854 return channel < priv->fan_count ? 0444 : 0;
855 case hwmon_pwm:
856 return channel < priv->fan_count ? 0444 : 0;
857 default:
858 return 0;
859 }
860 }
861
awcc_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)862 static int awcc_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
863 u32 attr, int channel, long *val)
864 {
865 struct awcc_priv *priv = dev_get_drvdata(dev);
866 const struct awcc_fan_data *fan;
867 u32 state;
868 int ret;
869 u8 temp;
870
871 switch (type) {
872 case hwmon_temp:
873 temp = find_nth_bit(priv->temp_sensors, AWCC_ID_BITMAP_SIZE, channel);
874
875 switch (attr) {
876 case hwmon_temp_input:
877 ret = awcc_op_get_temperature(priv->wdev, temp, &state);
878 if (ret)
879 return ret;
880
881 *val = state * MILLIDEGREE_PER_DEGREE;
882 break;
883 default:
884 return -EOPNOTSUPP;
885 }
886
887 break;
888 case hwmon_fan:
889 fan = priv->fan_data[channel];
890
891 switch (attr) {
892 case hwmon_fan_input:
893 ret = awcc_op_get_fan_rpm(priv->wdev, fan->id, &state);
894 if (ret)
895 return ret;
896
897 *val = state;
898 break;
899 case hwmon_fan_min:
900 *val = fan->min_rpm;
901 break;
902 case hwmon_fan_max:
903 *val = fan->max_rpm;
904 break;
905 default:
906 return -EOPNOTSUPP;
907 }
908
909 break;
910 case hwmon_pwm:
911 fan = priv->fan_data[channel];
912
913 switch (attr) {
914 case hwmon_pwm_auto_channels_temp:
915 *val = fan->auto_channels_temp;
916 break;
917 default:
918 return -EOPNOTSUPP;
919 }
920
921 break;
922 default:
923 return -EOPNOTSUPP;
924 }
925
926 return 0;
927 }
928
awcc_hwmon_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)929 static int awcc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
930 u32 attr, int channel, const char **str)
931 {
932 struct awcc_priv *priv = dev_get_drvdata(dev);
933 u8 temp;
934
935 switch (type) {
936 case hwmon_temp:
937 temp = find_nth_bit(priv->temp_sensors, AWCC_ID_BITMAP_SIZE, channel);
938
939 switch (temp) {
940 case AWCC_TEMP_SENSOR_CPU:
941 *str = "CPU";
942 break;
943 case AWCC_TEMP_SENSOR_FRONT:
944 *str = "Front";
945 break;
946 case AWCC_TEMP_SENSOR_GPU:
947 *str = "GPU";
948 break;
949 default:
950 *str = "Unknown";
951 break;
952 }
953
954 break;
955 case hwmon_fan:
956 switch (priv->fan_data[channel]->id) {
957 case AWCC_FAN_CPU_1:
958 case AWCC_FAN_CPU_2:
959 *str = "CPU Fan";
960 break;
961 case AWCC_FAN_GPU_1:
962 case AWCC_FAN_GPU_2:
963 *str = "GPU Fan";
964 break;
965 case AWCC_FAN_PCI:
966 *str = "PCI Fan";
967 break;
968 case AWCC_FAN_MID:
969 *str = "Mid Fan";
970 break;
971 case AWCC_FAN_TOP_1:
972 case AWCC_FAN_TOP_2:
973 case AWCC_FAN_TOP_3:
974 *str = "Top Fan";
975 break;
976 case AWCC_FAN_SIDE:
977 *str = "Side Fan";
978 break;
979 case AWCC_FAN_U2_1:
980 case AWCC_FAN_U2_2:
981 *str = "U.2 Fan";
982 break;
983 case AWCC_FAN_FRONT_1:
984 case AWCC_FAN_FRONT_2:
985 *str = "Front Fan";
986 break;
987 case AWCC_FAN_BOTTOM_1:
988 case AWCC_FAN_BOTTOM_2:
989 *str = "Bottom Fan";
990 break;
991 default:
992 *str = "Unknown Fan";
993 break;
994 }
995
996 break;
997 default:
998 return -EOPNOTSUPP;
999 }
1000
1001 return 0;
1002 }
1003
1004 static const struct hwmon_ops awcc_hwmon_ops = {
1005 .is_visible = awcc_hwmon_is_visible,
1006 .read = awcc_hwmon_read,
1007 .read_string = awcc_hwmon_read_string,
1008 };
1009
1010 static const struct hwmon_channel_info * const awcc_hwmon_info[] = {
1011 HWMON_CHANNEL_INFO(temp,
1012 HWMON_T_LABEL | HWMON_T_INPUT,
1013 HWMON_T_LABEL | HWMON_T_INPUT,
1014 HWMON_T_LABEL | HWMON_T_INPUT,
1015 HWMON_T_LABEL | HWMON_T_INPUT,
1016 HWMON_T_LABEL | HWMON_T_INPUT,
1017 HWMON_T_LABEL | HWMON_T_INPUT
1018 ),
1019 HWMON_CHANNEL_INFO(fan,
1020 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX,
1021 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX,
1022 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX,
1023 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX,
1024 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX,
1025 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX
1026 ),
1027 HWMON_CHANNEL_INFO(pwm,
1028 HWMON_PWM_AUTO_CHANNELS_TEMP,
1029 HWMON_PWM_AUTO_CHANNELS_TEMP,
1030 HWMON_PWM_AUTO_CHANNELS_TEMP,
1031 HWMON_PWM_AUTO_CHANNELS_TEMP,
1032 HWMON_PWM_AUTO_CHANNELS_TEMP,
1033 HWMON_PWM_AUTO_CHANNELS_TEMP
1034 ),
1035 NULL
1036 };
1037
1038 static const struct hwmon_chip_info awcc_hwmon_chip_info = {
1039 .ops = &awcc_hwmon_ops,
1040 .info = awcc_hwmon_info,
1041 };
1042
fan_boost_show(struct device * dev,struct device_attribute * attr,char * buf)1043 static ssize_t fan_boost_show(struct device *dev, struct device_attribute *attr,
1044 char *buf)
1045 {
1046 struct awcc_priv *priv = dev_get_drvdata(dev);
1047 int index = to_sensor_dev_attr(attr)->index;
1048 struct awcc_fan_data *fan = priv->fan_data[index];
1049 u32 boost;
1050 int ret;
1051
1052 ret = awcc_op_get_fan_boost(priv->wdev, fan->id, &boost);
1053 if (ret)
1054 return ret;
1055
1056 return sysfs_emit(buf, "%u\n", boost);
1057 }
1058
fan_boost_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1059 static ssize_t fan_boost_store(struct device *dev, struct device_attribute *attr,
1060 const char *buf, size_t count)
1061 {
1062 struct awcc_priv *priv = dev_get_drvdata(dev);
1063 int index = to_sensor_dev_attr(attr)->index;
1064 struct awcc_fan_data *fan = priv->fan_data[index];
1065 unsigned long val;
1066 int ret;
1067
1068 ret = kstrtoul(buf, 0, &val);
1069 if (ret)
1070 return ret;
1071
1072 ret = awcc_op_set_fan_boost(priv->wdev, fan->id, clamp_val(val, 0, 255));
1073
1074 return ret ? ret : count;
1075 }
1076
1077 static SENSOR_DEVICE_ATTR_RW(fan1_boost, fan_boost, 0);
1078 static SENSOR_DEVICE_ATTR_RW(fan2_boost, fan_boost, 1);
1079 static SENSOR_DEVICE_ATTR_RW(fan3_boost, fan_boost, 2);
1080 static SENSOR_DEVICE_ATTR_RW(fan4_boost, fan_boost, 3);
1081 static SENSOR_DEVICE_ATTR_RW(fan5_boost, fan_boost, 4);
1082 static SENSOR_DEVICE_ATTR_RW(fan6_boost, fan_boost, 5);
1083
fan_boost_attr_visible(struct kobject * kobj,struct attribute * attr,int n)1084 static umode_t fan_boost_attr_visible(struct kobject *kobj, struct attribute *attr, int n)
1085 {
1086 struct awcc_priv *priv = dev_get_drvdata(kobj_to_dev(kobj));
1087
1088 return n < priv->fan_count ? attr->mode : 0;
1089 }
1090
fan_boost_group_visible(struct kobject * kobj)1091 static bool fan_boost_group_visible(struct kobject *kobj)
1092 {
1093 return true;
1094 }
1095
1096 DEFINE_SYSFS_GROUP_VISIBLE(fan_boost);
1097
1098 static struct attribute *fan_boost_attrs[] = {
1099 &sensor_dev_attr_fan1_boost.dev_attr.attr,
1100 &sensor_dev_attr_fan2_boost.dev_attr.attr,
1101 &sensor_dev_attr_fan3_boost.dev_attr.attr,
1102 &sensor_dev_attr_fan4_boost.dev_attr.attr,
1103 &sensor_dev_attr_fan5_boost.dev_attr.attr,
1104 &sensor_dev_attr_fan6_boost.dev_attr.attr,
1105 NULL
1106 };
1107
1108 static const struct attribute_group fan_boost_group = {
1109 .attrs = fan_boost_attrs,
1110 .is_visible = SYSFS_GROUP_VISIBLE(fan_boost),
1111 };
1112
1113 static const struct attribute_group *awcc_hwmon_groups[] = {
1114 &fan_boost_group,
1115 NULL
1116 };
1117
awcc_hwmon_temps_init(struct wmi_device * wdev)1118 static int awcc_hwmon_temps_init(struct wmi_device *wdev)
1119 {
1120 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
1121 unsigned int i;
1122 int ret;
1123 u8 id;
1124
1125 for (i = 0; i < priv->temp_count; i++) {
1126 /*
1127 * Temperature sensors IDs are listed after the fan IDs at
1128 * offset `fan_count`
1129 */
1130 ret = awcc_op_get_resource_id(wdev, i + priv->fan_count, &id);
1131 if (ret)
1132 return ret;
1133
1134 __set_bit(id, priv->temp_sensors);
1135 }
1136
1137 return 0;
1138 }
1139
awcc_hwmon_fans_init(struct wmi_device * wdev)1140 static int awcc_hwmon_fans_init(struct wmi_device *wdev)
1141 {
1142 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
1143 unsigned long fan_temps[AWCC_ID_BITMAP_LONGS];
1144 unsigned long gather[AWCC_ID_BITMAP_LONGS];
1145 u32 min_rpm, max_rpm, temp_count, temp_id;
1146 struct awcc_fan_data *fan_data;
1147 unsigned int i, j;
1148 int ret;
1149 u8 id;
1150
1151 for (i = 0; i < priv->fan_count; i++) {
1152 fan_data = devm_kzalloc(&wdev->dev, sizeof(*fan_data), GFP_KERNEL);
1153 if (!fan_data)
1154 return -ENOMEM;
1155
1156 /*
1157 * Fan IDs are listed first at offset 0
1158 */
1159 ret = awcc_op_get_resource_id(wdev, i, &id);
1160 if (ret)
1161 return ret;
1162
1163 ret = awcc_thermal_information(wdev, AWCC_OP_GET_FAN_MIN_RPM, id,
1164 &min_rpm);
1165 if (ret)
1166 return ret;
1167
1168 ret = awcc_thermal_information(wdev, AWCC_OP_GET_FAN_MAX_RPM, id,
1169 &max_rpm);
1170 if (ret)
1171 return ret;
1172
1173 ret = awcc_get_fan_sensors(wdev, AWCC_OP_GET_TOTAL_FAN_TEMPS, id,
1174 0, &temp_count);
1175 if (ret)
1176 return ret;
1177
1178 bitmap_zero(fan_temps, AWCC_ID_BITMAP_SIZE);
1179
1180 for (j = 0; j < temp_count; j++) {
1181 ret = awcc_get_fan_sensors(wdev, AWCC_OP_GET_FAN_TEMP_ID,
1182 id, j, &temp_id);
1183 if (ret)
1184 break;
1185
1186 temp_id = FIELD_GET(AWCC_RESOURCE_ID_MASK, temp_id);
1187 __set_bit(temp_id, fan_temps);
1188 }
1189
1190 fan_data->id = id;
1191 fan_data->min_rpm = min_rpm;
1192 fan_data->max_rpm = max_rpm;
1193 bitmap_gather(gather, fan_temps, priv->temp_sensors, AWCC_ID_BITMAP_SIZE);
1194 bitmap_copy(&fan_data->auto_channels_temp, gather, BITS_PER_LONG);
1195 priv->fan_data[i] = fan_data;
1196 }
1197
1198 return 0;
1199 }
1200
awcc_hwmon_init(struct wmi_device * wdev)1201 static int awcc_hwmon_init(struct wmi_device *wdev)
1202 {
1203 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
1204 int ret;
1205
1206 priv->fan_data = devm_kcalloc(&wdev->dev, priv->fan_count,
1207 sizeof(*priv->fan_data), GFP_KERNEL);
1208 if (!priv->fan_data)
1209 return -ENOMEM;
1210
1211 ret = awcc_hwmon_temps_init(wdev);
1212 if (ret)
1213 return ret;
1214
1215 ret = awcc_hwmon_fans_init(wdev);
1216 if (ret)
1217 return ret;
1218
1219 priv->hwdev = devm_hwmon_device_register_with_info(&wdev->dev, "alienware_wmi",
1220 priv, &awcc_hwmon_chip_info,
1221 awcc_hwmon_groups);
1222
1223 return PTR_ERR_OR_ZERO(priv->hwdev);
1224 }
1225
awcc_hwmon_suspend(struct device * dev)1226 static void awcc_hwmon_suspend(struct device *dev)
1227 {
1228 struct awcc_priv *priv = dev_get_drvdata(dev);
1229 struct awcc_fan_data *fan;
1230 unsigned int i;
1231 u32 boost;
1232 int ret;
1233
1234 for (i = 0; i < priv->fan_count; i++) {
1235 fan = priv->fan_data[i];
1236
1237 ret = awcc_thermal_information(priv->wdev, AWCC_OP_GET_FAN_BOOST,
1238 fan->id, &boost);
1239 if (ret)
1240 dev_err(dev, "Failed to store Fan %u boost while suspending\n", i);
1241
1242 fan->suspend_cache = ret ? 0 : clamp_val(boost, 0, 255);
1243
1244 awcc_op_set_fan_boost(priv->wdev, fan->id, 0);
1245 if (ret)
1246 dev_err(dev, "Failed to set Fan %u boost to 0 while suspending\n", i);
1247 }
1248 }
1249
awcc_hwmon_resume(struct device * dev)1250 static void awcc_hwmon_resume(struct device *dev)
1251 {
1252 struct awcc_priv *priv = dev_get_drvdata(dev);
1253 struct awcc_fan_data *fan;
1254 unsigned int i;
1255 int ret;
1256
1257 for (i = 0; i < priv->fan_count; i++) {
1258 fan = priv->fan_data[i];
1259
1260 if (!fan->suspend_cache)
1261 continue;
1262
1263 ret = awcc_op_set_fan_boost(priv->wdev, fan->id, fan->suspend_cache);
1264 if (ret)
1265 dev_err(dev, "Failed to restore Fan %u boost while resuming\n", i);
1266 }
1267 }
1268
1269 /*
1270 * Thermal Profile control
1271 * - Provides thermal profile control through the Platform Profile API
1272 */
awcc_platform_profile_get(struct device * dev,enum platform_profile_option * profile)1273 static int awcc_platform_profile_get(struct device *dev,
1274 enum platform_profile_option *profile)
1275 {
1276 struct awcc_priv *priv = dev_get_drvdata(dev);
1277 u32 out_data;
1278 int ret;
1279
1280 ret = awcc_op_get_current_profile(priv->wdev, &out_data);
1281 if (ret)
1282 return ret;
1283
1284 switch (out_data) {
1285 case AWCC_SPECIAL_PROFILE_CUSTOM:
1286 *profile = PLATFORM_PROFILE_CUSTOM;
1287 return 0;
1288 case AWCC_SPECIAL_PROFILE_GMODE:
1289 *profile = PLATFORM_PROFILE_PERFORMANCE;
1290 return 0;
1291 default:
1292 break;
1293 }
1294
1295 if (!is_awcc_thermal_profile_id(out_data))
1296 return -ENODATA;
1297
1298 out_data = FIELD_GET(AWCC_THERMAL_MODE_MASK, out_data);
1299 *profile = awcc_mode_to_platform_profile[out_data];
1300
1301 return 0;
1302 }
1303
awcc_platform_profile_set(struct device * dev,enum platform_profile_option profile)1304 static int awcc_platform_profile_set(struct device *dev,
1305 enum platform_profile_option profile)
1306 {
1307 struct awcc_priv *priv = dev_get_drvdata(dev);
1308
1309 if (awcc->gmode) {
1310 u32 gmode_status;
1311 int ret;
1312
1313 ret = awcc_game_shift_status(priv->wdev,
1314 AWCC_OP_GET_GAME_SHIFT_STATUS,
1315 &gmode_status);
1316
1317 if (ret < 0)
1318 return ret;
1319
1320 if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) ||
1321 (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) {
1322 ret = awcc_game_shift_status(priv->wdev,
1323 AWCC_OP_TOGGLE_GAME_SHIFT,
1324 &gmode_status);
1325
1326 if (ret < 0)
1327 return ret;
1328 }
1329 }
1330
1331 return awcc_op_activate_profile(priv->wdev, priv->supported_profiles[profile]);
1332 }
1333
awcc_platform_profile_probe(void * drvdata,unsigned long * choices)1334 static int awcc_platform_profile_probe(void *drvdata, unsigned long *choices)
1335 {
1336 enum platform_profile_option profile;
1337 struct awcc_priv *priv = drvdata;
1338 enum awcc_thermal_profile mode;
1339 u8 id, offset = 0;
1340 int ret;
1341
1342 /*
1343 * Thermal profile IDs are listed last at offset
1344 * fan_count + temp_count + unknown_count
1345 */
1346 for (unsigned int i = 0; i < ARRAY_SIZE(priv->res_count) - 1; i++)
1347 offset += priv->res_count[i];
1348
1349 for (unsigned int i = 0; i < priv->profile_count; i++) {
1350 ret = awcc_op_get_resource_id(priv->wdev, i + offset, &id);
1351 /*
1352 * Some devices report an incorrect number of thermal profiles
1353 * so the resource ID list may end prematurely
1354 */
1355 if (ret == -EBADRQC)
1356 break;
1357 if (ret)
1358 return ret;
1359
1360 if (!is_awcc_thermal_profile_id(id)) {
1361 dev_dbg(&priv->wdev->dev, "Unmapped thermal profile ID 0x%02x\n", id);
1362 continue;
1363 }
1364
1365 mode = FIELD_GET(AWCC_THERMAL_MODE_MASK, id);
1366 profile = awcc_mode_to_platform_profile[mode];
1367 priv->supported_profiles[profile] = id;
1368
1369 __set_bit(profile, choices);
1370 }
1371
1372 if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
1373 return -ENODEV;
1374
1375 if (awcc->gmode) {
1376 priv->supported_profiles[PLATFORM_PROFILE_PERFORMANCE] =
1377 AWCC_SPECIAL_PROFILE_GMODE;
1378
1379 __set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
1380 }
1381
1382 /* Every model supports the "custom" profile */
1383 priv->supported_profiles[PLATFORM_PROFILE_CUSTOM] =
1384 AWCC_SPECIAL_PROFILE_CUSTOM;
1385
1386 __set_bit(PLATFORM_PROFILE_CUSTOM, choices);
1387
1388 return 0;
1389 }
1390
1391 static const struct platform_profile_ops awcc_platform_profile_ops = {
1392 .probe = awcc_platform_profile_probe,
1393 .profile_get = awcc_platform_profile_get,
1394 .profile_set = awcc_platform_profile_set,
1395 };
1396
awcc_platform_profile_init(struct wmi_device * wdev)1397 static int awcc_platform_profile_init(struct wmi_device *wdev)
1398 {
1399 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
1400
1401 priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
1402 priv, &awcc_platform_profile_ops);
1403
1404 return PTR_ERR_OR_ZERO(priv->ppdev);
1405 }
1406
1407 /*
1408 * DebugFS
1409 */
awcc_debugfs_system_description_read(struct seq_file * seq,void * data)1410 static int awcc_debugfs_system_description_read(struct seq_file *seq, void *data)
1411 {
1412 struct device *dev = seq->private;
1413 struct awcc_priv *priv = dev_get_drvdata(dev);
1414
1415 seq_printf(seq, "0x%08x\n", priv->system_description);
1416
1417 return 0;
1418 }
1419
awcc_debugfs_hwmon_data_read(struct seq_file * seq,void * data)1420 static int awcc_debugfs_hwmon_data_read(struct seq_file *seq, void *data)
1421 {
1422 struct device *dev = seq->private;
1423 struct awcc_priv *priv = dev_get_drvdata(dev);
1424 const struct awcc_fan_data *fan;
1425 unsigned int bit;
1426
1427 seq_printf(seq, "Number of fans: %u\n", priv->fan_count);
1428 seq_printf(seq, "Number of temperature sensors: %u\n\n", priv->temp_count);
1429
1430 for (u32 i = 0; i < priv->fan_count; i++) {
1431 fan = priv->fan_data[i];
1432
1433 seq_printf(seq, "Fan %u:\n", i);
1434 seq_printf(seq, " ID: 0x%02x\n", fan->id);
1435 seq_printf(seq, " Related temperature sensors bitmap: %lu\n",
1436 fan->auto_channels_temp);
1437 }
1438
1439 seq_puts(seq, "\nTemperature sensor IDs:\n");
1440 for_each_set_bit(bit, priv->temp_sensors, AWCC_ID_BITMAP_SIZE)
1441 seq_printf(seq, " 0x%02x\n", bit);
1442
1443 return 0;
1444 }
1445
awcc_debugfs_pprof_data_read(struct seq_file * seq,void * data)1446 static int awcc_debugfs_pprof_data_read(struct seq_file *seq, void *data)
1447 {
1448 struct device *dev = seq->private;
1449 struct awcc_priv *priv = dev_get_drvdata(dev);
1450
1451 seq_printf(seq, "Number of thermal profiles: %u\n\n", priv->profile_count);
1452
1453 for (u32 i = 0; i < PLATFORM_PROFILE_LAST; i++) {
1454 if (!priv->supported_profiles[i])
1455 continue;
1456
1457 seq_printf(seq, "Platform profile %u:\n", i);
1458 seq_printf(seq, " ID: 0x%02x\n", priv->supported_profiles[i]);
1459 }
1460
1461 return 0;
1462 }
1463
awcc_gpio_pin_show(struct seq_file * seq,void * data)1464 static int awcc_gpio_pin_show(struct seq_file *seq, void *data)
1465 {
1466 unsigned long pin = debugfs_get_aux_num(seq->file);
1467 struct wmi_device *wdev = seq->private;
1468 u32 status;
1469 int ret;
1470
1471 ret = awcc_read_gpio_status(wdev, pin, &status);
1472 if (ret)
1473 return ret;
1474
1475 seq_printf(seq, "%u\n", status);
1476
1477 return 0;
1478 }
1479
awcc_gpio_pin_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1480 static ssize_t awcc_gpio_pin_write(struct file *file, const char __user *buf,
1481 size_t count, loff_t *ppos)
1482 {
1483 unsigned long pin = debugfs_get_aux_num(file);
1484 struct seq_file *seq = file->private_data;
1485 struct wmi_device *wdev = seq->private;
1486 bool status;
1487 int ret;
1488
1489 if (!ppos || *ppos)
1490 return -EINVAL;
1491
1492 ret = kstrtobool_from_user(buf, count, &status);
1493 if (ret)
1494 return ret;
1495
1496 ret = awcc_fwup_gpio_control(wdev, pin, status);
1497 if (ret)
1498 return ret;
1499
1500 return count;
1501 }
1502
1503 DEFINE_SHOW_STORE_ATTRIBUTE(awcc_gpio_pin);
1504
awcc_debugfs_remove(void * data)1505 static void awcc_debugfs_remove(void *data)
1506 {
1507 struct dentry *root = data;
1508
1509 debugfs_remove(root);
1510 }
1511
awcc_debugfs_init(struct wmi_device * wdev)1512 static void awcc_debugfs_init(struct wmi_device *wdev)
1513 {
1514 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
1515 struct dentry *root, *gpio_ctl;
1516 u32 gpio_count;
1517 char name[64];
1518 int ret;
1519
1520 scnprintf(name, sizeof(name), "%s-%s", "alienware-wmi", dev_name(&wdev->dev));
1521 root = debugfs_create_dir(name, NULL);
1522
1523 debugfs_create_devm_seqfile(&wdev->dev, "system_description", root,
1524 awcc_debugfs_system_description_read);
1525
1526 if (awcc->hwmon)
1527 debugfs_create_devm_seqfile(&wdev->dev, "hwmon_data", root,
1528 awcc_debugfs_hwmon_data_read);
1529
1530 if (awcc->pprof)
1531 debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root,
1532 awcc_debugfs_pprof_data_read);
1533
1534 ret = awcc_read_total_gpios(wdev, &gpio_count);
1535 if (ret) {
1536 dev_dbg(&wdev->dev, "Failed to get total GPIO Pin count\n");
1537 goto out_add_action;
1538 } else if (gpio_count > AWCC_MAX_RES_COUNT) {
1539 dev_dbg(&wdev->dev, "Reported GPIO Pin count may be incorrect: %u\n", gpio_count);
1540 goto out_add_action;
1541 }
1542
1543 gpio_ctl = debugfs_create_dir("gpio_ctl", root);
1544
1545 priv->gpio_count = gpio_count;
1546 debugfs_create_u32("total_gpios", 0444, gpio_ctl, &priv->gpio_count);
1547
1548 for (unsigned int i = 0; i < gpio_count; i++) {
1549 scnprintf(name, sizeof(name), "pin%u", i);
1550 debugfs_create_file_aux_num(name, 0644, gpio_ctl, wdev, i,
1551 &awcc_gpio_pin_fops);
1552 }
1553
1554 out_add_action:
1555 devm_add_action_or_reset(&wdev->dev, awcc_debugfs_remove, root);
1556 }
1557
alienware_awcc_setup(struct wmi_device * wdev)1558 static int alienware_awcc_setup(struct wmi_device *wdev)
1559 {
1560 struct awcc_priv *priv;
1561 int ret;
1562
1563 priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
1564 if (!priv)
1565 return -ENOMEM;
1566
1567 ret = awcc_thermal_information(wdev, AWCC_OP_GET_SYSTEM_DESCRIPTION,
1568 0, &priv->system_description);
1569 if (ret < 0)
1570 return ret;
1571
1572 /* Sanity check */
1573 for (unsigned int i = 0; i < ARRAY_SIZE(priv->res_count); i++) {
1574 if (priv->res_count[i] > AWCC_MAX_RES_COUNT) {
1575 dev_err(&wdev->dev, "Malformed system description: 0x%08x\n",
1576 priv->system_description);
1577 return -ENXIO;
1578 }
1579 }
1580
1581 priv->wdev = wdev;
1582 dev_set_drvdata(&wdev->dev, priv);
1583
1584 if (awcc->hwmon) {
1585 ret = awcc_hwmon_init(wdev);
1586 if (ret)
1587 return ret;
1588 }
1589
1590 if (awcc->pprof) {
1591 ret = awcc_platform_profile_init(wdev);
1592 if (ret)
1593 return ret;
1594 }
1595
1596 awcc_debugfs_init(wdev);
1597
1598 return 0;
1599 }
1600
1601 /*
1602 * WMAX WMI driver
1603 */
wmax_wmi_update_led(struct alienfx_priv * priv,struct wmi_device * wdev,u8 location)1604 static int wmax_wmi_update_led(struct alienfx_priv *priv,
1605 struct wmi_device *wdev, u8 location)
1606 {
1607 struct wmax_led_args in_args = {
1608 .led_mask = 1 << location,
1609 .colors = priv->colors[location],
1610 .state = priv->lighting_control_state,
1611 };
1612
1613 return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args,
1614 sizeof(in_args), NULL);
1615 }
1616
wmax_wmi_update_brightness(struct alienfx_priv * priv,struct wmi_device * wdev,u8 brightness)1617 static int wmax_wmi_update_brightness(struct alienfx_priv *priv,
1618 struct wmi_device *wdev, u8 brightness)
1619 {
1620 struct wmax_brightness_args in_args = {
1621 .led_mask = 0xFF,
1622 .percentage = brightness,
1623 };
1624
1625 return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args,
1626 sizeof(in_args), NULL);
1627 }
1628
wmax_wmi_probe(struct wmi_device * wdev,const void * context)1629 static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
1630 {
1631 struct alienfx_platdata pdata = {
1632 .wdev = wdev,
1633 .ops = {
1634 .upd_led = wmax_wmi_update_led,
1635 .upd_brightness = wmax_wmi_update_brightness,
1636 },
1637 };
1638 int ret;
1639
1640 if (awcc)
1641 ret = alienware_awcc_setup(wdev);
1642 else
1643 ret = alienware_alienfx_setup(&pdata);
1644
1645 return ret;
1646 }
1647
wmax_wmi_suspend(struct device * dev)1648 static int wmax_wmi_suspend(struct device *dev)
1649 {
1650 if (awcc && awcc->hwmon)
1651 awcc_hwmon_suspend(dev);
1652
1653 return 0;
1654 }
1655
wmax_wmi_resume(struct device * dev)1656 static int wmax_wmi_resume(struct device *dev)
1657 {
1658 if (awcc && awcc->hwmon)
1659 awcc_hwmon_resume(dev);
1660
1661 return 0;
1662 }
1663
1664 static DEFINE_SIMPLE_DEV_PM_OPS(wmax_wmi_pm_ops, wmax_wmi_suspend, wmax_wmi_resume);
1665
1666 static const struct wmi_device_id alienware_wmax_device_id_table[] = {
1667 { WMAX_CONTROL_GUID, NULL },
1668 { },
1669 };
1670 MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table);
1671
1672 static struct wmi_driver alienware_wmax_wmi_driver = {
1673 .driver = {
1674 .name = "alienware-wmi-wmax",
1675 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1676 .pm = pm_sleep_ptr(&wmax_wmi_pm_ops),
1677 },
1678 .id_table = alienware_wmax_device_id_table,
1679 .probe = wmax_wmi_probe,
1680 .no_singleton = true,
1681 };
1682
alienware_wmax_wmi_init(void)1683 int __init alienware_wmax_wmi_init(void)
1684 {
1685 const struct dmi_system_id *id;
1686
1687 id = dmi_first_match(awcc_dmi_table);
1688 if (id)
1689 awcc = id->driver_data;
1690
1691 if (force_hwmon) {
1692 if (!awcc)
1693 awcc = &empty_quirks;
1694
1695 awcc->hwmon = true;
1696 }
1697
1698 if (force_platform_profile) {
1699 if (!awcc)
1700 awcc = &empty_quirks;
1701
1702 awcc->pprof = true;
1703 }
1704
1705 if (force_gmode) {
1706 if (awcc)
1707 awcc->gmode = true;
1708 else
1709 pr_warn("force_gmode requires platform profile support\n");
1710 }
1711
1712 return wmi_driver_register(&alienware_wmax_wmi_driver);
1713 }
1714
alienware_wmax_wmi_exit(void)1715 void __exit alienware_wmax_wmi_exit(void)
1716 {
1717 wmi_driver_unregister(&alienware_wmax_wmi_driver);
1718 }
1719