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