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