xref: /linux/drivers/platform/x86/acer-wmi.c (revision 9d588a1140b9ae211581a7a154d0b806d8cd8238)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Acer WMI Laptop Extras
4  *
5  *  Copyright (C) 2007-2009	Carlos Corbacho <carlos@strangeworlds.co.uk>
6  *
7  *  Based on acer_acpi:
8  *    Copyright (C) 2005-2007	E.M. Smith
9  *    Copyright (C) 2007-2008	Carlos Corbacho <cathectic@gmail.com>
10  */
11 
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 
14 #include <linux/kernel.h>
15 #include <linux/minmax.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/types.h>
19 #include <linux/dmi.h>
20 #include <linux/fixp-arith.h>
21 #include <linux/backlight.h>
22 #include <linux/leds.h>
23 #include <linux/platform_device.h>
24 #include <linux/platform_profile.h>
25 #include <linux/acpi.h>
26 #include <linux/i8042.h>
27 #include <linux/rfkill.h>
28 #include <linux/workqueue.h>
29 #include <linux/debugfs.h>
30 #include <linux/slab.h>
31 #include <linux/input.h>
32 #include <linux/input/sparse-keymap.h>
33 #include <acpi/video.h>
34 #include <linux/hwmon.h>
35 #include <linux/units.h>
36 #include <linux/unaligned.h>
37 #include <linux/bitfield.h>
38 #include <linux/bitmap.h>
39 
40 MODULE_AUTHOR("Carlos Corbacho");
41 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
42 MODULE_LICENSE("GPL");
43 
44 /*
45  * Magic Number
46  * Meaning is unknown - this number is required for writing to ACPI for AMW0
47  * (it's also used in acerhk when directly accessing the BIOS)
48  */
49 #define ACER_AMW0_WRITE	0x9610
50 
51 /*
52  * Bit masks for the AMW0 interface
53  */
54 #define ACER_AMW0_WIRELESS_MASK  0x35
55 #define ACER_AMW0_BLUETOOTH_MASK 0x34
56 #define ACER_AMW0_MAILLED_MASK   0x31
57 
58 /*
59  * Method IDs for WMID interface
60  */
61 #define ACER_WMID_GET_WIRELESS_METHODID		1
62 #define ACER_WMID_GET_BLUETOOTH_METHODID	2
63 #define ACER_WMID_GET_BRIGHTNESS_METHODID	3
64 #define ACER_WMID_SET_WIRELESS_METHODID		4
65 #define ACER_WMID_SET_BLUETOOTH_METHODID	5
66 #define ACER_WMID_SET_BRIGHTNESS_METHODID	6
67 #define ACER_WMID_GET_THREEG_METHODID		10
68 #define ACER_WMID_SET_THREEG_METHODID		11
69 
70 #define ACER_WMID_SET_GAMING_LED_METHODID 2
71 #define ACER_WMID_GET_GAMING_LED_METHODID 4
72 #define ACER_WMID_GET_GAMING_SYS_INFO_METHODID 5
73 #define ACER_WMID_SET_GAMING_FAN_BEHAVIOR_METHODID 14
74 #define ACER_WMID_GET_GAMING_FAN_BEHAVIOR_METHODID 15
75 #define ACER_WMID_SET_GAMING_FAN_SPEED_METHODID 16
76 #define ACER_WMID_GET_GAMING_FAN_SPEED_METHODID 17
77 #define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 22
78 #define ACER_WMID_GET_GAMING_MISC_SETTING_METHODID 23
79 
80 #define ACER_GAMING_FAN_BEHAVIOR_CPU BIT(0)
81 #define ACER_GAMING_FAN_BEHAVIOR_GPU BIT(3)
82 
83 #define ACER_GAMING_FAN_BEHAVIOR_STATUS_MASK GENMASK_ULL(7, 0)
84 #define ACER_GAMING_FAN_BEHAVIOR_ID_MASK GENMASK_ULL(15, 0)
85 #define ACER_GAMING_FAN_BEHAVIOR_SET_CPU_MODE_MASK GENMASK(17, 16)
86 #define ACER_GAMING_FAN_BEHAVIOR_SET_GPU_MODE_MASK GENMASK(23, 22)
87 #define ACER_GAMING_FAN_BEHAVIOR_GET_CPU_MODE_MASK GENMASK(9, 8)
88 #define ACER_GAMING_FAN_BEHAVIOR_GET_GPU_MODE_MASK GENMASK(15, 14)
89 
90 #define ACER_GAMING_FAN_SPEED_STATUS_MASK GENMASK_ULL(7, 0)
91 #define ACER_GAMING_FAN_SPEED_ID_MASK GENMASK_ULL(7, 0)
92 #define ACER_GAMING_FAN_SPEED_VALUE_MASK GENMASK_ULL(15, 8)
93 
94 #define ACER_GAMING_MISC_SETTING_STATUS_MASK GENMASK_ULL(7, 0)
95 #define ACER_GAMING_MISC_SETTING_INDEX_MASK GENMASK_ULL(7, 0)
96 #define ACER_GAMING_MISC_SETTING_VALUE_MASK GENMASK_ULL(15, 8)
97 
98 #define ACER_PREDATOR_V4_RETURN_STATUS_BIT_MASK GENMASK_ULL(7, 0)
99 #define ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK GENMASK_ULL(15, 8)
100 #define ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK GENMASK_ULL(23, 8)
101 #define ACER_PREDATOR_V4_SUPPORTED_SENSORS_BIT_MASK GENMASK_ULL(39, 24)
102 
103 /*
104  * Acer ACPI method GUIDs
105  */
106 #define AMW0_GUID1		"67C3371D-95A3-4C37-BB61-DD47B491DAAB"
107 #define AMW0_GUID2		"431F16ED-0C2B-444C-B267-27DEB140CF9C"
108 #define WMID_GUID1		"6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
109 #define WMID_GUID2		"95764E09-FB56-4E83-B31A-37761F60994A"
110 #define WMID_GUID3		"61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
111 #define WMID_GUID4		"7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56"
112 
113 /*
114  * Acer ACPI event GUIDs
115  */
116 #define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
117 
118 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
119 MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
120 MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
121 
122 enum acer_wmi_event_ids {
123 	WMID_HOTKEY_EVENT = 0x1,
124 	WMID_BACKLIGHT_EVENT = 0x4,
125 	WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
126 	WMID_GAMING_TURBO_KEY_EVENT = 0x7,
127 	WMID_AC_EVENT = 0x8,
128 };
129 
130 enum acer_wmi_predator_v4_sys_info_command {
131 	ACER_WMID_CMD_GET_PREDATOR_V4_SUPPORTED_SENSORS = 0x0000,
132 	ACER_WMID_CMD_GET_PREDATOR_V4_SENSOR_READING	= 0x0001,
133 	ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS	= 0x0002,
134 };
135 
136 enum acer_wmi_predator_v4_sensor_id {
137 	ACER_WMID_SENSOR_CPU_TEMPERATURE	= 0x01,
138 	ACER_WMID_SENSOR_CPU_FAN_SPEED		= 0x02,
139 	ACER_WMID_SENSOR_EXTERNAL_TEMPERATURE_2 = 0x03,
140 	ACER_WMID_SENSOR_GPU_FAN_SPEED		= 0x06,
141 	ACER_WMID_SENSOR_GPU_TEMPERATURE	= 0x0A,
142 };
143 
144 enum acer_wmi_gaming_fan_id {
145 	ACER_WMID_CPU_FAN	= 0x01,
146 	ACER_WMID_GPU_FAN	= 0x04,
147 };
148 
149 enum acer_wmi_gaming_fan_mode {
150 	ACER_WMID_FAN_MODE_AUTO		= 0x01,
151 	ACER_WMID_FAN_MODE_TURBO	= 0x02,
152 	ACER_WMID_FAN_MODE_CUSTOM	= 0x03,
153 };
154 
155 enum acer_wmi_predator_v4_oc {
156 	ACER_WMID_OC_NORMAL			= 0x0000,
157 	ACER_WMID_OC_TURBO			= 0x0002,
158 };
159 
160 enum acer_wmi_gaming_misc_setting {
161 	ACER_WMID_MISC_SETTING_OC_1			= 0x0005,
162 	ACER_WMID_MISC_SETTING_OC_2			= 0x0007,
163 	/* Unreliable on some models */
164 	ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES	= 0x000A,
165 	ACER_WMID_MISC_SETTING_PLATFORM_PROFILE		= 0x000B,
166 };
167 
168 static const struct key_entry acer_wmi_keymap[] __initconst = {
169 	{KE_KEY, 0x01, {KEY_WLAN} },     /* WiFi */
170 	{KE_KEY, 0x03, {KEY_WLAN} },     /* WiFi */
171 	{KE_KEY, 0x04, {KEY_WLAN} },     /* WiFi */
172 	{KE_KEY, 0x12, {KEY_BLUETOOTH} },	/* BT */
173 	{KE_KEY, 0x21, {KEY_PROG1} },    /* Backup */
174 	{KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
175 	{KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
176 	{KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
177 	{KE_KEY, 0x27, {KEY_HELP} },
178 	{KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
179 	{KE_IGNORE, 0x41, {KEY_MUTE} },
180 	{KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
181 	{KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },
182 	{KE_IGNORE, 0x43, {KEY_NEXTSONG} },
183 	{KE_IGNORE, 0x4e, {KEY_NEXTSONG} },
184 	{KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
185 	{KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },
186 	{KE_IGNORE, 0x45, {KEY_STOP} },
187 	{KE_IGNORE, 0x50, {KEY_STOP} },
188 	{KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
189 	{KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
190 	{KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
191 	/*
192 	 * 0x61 is KEY_SWITCHVIDEOMODE. Usually this is a duplicate input event
193 	 * with the "Video Bus" input device events. But sometimes it is not
194 	 * a dup. Map it to KEY_UNKNOWN instead of using KE_IGNORE so that
195 	 * udev/hwdb can override it on systems where it is not a dup.
196 	 */
197 	{KE_KEY, 0x61, {KEY_UNKNOWN} },
198 	{KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
199 	{KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
200 	{KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} },	/* Display Switch */
201 	{KE_IGNORE, 0x81, {KEY_SLEEP} },
202 	{KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} },	/* Touch Pad Toggle */
203 	{KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */
204 	{KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
205 	{KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
206 	{KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
207 	{KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
208 	{KE_KEY, 0x86, {KEY_WLAN} },
209 	{KE_KEY, 0x87, {KEY_POWER} },
210 	{KE_END, 0}
211 };
212 
213 static struct input_dev *acer_wmi_input_dev;
214 static struct input_dev *acer_wmi_accel_dev;
215 
216 struct event_return_value {
217 	u8 function;
218 	u8 key_num;
219 	u16 device_state;
220 	u16 reserved1;
221 	u8 kbd_dock_state;
222 	u8 reserved2;
223 } __packed;
224 
225 /*
226  * GUID3 Get Device Status device flags
227  */
228 #define ACER_WMID3_GDS_WIRELESS		(1<<0)	/* WiFi */
229 #define ACER_WMID3_GDS_THREEG		(1<<6)	/* 3G */
230 #define ACER_WMID3_GDS_WIMAX		(1<<7)	/* WiMAX */
231 #define ACER_WMID3_GDS_BLUETOOTH	(1<<11)	/* BT */
232 #define ACER_WMID3_GDS_RFBTN		(1<<14)	/* RF Button */
233 
234 #define ACER_WMID3_GDS_TOUCHPAD		(1<<1)	/* Touchpad */
235 
236 /* Hotkey Customized Setting and Acer Application Status.
237  * Set Device Default Value and Report Acer Application Status.
238  * When Acer Application starts, it will run this method to inform
239  * BIOS/EC that Acer Application is on.
240  * App Status
241  *	Bit[0]: Launch Manager Status
242  *	Bit[1]: ePM Status
243  *	Bit[2]: Device Control Status
244  *	Bit[3]: Acer Power Button Utility Status
245  *	Bit[4]: RF Button Status
246  *	Bit[5]: ODD PM Status
247  *	Bit[6]: Device Default Value Control
248  *	Bit[7]: Hall Sensor Application Status
249  */
250 struct func_input_params {
251 	u8 function_num;        /* Function Number */
252 	u16 commun_devices;     /* Communication type devices default status */
253 	u16 devices;            /* Other type devices default status */
254 	u8 app_status;          /* Acer Device Status. LM, ePM, RF Button... */
255 	u8 app_mask;		/* Bit mask to app_status */
256 	u8 reserved;
257 } __packed;
258 
259 struct func_return_value {
260 	u8 error_code;          /* Error Code */
261 	u8 ec_return_value;     /* EC Return Value */
262 	u16 reserved;
263 } __packed;
264 
265 struct wmid3_gds_set_input_param {     /* Set Device Status input parameter */
266 	u8 function_num;        /* Function Number */
267 	u8 hotkey_number;       /* Hotkey Number */
268 	u16 devices;            /* Set Device */
269 	u8 volume_value;        /* Volume Value */
270 } __packed;
271 
272 struct wmid3_gds_get_input_param {     /* Get Device Status input parameter */
273 	u8 function_num;	/* Function Number */
274 	u8 hotkey_number;	/* Hotkey Number */
275 	u16 devices;		/* Get Device */
276 } __packed;
277 
278 struct wmid3_gds_return_value {	/* Get Device Status return value*/
279 	u8 error_code;		/* Error Code */
280 	u8 ec_return_value;	/* EC Return Value */
281 	u16 devices;		/* Current Device Status */
282 	u32 reserved;
283 } __packed;
284 
285 struct hotkey_function_type_aa {
286 	u8 type;
287 	u8 length;
288 	u16 handle;
289 	u16 commun_func_bitmap;
290 	u16 application_func_bitmap;
291 	u16 media_func_bitmap;
292 	u16 display_func_bitmap;
293 	u16 others_func_bitmap;
294 	u8 commun_fn_key_number;
295 } __packed;
296 
297 /*
298  * Interface capability flags
299  */
300 #define ACER_CAP_MAILLED		BIT(0)
301 #define ACER_CAP_WIRELESS		BIT(1)
302 #define ACER_CAP_BLUETOOTH		BIT(2)
303 #define ACER_CAP_BRIGHTNESS		BIT(3)
304 #define ACER_CAP_THREEG			BIT(4)
305 #define ACER_CAP_SET_FUNCTION_MODE	BIT(5)
306 #define ACER_CAP_KBD_DOCK		BIT(6)
307 #define ACER_CAP_TURBO_OC		BIT(7)
308 #define ACER_CAP_TURBO_LED		BIT(8)
309 #define ACER_CAP_TURBO_FAN		BIT(9)
310 #define ACER_CAP_PLATFORM_PROFILE	BIT(10)
311 #define ACER_CAP_HWMON			BIT(11)
312 #define ACER_CAP_PWM			BIT(12)
313 
314 /*
315  * Interface type flags
316  */
317 enum interface_flags {
318 	ACER_AMW0,
319 	ACER_AMW0_V2,
320 	ACER_WMID,
321 	ACER_WMID_v2,
322 };
323 
324 static int max_brightness = 0xF;
325 
326 static int mailled = -1;
327 static int brightness = -1;
328 static int threeg = -1;
329 static int force_series;
330 static int force_caps = -1;
331 static bool ec_raw_mode;
332 static bool has_type_aa;
333 static u16 commun_func_bitmap;
334 static u8 commun_fn_key_number;
335 static bool cycle_gaming_thermal_profile = true;
336 static bool predator_v4;
337 static u64 supported_sensors;
338 
339 module_param(mailled, int, 0444);
340 module_param(brightness, int, 0444);
341 module_param(threeg, int, 0444);
342 module_param(force_series, int, 0444);
343 module_param(force_caps, int, 0444);
344 module_param(ec_raw_mode, bool, 0444);
345 module_param(cycle_gaming_thermal_profile, bool, 0644);
346 module_param(predator_v4, bool, 0444);
347 MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
348 MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
349 MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
350 MODULE_PARM_DESC(force_series, "Force a different laptop series");
351 MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value");
352 MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
353 MODULE_PARM_DESC(cycle_gaming_thermal_profile,
354 	"Set thermal mode key in cycle mode. Disabling it sets the mode key in turbo toggle mode");
355 MODULE_PARM_DESC(predator_v4,
356 	"Enable features for predator laptops that use predator sense v4");
357 
358 struct acer_data {
359 	int mailled;
360 	int threeg;
361 	int brightness;
362 };
363 
364 struct acer_debug {
365 	struct dentry *root;
366 	u32 wmid_devices;
367 };
368 
369 static struct rfkill *wireless_rfkill;
370 static struct rfkill *bluetooth_rfkill;
371 static struct rfkill *threeg_rfkill;
372 static bool rfkill_inited;
373 
374 /* Each low-level interface must define at least some of the following */
375 struct wmi_interface {
376 	/* The WMI device type */
377 	u32 type;
378 
379 	/* The capabilities this interface provides */
380 	u32 capability;
381 
382 	/* Private data for the current interface */
383 	struct acer_data data;
384 
385 	/* debugfs entries associated with this interface */
386 	struct acer_debug debug;
387 };
388 
389 /* The static interface pointer, points to the currently detected interface */
390 static struct wmi_interface *interface;
391 
392 /*
393  * Embedded Controller quirks
394  * Some laptops require us to directly access the EC to either enable or query
395  * features that are not available through WMI.
396  */
397 
398 struct quirk_entry {
399 	u8 wireless;
400 	u8 mailled;
401 	s8 brightness;
402 	u8 bluetooth;
403 	u8 turbo;
404 	u8 cpu_fans;
405 	u8 gpu_fans;
406 	u8 predator_v4;
407 	u8 pwm;
408 };
409 
410 static struct quirk_entry *quirks;
411 
set_quirks(void)412 static void __init set_quirks(void)
413 {
414 	if (quirks->mailled)
415 		interface->capability |= ACER_CAP_MAILLED;
416 
417 	if (quirks->brightness)
418 		interface->capability |= ACER_CAP_BRIGHTNESS;
419 
420 	if (quirks->turbo)
421 		interface->capability |= ACER_CAP_TURBO_OC | ACER_CAP_TURBO_LED
422 					 | ACER_CAP_TURBO_FAN;
423 
424 	if (quirks->predator_v4)
425 		interface->capability |= ACER_CAP_PLATFORM_PROFILE |
426 					 ACER_CAP_HWMON;
427 
428 	if (quirks->pwm)
429 		interface->capability |= ACER_CAP_PWM;
430 }
431 
dmi_matched(const struct dmi_system_id * dmi)432 static int __init dmi_matched(const struct dmi_system_id *dmi)
433 {
434 	quirks = dmi->driver_data;
435 	return 1;
436 }
437 
set_force_caps(const struct dmi_system_id * dmi)438 static int __init set_force_caps(const struct dmi_system_id *dmi)
439 {
440 	if (force_caps == -1) {
441 		force_caps = (uintptr_t)dmi->driver_data;
442 		pr_info("Found %s, set force_caps to 0x%x\n", dmi->ident, force_caps);
443 	}
444 	return 1;
445 }
446 
447 static struct quirk_entry quirk_unknown = {
448 };
449 
450 static struct quirk_entry quirk_acer_aspire_1520 = {
451 	.brightness = -1,
452 };
453 
454 static struct quirk_entry quirk_acer_travelmate_2490 = {
455 	.mailled = 1,
456 };
457 
458 static struct quirk_entry quirk_acer_predator_ph315_53 = {
459 	.turbo = 1,
460 	.cpu_fans = 1,
461 	.gpu_fans = 1,
462 };
463 
464 static struct quirk_entry quirk_acer_predator_ph16_72 = {
465 	.turbo = 1,
466 	.cpu_fans = 1,
467 	.gpu_fans = 1,
468 	.predator_v4 = 1,
469 	.pwm = 1,
470 };
471 
472 static struct quirk_entry quirk_acer_predator_pt14_51 = {
473 	.turbo = 1,
474 	.cpu_fans = 1,
475 	.gpu_fans = 1,
476 	.predator_v4 = 1,
477 	.pwm = 1,
478 };
479 
480 static struct quirk_entry quirk_acer_predator_v4 = {
481 	.predator_v4 = 1,
482 };
483 
484 /* This AMW0 laptop has no bluetooth */
485 static struct quirk_entry quirk_medion_md_98300 = {
486 	.wireless = 1,
487 };
488 
489 static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
490 	.wireless = 2,
491 };
492 
493 static struct quirk_entry quirk_lenovo_ideapad_s205 = {
494 	.wireless = 3,
495 };
496 
497 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
498 static const struct dmi_system_id acer_blacklist[] __initconst = {
499 	{
500 		.ident = "Acer Aspire One (SSD)",
501 		.matches = {
502 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
503 			DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
504 		},
505 	},
506 	{
507 		.ident = "Acer Aspire One (HDD)",
508 		.matches = {
509 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
510 			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
511 		},
512 	},
513 	{}
514 };
515 
516 static const struct dmi_system_id amw0_whitelist[] __initconst = {
517 	{
518 		.ident = "Acer",
519 		.matches = {
520 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
521 		},
522 	},
523 	{
524 		.ident = "Gateway",
525 		.matches = {
526 			DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),
527 		},
528 	},
529 	{
530 		.ident = "Packard Bell",
531 		.matches = {
532 			DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"),
533 		},
534 	},
535 	{}
536 };
537 
538 /*
539  * This quirk table is only for Acer/Gateway/Packard Bell family
540  * that those machines are supported by acer-wmi driver.
541  */
542 static const struct dmi_system_id acer_quirks[] __initconst = {
543 	{
544 		.callback = dmi_matched,
545 		.ident = "Acer Aspire 1360",
546 		.matches = {
547 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
548 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
549 		},
550 		.driver_data = &quirk_acer_aspire_1520,
551 	},
552 	{
553 		.callback = dmi_matched,
554 		.ident = "Acer Aspire 1520",
555 		.matches = {
556 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
557 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),
558 		},
559 		.driver_data = &quirk_acer_aspire_1520,
560 	},
561 	{
562 		.callback = dmi_matched,
563 		.ident = "Acer Aspire 3100",
564 		.matches = {
565 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
566 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
567 		},
568 		.driver_data = &quirk_acer_travelmate_2490,
569 	},
570 	{
571 		.callback = dmi_matched,
572 		.ident = "Acer Aspire 3610",
573 		.matches = {
574 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
575 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),
576 		},
577 		.driver_data = &quirk_acer_travelmate_2490,
578 	},
579 	{
580 		.callback = dmi_matched,
581 		.ident = "Acer Aspire 5100",
582 		.matches = {
583 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
584 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
585 		},
586 		.driver_data = &quirk_acer_travelmate_2490,
587 	},
588 	{
589 		.callback = dmi_matched,
590 		.ident = "Acer Aspire 5610",
591 		.matches = {
592 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
593 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
594 		},
595 		.driver_data = &quirk_acer_travelmate_2490,
596 	},
597 	{
598 		.callback = dmi_matched,
599 		.ident = "Acer Aspire 5630",
600 		.matches = {
601 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
602 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
603 		},
604 		.driver_data = &quirk_acer_travelmate_2490,
605 	},
606 	{
607 		.callback = dmi_matched,
608 		.ident = "Acer Aspire 5650",
609 		.matches = {
610 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
611 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
612 		},
613 		.driver_data = &quirk_acer_travelmate_2490,
614 	},
615 	{
616 		.callback = dmi_matched,
617 		.ident = "Acer Aspire 5680",
618 		.matches = {
619 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
620 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
621 		},
622 		.driver_data = &quirk_acer_travelmate_2490,
623 	},
624 	{
625 		.callback = dmi_matched,
626 		.ident = "Acer Aspire 9110",
627 		.matches = {
628 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
629 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
630 		},
631 		.driver_data = &quirk_acer_travelmate_2490,
632 	},
633 	{
634 		.callback = dmi_matched,
635 		.ident = "Acer TravelMate 2490",
636 		.matches = {
637 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
638 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
639 		},
640 		.driver_data = &quirk_acer_travelmate_2490,
641 	},
642 	{
643 		.callback = dmi_matched,
644 		.ident = "Acer TravelMate 4200",
645 		.matches = {
646 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
647 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"),
648 		},
649 		.driver_data = &quirk_acer_travelmate_2490,
650 	},
651 	{
652 		.callback = dmi_matched,
653 		.ident = "Acer Nitro AN515-58",
654 		.matches = {
655 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
656 			DMI_MATCH(DMI_PRODUCT_NAME, "Nitro AN515-58"),
657 		},
658 		.driver_data = &quirk_acer_predator_v4,
659 	},
660 	{
661 		.callback = dmi_matched,
662 		.ident = "Acer Predator PH315-53",
663 		.matches = {
664 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
665 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH315-53"),
666 		},
667 		.driver_data = &quirk_acer_predator_ph315_53,
668 	},
669 	{
670 		.callback = dmi_matched,
671 		.ident = "Acer Predator PHN16-71",
672 		.matches = {
673 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
674 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PHN16-71"),
675 		},
676 		.driver_data = &quirk_acer_predator_v4,
677 	},
678 	{
679 		.callback = dmi_matched,
680 		.ident = "Acer Predator PH16-71",
681 		.matches = {
682 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
683 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH16-71"),
684 		},
685 		.driver_data = &quirk_acer_predator_v4,
686 	},
687 	{
688 		.callback = dmi_matched,
689 		.ident = "Acer Predator PH16-72",
690 		.matches = {
691 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
692 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH16-72"),
693 		},
694 		.driver_data = &quirk_acer_predator_ph16_72,
695 	},
696 	{
697 		.callback = dmi_matched,
698 		.ident = "Acer Predator Helios Neo 16",
699 		.matches = {
700 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
701 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PHN16-72"),
702 		},
703 		.driver_data = &quirk_acer_predator_ph16_72,
704 	},
705 	{
706 		.callback = dmi_matched,
707 		.ident = "Acer Predator PH18-71",
708 		.matches = {
709 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
710 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH18-71"),
711 		},
712 		.driver_data = &quirk_acer_predator_v4,
713 	},
714 	{
715 		.callback = dmi_matched,
716 		.ident = "Acer Predator PT14-51",
717 		.matches = {
718 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
719 			DMI_MATCH(DMI_PRODUCT_NAME, "Predator PT14-51"),
720 		},
721 		.driver_data = &quirk_acer_predator_pt14_51,
722 	},
723 	{
724 		.callback = set_force_caps,
725 		.ident = "Acer Aspire Switch 10E SW3-016",
726 		.matches = {
727 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
728 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-016"),
729 		},
730 		.driver_data = (void *)ACER_CAP_KBD_DOCK,
731 	},
732 	{
733 		.callback = set_force_caps,
734 		.ident = "Acer Aspire Switch 10 SW5-012",
735 		.matches = {
736 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
737 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
738 		},
739 		.driver_data = (void *)ACER_CAP_KBD_DOCK,
740 	},
741 	{
742 		.callback = set_force_caps,
743 		.ident = "Acer Aspire Switch V 10 SW5-017",
744 		.matches = {
745 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
746 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
747 		},
748 		.driver_data = (void *)ACER_CAP_KBD_DOCK,
749 	},
750 	{
751 		.callback = set_force_caps,
752 		.ident = "Acer One 10 (S1003)",
753 		.matches = {
754 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
755 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
756 		},
757 		.driver_data = (void *)ACER_CAP_KBD_DOCK,
758 	},
759 	{}
760 };
761 
762 /*
763  * This quirk list is for those non-acer machines that have AMW0_GUID1
764  * but supported by acer-wmi in past days. Keeping this quirk list here
765  * is only for backward compatible. Please do not add new machine to
766  * here anymore. Those non-acer machines should be supported by
767  * appropriate wmi drivers.
768  */
769 static const struct dmi_system_id non_acer_quirks[] __initconst = {
770 	{
771 		.callback = dmi_matched,
772 		.ident = "Fujitsu Siemens Amilo Li 1718",
773 		.matches = {
774 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
775 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),
776 		},
777 		.driver_data = &quirk_fujitsu_amilo_li_1718,
778 	},
779 	{
780 		.callback = dmi_matched,
781 		.ident = "Medion MD 98300",
782 		.matches = {
783 			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
784 			DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"),
785 		},
786 		.driver_data = &quirk_medion_md_98300,
787 	},
788 	{
789 		.callback = dmi_matched,
790 		.ident = "Lenovo Ideapad S205",
791 		.matches = {
792 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
793 			DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
794 		},
795 		.driver_data = &quirk_lenovo_ideapad_s205,
796 	},
797 	{
798 		.callback = dmi_matched,
799 		.ident = "Lenovo Ideapad S205 (Brazos)",
800 		.matches = {
801 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
802 			DMI_MATCH(DMI_PRODUCT_NAME, "Brazos"),
803 		},
804 		.driver_data = &quirk_lenovo_ideapad_s205,
805 	},
806 	{
807 		.callback = dmi_matched,
808 		.ident = "Lenovo 3000 N200",
809 		.matches = {
810 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
811 			DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
812 		},
813 		.driver_data = &quirk_fujitsu_amilo_li_1718,
814 	},
815 	{
816 		.callback = dmi_matched,
817 		.ident = "Lenovo Ideapad S205-10382JG",
818 		.matches = {
819 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
820 			DMI_MATCH(DMI_PRODUCT_NAME, "10382JG"),
821 		},
822 		.driver_data = &quirk_lenovo_ideapad_s205,
823 	},
824 	{
825 		.callback = dmi_matched,
826 		.ident = "Lenovo Ideapad S205-1038DPG",
827 		.matches = {
828 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
829 			DMI_MATCH(DMI_PRODUCT_NAME, "1038DPG"),
830 		},
831 		.driver_data = &quirk_lenovo_ideapad_s205,
832 	},
833 	{}
834 };
835 
836 static struct device *platform_profile_device;
837 static bool platform_profile_support;
838 
839 /*
840  * The profile used before turbo mode. This variable is needed for
841  * returning from turbo mode when the mode key is in toggle mode.
842  */
843 static int last_non_turbo_profile = INT_MIN;
844 
845 enum acer_predator_v4_thermal_profile {
846 	ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET		= 0x00,
847 	ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED	= 0x01,
848 	ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE	= 0x04,
849 	ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO		= 0x05,
850 	ACER_PREDATOR_V4_THERMAL_PROFILE_ECO		= 0x06,
851 };
852 
853 /* Find which quirks are needed for a particular vendor/ model pair */
find_quirks(void)854 static void __init find_quirks(void)
855 {
856 	if (predator_v4) {
857 		quirks = &quirk_acer_predator_v4;
858 	} else if (!force_series) {
859 		dmi_check_system(acer_quirks);
860 		dmi_check_system(non_acer_quirks);
861 	} else if (force_series == 2490) {
862 		quirks = &quirk_acer_travelmate_2490;
863 	}
864 
865 	if (quirks == NULL)
866 		quirks = &quirk_unknown;
867 }
868 
869 /*
870  * General interface convenience methods
871  */
872 
has_cap(u32 cap)873 static bool has_cap(u32 cap)
874 {
875 	return interface->capability & cap;
876 }
877 
878 /*
879  * AMW0 (V1) interface
880  */
881 struct wmab_args {
882 	u32 eax;
883 	u32 ebx;
884 	u32 ecx;
885 	u32 edx;
886 };
887 
888 struct wmab_ret {
889 	u32 eax;
890 	u32 ebx;
891 	u32 ecx;
892 	u32 edx;
893 	u32 eex;
894 };
895 
wmab_execute(struct wmab_args * regbuf,struct acpi_buffer * result)896 static acpi_status wmab_execute(struct wmab_args *regbuf,
897 struct acpi_buffer *result)
898 {
899 	struct acpi_buffer input;
900 	acpi_status status;
901 	input.length = sizeof(struct wmab_args);
902 	input.pointer = (u8 *)regbuf;
903 
904 	status = wmi_evaluate_method(AMW0_GUID1, 0, 1, &input, result);
905 
906 	return status;
907 }
908 
AMW0_get_u32(u32 * value,u32 cap)909 static acpi_status AMW0_get_u32(u32 *value, u32 cap)
910 {
911 	int err;
912 	u8 result;
913 
914 	switch (cap) {
915 	case ACER_CAP_MAILLED:
916 		switch (quirks->mailled) {
917 		default:
918 			err = ec_read(0xA, &result);
919 			if (err)
920 				return AE_ERROR;
921 			*value = (result >> 7) & 0x1;
922 			return AE_OK;
923 		}
924 		break;
925 	case ACER_CAP_WIRELESS:
926 		switch (quirks->wireless) {
927 		case 1:
928 			err = ec_read(0x7B, &result);
929 			if (err)
930 				return AE_ERROR;
931 			*value = result & 0x1;
932 			return AE_OK;
933 		case 2:
934 			err = ec_read(0x71, &result);
935 			if (err)
936 				return AE_ERROR;
937 			*value = result & 0x1;
938 			return AE_OK;
939 		case 3:
940 			err = ec_read(0x78, &result);
941 			if (err)
942 				return AE_ERROR;
943 			*value = result & 0x1;
944 			return AE_OK;
945 		default:
946 			err = ec_read(0xA, &result);
947 			if (err)
948 				return AE_ERROR;
949 			*value = (result >> 2) & 0x1;
950 			return AE_OK;
951 		}
952 		break;
953 	case ACER_CAP_BLUETOOTH:
954 		switch (quirks->bluetooth) {
955 		default:
956 			err = ec_read(0xA, &result);
957 			if (err)
958 				return AE_ERROR;
959 			*value = (result >> 4) & 0x1;
960 			return AE_OK;
961 		}
962 		break;
963 	case ACER_CAP_BRIGHTNESS:
964 		switch (quirks->brightness) {
965 		default:
966 			err = ec_read(0x83, &result);
967 			if (err)
968 				return AE_ERROR;
969 			*value = result;
970 			return AE_OK;
971 		}
972 		break;
973 	default:
974 		return AE_ERROR;
975 	}
976 	return AE_OK;
977 }
978 
AMW0_set_u32(u32 value,u32 cap)979 static acpi_status AMW0_set_u32(u32 value, u32 cap)
980 {
981 	struct wmab_args args;
982 
983 	args.eax = ACER_AMW0_WRITE;
984 	args.ebx = value ? (1<<8) : 0;
985 	args.ecx = args.edx = 0;
986 
987 	switch (cap) {
988 	case ACER_CAP_MAILLED:
989 		if (value > 1)
990 			return AE_BAD_PARAMETER;
991 		args.ebx |= ACER_AMW0_MAILLED_MASK;
992 		break;
993 	case ACER_CAP_WIRELESS:
994 		if (value > 1)
995 			return AE_BAD_PARAMETER;
996 		args.ebx |= ACER_AMW0_WIRELESS_MASK;
997 		break;
998 	case ACER_CAP_BLUETOOTH:
999 		if (value > 1)
1000 			return AE_BAD_PARAMETER;
1001 		args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
1002 		break;
1003 	case ACER_CAP_BRIGHTNESS:
1004 		if (value > max_brightness)
1005 			return AE_BAD_PARAMETER;
1006 		switch (quirks->brightness) {
1007 		default:
1008 			return ec_write(0x83, value);
1009 		}
1010 	default:
1011 		return AE_ERROR;
1012 	}
1013 
1014 	/* Actually do the set */
1015 	return wmab_execute(&args, NULL);
1016 }
1017 
AMW0_find_mailled(void)1018 static acpi_status __init AMW0_find_mailled(void)
1019 {
1020 	struct wmab_args args;
1021 	struct wmab_ret ret;
1022 	acpi_status status = AE_OK;
1023 	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
1024 	union acpi_object *obj;
1025 
1026 	args.eax = 0x86;
1027 	args.ebx = args.ecx = args.edx = 0;
1028 
1029 	status = wmab_execute(&args, &out);
1030 	if (ACPI_FAILURE(status))
1031 		return status;
1032 
1033 	obj = (union acpi_object *) out.pointer;
1034 	if (obj && obj->type == ACPI_TYPE_BUFFER &&
1035 	obj->buffer.length == sizeof(struct wmab_ret)) {
1036 		ret = *((struct wmab_ret *) obj->buffer.pointer);
1037 	} else {
1038 		kfree(out.pointer);
1039 		return AE_ERROR;
1040 	}
1041 
1042 	if (ret.eex & 0x1)
1043 		interface->capability |= ACER_CAP_MAILLED;
1044 
1045 	kfree(out.pointer);
1046 
1047 	return AE_OK;
1048 }
1049 
1050 static const struct acpi_device_id norfkill_ids[] __initconst = {
1051 	{ "VPC2004", 0},
1052 	{ "IBM0068", 0},
1053 	{ "LEN0068", 0},
1054 	{ "SNY5001", 0},	/* sony-laptop in charge */
1055 	{ "HPQ6601", 0},
1056 	{ "", 0},
1057 };
1058 
AMW0_set_cap_acpi_check_device(void)1059 static int __init AMW0_set_cap_acpi_check_device(void)
1060 {
1061 	const struct acpi_device_id *id;
1062 
1063 	for (id = norfkill_ids; id->id[0]; id++)
1064 		if (acpi_dev_found(id->id))
1065 			return true;
1066 
1067 	return false;
1068 }
1069 
AMW0_set_capabilities(void)1070 static acpi_status __init AMW0_set_capabilities(void)
1071 {
1072 	struct wmab_args args;
1073 	struct wmab_ret ret;
1074 	acpi_status status;
1075 	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
1076 	union acpi_object *obj;
1077 
1078 	/*
1079 	 * On laptops with this strange GUID (non Acer), normal probing doesn't
1080 	 * work.
1081 	 */
1082 	if (wmi_has_guid(AMW0_GUID2)) {
1083 		if ((quirks != &quirk_unknown) ||
1084 		    !AMW0_set_cap_acpi_check_device())
1085 			interface->capability |= ACER_CAP_WIRELESS;
1086 		return AE_OK;
1087 	}
1088 
1089 	args.eax = ACER_AMW0_WRITE;
1090 	args.ecx = args.edx = 0;
1091 
1092 	args.ebx = 0xa2 << 8;
1093 	args.ebx |= ACER_AMW0_WIRELESS_MASK;
1094 
1095 	status = wmab_execute(&args, &out);
1096 	if (ACPI_FAILURE(status))
1097 		return status;
1098 
1099 	obj = out.pointer;
1100 	if (obj && obj->type == ACPI_TYPE_BUFFER &&
1101 	obj->buffer.length == sizeof(struct wmab_ret)) {
1102 		ret = *((struct wmab_ret *) obj->buffer.pointer);
1103 	} else {
1104 		status = AE_ERROR;
1105 		goto out;
1106 	}
1107 
1108 	if (ret.eax & 0x1)
1109 		interface->capability |= ACER_CAP_WIRELESS;
1110 
1111 	args.ebx = 2 << 8;
1112 	args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
1113 
1114 	/*
1115 	 * It's ok to use existing buffer for next wmab_execute call.
1116 	 * But we need to kfree(out.pointer) if next wmab_execute fail.
1117 	 */
1118 	status = wmab_execute(&args, &out);
1119 	if (ACPI_FAILURE(status))
1120 		goto out;
1121 
1122 	obj = (union acpi_object *) out.pointer;
1123 	if (obj && obj->type == ACPI_TYPE_BUFFER
1124 	&& obj->buffer.length == sizeof(struct wmab_ret)) {
1125 		ret = *((struct wmab_ret *) obj->buffer.pointer);
1126 	} else {
1127 		status = AE_ERROR;
1128 		goto out;
1129 	}
1130 
1131 	if (ret.eax & 0x1)
1132 		interface->capability |= ACER_CAP_BLUETOOTH;
1133 
1134 	/*
1135 	 * This appears to be safe to enable, since all Wistron based laptops
1136 	 * appear to use the same EC register for brightness, even if they
1137 	 * differ for wireless, etc
1138 	 */
1139 	if (quirks->brightness >= 0)
1140 		interface->capability |= ACER_CAP_BRIGHTNESS;
1141 
1142 	status = AE_OK;
1143 out:
1144 	kfree(out.pointer);
1145 	return status;
1146 }
1147 
1148 static struct wmi_interface AMW0_interface = {
1149 	.type = ACER_AMW0,
1150 };
1151 
1152 static struct wmi_interface AMW0_V2_interface = {
1153 	.type = ACER_AMW0_V2,
1154 };
1155 
1156 /*
1157  * New interface (The WMID interface)
1158  */
1159 static acpi_status
WMI_execute_u32(u32 method_id,u32 in,u32 * out)1160 WMI_execute_u32(u32 method_id, u32 in, u32 *out)
1161 {
1162 	struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
1163 	struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
1164 	union acpi_object *obj;
1165 	u32 tmp = 0;
1166 	acpi_status status;
1167 
1168 	status = wmi_evaluate_method(WMID_GUID1, 0, method_id, &input, &result);
1169 
1170 	if (ACPI_FAILURE(status))
1171 		return status;
1172 
1173 	obj = (union acpi_object *) result.pointer;
1174 	if (obj) {
1175 		if (obj->type == ACPI_TYPE_BUFFER &&
1176 			(obj->buffer.length == sizeof(u32) ||
1177 			obj->buffer.length == sizeof(u64))) {
1178 			tmp = *((u32 *) obj->buffer.pointer);
1179 		} else if (obj->type == ACPI_TYPE_INTEGER) {
1180 			tmp = (u32) obj->integer.value;
1181 		}
1182 	}
1183 
1184 	if (out)
1185 		*out = tmp;
1186 
1187 	kfree(result.pointer);
1188 
1189 	return status;
1190 }
1191 
WMID_get_u32(u32 * value,u32 cap)1192 static acpi_status WMID_get_u32(u32 *value, u32 cap)
1193 {
1194 	acpi_status status;
1195 	u8 tmp;
1196 	u32 result, method_id = 0;
1197 
1198 	switch (cap) {
1199 	case ACER_CAP_WIRELESS:
1200 		method_id = ACER_WMID_GET_WIRELESS_METHODID;
1201 		break;
1202 	case ACER_CAP_BLUETOOTH:
1203 		method_id = ACER_WMID_GET_BLUETOOTH_METHODID;
1204 		break;
1205 	case ACER_CAP_BRIGHTNESS:
1206 		method_id = ACER_WMID_GET_BRIGHTNESS_METHODID;
1207 		break;
1208 	case ACER_CAP_THREEG:
1209 		method_id = ACER_WMID_GET_THREEG_METHODID;
1210 		break;
1211 	case ACER_CAP_MAILLED:
1212 		if (quirks->mailled == 1) {
1213 			ec_read(0x9f, &tmp);
1214 			*value = tmp & 0x1;
1215 			return 0;
1216 		}
1217 		fallthrough;
1218 	default:
1219 		return AE_ERROR;
1220 	}
1221 	status = WMI_execute_u32(method_id, 0, &result);
1222 
1223 	if (ACPI_SUCCESS(status))
1224 		*value = (u8)result;
1225 
1226 	return status;
1227 }
1228 
WMID_set_u32(u32 value,u32 cap)1229 static acpi_status WMID_set_u32(u32 value, u32 cap)
1230 {
1231 	u32 method_id = 0;
1232 	char param;
1233 
1234 	switch (cap) {
1235 	case ACER_CAP_BRIGHTNESS:
1236 		if (value > max_brightness)
1237 			return AE_BAD_PARAMETER;
1238 		method_id = ACER_WMID_SET_BRIGHTNESS_METHODID;
1239 		break;
1240 	case ACER_CAP_WIRELESS:
1241 		if (value > 1)
1242 			return AE_BAD_PARAMETER;
1243 		method_id = ACER_WMID_SET_WIRELESS_METHODID;
1244 		break;
1245 	case ACER_CAP_BLUETOOTH:
1246 		if (value > 1)
1247 			return AE_BAD_PARAMETER;
1248 		method_id = ACER_WMID_SET_BLUETOOTH_METHODID;
1249 		break;
1250 	case ACER_CAP_THREEG:
1251 		if (value > 1)
1252 			return AE_BAD_PARAMETER;
1253 		method_id = ACER_WMID_SET_THREEG_METHODID;
1254 		break;
1255 	case ACER_CAP_MAILLED:
1256 		if (value > 1)
1257 			return AE_BAD_PARAMETER;
1258 		if (quirks->mailled == 1) {
1259 			param = value ? 0x92 : 0x93;
1260 			i8042_lock_chip();
1261 			i8042_command(&param, 0x1059);
1262 			i8042_unlock_chip();
1263 			return 0;
1264 		}
1265 		break;
1266 	default:
1267 		return AE_ERROR;
1268 	}
1269 	return WMI_execute_u32(method_id, (u32)value, NULL);
1270 }
1271 
wmid3_get_device_status(u32 * value,u16 device)1272 static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1273 {
1274 	struct wmid3_gds_return_value return_value;
1275 	acpi_status status;
1276 	union acpi_object *obj;
1277 	struct wmid3_gds_get_input_param params = {
1278 		.function_num = 0x1,
1279 		.hotkey_number = commun_fn_key_number,
1280 		.devices = device,
1281 	};
1282 	struct acpi_buffer input = {
1283 		sizeof(struct wmid3_gds_get_input_param),
1284 		&params
1285 	};
1286 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1287 
1288 	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1289 	if (ACPI_FAILURE(status))
1290 		return status;
1291 
1292 	obj = output.pointer;
1293 
1294 	if (!obj)
1295 		return AE_ERROR;
1296 	else if (obj->type != ACPI_TYPE_BUFFER) {
1297 		kfree(obj);
1298 		return AE_ERROR;
1299 	}
1300 	if (obj->buffer.length != 8) {
1301 		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1302 		kfree(obj);
1303 		return AE_ERROR;
1304 	}
1305 
1306 	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1307 	kfree(obj);
1308 
1309 	if (return_value.error_code || return_value.ec_return_value)
1310 		pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
1311 			device,
1312 			return_value.error_code,
1313 			return_value.ec_return_value);
1314 	else
1315 		*value = !!(return_value.devices & device);
1316 
1317 	return status;
1318 }
1319 
wmid_v2_get_u32(u32 * value,u32 cap)1320 static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
1321 {
1322 	u16 device;
1323 
1324 	switch (cap) {
1325 	case ACER_CAP_WIRELESS:
1326 		device = ACER_WMID3_GDS_WIRELESS;
1327 		break;
1328 	case ACER_CAP_BLUETOOTH:
1329 		device = ACER_WMID3_GDS_BLUETOOTH;
1330 		break;
1331 	case ACER_CAP_THREEG:
1332 		device = ACER_WMID3_GDS_THREEG;
1333 		break;
1334 	default:
1335 		return AE_ERROR;
1336 	}
1337 	return wmid3_get_device_status(value, device);
1338 }
1339 
wmid3_set_device_status(u32 value,u16 device)1340 static acpi_status wmid3_set_device_status(u32 value, u16 device)
1341 {
1342 	struct wmid3_gds_return_value return_value;
1343 	acpi_status status;
1344 	union acpi_object *obj;
1345 	u16 devices;
1346 	struct wmid3_gds_get_input_param get_params = {
1347 		.function_num = 0x1,
1348 		.hotkey_number = commun_fn_key_number,
1349 		.devices = commun_func_bitmap,
1350 	};
1351 	struct acpi_buffer get_input = {
1352 		sizeof(struct wmid3_gds_get_input_param),
1353 		&get_params
1354 	};
1355 	struct wmid3_gds_set_input_param set_params = {
1356 		.function_num = 0x2,
1357 		.hotkey_number = commun_fn_key_number,
1358 		.devices = commun_func_bitmap,
1359 	};
1360 	struct acpi_buffer set_input = {
1361 		sizeof(struct wmid3_gds_set_input_param),
1362 		&set_params
1363 	};
1364 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1365 	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1366 
1367 	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &get_input, &output);
1368 	if (ACPI_FAILURE(status))
1369 		return status;
1370 
1371 	obj = output.pointer;
1372 
1373 	if (!obj)
1374 		return AE_ERROR;
1375 	else if (obj->type != ACPI_TYPE_BUFFER) {
1376 		kfree(obj);
1377 		return AE_ERROR;
1378 	}
1379 	if (obj->buffer.length != 8) {
1380 		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1381 		kfree(obj);
1382 		return AE_ERROR;
1383 	}
1384 
1385 	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1386 	kfree(obj);
1387 
1388 	if (return_value.error_code || return_value.ec_return_value) {
1389 		pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",
1390 			return_value.error_code,
1391 			return_value.ec_return_value);
1392 		return status;
1393 	}
1394 
1395 	devices = return_value.devices;
1396 	set_params.devices = (value) ? (devices | device) : (devices & ~device);
1397 
1398 	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &set_input, &output2);
1399 	if (ACPI_FAILURE(status))
1400 		return status;
1401 
1402 	obj = output2.pointer;
1403 
1404 	if (!obj)
1405 		return AE_ERROR;
1406 	else if (obj->type != ACPI_TYPE_BUFFER) {
1407 		kfree(obj);
1408 		return AE_ERROR;
1409 	}
1410 	if (obj->buffer.length != 4) {
1411 		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1412 		kfree(obj);
1413 		return AE_ERROR;
1414 	}
1415 
1416 	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1417 	kfree(obj);
1418 
1419 	if (return_value.error_code || return_value.ec_return_value)
1420 		pr_warn("Set Device Status failed: 0x%x - 0x%x\n",
1421 			return_value.error_code,
1422 			return_value.ec_return_value);
1423 
1424 	return status;
1425 }
1426 
wmid_v2_set_u32(u32 value,u32 cap)1427 static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1428 {
1429 	u16 device;
1430 
1431 	switch (cap) {
1432 	case ACER_CAP_WIRELESS:
1433 		device = ACER_WMID3_GDS_WIRELESS;
1434 		break;
1435 	case ACER_CAP_BLUETOOTH:
1436 		device = ACER_WMID3_GDS_BLUETOOTH;
1437 		break;
1438 	case ACER_CAP_THREEG:
1439 		device = ACER_WMID3_GDS_THREEG;
1440 		break;
1441 	default:
1442 		return AE_ERROR;
1443 	}
1444 	return wmid3_set_device_status(value, device);
1445 }
1446 
type_aa_dmi_decode(const struct dmi_header * header,void * d)1447 static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)
1448 {
1449 	struct hotkey_function_type_aa *type_aa;
1450 
1451 	/* We are looking for OEM-specific Type AAh */
1452 	if (header->type != 0xAA)
1453 		return;
1454 
1455 	has_type_aa = true;
1456 	type_aa = (struct hotkey_function_type_aa *) header;
1457 
1458 	pr_info("Function bitmap for Communication Button: 0x%x\n",
1459 		type_aa->commun_func_bitmap);
1460 	commun_func_bitmap = type_aa->commun_func_bitmap;
1461 
1462 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
1463 		interface->capability |= ACER_CAP_WIRELESS;
1464 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
1465 		interface->capability |= ACER_CAP_THREEG;
1466 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
1467 		interface->capability |= ACER_CAP_BLUETOOTH;
1468 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN)
1469 		commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN;
1470 
1471 	commun_fn_key_number = type_aa->commun_fn_key_number;
1472 }
1473 
WMID_set_capabilities(void)1474 static acpi_status __init WMID_set_capabilities(void)
1475 {
1476 	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1477 	union acpi_object *obj;
1478 	acpi_status status;
1479 	u32 devices;
1480 
1481 	status = wmi_query_block(WMID_GUID2, 0, &out);
1482 	if (ACPI_FAILURE(status))
1483 		return status;
1484 
1485 	obj = (union acpi_object *) out.pointer;
1486 	if (obj) {
1487 		if (obj->type == ACPI_TYPE_BUFFER &&
1488 			(obj->buffer.length == sizeof(u32) ||
1489 			obj->buffer.length == sizeof(u64))) {
1490 			devices = *((u32 *) obj->buffer.pointer);
1491 		} else if (obj->type == ACPI_TYPE_INTEGER) {
1492 			devices = (u32) obj->integer.value;
1493 		} else {
1494 			kfree(out.pointer);
1495 			return AE_ERROR;
1496 		}
1497 	} else {
1498 		kfree(out.pointer);
1499 		return AE_ERROR;
1500 	}
1501 
1502 	pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
1503 	if (devices & 0x07)
1504 		interface->capability |= ACER_CAP_WIRELESS;
1505 	if (devices & 0x40)
1506 		interface->capability |= ACER_CAP_THREEG;
1507 	if (devices & 0x10)
1508 		interface->capability |= ACER_CAP_BLUETOOTH;
1509 
1510 	if (!(devices & 0x20))
1511 		max_brightness = 0x9;
1512 
1513 	kfree(out.pointer);
1514 	return status;
1515 }
1516 
1517 static struct wmi_interface wmid_interface = {
1518 	.type = ACER_WMID,
1519 };
1520 
1521 static struct wmi_interface wmid_v2_interface = {
1522 	.type = ACER_WMID_v2,
1523 };
1524 
1525 /*
1526  * WMID Gaming interface
1527  */
1528 
1529 static acpi_status
WMI_gaming_execute_u64(u32 method_id,u64 in,u64 * out)1530 WMI_gaming_execute_u64(u32 method_id, u64 in, u64 *out)
1531 {
1532 	struct acpi_buffer input = { (acpi_size) sizeof(u64), (void *)(&in) };
1533 	struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
1534 	union acpi_object *obj;
1535 	u64 tmp = 0;
1536 	acpi_status status;
1537 
1538 	status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result);
1539 
1540 	if (ACPI_FAILURE(status))
1541 		return status;
1542 	obj = (union acpi_object *) result.pointer;
1543 
1544 	if (obj) {
1545 		if (obj->type == ACPI_TYPE_BUFFER) {
1546 			if (obj->buffer.length == sizeof(u32))
1547 				tmp = *((u32 *) obj->buffer.pointer);
1548 			else if (obj->buffer.length == sizeof(u64))
1549 				tmp = *((u64 *) obj->buffer.pointer);
1550 		} else if (obj->type == ACPI_TYPE_INTEGER) {
1551 			tmp = (u64) obj->integer.value;
1552 		}
1553 	}
1554 
1555 	if (out)
1556 		*out = tmp;
1557 
1558 	kfree(result.pointer);
1559 
1560 	return status;
1561 }
1562 
WMI_gaming_execute_u32_u64(u32 method_id,u32 in,u64 * out)1563 static int WMI_gaming_execute_u32_u64(u32 method_id, u32 in, u64 *out)
1564 {
1565 	struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
1566 	struct acpi_buffer input = {
1567 		.length = sizeof(in),
1568 		.pointer = &in,
1569 	};
1570 	union acpi_object *obj;
1571 	acpi_status status;
1572 	int ret = 0;
1573 
1574 	status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result);
1575 	if (ACPI_FAILURE(status))
1576 		return -EIO;
1577 
1578 	obj = result.pointer;
1579 	if (obj && out) {
1580 		switch (obj->type) {
1581 		case ACPI_TYPE_INTEGER:
1582 			*out = obj->integer.value;
1583 			break;
1584 		case ACPI_TYPE_BUFFER:
1585 			if (obj->buffer.length < sizeof(*out))
1586 				ret = -ENOMSG;
1587 			else
1588 				*out = get_unaligned_le64(obj->buffer.pointer);
1589 
1590 			break;
1591 		default:
1592 			ret = -ENOMSG;
1593 			break;
1594 		}
1595 	}
1596 
1597 	kfree(obj);
1598 
1599 	return ret;
1600 }
1601 
WMID_gaming_set_u64(u64 value,u32 cap)1602 static acpi_status WMID_gaming_set_u64(u64 value, u32 cap)
1603 {
1604 	u32 method_id = 0;
1605 
1606 	if (!(interface->capability & cap))
1607 		return AE_BAD_PARAMETER;
1608 
1609 	switch (cap) {
1610 	case ACER_CAP_TURBO_LED:
1611 		method_id = ACER_WMID_SET_GAMING_LED_METHODID;
1612 		break;
1613 	default:
1614 		return AE_BAD_PARAMETER;
1615 	}
1616 
1617 	return WMI_gaming_execute_u64(method_id, value, NULL);
1618 }
1619 
WMID_gaming_get_u64(u64 * value,u32 cap)1620 static acpi_status WMID_gaming_get_u64(u64 *value, u32 cap)
1621 {
1622 	acpi_status status;
1623 	u64 result;
1624 	u64 input;
1625 	u32 method_id;
1626 
1627 	if (!(interface->capability & cap))
1628 		return AE_BAD_PARAMETER;
1629 
1630 	switch (cap) {
1631 	case ACER_CAP_TURBO_LED:
1632 		method_id = ACER_WMID_GET_GAMING_LED_METHODID;
1633 		input = 0x1;
1634 		break;
1635 	default:
1636 		return AE_BAD_PARAMETER;
1637 	}
1638 	status = WMI_gaming_execute_u64(method_id, input, &result);
1639 	if (ACPI_SUCCESS(status))
1640 		*value = (u64) result;
1641 
1642 	return status;
1643 }
1644 
WMID_gaming_get_sys_info(u32 command,u64 * out)1645 static int WMID_gaming_get_sys_info(u32 command, u64 *out)
1646 {
1647 	acpi_status status;
1648 	u64 result;
1649 
1650 	status = WMI_gaming_execute_u64(ACER_WMID_GET_GAMING_SYS_INFO_METHODID, command, &result);
1651 	if (ACPI_FAILURE(status))
1652 		return -EIO;
1653 
1654 	/* The return status must be zero for the operation to have succeeded */
1655 	if (FIELD_GET(ACER_PREDATOR_V4_RETURN_STATUS_BIT_MASK, result))
1656 		return -EIO;
1657 
1658 	*out = result;
1659 
1660 	return 0;
1661 }
1662 
WMID_gaming_set_fan_behavior(u16 fan_bitmap,enum acer_wmi_gaming_fan_mode mode)1663 static int WMID_gaming_set_fan_behavior(u16 fan_bitmap, enum acer_wmi_gaming_fan_mode mode)
1664 {
1665 	acpi_status status;
1666 	u64 input = 0;
1667 	u64 result;
1668 
1669 	input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_ID_MASK, fan_bitmap);
1670 
1671 	if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_CPU)
1672 		input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_SET_CPU_MODE_MASK, mode);
1673 
1674 	if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_GPU)
1675 		input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_SET_GPU_MODE_MASK, mode);
1676 
1677 	status = WMI_gaming_execute_u64(ACER_WMID_SET_GAMING_FAN_BEHAVIOR_METHODID, input,
1678 					&result);
1679 	if (ACPI_FAILURE(status))
1680 		return -EIO;
1681 
1682 	/* The return status must be zero for the operation to have succeeded */
1683 	if (FIELD_GET(ACER_GAMING_FAN_BEHAVIOR_STATUS_MASK, result))
1684 		return -EIO;
1685 
1686 	return 0;
1687 }
1688 
WMID_gaming_get_fan_behavior(u16 fan_bitmap,enum acer_wmi_gaming_fan_mode * mode)1689 static int WMID_gaming_get_fan_behavior(u16 fan_bitmap, enum acer_wmi_gaming_fan_mode *mode)
1690 {
1691 	acpi_status status;
1692 	u32 input = 0;
1693 	u64 result;
1694 	int value;
1695 
1696 	input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_ID_MASK, fan_bitmap);
1697 	status = WMI_gaming_execute_u32_u64(ACER_WMID_GET_GAMING_FAN_BEHAVIOR_METHODID, input,
1698 					    &result);
1699 	if (ACPI_FAILURE(status))
1700 		return -EIO;
1701 
1702 	/* The return status must be zero for the operation to have succeeded */
1703 	if (FIELD_GET(ACER_GAMING_FAN_BEHAVIOR_STATUS_MASK, result))
1704 		return -EIO;
1705 
1706 	/* Theoretically multiple fans can be specified, but this is currently unused */
1707 	if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_CPU)
1708 		value = FIELD_GET(ACER_GAMING_FAN_BEHAVIOR_GET_CPU_MODE_MASK, result);
1709 	else if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_GPU)
1710 		value = FIELD_GET(ACER_GAMING_FAN_BEHAVIOR_GET_GPU_MODE_MASK, result);
1711 	else
1712 		return -EINVAL;
1713 
1714 	if (value < ACER_WMID_FAN_MODE_AUTO || value > ACER_WMID_FAN_MODE_CUSTOM)
1715 		return -ENXIO;
1716 
1717 	*mode = value;
1718 
1719 	return 0;
1720 }
1721 
WMID_gaming_set_fan_mode(enum acer_wmi_gaming_fan_mode mode)1722 static void WMID_gaming_set_fan_mode(enum acer_wmi_gaming_fan_mode mode)
1723 {
1724 	u16 fan_bitmap = 0;
1725 
1726 	if (quirks->cpu_fans > 0)
1727 		fan_bitmap |= ACER_GAMING_FAN_BEHAVIOR_CPU;
1728 
1729 	if (quirks->gpu_fans > 0)
1730 		fan_bitmap |= ACER_GAMING_FAN_BEHAVIOR_GPU;
1731 
1732 	WMID_gaming_set_fan_behavior(fan_bitmap, mode);
1733 }
1734 
WMID_gaming_set_gaming_fan_speed(u8 fan,u8 speed)1735 static int WMID_gaming_set_gaming_fan_speed(u8 fan, u8 speed)
1736 {
1737 	acpi_status status;
1738 	u64 input = 0;
1739 	u64 result;
1740 
1741 	if (speed > 100)
1742 		return -EINVAL;
1743 
1744 	input |= FIELD_PREP(ACER_GAMING_FAN_SPEED_ID_MASK, fan);
1745 	input |= FIELD_PREP(ACER_GAMING_FAN_SPEED_VALUE_MASK, speed);
1746 
1747 	status = WMI_gaming_execute_u64(ACER_WMID_SET_GAMING_FAN_SPEED_METHODID, input, &result);
1748 	if (ACPI_FAILURE(status))
1749 		return -EIO;
1750 
1751 	switch (FIELD_GET(ACER_GAMING_FAN_SPEED_STATUS_MASK, result)) {
1752 	case 0x00:
1753 		return 0;
1754 	case 0x01:
1755 		return -ENODEV;
1756 	case 0x02:
1757 		return -EINVAL;
1758 	default:
1759 		return -ENXIO;
1760 	}
1761 }
1762 
WMID_gaming_get_gaming_fan_speed(u8 fan,u8 * speed)1763 static int WMID_gaming_get_gaming_fan_speed(u8 fan, u8 *speed)
1764 {
1765 	acpi_status status;
1766 	u32 input = 0;
1767 	u64 result;
1768 
1769 	input |= FIELD_PREP(ACER_GAMING_FAN_SPEED_ID_MASK, fan);
1770 
1771 	status = WMI_gaming_execute_u32_u64(ACER_WMID_GET_GAMING_FAN_SPEED_METHODID, input,
1772 					    &result);
1773 	if (ACPI_FAILURE(status))
1774 		return -EIO;
1775 
1776 	if (FIELD_GET(ACER_GAMING_FAN_SPEED_STATUS_MASK, result))
1777 		return -ENODEV;
1778 
1779 	*speed = FIELD_GET(ACER_GAMING_FAN_SPEED_VALUE_MASK, result);
1780 
1781 	return 0;
1782 }
1783 
WMID_gaming_set_misc_setting(enum acer_wmi_gaming_misc_setting setting,u8 value)1784 static int WMID_gaming_set_misc_setting(enum acer_wmi_gaming_misc_setting setting, u8 value)
1785 {
1786 	acpi_status status;
1787 	u64 input = 0;
1788 	u64 result;
1789 
1790 	input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_INDEX_MASK, setting);
1791 	input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_VALUE_MASK, value);
1792 
1793 	status = WMI_gaming_execute_u64(ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, input, &result);
1794 	if (ACPI_FAILURE(status))
1795 		return -EIO;
1796 
1797 	/* The return status must be zero for the operation to have succeeded */
1798 	if (FIELD_GET(ACER_GAMING_MISC_SETTING_STATUS_MASK, result))
1799 		return -EIO;
1800 
1801 	return 0;
1802 }
1803 
WMID_gaming_get_misc_setting(enum acer_wmi_gaming_misc_setting setting,u8 * value)1804 static int WMID_gaming_get_misc_setting(enum acer_wmi_gaming_misc_setting setting, u8 *value)
1805 {
1806 	u64 input = 0;
1807 	u64 result;
1808 	int ret;
1809 
1810 	input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_INDEX_MASK, setting);
1811 
1812 	ret = WMI_gaming_execute_u32_u64(ACER_WMID_GET_GAMING_MISC_SETTING_METHODID, input,
1813 					 &result);
1814 	if (ret < 0)
1815 		return ret;
1816 
1817 	/* The return status must be zero for the operation to have succeeded */
1818 	if (FIELD_GET(ACER_GAMING_MISC_SETTING_STATUS_MASK, result))
1819 		return -EIO;
1820 
1821 	*value = FIELD_GET(ACER_GAMING_MISC_SETTING_VALUE_MASK, result);
1822 
1823 	return 0;
1824 }
1825 
1826 /*
1827  * Generic Device (interface-independent)
1828  */
1829 
get_u32(u32 * value,u32 cap)1830 static acpi_status get_u32(u32 *value, u32 cap)
1831 {
1832 	acpi_status status = AE_ERROR;
1833 
1834 	switch (interface->type) {
1835 	case ACER_AMW0:
1836 		status = AMW0_get_u32(value, cap);
1837 		break;
1838 	case ACER_AMW0_V2:
1839 		if (cap == ACER_CAP_MAILLED) {
1840 			status = AMW0_get_u32(value, cap);
1841 			break;
1842 		}
1843 		fallthrough;
1844 	case ACER_WMID:
1845 		status = WMID_get_u32(value, cap);
1846 		break;
1847 	case ACER_WMID_v2:
1848 		if (cap & (ACER_CAP_WIRELESS |
1849 			   ACER_CAP_BLUETOOTH |
1850 			   ACER_CAP_THREEG))
1851 			status = wmid_v2_get_u32(value, cap);
1852 		else if (wmi_has_guid(WMID_GUID2))
1853 			status = WMID_get_u32(value, cap);
1854 		break;
1855 	}
1856 
1857 	return status;
1858 }
1859 
set_u32(u32 value,u32 cap)1860 static acpi_status set_u32(u32 value, u32 cap)
1861 {
1862 	acpi_status status;
1863 
1864 	if (interface->capability & cap) {
1865 		switch (interface->type) {
1866 		case ACER_AMW0:
1867 			return AMW0_set_u32(value, cap);
1868 		case ACER_AMW0_V2:
1869 			if (cap == ACER_CAP_MAILLED)
1870 				return AMW0_set_u32(value, cap);
1871 
1872 			/*
1873 			 * On some models, some WMID methods don't toggle
1874 			 * properly. For those cases, we want to run the AMW0
1875 			 * method afterwards to be certain we've really toggled
1876 			 * the device state.
1877 			 */
1878 			if (cap == ACER_CAP_WIRELESS ||
1879 				cap == ACER_CAP_BLUETOOTH) {
1880 				status = WMID_set_u32(value, cap);
1881 				if (ACPI_FAILURE(status))
1882 					return status;
1883 
1884 				return AMW0_set_u32(value, cap);
1885 			}
1886 			fallthrough;
1887 		case ACER_WMID:
1888 			return WMID_set_u32(value, cap);
1889 		case ACER_WMID_v2:
1890 			if (cap & (ACER_CAP_WIRELESS |
1891 				   ACER_CAP_BLUETOOTH |
1892 				   ACER_CAP_THREEG))
1893 				return wmid_v2_set_u32(value, cap);
1894 			else if (wmi_has_guid(WMID_GUID2))
1895 				return WMID_set_u32(value, cap);
1896 			fallthrough;
1897 		default:
1898 			return AE_BAD_PARAMETER;
1899 		}
1900 	}
1901 	return AE_BAD_PARAMETER;
1902 }
1903 
acer_commandline_init(void)1904 static void __init acer_commandline_init(void)
1905 {
1906 	/*
1907 	 * These will all fail silently if the value given is invalid, or the
1908 	 * capability isn't available on the given interface
1909 	 */
1910 	if (mailled >= 0)
1911 		set_u32(mailled, ACER_CAP_MAILLED);
1912 	if (!has_type_aa && threeg >= 0)
1913 		set_u32(threeg, ACER_CAP_THREEG);
1914 	if (brightness >= 0)
1915 		set_u32(brightness, ACER_CAP_BRIGHTNESS);
1916 }
1917 
1918 /*
1919  * LED device (Mail LED only, no other LEDs known yet)
1920  */
mail_led_set(struct led_classdev * led_cdev,enum led_brightness value)1921 static void mail_led_set(struct led_classdev *led_cdev,
1922 enum led_brightness value)
1923 {
1924 	set_u32(value, ACER_CAP_MAILLED);
1925 }
1926 
1927 static struct led_classdev mail_led = {
1928 	.name = "acer-wmi::mail",
1929 	.brightness_set = mail_led_set,
1930 };
1931 
acer_led_init(struct device * dev)1932 static int acer_led_init(struct device *dev)
1933 {
1934 	return led_classdev_register(dev, &mail_led);
1935 }
1936 
acer_led_exit(void)1937 static void acer_led_exit(void)
1938 {
1939 	set_u32(LED_OFF, ACER_CAP_MAILLED);
1940 	led_classdev_unregister(&mail_led);
1941 }
1942 
1943 /*
1944  * Backlight device
1945  */
1946 static struct backlight_device *acer_backlight_device;
1947 
read_brightness(struct backlight_device * bd)1948 static int read_brightness(struct backlight_device *bd)
1949 {
1950 	u32 value;
1951 	get_u32(&value, ACER_CAP_BRIGHTNESS);
1952 	return value;
1953 }
1954 
update_bl_status(struct backlight_device * bd)1955 static int update_bl_status(struct backlight_device *bd)
1956 {
1957 	int intensity = backlight_get_brightness(bd);
1958 
1959 	set_u32(intensity, ACER_CAP_BRIGHTNESS);
1960 
1961 	return 0;
1962 }
1963 
1964 static const struct backlight_ops acer_bl_ops = {
1965 	.get_brightness = read_brightness,
1966 	.update_status = update_bl_status,
1967 };
1968 
acer_backlight_init(struct device * dev)1969 static int acer_backlight_init(struct device *dev)
1970 {
1971 	struct backlight_properties props;
1972 	struct backlight_device *bd;
1973 
1974 	memset(&props, 0, sizeof(struct backlight_properties));
1975 	props.type = BACKLIGHT_PLATFORM;
1976 	props.max_brightness = max_brightness;
1977 	bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
1978 				       &props);
1979 	if (IS_ERR(bd)) {
1980 		pr_err("Could not register Acer backlight device\n");
1981 		acer_backlight_device = NULL;
1982 		return PTR_ERR(bd);
1983 	}
1984 
1985 	acer_backlight_device = bd;
1986 
1987 	bd->props.power = BACKLIGHT_POWER_ON;
1988 	bd->props.brightness = read_brightness(bd);
1989 	backlight_update_status(bd);
1990 	return 0;
1991 }
1992 
acer_backlight_exit(void)1993 static void acer_backlight_exit(void)
1994 {
1995 	backlight_device_unregister(acer_backlight_device);
1996 }
1997 
1998 /*
1999  * Accelerometer device
2000  */
2001 static acpi_handle gsensor_handle;
2002 
acer_gsensor_init(void)2003 static int acer_gsensor_init(void)
2004 {
2005 	acpi_status status;
2006 	struct acpi_buffer output;
2007 	union acpi_object out_obj;
2008 
2009 	output.length = sizeof(out_obj);
2010 	output.pointer = &out_obj;
2011 	status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output);
2012 	if (ACPI_FAILURE(status))
2013 		return -1;
2014 
2015 	return 0;
2016 }
2017 
acer_gsensor_open(struct input_dev * input)2018 static int acer_gsensor_open(struct input_dev *input)
2019 {
2020 	return acer_gsensor_init();
2021 }
2022 
acer_gsensor_event(void)2023 static int acer_gsensor_event(void)
2024 {
2025 	acpi_status status;
2026 	struct acpi_buffer output;
2027 	union acpi_object out_obj[5];
2028 
2029 	if (!acer_wmi_accel_dev)
2030 		return -1;
2031 
2032 	output.length = sizeof(out_obj);
2033 	output.pointer = out_obj;
2034 
2035 	status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output);
2036 	if (ACPI_FAILURE(status))
2037 		return -1;
2038 
2039 	if (out_obj->package.count != 4)
2040 		return -1;
2041 
2042 	input_report_abs(acer_wmi_accel_dev, ABS_X,
2043 		(s16)out_obj->package.elements[0].integer.value);
2044 	input_report_abs(acer_wmi_accel_dev, ABS_Y,
2045 		(s16)out_obj->package.elements[1].integer.value);
2046 	input_report_abs(acer_wmi_accel_dev, ABS_Z,
2047 		(s16)out_obj->package.elements[2].integer.value);
2048 	input_sync(acer_wmi_accel_dev);
2049 	return 0;
2050 }
2051 
2052 /*
2053  *  Predator series turbo button
2054  */
acer_toggle_turbo(void)2055 static int acer_toggle_turbo(void)
2056 {
2057 	u64 turbo_led_state;
2058 
2059 	/* Get current state from turbo button */
2060 	if (ACPI_FAILURE(WMID_gaming_get_u64(&turbo_led_state, ACER_CAP_TURBO_LED)))
2061 		return -1;
2062 
2063 	if (turbo_led_state) {
2064 		/* Turn off turbo led */
2065 		WMID_gaming_set_u64(0x1, ACER_CAP_TURBO_LED);
2066 
2067 		/* Set FAN mode to auto */
2068 		WMID_gaming_set_fan_mode(ACER_WMID_FAN_MODE_AUTO);
2069 
2070 		/* Set OC to normal */
2071 		if (has_cap(ACER_CAP_TURBO_OC)) {
2072 			WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_1,
2073 						     ACER_WMID_OC_NORMAL);
2074 			WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_2,
2075 						     ACER_WMID_OC_NORMAL);
2076 		}
2077 	} else {
2078 		/* Turn on turbo led */
2079 		WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED);
2080 
2081 		/* Set FAN mode to turbo */
2082 		WMID_gaming_set_fan_mode(ACER_WMID_FAN_MODE_TURBO);
2083 
2084 		/* Set OC to turbo mode */
2085 		if (has_cap(ACER_CAP_TURBO_OC)) {
2086 			WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_1,
2087 						     ACER_WMID_OC_TURBO);
2088 			WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_2,
2089 						     ACER_WMID_OC_TURBO);
2090 		}
2091 	}
2092 	return turbo_led_state;
2093 }
2094 
2095 static int
acer_predator_v4_platform_profile_get(struct device * dev,enum platform_profile_option * profile)2096 acer_predator_v4_platform_profile_get(struct device *dev,
2097 				      enum platform_profile_option *profile)
2098 {
2099 	u8 tp;
2100 	int err;
2101 
2102 	err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, &tp);
2103 	if (err)
2104 		return err;
2105 
2106 	switch (tp) {
2107 	case ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO:
2108 		*profile = PLATFORM_PROFILE_PERFORMANCE;
2109 		break;
2110 	case ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE:
2111 		*profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
2112 		break;
2113 	case ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED:
2114 		*profile = PLATFORM_PROFILE_BALANCED;
2115 		break;
2116 	case ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET:
2117 		*profile = PLATFORM_PROFILE_QUIET;
2118 		break;
2119 	case ACER_PREDATOR_V4_THERMAL_PROFILE_ECO:
2120 		*profile = PLATFORM_PROFILE_LOW_POWER;
2121 		break;
2122 	default:
2123 		return -EOPNOTSUPP;
2124 	}
2125 
2126 	return 0;
2127 }
2128 
2129 static int
acer_predator_v4_platform_profile_set(struct device * dev,enum platform_profile_option profile)2130 acer_predator_v4_platform_profile_set(struct device *dev,
2131 				      enum platform_profile_option profile)
2132 {
2133 	int err, tp;
2134 
2135 	switch (profile) {
2136 	case PLATFORM_PROFILE_PERFORMANCE:
2137 		tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO;
2138 		break;
2139 	case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
2140 		tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE;
2141 		break;
2142 	case PLATFORM_PROFILE_BALANCED:
2143 		tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED;
2144 		break;
2145 	case PLATFORM_PROFILE_QUIET:
2146 		tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET;
2147 		break;
2148 	case PLATFORM_PROFILE_LOW_POWER:
2149 		tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO;
2150 		break;
2151 	default:
2152 		return -EOPNOTSUPP;
2153 	}
2154 
2155 	err = WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, tp);
2156 	if (err)
2157 		return err;
2158 
2159 	if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO)
2160 		last_non_turbo_profile = tp;
2161 
2162 	return 0;
2163 }
2164 
2165 static int
acer_predator_v4_platform_profile_probe(void * drvdata,unsigned long * choices)2166 acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices)
2167 {
2168 	set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
2169 	set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
2170 	set_bit(PLATFORM_PROFILE_BALANCED, choices);
2171 	set_bit(PLATFORM_PROFILE_QUIET, choices);
2172 	set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
2173 
2174 	/* Set default non-turbo profile */
2175 	last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED;
2176 
2177 	return 0;
2178 }
2179 
2180 static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
2181 	.probe = acer_predator_v4_platform_profile_probe,
2182 	.profile_get = acer_predator_v4_platform_profile_get,
2183 	.profile_set = acer_predator_v4_platform_profile_set,
2184 };
2185 
acer_platform_profile_setup(struct platform_device * device)2186 static int acer_platform_profile_setup(struct platform_device *device)
2187 {
2188 	if (quirks->predator_v4) {
2189 		platform_profile_device = devm_platform_profile_register(
2190 			&device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
2191 		if (IS_ERR(platform_profile_device))
2192 			return PTR_ERR(platform_profile_device);
2193 
2194 		platform_profile_support = true;
2195 	}
2196 	return 0;
2197 }
2198 
acer_thermal_profile_change(void)2199 static int acer_thermal_profile_change(void)
2200 {
2201 	/*
2202 	 * This mode key will either cycle through each mode or toggle the
2203 	 * most performant profile.
2204 	 */
2205 	if (quirks->predator_v4) {
2206 		u8 current_tp;
2207 		int err, tp;
2208 
2209 		if (cycle_gaming_thermal_profile) {
2210 			platform_profile_cycle();
2211 		} else {
2212 			err = WMID_gaming_get_misc_setting(
2213 				ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, &current_tp);
2214 			if (err)
2215 				return err;
2216 
2217 			if (current_tp == ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO)
2218 				tp = last_non_turbo_profile;
2219 			else
2220 				tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO;
2221 
2222 			err = WMID_gaming_set_misc_setting(
2223 				ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, tp);
2224 			if (err)
2225 				return err;
2226 
2227 			/* Store last profile for toggle */
2228 			if (current_tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO)
2229 				last_non_turbo_profile = current_tp;
2230 
2231 			platform_profile_notify(platform_profile_device);
2232 		}
2233 	}
2234 
2235 	return 0;
2236 }
2237 
2238 /*
2239  * Switch series keyboard dock status
2240  */
acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)2241 static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)
2242 {
2243 	switch (kbd_dock_state) {
2244 	case 0x01: /* Docked, traditional clamshell laptop mode */
2245 		return 0;
2246 	case 0x04: /* Stand-alone tablet */
2247 	case 0x40: /* Docked, tent mode, keyboard not usable */
2248 		return 1;
2249 	default:
2250 		pr_warn("Unknown kbd_dock_state 0x%02x\n", kbd_dock_state);
2251 	}
2252 
2253 	return 0;
2254 }
2255 
acer_kbd_dock_get_initial_state(void)2256 static void acer_kbd_dock_get_initial_state(void)
2257 {
2258 	u8 *output, input[8] = { 0x05, 0x00, };
2259 	struct acpi_buffer input_buf = { sizeof(input), input };
2260 	struct acpi_buffer output_buf = { ACPI_ALLOCATE_BUFFER, NULL };
2261 	union acpi_object *obj;
2262 	acpi_status status;
2263 	int sw_tablet_mode;
2264 
2265 	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);
2266 	if (ACPI_FAILURE(status)) {
2267 		pr_err("Error getting keyboard-dock initial status: %s\n",
2268 		       acpi_format_exception(status));
2269 		return;
2270 	}
2271 
2272 	obj = output_buf.pointer;
2273 	if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
2274 		pr_err("Unexpected output format getting keyboard-dock initial status\n");
2275 		goto out_free_obj;
2276 	}
2277 
2278 	output = obj->buffer.pointer;
2279 	if (output[0] != 0x00 || (output[3] != 0x05 && output[3] != 0x45)) {
2280 		pr_err("Unexpected output [0]=0x%02x [3]=0x%02x getting keyboard-dock initial status\n",
2281 		       output[0], output[3]);
2282 		goto out_free_obj;
2283 	}
2284 
2285 	sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(output[4]);
2286 	input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
2287 
2288 out_free_obj:
2289 	kfree(obj);
2290 }
2291 
acer_kbd_dock_event(const struct event_return_value * event)2292 static void acer_kbd_dock_event(const struct event_return_value *event)
2293 {
2294 	int sw_tablet_mode;
2295 
2296 	if (!has_cap(ACER_CAP_KBD_DOCK))
2297 		return;
2298 
2299 	sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(event->kbd_dock_state);
2300 	input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
2301 	input_sync(acer_wmi_input_dev);
2302 }
2303 
2304 /*
2305  * Rfkill devices
2306  */
2307 static void acer_rfkill_update(struct work_struct *ignored);
2308 static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
acer_rfkill_update(struct work_struct * ignored)2309 static void acer_rfkill_update(struct work_struct *ignored)
2310 {
2311 	u32 state;
2312 	acpi_status status;
2313 
2314 	if (has_cap(ACER_CAP_WIRELESS)) {
2315 		status = get_u32(&state, ACER_CAP_WIRELESS);
2316 		if (ACPI_SUCCESS(status)) {
2317 			if (quirks->wireless == 3)
2318 				rfkill_set_hw_state(wireless_rfkill, !state);
2319 			else
2320 				rfkill_set_sw_state(wireless_rfkill, !state);
2321 		}
2322 	}
2323 
2324 	if (has_cap(ACER_CAP_BLUETOOTH)) {
2325 		status = get_u32(&state, ACER_CAP_BLUETOOTH);
2326 		if (ACPI_SUCCESS(status))
2327 			rfkill_set_sw_state(bluetooth_rfkill, !state);
2328 	}
2329 
2330 	if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
2331 		status = get_u32(&state, ACER_WMID3_GDS_THREEG);
2332 		if (ACPI_SUCCESS(status))
2333 			rfkill_set_sw_state(threeg_rfkill, !state);
2334 	}
2335 
2336 	schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
2337 }
2338 
acer_rfkill_set(void * data,bool blocked)2339 static int acer_rfkill_set(void *data, bool blocked)
2340 {
2341 	acpi_status status;
2342 	u32 cap = (unsigned long)data;
2343 
2344 	if (rfkill_inited) {
2345 		status = set_u32(!blocked, cap);
2346 		if (ACPI_FAILURE(status))
2347 			return -ENODEV;
2348 	}
2349 
2350 	return 0;
2351 }
2352 
2353 static const struct rfkill_ops acer_rfkill_ops = {
2354 	.set_block = acer_rfkill_set,
2355 };
2356 
acer_rfkill_register(struct device * dev,enum rfkill_type type,char * name,u32 cap)2357 static struct rfkill *acer_rfkill_register(struct device *dev,
2358 					   enum rfkill_type type,
2359 					   char *name, u32 cap)
2360 {
2361 	int err;
2362 	struct rfkill *rfkill_dev;
2363 	u32 state;
2364 	acpi_status status;
2365 
2366 	rfkill_dev = rfkill_alloc(name, dev, type,
2367 				  &acer_rfkill_ops,
2368 				  (void *)(unsigned long)cap);
2369 	if (!rfkill_dev)
2370 		return ERR_PTR(-ENOMEM);
2371 
2372 	status = get_u32(&state, cap);
2373 
2374 	err = rfkill_register(rfkill_dev);
2375 	if (err) {
2376 		rfkill_destroy(rfkill_dev);
2377 		return ERR_PTR(err);
2378 	}
2379 
2380 	if (ACPI_SUCCESS(status))
2381 		rfkill_set_sw_state(rfkill_dev, !state);
2382 
2383 	return rfkill_dev;
2384 }
2385 
acer_rfkill_init(struct device * dev)2386 static int acer_rfkill_init(struct device *dev)
2387 {
2388 	int err;
2389 
2390 	if (has_cap(ACER_CAP_WIRELESS)) {
2391 		wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
2392 			"acer-wireless", ACER_CAP_WIRELESS);
2393 		if (IS_ERR(wireless_rfkill)) {
2394 			err = PTR_ERR(wireless_rfkill);
2395 			goto error_wireless;
2396 		}
2397 	}
2398 
2399 	if (has_cap(ACER_CAP_BLUETOOTH)) {
2400 		bluetooth_rfkill = acer_rfkill_register(dev,
2401 			RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
2402 			ACER_CAP_BLUETOOTH);
2403 		if (IS_ERR(bluetooth_rfkill)) {
2404 			err = PTR_ERR(bluetooth_rfkill);
2405 			goto error_bluetooth;
2406 		}
2407 	}
2408 
2409 	if (has_cap(ACER_CAP_THREEG)) {
2410 		threeg_rfkill = acer_rfkill_register(dev,
2411 			RFKILL_TYPE_WWAN, "acer-threeg",
2412 			ACER_CAP_THREEG);
2413 		if (IS_ERR(threeg_rfkill)) {
2414 			err = PTR_ERR(threeg_rfkill);
2415 			goto error_threeg;
2416 		}
2417 	}
2418 
2419 	rfkill_inited = true;
2420 
2421 	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
2422 	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
2423 		schedule_delayed_work(&acer_rfkill_work,
2424 			round_jiffies_relative(HZ));
2425 
2426 	return 0;
2427 
2428 error_threeg:
2429 	if (has_cap(ACER_CAP_BLUETOOTH)) {
2430 		rfkill_unregister(bluetooth_rfkill);
2431 		rfkill_destroy(bluetooth_rfkill);
2432 	}
2433 error_bluetooth:
2434 	if (has_cap(ACER_CAP_WIRELESS)) {
2435 		rfkill_unregister(wireless_rfkill);
2436 		rfkill_destroy(wireless_rfkill);
2437 	}
2438 error_wireless:
2439 	return err;
2440 }
2441 
acer_rfkill_exit(void)2442 static void acer_rfkill_exit(void)
2443 {
2444 	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
2445 	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
2446 		cancel_delayed_work_sync(&acer_rfkill_work);
2447 
2448 	if (has_cap(ACER_CAP_WIRELESS)) {
2449 		rfkill_unregister(wireless_rfkill);
2450 		rfkill_destroy(wireless_rfkill);
2451 	}
2452 
2453 	if (has_cap(ACER_CAP_BLUETOOTH)) {
2454 		rfkill_unregister(bluetooth_rfkill);
2455 		rfkill_destroy(bluetooth_rfkill);
2456 	}
2457 
2458 	if (has_cap(ACER_CAP_THREEG)) {
2459 		rfkill_unregister(threeg_rfkill);
2460 		rfkill_destroy(threeg_rfkill);
2461 	}
2462 }
2463 
acer_wmi_notify(union acpi_object * obj,void * context)2464 static void acer_wmi_notify(union acpi_object *obj, void *context)
2465 {
2466 	struct event_return_value return_value;
2467 	u16 device_state;
2468 	const struct key_entry *key;
2469 	u32 scancode;
2470 
2471 	if (!obj)
2472 		return;
2473 	if (obj->type != ACPI_TYPE_BUFFER) {
2474 		pr_warn("Unknown response received %d\n", obj->type);
2475 		return;
2476 	}
2477 	if (obj->buffer.length != 8) {
2478 		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
2479 		return;
2480 	}
2481 
2482 	return_value = *((struct event_return_value *)obj->buffer.pointer);
2483 
2484 	switch (return_value.function) {
2485 	case WMID_HOTKEY_EVENT:
2486 		device_state = return_value.device_state;
2487 		pr_debug("device state: 0x%x\n", device_state);
2488 
2489 		key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
2490 							return_value.key_num);
2491 		if (!key) {
2492 			pr_warn("Unknown key number - 0x%x\n",
2493 				return_value.key_num);
2494 		} else {
2495 			scancode = return_value.key_num;
2496 			switch (key->keycode) {
2497 			case KEY_WLAN:
2498 			case KEY_BLUETOOTH:
2499 				if (has_cap(ACER_CAP_WIRELESS))
2500 					rfkill_set_sw_state(wireless_rfkill,
2501 						!(device_state & ACER_WMID3_GDS_WIRELESS));
2502 				if (has_cap(ACER_CAP_THREEG))
2503 					rfkill_set_sw_state(threeg_rfkill,
2504 						!(device_state & ACER_WMID3_GDS_THREEG));
2505 				if (has_cap(ACER_CAP_BLUETOOTH))
2506 					rfkill_set_sw_state(bluetooth_rfkill,
2507 						!(device_state & ACER_WMID3_GDS_BLUETOOTH));
2508 				break;
2509 			case KEY_TOUCHPAD_TOGGLE:
2510 				scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ?
2511 						KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF;
2512 			}
2513 			sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
2514 		}
2515 		break;
2516 	case WMID_BACKLIGHT_EVENT:
2517 		/* Already handled by acpi-video */
2518 		break;
2519 	case WMID_ACCEL_OR_KBD_DOCK_EVENT:
2520 		acer_gsensor_event();
2521 		acer_kbd_dock_event(&return_value);
2522 		break;
2523 	case WMID_GAMING_TURBO_KEY_EVENT:
2524 		if (return_value.key_num == 0x4)
2525 			acer_toggle_turbo();
2526 		if (return_value.key_num == 0x5 && has_cap(ACER_CAP_PLATFORM_PROFILE))
2527 			acer_thermal_profile_change();
2528 		break;
2529 	case WMID_AC_EVENT:
2530 		/* We ignore AC events here */
2531 		break;
2532 	default:
2533 		pr_warn("Unknown function number - %d - %d\n",
2534 			return_value.function, return_value.key_num);
2535 		break;
2536 	}
2537 }
2538 
2539 static acpi_status __init
wmid3_set_function_mode(struct func_input_params * params,struct func_return_value * return_value)2540 wmid3_set_function_mode(struct func_input_params *params,
2541 			struct func_return_value *return_value)
2542 {
2543 	acpi_status status;
2544 	union acpi_object *obj;
2545 
2546 	struct acpi_buffer input = { sizeof(struct func_input_params), params };
2547 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
2548 
2549 	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
2550 	if (ACPI_FAILURE(status))
2551 		return status;
2552 
2553 	obj = output.pointer;
2554 
2555 	if (!obj)
2556 		return AE_ERROR;
2557 	else if (obj->type != ACPI_TYPE_BUFFER) {
2558 		kfree(obj);
2559 		return AE_ERROR;
2560 	}
2561 	if (obj->buffer.length != 4) {
2562 		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
2563 		kfree(obj);
2564 		return AE_ERROR;
2565 	}
2566 
2567 	*return_value = *((struct func_return_value *)obj->buffer.pointer);
2568 	kfree(obj);
2569 
2570 	return status;
2571 }
2572 
acer_wmi_enable_ec_raw(void)2573 static int __init acer_wmi_enable_ec_raw(void)
2574 {
2575 	struct func_return_value return_value;
2576 	acpi_status status;
2577 	struct func_input_params params = {
2578 		.function_num = 0x1,
2579 		.commun_devices = 0xFFFF,
2580 		.devices = 0xFFFF,
2581 		.app_status = 0x00,		/* Launch Manager Deactive */
2582 		.app_mask = 0x01,
2583 	};
2584 
2585 	status = wmid3_set_function_mode(&params, &return_value);
2586 
2587 	if (return_value.error_code || return_value.ec_return_value)
2588 		pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
2589 			return_value.error_code,
2590 			return_value.ec_return_value);
2591 	else
2592 		pr_info("Enabled EC raw mode\n");
2593 
2594 	return status;
2595 }
2596 
acer_wmi_enable_lm(void)2597 static int __init acer_wmi_enable_lm(void)
2598 {
2599 	struct func_return_value return_value;
2600 	acpi_status status;
2601 	struct func_input_params params = {
2602 		.function_num = 0x1,
2603 		.commun_devices = 0xFFFF,
2604 		.devices = 0xFFFF,
2605 		.app_status = 0x01,            /* Launch Manager Active */
2606 		.app_mask = 0x01,
2607 	};
2608 
2609 	status = wmid3_set_function_mode(&params, &return_value);
2610 
2611 	if (return_value.error_code || return_value.ec_return_value)
2612 		pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
2613 			return_value.error_code,
2614 			return_value.ec_return_value);
2615 
2616 	return status;
2617 }
2618 
acer_wmi_enable_rf_button(void)2619 static int __init acer_wmi_enable_rf_button(void)
2620 {
2621 	struct func_return_value return_value;
2622 	acpi_status status;
2623 	struct func_input_params params = {
2624 		.function_num = 0x1,
2625 		.commun_devices = 0xFFFF,
2626 		.devices = 0xFFFF,
2627 		.app_status = 0x10,            /* RF Button Active */
2628 		.app_mask = 0x10,
2629 	};
2630 
2631 	status = wmid3_set_function_mode(&params, &return_value);
2632 
2633 	if (return_value.error_code || return_value.ec_return_value)
2634 		pr_warn("Enabling RF Button failed: 0x%x - 0x%x\n",
2635 			return_value.error_code,
2636 			return_value.ec_return_value);
2637 
2638 	return status;
2639 }
2640 
acer_wmi_accel_setup(void)2641 static int __init acer_wmi_accel_setup(void)
2642 {
2643 	struct acpi_device *adev;
2644 	int err;
2645 
2646 	adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1);
2647 	if (!adev)
2648 		return -ENODEV;
2649 
2650 	gsensor_handle = acpi_device_handle(adev);
2651 	acpi_dev_put(adev);
2652 
2653 	acer_wmi_accel_dev = input_allocate_device();
2654 	if (!acer_wmi_accel_dev)
2655 		return -ENOMEM;
2656 
2657 	acer_wmi_accel_dev->open = acer_gsensor_open;
2658 
2659 	acer_wmi_accel_dev->name = "Acer BMA150 accelerometer";
2660 	acer_wmi_accel_dev->phys = "wmi/input1";
2661 	acer_wmi_accel_dev->id.bustype = BUS_HOST;
2662 	acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS);
2663 	input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0);
2664 	input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0);
2665 	input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0);
2666 
2667 	err = input_register_device(acer_wmi_accel_dev);
2668 	if (err)
2669 		goto err_free_dev;
2670 
2671 	return 0;
2672 
2673 err_free_dev:
2674 	input_free_device(acer_wmi_accel_dev);
2675 	return err;
2676 }
2677 
acer_wmi_input_setup(void)2678 static int __init acer_wmi_input_setup(void)
2679 {
2680 	acpi_status status;
2681 	int err;
2682 
2683 	acer_wmi_input_dev = input_allocate_device();
2684 	if (!acer_wmi_input_dev)
2685 		return -ENOMEM;
2686 
2687 	acer_wmi_input_dev->name = "Acer WMI hotkeys";
2688 	acer_wmi_input_dev->phys = "wmi/input0";
2689 	acer_wmi_input_dev->id.bustype = BUS_HOST;
2690 
2691 	err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
2692 	if (err)
2693 		goto err_free_dev;
2694 
2695 	if (has_cap(ACER_CAP_KBD_DOCK))
2696 		input_set_capability(acer_wmi_input_dev, EV_SW, SW_TABLET_MODE);
2697 
2698 	status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
2699 						acer_wmi_notify, NULL);
2700 	if (ACPI_FAILURE(status)) {
2701 		err = -EIO;
2702 		goto err_free_dev;
2703 	}
2704 
2705 	if (has_cap(ACER_CAP_KBD_DOCK))
2706 		acer_kbd_dock_get_initial_state();
2707 
2708 	err = input_register_device(acer_wmi_input_dev);
2709 	if (err)
2710 		goto err_uninstall_notifier;
2711 
2712 	return 0;
2713 
2714 err_uninstall_notifier:
2715 	wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2716 err_free_dev:
2717 	input_free_device(acer_wmi_input_dev);
2718 	return err;
2719 }
2720 
acer_wmi_input_destroy(void)2721 static void acer_wmi_input_destroy(void)
2722 {
2723 	wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2724 	input_unregister_device(acer_wmi_input_dev);
2725 }
2726 
2727 /*
2728  * debugfs functions
2729  */
get_wmid_devices(void)2730 static u32 get_wmid_devices(void)
2731 {
2732 	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
2733 	union acpi_object *obj;
2734 	acpi_status status;
2735 	u32 devices = 0;
2736 
2737 	status = wmi_query_block(WMID_GUID2, 0, &out);
2738 	if (ACPI_FAILURE(status))
2739 		return 0;
2740 
2741 	obj = (union acpi_object *) out.pointer;
2742 	if (obj) {
2743 		if (obj->type == ACPI_TYPE_BUFFER &&
2744 			(obj->buffer.length == sizeof(u32) ||
2745 			obj->buffer.length == sizeof(u64))) {
2746 			devices = *((u32 *) obj->buffer.pointer);
2747 		} else if (obj->type == ACPI_TYPE_INTEGER) {
2748 			devices = (u32) obj->integer.value;
2749 		}
2750 	}
2751 
2752 	kfree(out.pointer);
2753 	return devices;
2754 }
2755 
2756 static int acer_wmi_hwmon_init(void);
2757 
2758 /*
2759  * Platform device
2760  */
acer_platform_probe(struct platform_device * device)2761 static int acer_platform_probe(struct platform_device *device)
2762 {
2763 	int err;
2764 
2765 	if (has_cap(ACER_CAP_MAILLED)) {
2766 		err = acer_led_init(&device->dev);
2767 		if (err)
2768 			goto error_mailled;
2769 	}
2770 
2771 	if (has_cap(ACER_CAP_BRIGHTNESS)) {
2772 		err = acer_backlight_init(&device->dev);
2773 		if (err)
2774 			goto error_brightness;
2775 	}
2776 
2777 	err = acer_rfkill_init(&device->dev);
2778 	if (err)
2779 		goto error_rfkill;
2780 
2781 	if (has_cap(ACER_CAP_PLATFORM_PROFILE)) {
2782 		err = acer_platform_profile_setup(device);
2783 		if (err)
2784 			goto error_platform_profile;
2785 	}
2786 
2787 	if (has_cap(ACER_CAP_HWMON)) {
2788 		err = acer_wmi_hwmon_init();
2789 		if (err)
2790 			goto error_hwmon;
2791 	}
2792 
2793 	return 0;
2794 
2795 error_hwmon:
2796 error_platform_profile:
2797 	acer_rfkill_exit();
2798 error_rfkill:
2799 	if (has_cap(ACER_CAP_BRIGHTNESS))
2800 		acer_backlight_exit();
2801 error_brightness:
2802 	if (has_cap(ACER_CAP_MAILLED))
2803 		acer_led_exit();
2804 error_mailled:
2805 	return err;
2806 }
2807 
acer_platform_remove(struct platform_device * device)2808 static void acer_platform_remove(struct platform_device *device)
2809 {
2810 	if (has_cap(ACER_CAP_MAILLED))
2811 		acer_led_exit();
2812 	if (has_cap(ACER_CAP_BRIGHTNESS))
2813 		acer_backlight_exit();
2814 
2815 	acer_rfkill_exit();
2816 }
2817 
2818 #ifdef CONFIG_PM_SLEEP
acer_suspend(struct device * dev)2819 static int acer_suspend(struct device *dev)
2820 {
2821 	u32 value;
2822 	struct acer_data *data = &interface->data;
2823 
2824 	if (!data)
2825 		return -ENOMEM;
2826 
2827 	if (has_cap(ACER_CAP_MAILLED)) {
2828 		get_u32(&value, ACER_CAP_MAILLED);
2829 		set_u32(LED_OFF, ACER_CAP_MAILLED);
2830 		data->mailled = value;
2831 	}
2832 
2833 	if (has_cap(ACER_CAP_BRIGHTNESS)) {
2834 		get_u32(&value, ACER_CAP_BRIGHTNESS);
2835 		data->brightness = value;
2836 	}
2837 
2838 	return 0;
2839 }
2840 
acer_resume(struct device * dev)2841 static int acer_resume(struct device *dev)
2842 {
2843 	struct acer_data *data = &interface->data;
2844 
2845 	if (!data)
2846 		return -ENOMEM;
2847 
2848 	if (has_cap(ACER_CAP_MAILLED))
2849 		set_u32(data->mailled, ACER_CAP_MAILLED);
2850 
2851 	if (has_cap(ACER_CAP_BRIGHTNESS))
2852 		set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
2853 
2854 	if (acer_wmi_accel_dev)
2855 		acer_gsensor_init();
2856 
2857 	return 0;
2858 }
2859 #else
2860 #define acer_suspend	NULL
2861 #define acer_resume	NULL
2862 #endif
2863 
2864 static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
2865 
acer_platform_shutdown(struct platform_device * device)2866 static void acer_platform_shutdown(struct platform_device *device)
2867 {
2868 	struct acer_data *data = &interface->data;
2869 
2870 	if (!data)
2871 		return;
2872 
2873 	if (has_cap(ACER_CAP_MAILLED))
2874 		set_u32(LED_OFF, ACER_CAP_MAILLED);
2875 }
2876 
2877 static struct platform_driver acer_platform_driver = {
2878 	.driver = {
2879 		.name = "acer-wmi",
2880 		.pm = &acer_pm,
2881 	},
2882 	.probe = acer_platform_probe,
2883 	.remove = acer_platform_remove,
2884 	.shutdown = acer_platform_shutdown,
2885 };
2886 
2887 static struct platform_device *acer_platform_device;
2888 
remove_debugfs(void)2889 static void remove_debugfs(void)
2890 {
2891 	debugfs_remove_recursive(interface->debug.root);
2892 }
2893 
create_debugfs(void)2894 static void __init create_debugfs(void)
2895 {
2896 	interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
2897 
2898 	debugfs_create_u32("devices", S_IRUGO, interface->debug.root,
2899 			   &interface->debug.wmid_devices);
2900 }
2901 
2902 static const enum acer_wmi_predator_v4_sensor_id acer_wmi_temp_channel_to_sensor_id[] = {
2903 	[0] = ACER_WMID_SENSOR_CPU_TEMPERATURE,
2904 	[1] = ACER_WMID_SENSOR_GPU_TEMPERATURE,
2905 	[2] = ACER_WMID_SENSOR_EXTERNAL_TEMPERATURE_2,
2906 };
2907 
2908 static const enum acer_wmi_predator_v4_sensor_id acer_wmi_fan_channel_to_sensor_id[] = {
2909 	[0] = ACER_WMID_SENSOR_CPU_FAN_SPEED,
2910 	[1] = ACER_WMID_SENSOR_GPU_FAN_SPEED,
2911 };
2912 
2913 static const enum acer_wmi_gaming_fan_id acer_wmi_fan_channel_to_fan_id[] = {
2914 	[0] = ACER_WMID_CPU_FAN,
2915 	[1] = ACER_WMID_GPU_FAN,
2916 };
2917 
2918 static const u16 acer_wmi_fan_channel_to_fan_bitmap[] = {
2919 	[0] = ACER_GAMING_FAN_BEHAVIOR_CPU,
2920 	[1] = ACER_GAMING_FAN_BEHAVIOR_GPU,
2921 };
2922 
acer_wmi_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)2923 static umode_t acer_wmi_hwmon_is_visible(const void *data,
2924 					 enum hwmon_sensor_types type, u32 attr,
2925 					 int channel)
2926 {
2927 	enum acer_wmi_predator_v4_sensor_id sensor_id;
2928 	const u64 *supported_sensors = data;
2929 
2930 	switch (type) {
2931 	case hwmon_temp:
2932 		sensor_id = acer_wmi_temp_channel_to_sensor_id[channel];
2933 		break;
2934 	case hwmon_pwm:
2935 		if (!has_cap(ACER_CAP_PWM))
2936 			return 0;
2937 
2938 		fallthrough;
2939 	case hwmon_fan:
2940 		sensor_id = acer_wmi_fan_channel_to_sensor_id[channel];
2941 		break;
2942 	default:
2943 		return 0;
2944 	}
2945 
2946 	if (*supported_sensors & BIT(sensor_id - 1)) {
2947 		if (type == hwmon_pwm)
2948 			return 0644;
2949 
2950 		return 0444;
2951 	}
2952 
2953 	return 0;
2954 }
2955 
acer_wmi_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)2956 static int acer_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
2957 			       u32 attr, int channel, long *val)
2958 {
2959 	u64 command = ACER_WMID_CMD_GET_PREDATOR_V4_SENSOR_READING;
2960 	enum acer_wmi_gaming_fan_mode mode;
2961 	u16 fan_bitmap;
2962 	u8 fan, speed;
2963 	u64 result;
2964 	int ret;
2965 
2966 	switch (type) {
2967 	case hwmon_temp:
2968 		command |= FIELD_PREP(ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK,
2969 				      acer_wmi_temp_channel_to_sensor_id[channel]);
2970 
2971 		ret = WMID_gaming_get_sys_info(command, &result);
2972 		if (ret < 0)
2973 			return ret;
2974 
2975 		result = FIELD_GET(ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK, result);
2976 		*val = result * MILLIDEGREE_PER_DEGREE;
2977 		return 0;
2978 	case hwmon_fan:
2979 		command |= FIELD_PREP(ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK,
2980 				      acer_wmi_fan_channel_to_sensor_id[channel]);
2981 
2982 		ret = WMID_gaming_get_sys_info(command, &result);
2983 		if (ret < 0)
2984 			return ret;
2985 
2986 		*val = FIELD_GET(ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK, result);
2987 		return 0;
2988 	case hwmon_pwm:
2989 		switch (attr) {
2990 		case hwmon_pwm_input:
2991 			fan = acer_wmi_fan_channel_to_fan_id[channel];
2992 			ret = WMID_gaming_get_gaming_fan_speed(fan, &speed);
2993 			if (ret < 0)
2994 				return ret;
2995 
2996 			*val = fixp_linear_interpolate(0, 0, 100, U8_MAX, speed);
2997 			return 0;
2998 		case hwmon_pwm_enable:
2999 			fan_bitmap = acer_wmi_fan_channel_to_fan_bitmap[channel];
3000 			ret = WMID_gaming_get_fan_behavior(fan_bitmap, &mode);
3001 			if (ret < 0)
3002 				return ret;
3003 
3004 			switch (mode) {
3005 			case ACER_WMID_FAN_MODE_AUTO:
3006 				*val = 2;
3007 				return 0;
3008 			case ACER_WMID_FAN_MODE_TURBO:
3009 				*val = 0;
3010 				return 0;
3011 			case ACER_WMID_FAN_MODE_CUSTOM:
3012 				*val = 1;
3013 				return 0;
3014 			default:
3015 				return -ENXIO;
3016 			}
3017 		default:
3018 			return -EOPNOTSUPP;
3019 		}
3020 	default:
3021 		return -EOPNOTSUPP;
3022 	}
3023 }
3024 
acer_wmi_hwmon_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)3025 static int acer_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
3026 				u32 attr, int channel, long val)
3027 {
3028 	enum acer_wmi_gaming_fan_mode mode;
3029 	u16 fan_bitmap;
3030 	u8 fan, speed;
3031 
3032 	switch (type) {
3033 	case hwmon_pwm:
3034 		switch (attr) {
3035 		case hwmon_pwm_input:
3036 			fan = acer_wmi_fan_channel_to_fan_id[channel];
3037 			speed = fixp_linear_interpolate(0, 0, U8_MAX, 100,
3038 							clamp_val(val, 0, U8_MAX));
3039 
3040 			return WMID_gaming_set_gaming_fan_speed(fan, speed);
3041 		case hwmon_pwm_enable:
3042 			fan_bitmap = acer_wmi_fan_channel_to_fan_bitmap[channel];
3043 
3044 			switch (val) {
3045 			case 0:
3046 				mode = ACER_WMID_FAN_MODE_TURBO;
3047 				break;
3048 			case 1:
3049 				mode = ACER_WMID_FAN_MODE_CUSTOM;
3050 				break;
3051 			case 2:
3052 				mode = ACER_WMID_FAN_MODE_AUTO;
3053 				break;
3054 			default:
3055 				return -EINVAL;
3056 			}
3057 
3058 			return WMID_gaming_set_fan_behavior(fan_bitmap, mode);
3059 		default:
3060 			return -EOPNOTSUPP;
3061 		}
3062 	default:
3063 		return -EOPNOTSUPP;
3064 	}
3065 }
3066 
3067 static const struct hwmon_channel_info *const acer_wmi_hwmon_info[] = {
3068 	HWMON_CHANNEL_INFO(temp,
3069 			   HWMON_T_INPUT,
3070 			   HWMON_T_INPUT,
3071 			   HWMON_T_INPUT
3072 			   ),
3073 	HWMON_CHANNEL_INFO(fan,
3074 			   HWMON_F_INPUT,
3075 			   HWMON_F_INPUT
3076 			   ),
3077 	HWMON_CHANNEL_INFO(pwm,
3078 			   HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
3079 			   HWMON_PWM_INPUT | HWMON_PWM_ENABLE
3080 			   ),
3081 	NULL
3082 };
3083 
3084 static const struct hwmon_ops acer_wmi_hwmon_ops = {
3085 	.read = acer_wmi_hwmon_read,
3086 	.write = acer_wmi_hwmon_write,
3087 	.is_visible = acer_wmi_hwmon_is_visible,
3088 };
3089 
3090 static const struct hwmon_chip_info acer_wmi_hwmon_chip_info = {
3091 	.ops = &acer_wmi_hwmon_ops,
3092 	.info = acer_wmi_hwmon_info,
3093 };
3094 
acer_wmi_hwmon_init(void)3095 static int acer_wmi_hwmon_init(void)
3096 {
3097 	struct device *dev = &acer_platform_device->dev;
3098 	struct device *hwmon;
3099 	u64 result;
3100 	int ret;
3101 
3102 	ret = WMID_gaming_get_sys_info(ACER_WMID_CMD_GET_PREDATOR_V4_SUPPORTED_SENSORS, &result);
3103 	if (ret < 0)
3104 		return ret;
3105 
3106 	/* Return early if no sensors are available */
3107 	supported_sensors = FIELD_GET(ACER_PREDATOR_V4_SUPPORTED_SENSORS_BIT_MASK, result);
3108 	if (!supported_sensors)
3109 		return 0;
3110 
3111 	hwmon = devm_hwmon_device_register_with_info(dev, "acer",
3112 						     &supported_sensors,
3113 						     &acer_wmi_hwmon_chip_info,
3114 						     NULL);
3115 
3116 	if (IS_ERR(hwmon)) {
3117 		dev_err(dev, "Could not register acer hwmon device\n");
3118 		return PTR_ERR(hwmon);
3119 	}
3120 
3121 	return 0;
3122 }
3123 
acer_wmi_init(void)3124 static int __init acer_wmi_init(void)
3125 {
3126 	int err;
3127 
3128 	pr_info("Acer Laptop ACPI-WMI Extras\n");
3129 
3130 	if (dmi_check_system(acer_blacklist)) {
3131 		pr_info("Blacklisted hardware detected - not loading\n");
3132 		return -ENODEV;
3133 	}
3134 
3135 	find_quirks();
3136 
3137 	/*
3138 	 * The AMW0_GUID1 wmi is not only found on Acer family but also other
3139 	 * machines like Lenovo, Fujitsu and Medion. In the past days,
3140 	 * acer-wmi driver handled those non-Acer machines by quirks list.
3141 	 * But actually acer-wmi driver was loaded on any machines that have
3142 	 * AMW0_GUID1. This behavior is strange because those machines should
3143 	 * be supported by appropriate wmi drivers. e.g. fujitsu-laptop,
3144 	 * ideapad-laptop. So, here checks the machine that has AMW0_GUID1
3145 	 * should be in Acer/Gateway/Packard Bell white list, or it's already
3146 	 * in the past quirk list.
3147 	 */
3148 	if (wmi_has_guid(AMW0_GUID1) &&
3149 	    !dmi_check_system(amw0_whitelist) &&
3150 	    quirks == &quirk_unknown) {
3151 		pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n");
3152 		return -ENODEV;
3153 	}
3154 
3155 	/*
3156 	 * Detect which ACPI-WMI interface we're using.
3157 	 */
3158 	if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
3159 		interface = &AMW0_V2_interface;
3160 
3161 	if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
3162 		interface = &wmid_interface;
3163 
3164 	if (wmi_has_guid(WMID_GUID3))
3165 		interface = &wmid_v2_interface;
3166 
3167 	if (interface)
3168 		dmi_walk(type_aa_dmi_decode, NULL);
3169 
3170 	if (wmi_has_guid(WMID_GUID2) && interface) {
3171 		if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
3172 			pr_err("Unable to detect available WMID devices\n");
3173 			return -ENODEV;
3174 		}
3175 		/* WMID always provides brightness methods */
3176 		interface->capability |= ACER_CAP_BRIGHTNESS;
3177 	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa && force_caps == -1) {
3178 		pr_err("No WMID device detection method found\n");
3179 		return -ENODEV;
3180 	}
3181 
3182 	if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) {
3183 		interface = &AMW0_interface;
3184 
3185 		if (ACPI_FAILURE(AMW0_set_capabilities())) {
3186 			pr_err("Unable to detect available AMW0 devices\n");
3187 			return -ENODEV;
3188 		}
3189 	}
3190 
3191 	if (wmi_has_guid(AMW0_GUID1))
3192 		AMW0_find_mailled();
3193 
3194 	if (!interface) {
3195 		pr_err("No or unsupported WMI interface, unable to load\n");
3196 		return -ENODEV;
3197 	}
3198 
3199 	set_quirks();
3200 
3201 	if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
3202 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
3203 
3204 	if (wmi_has_guid(WMID_GUID3))
3205 		interface->capability |= ACER_CAP_SET_FUNCTION_MODE;
3206 
3207 	if (force_caps != -1)
3208 		interface->capability = force_caps;
3209 
3210 	if (wmi_has_guid(WMID_GUID3) &&
3211 	    (interface->capability & ACER_CAP_SET_FUNCTION_MODE)) {
3212 		if (ACPI_FAILURE(acer_wmi_enable_rf_button()))
3213 			pr_warn("Cannot enable RF Button Driver\n");
3214 
3215 		if (ec_raw_mode) {
3216 			if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
3217 				pr_err("Cannot enable EC raw mode\n");
3218 				return -ENODEV;
3219 			}
3220 		} else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
3221 			pr_err("Cannot enable Launch Manager mode\n");
3222 			return -ENODEV;
3223 		}
3224 	} else if (ec_raw_mode) {
3225 		pr_info("No WMID EC raw mode enable method\n");
3226 	}
3227 
3228 	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
3229 		err = acer_wmi_input_setup();
3230 		if (err)
3231 			return err;
3232 		err = acer_wmi_accel_setup();
3233 		if (err && err != -ENODEV)
3234 			pr_warn("Cannot enable accelerometer\n");
3235 	}
3236 
3237 	err = platform_driver_register(&acer_platform_driver);
3238 	if (err) {
3239 		pr_err("Unable to register platform driver\n");
3240 		goto error_platform_register;
3241 	}
3242 
3243 	acer_platform_device = platform_device_alloc("acer-wmi", PLATFORM_DEVID_NONE);
3244 	if (!acer_platform_device) {
3245 		err = -ENOMEM;
3246 		goto error_device_alloc;
3247 	}
3248 
3249 	err = platform_device_add(acer_platform_device);
3250 	if (err)
3251 		goto error_device_add;
3252 
3253 	if (wmi_has_guid(WMID_GUID2)) {
3254 		interface->debug.wmid_devices = get_wmid_devices();
3255 		create_debugfs();
3256 	}
3257 
3258 	/* Override any initial settings with values from the commandline */
3259 	acer_commandline_init();
3260 
3261 	return 0;
3262 
3263 error_device_add:
3264 	platform_device_put(acer_platform_device);
3265 error_device_alloc:
3266 	platform_driver_unregister(&acer_platform_driver);
3267 error_platform_register:
3268 	if (wmi_has_guid(ACERWMID_EVENT_GUID))
3269 		acer_wmi_input_destroy();
3270 	if (acer_wmi_accel_dev)
3271 		input_unregister_device(acer_wmi_accel_dev);
3272 
3273 	return err;
3274 }
3275 
acer_wmi_exit(void)3276 static void __exit acer_wmi_exit(void)
3277 {
3278 	if (wmi_has_guid(ACERWMID_EVENT_GUID))
3279 		acer_wmi_input_destroy();
3280 
3281 	if (acer_wmi_accel_dev)
3282 		input_unregister_device(acer_wmi_accel_dev);
3283 
3284 	remove_debugfs();
3285 	platform_device_unregister(acer_platform_device);
3286 	platform_driver_unregister(&acer_platform_driver);
3287 
3288 	pr_info("Acer Laptop WMI Extras unloaded\n");
3289 }
3290 
3291 module_init(acer_wmi_init);
3292 module_exit(acer_wmi_exit);
3293