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(¶m, 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 ¶ms
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, ¤t_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(¶ms, &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(¶ms, &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(¶ms, &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