blob: d27a564389a473b4a9b37b28eb4943b85b03ca61 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-or-later
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
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>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000010 */
11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/types.h>
18#include <linux/dmi.h>
19#include <linux/fb.h>
20#include <linux/backlight.h>
21#include <linux/leds.h>
22#include <linux/platform_device.h>
23#include <linux/acpi.h>
24#include <linux/i8042.h>
25#include <linux/rfkill.h>
26#include <linux/workqueue.h>
27#include <linux/debugfs.h>
28#include <linux/slab.h>
29#include <linux/input.h>
30#include <linux/input/sparse-keymap.h>
31#include <acpi/video.h>
32
Olivier Deprez0e641232021-09-23 10:07:05 +020033ACPI_MODULE_NAME(KBUILD_MODNAME);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000034MODULE_AUTHOR("Carlos Corbacho");
35MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
36MODULE_LICENSE("GPL");
37
38/*
39 * Magic Number
40 * Meaning is unknown - this number is required for writing to ACPI for AMW0
41 * (it's also used in acerhk when directly accessing the BIOS)
42 */
43#define ACER_AMW0_WRITE 0x9610
44
45/*
46 * Bit masks for the AMW0 interface
47 */
48#define ACER_AMW0_WIRELESS_MASK 0x35
49#define ACER_AMW0_BLUETOOTH_MASK 0x34
50#define ACER_AMW0_MAILLED_MASK 0x31
51
52/*
53 * Method IDs for WMID interface
54 */
55#define ACER_WMID_GET_WIRELESS_METHODID 1
56#define ACER_WMID_GET_BLUETOOTH_METHODID 2
57#define ACER_WMID_GET_BRIGHTNESS_METHODID 3
58#define ACER_WMID_SET_WIRELESS_METHODID 4
59#define ACER_WMID_SET_BLUETOOTH_METHODID 5
60#define ACER_WMID_SET_BRIGHTNESS_METHODID 6
61#define ACER_WMID_GET_THREEG_METHODID 10
62#define ACER_WMID_SET_THREEG_METHODID 11
63
64/*
65 * Acer ACPI method GUIDs
66 */
67#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
68#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
69#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
70#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"
71#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
72
73/*
74 * Acer ACPI event GUIDs
75 */
76#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
77
78MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
79MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
80MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
81
82enum acer_wmi_event_ids {
83 WMID_HOTKEY_EVENT = 0x1,
Olivier Deprez0e641232021-09-23 10:07:05 +020084 WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000085};
86
87static const struct key_entry acer_wmi_keymap[] __initconst = {
88 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
89 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
90 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */
91 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
92 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
93 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
94 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */
95 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */
96 {KE_KEY, 0x29, {KEY_PROG3} }, /* P_Key for TM8372 */
97 {KE_IGNORE, 0x41, {KEY_MUTE} },
98 {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
99 {KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },
100 {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
101 {KE_IGNORE, 0x4e, {KEY_NEXTSONG} },
102 {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
103 {KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },
104 {KE_IGNORE, 0x45, {KEY_STOP} },
105 {KE_IGNORE, 0x50, {KEY_STOP} },
106 {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
107 {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
108 {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
109 {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
110 {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
111 {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
112 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
113 {KE_IGNORE, 0x81, {KEY_SLEEP} },
114 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */
Olivier Deprez0e641232021-09-23 10:07:05 +0200115 {KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000116 {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
117 {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
118 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
119 {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
120 {KE_KEY, 0x86, {KEY_WLAN} },
121 {KE_KEY, 0x87, {KEY_POWER} },
122 {KE_END, 0}
123};
124
125static struct input_dev *acer_wmi_input_dev;
126static struct input_dev *acer_wmi_accel_dev;
127
128struct event_return_value {
129 u8 function;
130 u8 key_num;
131 u16 device_state;
Olivier Deprez0e641232021-09-23 10:07:05 +0200132 u16 reserved1;
133 u8 kbd_dock_state;
134 u8 reserved2;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000135} __attribute__((packed));
136
137/*
138 * GUID3 Get Device Status device flags
139 */
140#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
141#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
142#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
143#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
144#define ACER_WMID3_GDS_RFBTN (1<<14) /* RF Button */
145
146#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */
147
148/* Hotkey Customized Setting and Acer Application Status.
149 * Set Device Default Value and Report Acer Application Status.
150 * When Acer Application starts, it will run this method to inform
151 * BIOS/EC that Acer Application is on.
152 * App Status
153 * Bit[0]: Launch Manager Status
154 * Bit[1]: ePM Status
155 * Bit[2]: Device Control Status
156 * Bit[3]: Acer Power Button Utility Status
157 * Bit[4]: RF Button Status
158 * Bit[5]: ODD PM Status
159 * Bit[6]: Device Default Value Control
160 * Bit[7]: Hall Sensor Application Status
161 */
162struct func_input_params {
163 u8 function_num; /* Function Number */
164 u16 commun_devices; /* Communication type devices default status */
165 u16 devices; /* Other type devices default status */
166 u8 app_status; /* Acer Device Status. LM, ePM, RF Button... */
167 u8 app_mask; /* Bit mask to app_status */
168 u8 reserved;
169} __attribute__((packed));
170
171struct func_return_value {
172 u8 error_code; /* Error Code */
173 u8 ec_return_value; /* EC Return Value */
174 u16 reserved;
175} __attribute__((packed));
176
177struct wmid3_gds_set_input_param { /* Set Device Status input parameter */
178 u8 function_num; /* Function Number */
179 u8 hotkey_number; /* Hotkey Number */
180 u16 devices; /* Set Device */
181 u8 volume_value; /* Volume Value */
182} __attribute__((packed));
183
184struct wmid3_gds_get_input_param { /* Get Device Status input parameter */
185 u8 function_num; /* Function Number */
186 u8 hotkey_number; /* Hotkey Number */
187 u16 devices; /* Get Device */
188} __attribute__((packed));
189
190struct wmid3_gds_return_value { /* Get Device Status return value*/
191 u8 error_code; /* Error Code */
192 u8 ec_return_value; /* EC Return Value */
193 u16 devices; /* Current Device Status */
194 u32 reserved;
195} __attribute__((packed));
196
197struct hotkey_function_type_aa {
198 u8 type;
199 u8 length;
200 u16 handle;
201 u16 commun_func_bitmap;
202 u16 application_func_bitmap;
203 u16 media_func_bitmap;
204 u16 display_func_bitmap;
205 u16 others_func_bitmap;
206 u8 commun_fn_key_number;
207} __attribute__((packed));
208
209/*
210 * Interface capability flags
211 */
Olivier Deprez0e641232021-09-23 10:07:05 +0200212#define ACER_CAP_MAILLED BIT(0)
213#define ACER_CAP_WIRELESS BIT(1)
214#define ACER_CAP_BLUETOOTH BIT(2)
215#define ACER_CAP_BRIGHTNESS BIT(3)
216#define ACER_CAP_THREEG BIT(4)
217#define ACER_CAP_SET_FUNCTION_MODE BIT(5)
218#define ACER_CAP_KBD_DOCK BIT(6)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000219
220/*
221 * Interface type flags
222 */
223enum interface_flags {
224 ACER_AMW0,
225 ACER_AMW0_V2,
226 ACER_WMID,
227 ACER_WMID_v2,
228};
229
230#define ACER_DEFAULT_WIRELESS 0
231#define ACER_DEFAULT_BLUETOOTH 0
232#define ACER_DEFAULT_MAILLED 0
233#define ACER_DEFAULT_THREEG 0
234
235static int max_brightness = 0xF;
236
237static int mailled = -1;
238static int brightness = -1;
239static int threeg = -1;
240static int force_series;
Olivier Deprez0e641232021-09-23 10:07:05 +0200241static int force_caps = -1;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000242static bool ec_raw_mode;
243static bool has_type_aa;
244static u16 commun_func_bitmap;
245static u8 commun_fn_key_number;
246
247module_param(mailled, int, 0444);
248module_param(brightness, int, 0444);
249module_param(threeg, int, 0444);
250module_param(force_series, int, 0444);
Olivier Deprez0e641232021-09-23 10:07:05 +0200251module_param(force_caps, int, 0444);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000252module_param(ec_raw_mode, bool, 0444);
253MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
254MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
255MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
256MODULE_PARM_DESC(force_series, "Force a different laptop series");
Olivier Deprez0e641232021-09-23 10:07:05 +0200257MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000258MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
259
260struct acer_data {
261 int mailled;
262 int threeg;
263 int brightness;
264};
265
266struct acer_debug {
267 struct dentry *root;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000268 u32 wmid_devices;
269};
270
271static struct rfkill *wireless_rfkill;
272static struct rfkill *bluetooth_rfkill;
273static struct rfkill *threeg_rfkill;
274static bool rfkill_inited;
275
276/* Each low-level interface must define at least some of the following */
277struct wmi_interface {
278 /* The WMI device type */
279 u32 type;
280
281 /* The capabilities this interface provides */
282 u32 capability;
283
284 /* Private data for the current interface */
285 struct acer_data data;
286
287 /* debugfs entries associated with this interface */
288 struct acer_debug debug;
289};
290
291/* The static interface pointer, points to the currently detected interface */
292static struct wmi_interface *interface;
293
294/*
295 * Embedded Controller quirks
296 * Some laptops require us to directly access the EC to either enable or query
297 * features that are not available through WMI.
298 */
299
300struct quirk_entry {
301 u8 wireless;
302 u8 mailled;
303 s8 brightness;
304 u8 bluetooth;
305};
306
307static struct quirk_entry *quirks;
308
309static void __init set_quirks(void)
310{
311 if (!interface)
312 return;
313
314 if (quirks->mailled)
315 interface->capability |= ACER_CAP_MAILLED;
316
317 if (quirks->brightness)
318 interface->capability |= ACER_CAP_BRIGHTNESS;
319}
320
321static int __init dmi_matched(const struct dmi_system_id *dmi)
322{
323 quirks = dmi->driver_data;
324 return 1;
325}
326
Olivier Deprez0e641232021-09-23 10:07:05 +0200327static int __init set_force_caps(const struct dmi_system_id *dmi)
328{
329 if (force_caps == -1) {
330 force_caps = (uintptr_t)dmi->driver_data;
331 pr_info("Found %s, set force_caps to 0x%x\n", dmi->ident, force_caps);
332 }
333 return 1;
334}
335
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000336static struct quirk_entry quirk_unknown = {
337};
338
339static struct quirk_entry quirk_acer_aspire_1520 = {
340 .brightness = -1,
341};
342
343static struct quirk_entry quirk_acer_travelmate_2490 = {
344 .mailled = 1,
345};
346
347/* This AMW0 laptop has no bluetooth */
348static struct quirk_entry quirk_medion_md_98300 = {
349 .wireless = 1,
350};
351
352static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
353 .wireless = 2,
354};
355
356static struct quirk_entry quirk_lenovo_ideapad_s205 = {
357 .wireless = 3,
358};
359
360/* The Aspire One has a dummy ACPI-WMI interface - disable it */
361static const struct dmi_system_id acer_blacklist[] __initconst = {
362 {
363 .ident = "Acer Aspire One (SSD)",
364 .matches = {
365 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
366 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
367 },
368 },
369 {
370 .ident = "Acer Aspire One (HDD)",
371 .matches = {
372 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
373 DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
374 },
375 },
376 {}
377};
378
379static const struct dmi_system_id amw0_whitelist[] __initconst = {
380 {
381 .ident = "Acer",
382 .matches = {
383 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
384 },
385 },
386 {
387 .ident = "Gateway",
388 .matches = {
389 DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),
390 },
391 },
392 {
393 .ident = "Packard Bell",
394 .matches = {
395 DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"),
396 },
397 },
398 {}
399};
400
401/*
402 * This quirk table is only for Acer/Gateway/Packard Bell family
403 * that those machines are supported by acer-wmi driver.
404 */
405static const struct dmi_system_id acer_quirks[] __initconst = {
406 {
407 .callback = dmi_matched,
408 .ident = "Acer Aspire 1360",
409 .matches = {
410 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
411 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
412 },
413 .driver_data = &quirk_acer_aspire_1520,
414 },
415 {
416 .callback = dmi_matched,
417 .ident = "Acer Aspire 1520",
418 .matches = {
419 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
420 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),
421 },
422 .driver_data = &quirk_acer_aspire_1520,
423 },
424 {
425 .callback = dmi_matched,
426 .ident = "Acer Aspire 3100",
427 .matches = {
428 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
429 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
430 },
431 .driver_data = &quirk_acer_travelmate_2490,
432 },
433 {
434 .callback = dmi_matched,
435 .ident = "Acer Aspire 3610",
436 .matches = {
437 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
438 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),
439 },
440 .driver_data = &quirk_acer_travelmate_2490,
441 },
442 {
443 .callback = dmi_matched,
444 .ident = "Acer Aspire 5100",
445 .matches = {
446 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
447 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
448 },
449 .driver_data = &quirk_acer_travelmate_2490,
450 },
451 {
452 .callback = dmi_matched,
453 .ident = "Acer Aspire 5610",
454 .matches = {
455 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
456 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
457 },
458 .driver_data = &quirk_acer_travelmate_2490,
459 },
460 {
461 .callback = dmi_matched,
462 .ident = "Acer Aspire 5630",
463 .matches = {
464 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
465 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
466 },
467 .driver_data = &quirk_acer_travelmate_2490,
468 },
469 {
470 .callback = dmi_matched,
471 .ident = "Acer Aspire 5650",
472 .matches = {
473 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
474 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
475 },
476 .driver_data = &quirk_acer_travelmate_2490,
477 },
478 {
479 .callback = dmi_matched,
480 .ident = "Acer Aspire 5680",
481 .matches = {
482 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
483 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
484 },
485 .driver_data = &quirk_acer_travelmate_2490,
486 },
487 {
488 .callback = dmi_matched,
489 .ident = "Acer Aspire 9110",
490 .matches = {
491 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
492 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
493 },
494 .driver_data = &quirk_acer_travelmate_2490,
495 },
496 {
497 .callback = dmi_matched,
498 .ident = "Acer TravelMate 2490",
499 .matches = {
500 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
501 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
502 },
503 .driver_data = &quirk_acer_travelmate_2490,
504 },
505 {
506 .callback = dmi_matched,
507 .ident = "Acer TravelMate 4200",
508 .matches = {
509 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
510 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"),
511 },
512 .driver_data = &quirk_acer_travelmate_2490,
513 },
Olivier Deprez0e641232021-09-23 10:07:05 +0200514 {
515 .callback = set_force_caps,
516 .ident = "Acer Aspire Switch 10E SW3-016",
517 .matches = {
518 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
519 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-016"),
520 },
521 .driver_data = (void *)ACER_CAP_KBD_DOCK,
522 },
523 {
524 .callback = set_force_caps,
525 .ident = "Acer Aspire Switch 10 SW5-012",
526 .matches = {
527 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
528 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
529 },
530 .driver_data = (void *)ACER_CAP_KBD_DOCK,
531 },
532 {
533 .callback = set_force_caps,
534 .ident = "Acer One 10 (S1003)",
535 .matches = {
536 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
537 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
538 },
539 .driver_data = (void *)ACER_CAP_KBD_DOCK,
540 },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000541 {}
542};
543
544/*
545 * This quirk list is for those non-acer machines that have AMW0_GUID1
546 * but supported by acer-wmi in past days. Keeping this quirk list here
547 * is only for backward compatible. Please do not add new machine to
548 * here anymore. Those non-acer machines should be supported by
549 * appropriate wmi drivers.
550 */
551static const struct dmi_system_id non_acer_quirks[] __initconst = {
552 {
553 .callback = dmi_matched,
554 .ident = "Fujitsu Siemens Amilo Li 1718",
555 .matches = {
556 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
557 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),
558 },
559 .driver_data = &quirk_fujitsu_amilo_li_1718,
560 },
561 {
562 .callback = dmi_matched,
563 .ident = "Medion MD 98300",
564 .matches = {
565 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
566 DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"),
567 },
568 .driver_data = &quirk_medion_md_98300,
569 },
570 {
571 .callback = dmi_matched,
572 .ident = "Lenovo Ideapad S205",
573 .matches = {
574 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
575 DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
576 },
577 .driver_data = &quirk_lenovo_ideapad_s205,
578 },
579 {
580 .callback = dmi_matched,
581 .ident = "Lenovo Ideapad S205 (Brazos)",
582 .matches = {
583 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
584 DMI_MATCH(DMI_PRODUCT_NAME, "Brazos"),
585 },
586 .driver_data = &quirk_lenovo_ideapad_s205,
587 },
588 {
589 .callback = dmi_matched,
590 .ident = "Lenovo 3000 N200",
591 .matches = {
592 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
593 DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
594 },
595 .driver_data = &quirk_fujitsu_amilo_li_1718,
596 },
597 {
598 .callback = dmi_matched,
599 .ident = "Lenovo Ideapad S205-10382JG",
600 .matches = {
601 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
602 DMI_MATCH(DMI_PRODUCT_NAME, "10382JG"),
603 },
604 .driver_data = &quirk_lenovo_ideapad_s205,
605 },
606 {
607 .callback = dmi_matched,
608 .ident = "Lenovo Ideapad S205-1038DPG",
609 .matches = {
610 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
611 DMI_MATCH(DMI_PRODUCT_NAME, "1038DPG"),
612 },
613 .driver_data = &quirk_lenovo_ideapad_s205,
614 },
615 {}
616};
617
618static int __init
619video_set_backlight_video_vendor(const struct dmi_system_id *d)
620{
621 interface->capability &= ~ACER_CAP_BRIGHTNESS;
622 pr_info("Brightness must be controlled by generic video driver\n");
623 return 0;
624}
625
626static const struct dmi_system_id video_vendor_dmi_table[] __initconst = {
627 {
628 .callback = video_set_backlight_video_vendor,
629 .ident = "Acer TravelMate 4750",
630 .matches = {
631 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
632 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
633 },
634 },
635 {
636 .callback = video_set_backlight_video_vendor,
637 .ident = "Acer Extensa 5235",
638 .matches = {
639 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
640 DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
641 },
642 },
643 {
644 .callback = video_set_backlight_video_vendor,
645 .ident = "Acer TravelMate 5760",
646 .matches = {
647 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
648 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
649 },
650 },
651 {
652 .callback = video_set_backlight_video_vendor,
653 .ident = "Acer Aspire 5750",
654 .matches = {
655 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
656 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
657 },
658 },
659 {
660 .callback = video_set_backlight_video_vendor,
661 .ident = "Acer Aspire 5741",
662 .matches = {
663 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
664 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
665 },
666 },
667 {
668 /*
669 * Note no video_set_backlight_video_vendor, we must use the
670 * acer interface, as there is no native backlight interface.
671 */
672 .ident = "Acer KAV80",
673 .matches = {
674 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
675 DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"),
676 },
677 },
678 {}
679};
680
681/* Find which quirks are needed for a particular vendor/ model pair */
682static void __init find_quirks(void)
683{
684 if (!force_series) {
685 dmi_check_system(acer_quirks);
686 dmi_check_system(non_acer_quirks);
687 } else if (force_series == 2490) {
688 quirks = &quirk_acer_travelmate_2490;
689 }
690
691 if (quirks == NULL)
692 quirks = &quirk_unknown;
693
694 set_quirks();
695}
696
697/*
698 * General interface convenience methods
699 */
700
701static bool has_cap(u32 cap)
702{
703 return interface->capability & cap;
704}
705
706/*
707 * AMW0 (V1) interface
708 */
709struct wmab_args {
710 u32 eax;
711 u32 ebx;
712 u32 ecx;
713 u32 edx;
714};
715
716struct wmab_ret {
717 u32 eax;
718 u32 ebx;
719 u32 ecx;
720 u32 edx;
721 u32 eex;
722};
723
724static acpi_status wmab_execute(struct wmab_args *regbuf,
725struct acpi_buffer *result)
726{
727 struct acpi_buffer input;
728 acpi_status status;
729 input.length = sizeof(struct wmab_args);
730 input.pointer = (u8 *)regbuf;
731
732 status = wmi_evaluate_method(AMW0_GUID1, 0, 1, &input, result);
733
734 return status;
735}
736
737static acpi_status AMW0_get_u32(u32 *value, u32 cap)
738{
739 int err;
740 u8 result;
741
742 switch (cap) {
743 case ACER_CAP_MAILLED:
744 switch (quirks->mailled) {
745 default:
746 err = ec_read(0xA, &result);
747 if (err)
748 return AE_ERROR;
749 *value = (result >> 7) & 0x1;
750 return AE_OK;
751 }
752 break;
753 case ACER_CAP_WIRELESS:
754 switch (quirks->wireless) {
755 case 1:
756 err = ec_read(0x7B, &result);
757 if (err)
758 return AE_ERROR;
759 *value = result & 0x1;
760 return AE_OK;
761 case 2:
762 err = ec_read(0x71, &result);
763 if (err)
764 return AE_ERROR;
765 *value = result & 0x1;
766 return AE_OK;
767 case 3:
768 err = ec_read(0x78, &result);
769 if (err)
770 return AE_ERROR;
771 *value = result & 0x1;
772 return AE_OK;
773 default:
774 err = ec_read(0xA, &result);
775 if (err)
776 return AE_ERROR;
777 *value = (result >> 2) & 0x1;
778 return AE_OK;
779 }
780 break;
781 case ACER_CAP_BLUETOOTH:
782 switch (quirks->bluetooth) {
783 default:
784 err = ec_read(0xA, &result);
785 if (err)
786 return AE_ERROR;
787 *value = (result >> 4) & 0x1;
788 return AE_OK;
789 }
790 break;
791 case ACER_CAP_BRIGHTNESS:
792 switch (quirks->brightness) {
793 default:
794 err = ec_read(0x83, &result);
795 if (err)
796 return AE_ERROR;
797 *value = result;
798 return AE_OK;
799 }
800 break;
801 default:
802 return AE_ERROR;
803 }
804 return AE_OK;
805}
806
807static acpi_status AMW0_set_u32(u32 value, u32 cap)
808{
809 struct wmab_args args;
810
811 args.eax = ACER_AMW0_WRITE;
812 args.ebx = value ? (1<<8) : 0;
813 args.ecx = args.edx = 0;
814
815 switch (cap) {
816 case ACER_CAP_MAILLED:
817 if (value > 1)
818 return AE_BAD_PARAMETER;
819 args.ebx |= ACER_AMW0_MAILLED_MASK;
820 break;
821 case ACER_CAP_WIRELESS:
822 if (value > 1)
823 return AE_BAD_PARAMETER;
824 args.ebx |= ACER_AMW0_WIRELESS_MASK;
825 break;
826 case ACER_CAP_BLUETOOTH:
827 if (value > 1)
828 return AE_BAD_PARAMETER;
829 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
830 break;
831 case ACER_CAP_BRIGHTNESS:
832 if (value > max_brightness)
833 return AE_BAD_PARAMETER;
834 switch (quirks->brightness) {
835 default:
836 return ec_write(0x83, value);
837 break;
838 }
839 default:
840 return AE_ERROR;
841 }
842
843 /* Actually do the set */
844 return wmab_execute(&args, NULL);
845}
846
847static acpi_status __init AMW0_find_mailled(void)
848{
849 struct wmab_args args;
850 struct wmab_ret ret;
851 acpi_status status = AE_OK;
852 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
853 union acpi_object *obj;
854
855 args.eax = 0x86;
856 args.ebx = args.ecx = args.edx = 0;
857
858 status = wmab_execute(&args, &out);
859 if (ACPI_FAILURE(status))
860 return status;
861
862 obj = (union acpi_object *) out.pointer;
863 if (obj && obj->type == ACPI_TYPE_BUFFER &&
864 obj->buffer.length == sizeof(struct wmab_ret)) {
865 ret = *((struct wmab_ret *) obj->buffer.pointer);
866 } else {
867 kfree(out.pointer);
868 return AE_ERROR;
869 }
870
871 if (ret.eex & 0x1)
872 interface->capability |= ACER_CAP_MAILLED;
873
874 kfree(out.pointer);
875
876 return AE_OK;
877}
878
879static const struct acpi_device_id norfkill_ids[] __initconst = {
880 { "VPC2004", 0},
881 { "IBM0068", 0},
882 { "LEN0068", 0},
883 { "SNY5001", 0}, /* sony-laptop in charge */
884 { "HPQ6601", 0},
885 { "", 0},
886};
887
888static int __init AMW0_set_cap_acpi_check_device(void)
889{
890 const struct acpi_device_id *id;
891
892 for (id = norfkill_ids; id->id[0]; id++)
893 if (acpi_dev_found(id->id))
894 return true;
895
896 return false;
897}
898
899static acpi_status __init AMW0_set_capabilities(void)
900{
901 struct wmab_args args;
902 struct wmab_ret ret;
903 acpi_status status;
904 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
905 union acpi_object *obj;
906
907 /*
908 * On laptops with this strange GUID (non Acer), normal probing doesn't
909 * work.
910 */
911 if (wmi_has_guid(AMW0_GUID2)) {
912 if ((quirks != &quirk_unknown) ||
913 !AMW0_set_cap_acpi_check_device())
914 interface->capability |= ACER_CAP_WIRELESS;
915 return AE_OK;
916 }
917
918 args.eax = ACER_AMW0_WRITE;
919 args.ecx = args.edx = 0;
920
921 args.ebx = 0xa2 << 8;
922 args.ebx |= ACER_AMW0_WIRELESS_MASK;
923
924 status = wmab_execute(&args, &out);
925 if (ACPI_FAILURE(status))
926 return status;
927
928 obj = out.pointer;
929 if (obj && obj->type == ACPI_TYPE_BUFFER &&
930 obj->buffer.length == sizeof(struct wmab_ret)) {
931 ret = *((struct wmab_ret *) obj->buffer.pointer);
932 } else {
933 status = AE_ERROR;
934 goto out;
935 }
936
937 if (ret.eax & 0x1)
938 interface->capability |= ACER_CAP_WIRELESS;
939
940 args.ebx = 2 << 8;
941 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
942
943 /*
944 * It's ok to use existing buffer for next wmab_execute call.
945 * But we need to kfree(out.pointer) if next wmab_execute fail.
946 */
947 status = wmab_execute(&args, &out);
948 if (ACPI_FAILURE(status))
949 goto out;
950
951 obj = (union acpi_object *) out.pointer;
952 if (obj && obj->type == ACPI_TYPE_BUFFER
953 && obj->buffer.length == sizeof(struct wmab_ret)) {
954 ret = *((struct wmab_ret *) obj->buffer.pointer);
955 } else {
956 status = AE_ERROR;
957 goto out;
958 }
959
960 if (ret.eax & 0x1)
961 interface->capability |= ACER_CAP_BLUETOOTH;
962
963 /*
964 * This appears to be safe to enable, since all Wistron based laptops
965 * appear to use the same EC register for brightness, even if they
966 * differ for wireless, etc
967 */
968 if (quirks->brightness >= 0)
969 interface->capability |= ACER_CAP_BRIGHTNESS;
970
971 status = AE_OK;
972out:
973 kfree(out.pointer);
974 return status;
975}
976
977static struct wmi_interface AMW0_interface = {
978 .type = ACER_AMW0,
979};
980
981static struct wmi_interface AMW0_V2_interface = {
982 .type = ACER_AMW0_V2,
983};
984
985/*
986 * New interface (The WMID interface)
987 */
988static acpi_status
989WMI_execute_u32(u32 method_id, u32 in, u32 *out)
990{
991 struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
992 struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
993 union acpi_object *obj;
994 u32 tmp = 0;
995 acpi_status status;
996
997 status = wmi_evaluate_method(WMID_GUID1, 0, method_id, &input, &result);
998
999 if (ACPI_FAILURE(status))
1000 return status;
1001
1002 obj = (union acpi_object *) result.pointer;
1003 if (obj) {
1004 if (obj->type == ACPI_TYPE_BUFFER &&
1005 (obj->buffer.length == sizeof(u32) ||
1006 obj->buffer.length == sizeof(u64))) {
1007 tmp = *((u32 *) obj->buffer.pointer);
1008 } else if (obj->type == ACPI_TYPE_INTEGER) {
1009 tmp = (u32) obj->integer.value;
1010 }
1011 }
1012
1013 if (out)
1014 *out = tmp;
1015
1016 kfree(result.pointer);
1017
1018 return status;
1019}
1020
1021static acpi_status WMID_get_u32(u32 *value, u32 cap)
1022{
1023 acpi_status status;
1024 u8 tmp;
1025 u32 result, method_id = 0;
1026
1027 switch (cap) {
1028 case ACER_CAP_WIRELESS:
1029 method_id = ACER_WMID_GET_WIRELESS_METHODID;
1030 break;
1031 case ACER_CAP_BLUETOOTH:
1032 method_id = ACER_WMID_GET_BLUETOOTH_METHODID;
1033 break;
1034 case ACER_CAP_BRIGHTNESS:
1035 method_id = ACER_WMID_GET_BRIGHTNESS_METHODID;
1036 break;
1037 case ACER_CAP_THREEG:
1038 method_id = ACER_WMID_GET_THREEG_METHODID;
1039 break;
1040 case ACER_CAP_MAILLED:
1041 if (quirks->mailled == 1) {
1042 ec_read(0x9f, &tmp);
1043 *value = tmp & 0x1;
1044 return 0;
1045 }
David Brazdil0f672f62019-12-10 10:32:29 +00001046 /* fall through */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001047 default:
1048 return AE_ERROR;
1049 }
1050 status = WMI_execute_u32(method_id, 0, &result);
1051
1052 if (ACPI_SUCCESS(status))
1053 *value = (u8)result;
1054
1055 return status;
1056}
1057
1058static acpi_status WMID_set_u32(u32 value, u32 cap)
1059{
1060 u32 method_id = 0;
1061 char param;
1062
1063 switch (cap) {
1064 case ACER_CAP_BRIGHTNESS:
1065 if (value > max_brightness)
1066 return AE_BAD_PARAMETER;
1067 method_id = ACER_WMID_SET_BRIGHTNESS_METHODID;
1068 break;
1069 case ACER_CAP_WIRELESS:
1070 if (value > 1)
1071 return AE_BAD_PARAMETER;
1072 method_id = ACER_WMID_SET_WIRELESS_METHODID;
1073 break;
1074 case ACER_CAP_BLUETOOTH:
1075 if (value > 1)
1076 return AE_BAD_PARAMETER;
1077 method_id = ACER_WMID_SET_BLUETOOTH_METHODID;
1078 break;
1079 case ACER_CAP_THREEG:
1080 if (value > 1)
1081 return AE_BAD_PARAMETER;
1082 method_id = ACER_WMID_SET_THREEG_METHODID;
1083 break;
1084 case ACER_CAP_MAILLED:
1085 if (value > 1)
1086 return AE_BAD_PARAMETER;
1087 if (quirks->mailled == 1) {
1088 param = value ? 0x92 : 0x93;
1089 i8042_lock_chip();
1090 i8042_command(&param, 0x1059);
1091 i8042_unlock_chip();
1092 return 0;
1093 }
1094 break;
1095 default:
1096 return AE_ERROR;
1097 }
1098 return WMI_execute_u32(method_id, (u32)value, NULL);
1099}
1100
1101static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1102{
1103 struct wmid3_gds_return_value return_value;
1104 acpi_status status;
1105 union acpi_object *obj;
1106 struct wmid3_gds_get_input_param params = {
1107 .function_num = 0x1,
1108 .hotkey_number = commun_fn_key_number,
1109 .devices = device,
1110 };
1111 struct acpi_buffer input = {
1112 sizeof(struct wmid3_gds_get_input_param),
1113 &params
1114 };
1115 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1116
1117 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1118 if (ACPI_FAILURE(status))
1119 return status;
1120
1121 obj = output.pointer;
1122
1123 if (!obj)
1124 return AE_ERROR;
1125 else if (obj->type != ACPI_TYPE_BUFFER) {
1126 kfree(obj);
1127 return AE_ERROR;
1128 }
1129 if (obj->buffer.length != 8) {
1130 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1131 kfree(obj);
1132 return AE_ERROR;
1133 }
1134
1135 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1136 kfree(obj);
1137
1138 if (return_value.error_code || return_value.ec_return_value)
1139 pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
1140 device,
1141 return_value.error_code,
1142 return_value.ec_return_value);
1143 else
1144 *value = !!(return_value.devices & device);
1145
1146 return status;
1147}
1148
1149static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
1150{
1151 u16 device;
1152
1153 switch (cap) {
1154 case ACER_CAP_WIRELESS:
1155 device = ACER_WMID3_GDS_WIRELESS;
1156 break;
1157 case ACER_CAP_BLUETOOTH:
1158 device = ACER_WMID3_GDS_BLUETOOTH;
1159 break;
1160 case ACER_CAP_THREEG:
1161 device = ACER_WMID3_GDS_THREEG;
1162 break;
1163 default:
1164 return AE_ERROR;
1165 }
1166 return wmid3_get_device_status(value, device);
1167}
1168
1169static acpi_status wmid3_set_device_status(u32 value, u16 device)
1170{
1171 struct wmid3_gds_return_value return_value;
1172 acpi_status status;
1173 union acpi_object *obj;
1174 u16 devices;
1175 struct wmid3_gds_get_input_param get_params = {
1176 .function_num = 0x1,
1177 .hotkey_number = commun_fn_key_number,
1178 .devices = commun_func_bitmap,
1179 };
1180 struct acpi_buffer get_input = {
1181 sizeof(struct wmid3_gds_get_input_param),
1182 &get_params
1183 };
1184 struct wmid3_gds_set_input_param set_params = {
1185 .function_num = 0x2,
1186 .hotkey_number = commun_fn_key_number,
1187 .devices = commun_func_bitmap,
1188 };
1189 struct acpi_buffer set_input = {
1190 sizeof(struct wmid3_gds_set_input_param),
1191 &set_params
1192 };
1193 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1194 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1195
1196 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &get_input, &output);
1197 if (ACPI_FAILURE(status))
1198 return status;
1199
1200 obj = output.pointer;
1201
1202 if (!obj)
1203 return AE_ERROR;
1204 else if (obj->type != ACPI_TYPE_BUFFER) {
1205 kfree(obj);
1206 return AE_ERROR;
1207 }
1208 if (obj->buffer.length != 8) {
1209 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1210 kfree(obj);
1211 return AE_ERROR;
1212 }
1213
1214 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1215 kfree(obj);
1216
1217 if (return_value.error_code || return_value.ec_return_value) {
1218 pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",
1219 return_value.error_code,
1220 return_value.ec_return_value);
1221 return status;
1222 }
1223
1224 devices = return_value.devices;
1225 set_params.devices = (value) ? (devices | device) : (devices & ~device);
1226
1227 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &set_input, &output2);
1228 if (ACPI_FAILURE(status))
1229 return status;
1230
1231 obj = output2.pointer;
1232
1233 if (!obj)
1234 return AE_ERROR;
1235 else if (obj->type != ACPI_TYPE_BUFFER) {
1236 kfree(obj);
1237 return AE_ERROR;
1238 }
1239 if (obj->buffer.length != 4) {
1240 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1241 kfree(obj);
1242 return AE_ERROR;
1243 }
1244
1245 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1246 kfree(obj);
1247
1248 if (return_value.error_code || return_value.ec_return_value)
1249 pr_warn("Set Device Status failed: 0x%x - 0x%x\n",
1250 return_value.error_code,
1251 return_value.ec_return_value);
1252
1253 return status;
1254}
1255
1256static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1257{
1258 u16 device;
1259
1260 switch (cap) {
1261 case ACER_CAP_WIRELESS:
1262 device = ACER_WMID3_GDS_WIRELESS;
1263 break;
1264 case ACER_CAP_BLUETOOTH:
1265 device = ACER_WMID3_GDS_BLUETOOTH;
1266 break;
1267 case ACER_CAP_THREEG:
1268 device = ACER_WMID3_GDS_THREEG;
1269 break;
1270 default:
1271 return AE_ERROR;
1272 }
1273 return wmid3_set_device_status(value, device);
1274}
1275
1276static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)
1277{
1278 struct hotkey_function_type_aa *type_aa;
1279
1280 /* We are looking for OEM-specific Type AAh */
1281 if (header->type != 0xAA)
1282 return;
1283
1284 has_type_aa = true;
1285 type_aa = (struct hotkey_function_type_aa *) header;
1286
1287 pr_info("Function bitmap for Communication Button: 0x%x\n",
1288 type_aa->commun_func_bitmap);
1289 commun_func_bitmap = type_aa->commun_func_bitmap;
1290
1291 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
1292 interface->capability |= ACER_CAP_WIRELESS;
1293 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
1294 interface->capability |= ACER_CAP_THREEG;
1295 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
1296 interface->capability |= ACER_CAP_BLUETOOTH;
Olivier Deprez0e641232021-09-23 10:07:05 +02001297 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001298 commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001299
1300 commun_fn_key_number = type_aa->commun_fn_key_number;
1301}
1302
1303static acpi_status __init WMID_set_capabilities(void)
1304{
1305 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1306 union acpi_object *obj;
1307 acpi_status status;
1308 u32 devices;
1309
1310 status = wmi_query_block(WMID_GUID2, 0, &out);
1311 if (ACPI_FAILURE(status))
1312 return status;
1313
1314 obj = (union acpi_object *) out.pointer;
1315 if (obj) {
1316 if (obj->type == ACPI_TYPE_BUFFER &&
1317 (obj->buffer.length == sizeof(u32) ||
1318 obj->buffer.length == sizeof(u64))) {
1319 devices = *((u32 *) obj->buffer.pointer);
1320 } else if (obj->type == ACPI_TYPE_INTEGER) {
1321 devices = (u32) obj->integer.value;
1322 } else {
1323 kfree(out.pointer);
1324 return AE_ERROR;
1325 }
1326 } else {
1327 kfree(out.pointer);
1328 return AE_ERROR;
1329 }
1330
1331 pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
1332 if (devices & 0x07)
1333 interface->capability |= ACER_CAP_WIRELESS;
1334 if (devices & 0x40)
1335 interface->capability |= ACER_CAP_THREEG;
1336 if (devices & 0x10)
1337 interface->capability |= ACER_CAP_BLUETOOTH;
1338
1339 if (!(devices & 0x20))
1340 max_brightness = 0x9;
1341
1342 kfree(out.pointer);
1343 return status;
1344}
1345
1346static struct wmi_interface wmid_interface = {
1347 .type = ACER_WMID,
1348};
1349
1350static struct wmi_interface wmid_v2_interface = {
1351 .type = ACER_WMID_v2,
1352};
1353
1354/*
1355 * Generic Device (interface-independent)
1356 */
1357
1358static acpi_status get_u32(u32 *value, u32 cap)
1359{
1360 acpi_status status = AE_ERROR;
1361
1362 switch (interface->type) {
1363 case ACER_AMW0:
1364 status = AMW0_get_u32(value, cap);
1365 break;
1366 case ACER_AMW0_V2:
1367 if (cap == ACER_CAP_MAILLED) {
1368 status = AMW0_get_u32(value, cap);
1369 break;
1370 }
David Brazdil0f672f62019-12-10 10:32:29 +00001371 /* fall through */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001372 case ACER_WMID:
1373 status = WMID_get_u32(value, cap);
1374 break;
1375 case ACER_WMID_v2:
1376 if (cap & (ACER_CAP_WIRELESS |
1377 ACER_CAP_BLUETOOTH |
1378 ACER_CAP_THREEG))
1379 status = wmid_v2_get_u32(value, cap);
1380 else if (wmi_has_guid(WMID_GUID2))
1381 status = WMID_get_u32(value, cap);
1382 break;
1383 }
1384
1385 return status;
1386}
1387
1388static acpi_status set_u32(u32 value, u32 cap)
1389{
1390 acpi_status status;
1391
1392 if (interface->capability & cap) {
1393 switch (interface->type) {
1394 case ACER_AMW0:
1395 return AMW0_set_u32(value, cap);
1396 case ACER_AMW0_V2:
1397 if (cap == ACER_CAP_MAILLED)
1398 return AMW0_set_u32(value, cap);
1399
1400 /*
1401 * On some models, some WMID methods don't toggle
1402 * properly. For those cases, we want to run the AMW0
1403 * method afterwards to be certain we've really toggled
1404 * the device state.
1405 */
1406 if (cap == ACER_CAP_WIRELESS ||
1407 cap == ACER_CAP_BLUETOOTH) {
1408 status = WMID_set_u32(value, cap);
1409 if (ACPI_FAILURE(status))
1410 return status;
1411
1412 return AMW0_set_u32(value, cap);
1413 }
David Brazdil0f672f62019-12-10 10:32:29 +00001414 /* fall through */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001415 case ACER_WMID:
1416 return WMID_set_u32(value, cap);
1417 case ACER_WMID_v2:
1418 if (cap & (ACER_CAP_WIRELESS |
1419 ACER_CAP_BLUETOOTH |
1420 ACER_CAP_THREEG))
1421 return wmid_v2_set_u32(value, cap);
1422 else if (wmi_has_guid(WMID_GUID2))
1423 return WMID_set_u32(value, cap);
David Brazdil0f672f62019-12-10 10:32:29 +00001424 /* fall through */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001425 default:
1426 return AE_BAD_PARAMETER;
1427 }
1428 }
1429 return AE_BAD_PARAMETER;
1430}
1431
1432static void __init acer_commandline_init(void)
1433{
1434 /*
1435 * These will all fail silently if the value given is invalid, or the
1436 * capability isn't available on the given interface
1437 */
1438 if (mailled >= 0)
1439 set_u32(mailled, ACER_CAP_MAILLED);
1440 if (!has_type_aa && threeg >= 0)
1441 set_u32(threeg, ACER_CAP_THREEG);
1442 if (brightness >= 0)
1443 set_u32(brightness, ACER_CAP_BRIGHTNESS);
1444}
1445
1446/*
1447 * LED device (Mail LED only, no other LEDs known yet)
1448 */
1449static void mail_led_set(struct led_classdev *led_cdev,
1450enum led_brightness value)
1451{
1452 set_u32(value, ACER_CAP_MAILLED);
1453}
1454
1455static struct led_classdev mail_led = {
1456 .name = "acer-wmi::mail",
1457 .brightness_set = mail_led_set,
1458};
1459
1460static int acer_led_init(struct device *dev)
1461{
1462 return led_classdev_register(dev, &mail_led);
1463}
1464
1465static void acer_led_exit(void)
1466{
1467 set_u32(LED_OFF, ACER_CAP_MAILLED);
1468 led_classdev_unregister(&mail_led);
1469}
1470
1471/*
1472 * Backlight device
1473 */
1474static struct backlight_device *acer_backlight_device;
1475
1476static int read_brightness(struct backlight_device *bd)
1477{
1478 u32 value;
1479 get_u32(&value, ACER_CAP_BRIGHTNESS);
1480 return value;
1481}
1482
1483static int update_bl_status(struct backlight_device *bd)
1484{
1485 int intensity = bd->props.brightness;
1486
1487 if (bd->props.power != FB_BLANK_UNBLANK)
1488 intensity = 0;
1489 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
1490 intensity = 0;
1491
1492 set_u32(intensity, ACER_CAP_BRIGHTNESS);
1493
1494 return 0;
1495}
1496
1497static const struct backlight_ops acer_bl_ops = {
1498 .get_brightness = read_brightness,
1499 .update_status = update_bl_status,
1500};
1501
1502static int acer_backlight_init(struct device *dev)
1503{
1504 struct backlight_properties props;
1505 struct backlight_device *bd;
1506
1507 memset(&props, 0, sizeof(struct backlight_properties));
1508 props.type = BACKLIGHT_PLATFORM;
1509 props.max_brightness = max_brightness;
1510 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
1511 &props);
1512 if (IS_ERR(bd)) {
1513 pr_err("Could not register Acer backlight device\n");
1514 acer_backlight_device = NULL;
1515 return PTR_ERR(bd);
1516 }
1517
1518 acer_backlight_device = bd;
1519
1520 bd->props.power = FB_BLANK_UNBLANK;
1521 bd->props.brightness = read_brightness(bd);
1522 backlight_update_status(bd);
1523 return 0;
1524}
1525
1526static void acer_backlight_exit(void)
1527{
1528 backlight_device_unregister(acer_backlight_device);
1529}
1530
1531/*
1532 * Accelerometer device
1533 */
1534static acpi_handle gsensor_handle;
1535
1536static int acer_gsensor_init(void)
1537{
1538 acpi_status status;
1539 struct acpi_buffer output;
1540 union acpi_object out_obj;
1541
1542 output.length = sizeof(out_obj);
1543 output.pointer = &out_obj;
1544 status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output);
1545 if (ACPI_FAILURE(status))
1546 return -1;
1547
1548 return 0;
1549}
1550
1551static int acer_gsensor_open(struct input_dev *input)
1552{
1553 return acer_gsensor_init();
1554}
1555
1556static int acer_gsensor_event(void)
1557{
1558 acpi_status status;
1559 struct acpi_buffer output;
1560 union acpi_object out_obj[5];
1561
Olivier Deprez0e641232021-09-23 10:07:05 +02001562 if (!acer_wmi_accel_dev)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001563 return -1;
1564
1565 output.length = sizeof(out_obj);
1566 output.pointer = out_obj;
1567
1568 status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output);
1569 if (ACPI_FAILURE(status))
1570 return -1;
1571
1572 if (out_obj->package.count != 4)
1573 return -1;
1574
1575 input_report_abs(acer_wmi_accel_dev, ABS_X,
1576 (s16)out_obj->package.elements[0].integer.value);
1577 input_report_abs(acer_wmi_accel_dev, ABS_Y,
1578 (s16)out_obj->package.elements[1].integer.value);
1579 input_report_abs(acer_wmi_accel_dev, ABS_Z,
1580 (s16)out_obj->package.elements[2].integer.value);
1581 input_sync(acer_wmi_accel_dev);
1582 return 0;
1583}
1584
1585/*
Olivier Deprez0e641232021-09-23 10:07:05 +02001586 * Switch series keyboard dock status
1587 */
1588static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)
1589{
1590 switch (kbd_dock_state) {
1591 case 0x01: /* Docked, traditional clamshell laptop mode */
1592 return 0;
1593 case 0x04: /* Stand-alone tablet */
1594 case 0x40: /* Docked, tent mode, keyboard not usable */
1595 return 1;
1596 default:
1597 pr_warn("Unknown kbd_dock_state 0x%02x\n", kbd_dock_state);
1598 }
1599
1600 return 0;
1601}
1602
1603static void acer_kbd_dock_get_initial_state(void)
1604{
1605 u8 *output, input[8] = { 0x05, 0x00, };
1606 struct acpi_buffer input_buf = { sizeof(input), input };
1607 struct acpi_buffer output_buf = { ACPI_ALLOCATE_BUFFER, NULL };
1608 union acpi_object *obj;
1609 acpi_status status;
1610 int sw_tablet_mode;
1611
1612 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);
1613 if (ACPI_FAILURE(status)) {
1614 ACPI_EXCEPTION((AE_INFO, status, "Error getting keyboard-dock initial status"));
1615 return;
1616 }
1617
1618 obj = output_buf.pointer;
1619 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
1620 pr_err("Unexpected output format getting keyboard-dock initial status\n");
1621 goto out_free_obj;
1622 }
1623
1624 output = obj->buffer.pointer;
1625 if (output[0] != 0x00 || (output[3] != 0x05 && output[3] != 0x45)) {
1626 pr_err("Unexpected output [0]=0x%02x [3]=0x%02x getting keyboard-dock initial status\n",
1627 output[0], output[3]);
1628 goto out_free_obj;
1629 }
1630
1631 sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(output[4]);
1632 input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
1633
1634out_free_obj:
1635 kfree(obj);
1636}
1637
1638static void acer_kbd_dock_event(const struct event_return_value *event)
1639{
1640 int sw_tablet_mode;
1641
1642 if (!has_cap(ACER_CAP_KBD_DOCK))
1643 return;
1644
1645 sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(event->kbd_dock_state);
1646 input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
1647 input_sync(acer_wmi_input_dev);
1648}
1649
1650/*
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001651 * Rfkill devices
1652 */
1653static void acer_rfkill_update(struct work_struct *ignored);
1654static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
1655static void acer_rfkill_update(struct work_struct *ignored)
1656{
1657 u32 state;
1658 acpi_status status;
1659
1660 if (has_cap(ACER_CAP_WIRELESS)) {
1661 status = get_u32(&state, ACER_CAP_WIRELESS);
1662 if (ACPI_SUCCESS(status)) {
1663 if (quirks->wireless == 3)
1664 rfkill_set_hw_state(wireless_rfkill, !state);
1665 else
1666 rfkill_set_sw_state(wireless_rfkill, !state);
1667 }
1668 }
1669
1670 if (has_cap(ACER_CAP_BLUETOOTH)) {
1671 status = get_u32(&state, ACER_CAP_BLUETOOTH);
1672 if (ACPI_SUCCESS(status))
1673 rfkill_set_sw_state(bluetooth_rfkill, !state);
1674 }
1675
1676 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1677 status = get_u32(&state, ACER_WMID3_GDS_THREEG);
1678 if (ACPI_SUCCESS(status))
1679 rfkill_set_sw_state(threeg_rfkill, !state);
1680 }
1681
1682 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
1683}
1684
1685static int acer_rfkill_set(void *data, bool blocked)
1686{
1687 acpi_status status;
1688 u32 cap = (unsigned long)data;
1689
1690 if (rfkill_inited) {
1691 status = set_u32(!blocked, cap);
1692 if (ACPI_FAILURE(status))
1693 return -ENODEV;
1694 }
1695
1696 return 0;
1697}
1698
1699static const struct rfkill_ops acer_rfkill_ops = {
1700 .set_block = acer_rfkill_set,
1701};
1702
1703static struct rfkill *acer_rfkill_register(struct device *dev,
1704 enum rfkill_type type,
1705 char *name, u32 cap)
1706{
1707 int err;
1708 struct rfkill *rfkill_dev;
1709 u32 state;
1710 acpi_status status;
1711
1712 rfkill_dev = rfkill_alloc(name, dev, type,
1713 &acer_rfkill_ops,
1714 (void *)(unsigned long)cap);
1715 if (!rfkill_dev)
1716 return ERR_PTR(-ENOMEM);
1717
1718 status = get_u32(&state, cap);
1719
1720 err = rfkill_register(rfkill_dev);
1721 if (err) {
1722 rfkill_destroy(rfkill_dev);
1723 return ERR_PTR(err);
1724 }
1725
1726 if (ACPI_SUCCESS(status))
1727 rfkill_set_sw_state(rfkill_dev, !state);
1728
1729 return rfkill_dev;
1730}
1731
1732static int acer_rfkill_init(struct device *dev)
1733{
1734 int err;
1735
1736 if (has_cap(ACER_CAP_WIRELESS)) {
1737 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
1738 "acer-wireless", ACER_CAP_WIRELESS);
1739 if (IS_ERR(wireless_rfkill)) {
1740 err = PTR_ERR(wireless_rfkill);
1741 goto error_wireless;
1742 }
1743 }
1744
1745 if (has_cap(ACER_CAP_BLUETOOTH)) {
1746 bluetooth_rfkill = acer_rfkill_register(dev,
1747 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
1748 ACER_CAP_BLUETOOTH);
1749 if (IS_ERR(bluetooth_rfkill)) {
1750 err = PTR_ERR(bluetooth_rfkill);
1751 goto error_bluetooth;
1752 }
1753 }
1754
1755 if (has_cap(ACER_CAP_THREEG)) {
1756 threeg_rfkill = acer_rfkill_register(dev,
1757 RFKILL_TYPE_WWAN, "acer-threeg",
1758 ACER_CAP_THREEG);
1759 if (IS_ERR(threeg_rfkill)) {
1760 err = PTR_ERR(threeg_rfkill);
1761 goto error_threeg;
1762 }
1763 }
1764
1765 rfkill_inited = true;
1766
1767 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1768 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1769 schedule_delayed_work(&acer_rfkill_work,
1770 round_jiffies_relative(HZ));
1771
1772 return 0;
1773
1774error_threeg:
1775 if (has_cap(ACER_CAP_BLUETOOTH)) {
1776 rfkill_unregister(bluetooth_rfkill);
1777 rfkill_destroy(bluetooth_rfkill);
1778 }
1779error_bluetooth:
1780 if (has_cap(ACER_CAP_WIRELESS)) {
1781 rfkill_unregister(wireless_rfkill);
1782 rfkill_destroy(wireless_rfkill);
1783 }
1784error_wireless:
1785 return err;
1786}
1787
1788static void acer_rfkill_exit(void)
1789{
1790 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1791 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1792 cancel_delayed_work_sync(&acer_rfkill_work);
1793
1794 if (has_cap(ACER_CAP_WIRELESS)) {
1795 rfkill_unregister(wireless_rfkill);
1796 rfkill_destroy(wireless_rfkill);
1797 }
1798
1799 if (has_cap(ACER_CAP_BLUETOOTH)) {
1800 rfkill_unregister(bluetooth_rfkill);
1801 rfkill_destroy(bluetooth_rfkill);
1802 }
1803
1804 if (has_cap(ACER_CAP_THREEG)) {
1805 rfkill_unregister(threeg_rfkill);
1806 rfkill_destroy(threeg_rfkill);
1807 }
1808 return;
1809}
1810
1811static void acer_wmi_notify(u32 value, void *context)
1812{
1813 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1814 union acpi_object *obj;
1815 struct event_return_value return_value;
1816 acpi_status status;
1817 u16 device_state;
1818 const struct key_entry *key;
1819 u32 scancode;
1820
1821 status = wmi_get_event_data(value, &response);
1822 if (status != AE_OK) {
1823 pr_warn("bad event status 0x%x\n", status);
1824 return;
1825 }
1826
1827 obj = (union acpi_object *)response.pointer;
1828
1829 if (!obj)
1830 return;
1831 if (obj->type != ACPI_TYPE_BUFFER) {
1832 pr_warn("Unknown response received %d\n", obj->type);
1833 kfree(obj);
1834 return;
1835 }
1836 if (obj->buffer.length != 8) {
1837 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1838 kfree(obj);
1839 return;
1840 }
1841
1842 return_value = *((struct event_return_value *)obj->buffer.pointer);
1843 kfree(obj);
1844
1845 switch (return_value.function) {
1846 case WMID_HOTKEY_EVENT:
1847 device_state = return_value.device_state;
1848 pr_debug("device state: 0x%x\n", device_state);
1849
1850 key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
1851 return_value.key_num);
1852 if (!key) {
1853 pr_warn("Unknown key number - 0x%x\n",
1854 return_value.key_num);
1855 } else {
1856 scancode = return_value.key_num;
1857 switch (key->keycode) {
1858 case KEY_WLAN:
1859 case KEY_BLUETOOTH:
1860 if (has_cap(ACER_CAP_WIRELESS))
1861 rfkill_set_sw_state(wireless_rfkill,
1862 !(device_state & ACER_WMID3_GDS_WIRELESS));
1863 if (has_cap(ACER_CAP_THREEG))
1864 rfkill_set_sw_state(threeg_rfkill,
1865 !(device_state & ACER_WMID3_GDS_THREEG));
1866 if (has_cap(ACER_CAP_BLUETOOTH))
1867 rfkill_set_sw_state(bluetooth_rfkill,
1868 !(device_state & ACER_WMID3_GDS_BLUETOOTH));
1869 break;
1870 case KEY_TOUCHPAD_TOGGLE:
1871 scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ?
1872 KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF;
1873 }
1874 sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
1875 }
1876 break;
Olivier Deprez0e641232021-09-23 10:07:05 +02001877 case WMID_ACCEL_OR_KBD_DOCK_EVENT:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001878 acer_gsensor_event();
Olivier Deprez0e641232021-09-23 10:07:05 +02001879 acer_kbd_dock_event(&return_value);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001880 break;
1881 default:
1882 pr_warn("Unknown function number - %d - %d\n",
1883 return_value.function, return_value.key_num);
1884 break;
1885 }
1886}
1887
1888static acpi_status __init
1889wmid3_set_function_mode(struct func_input_params *params,
1890 struct func_return_value *return_value)
1891{
1892 acpi_status status;
1893 union acpi_object *obj;
1894
1895 struct acpi_buffer input = { sizeof(struct func_input_params), params };
1896 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1897
1898 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
1899 if (ACPI_FAILURE(status))
1900 return status;
1901
1902 obj = output.pointer;
1903
1904 if (!obj)
1905 return AE_ERROR;
1906 else if (obj->type != ACPI_TYPE_BUFFER) {
1907 kfree(obj);
1908 return AE_ERROR;
1909 }
1910 if (obj->buffer.length != 4) {
1911 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1912 kfree(obj);
1913 return AE_ERROR;
1914 }
1915
1916 *return_value = *((struct func_return_value *)obj->buffer.pointer);
1917 kfree(obj);
1918
1919 return status;
1920}
1921
1922static int __init acer_wmi_enable_ec_raw(void)
1923{
1924 struct func_return_value return_value;
1925 acpi_status status;
1926 struct func_input_params params = {
1927 .function_num = 0x1,
1928 .commun_devices = 0xFFFF,
1929 .devices = 0xFFFF,
1930 .app_status = 0x00, /* Launch Manager Deactive */
1931 .app_mask = 0x01,
1932 };
1933
1934 status = wmid3_set_function_mode(&params, &return_value);
1935
1936 if (return_value.error_code || return_value.ec_return_value)
1937 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1938 return_value.error_code,
1939 return_value.ec_return_value);
1940 else
1941 pr_info("Enabled EC raw mode\n");
1942
1943 return status;
1944}
1945
1946static int __init acer_wmi_enable_lm(void)
1947{
1948 struct func_return_value return_value;
1949 acpi_status status;
1950 struct func_input_params params = {
1951 .function_num = 0x1,
1952 .commun_devices = 0xFFFF,
1953 .devices = 0xFFFF,
1954 .app_status = 0x01, /* Launch Manager Active */
1955 .app_mask = 0x01,
1956 };
1957
1958 status = wmid3_set_function_mode(&params, &return_value);
1959
1960 if (return_value.error_code || return_value.ec_return_value)
1961 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1962 return_value.error_code,
1963 return_value.ec_return_value);
1964
1965 return status;
1966}
1967
1968static int __init acer_wmi_enable_rf_button(void)
1969{
1970 struct func_return_value return_value;
1971 acpi_status status;
1972 struct func_input_params params = {
1973 .function_num = 0x1,
1974 .commun_devices = 0xFFFF,
1975 .devices = 0xFFFF,
1976 .app_status = 0x10, /* RF Button Active */
1977 .app_mask = 0x10,
1978 };
1979
1980 status = wmid3_set_function_mode(&params, &return_value);
1981
1982 if (return_value.error_code || return_value.ec_return_value)
1983 pr_warn("Enabling RF Button failed: 0x%x - 0x%x\n",
1984 return_value.error_code,
1985 return_value.ec_return_value);
1986
1987 return status;
1988}
1989
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001990static int __init acer_wmi_accel_setup(void)
1991{
David Brazdil0f672f62019-12-10 10:32:29 +00001992 struct acpi_device *adev;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001993 int err;
1994
David Brazdil0f672f62019-12-10 10:32:29 +00001995 adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1);
1996 if (!adev)
1997 return -ENODEV;
1998
1999 gsensor_handle = acpi_device_handle(adev);
2000 acpi_dev_put(adev);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002001
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002002 acer_wmi_accel_dev = input_allocate_device();
2003 if (!acer_wmi_accel_dev)
2004 return -ENOMEM;
2005
2006 acer_wmi_accel_dev->open = acer_gsensor_open;
2007
2008 acer_wmi_accel_dev->name = "Acer BMA150 accelerometer";
2009 acer_wmi_accel_dev->phys = "wmi/input1";
2010 acer_wmi_accel_dev->id.bustype = BUS_HOST;
2011 acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS);
2012 input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0);
2013 input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0);
2014 input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0);
2015
2016 err = input_register_device(acer_wmi_accel_dev);
2017 if (err)
2018 goto err_free_dev;
2019
2020 return 0;
2021
2022err_free_dev:
2023 input_free_device(acer_wmi_accel_dev);
2024 return err;
2025}
2026
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002027static int __init acer_wmi_input_setup(void)
2028{
2029 acpi_status status;
2030 int err;
2031
2032 acer_wmi_input_dev = input_allocate_device();
2033 if (!acer_wmi_input_dev)
2034 return -ENOMEM;
2035
2036 acer_wmi_input_dev->name = "Acer WMI hotkeys";
2037 acer_wmi_input_dev->phys = "wmi/input0";
2038 acer_wmi_input_dev->id.bustype = BUS_HOST;
2039
2040 err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
2041 if (err)
2042 goto err_free_dev;
2043
Olivier Deprez0e641232021-09-23 10:07:05 +02002044 if (has_cap(ACER_CAP_KBD_DOCK))
2045 input_set_capability(acer_wmi_input_dev, EV_SW, SW_TABLET_MODE);
2046
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002047 status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
2048 acer_wmi_notify, NULL);
2049 if (ACPI_FAILURE(status)) {
2050 err = -EIO;
2051 goto err_free_dev;
2052 }
2053
Olivier Deprez0e641232021-09-23 10:07:05 +02002054 if (has_cap(ACER_CAP_KBD_DOCK))
2055 acer_kbd_dock_get_initial_state();
2056
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002057 err = input_register_device(acer_wmi_input_dev);
2058 if (err)
2059 goto err_uninstall_notifier;
2060
2061 return 0;
2062
2063err_uninstall_notifier:
2064 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2065err_free_dev:
2066 input_free_device(acer_wmi_input_dev);
2067 return err;
2068}
2069
2070static void acer_wmi_input_destroy(void)
2071{
2072 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2073 input_unregister_device(acer_wmi_input_dev);
2074}
2075
2076/*
2077 * debugfs functions
2078 */
2079static u32 get_wmid_devices(void)
2080{
2081 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
2082 union acpi_object *obj;
2083 acpi_status status;
2084 u32 devices = 0;
2085
2086 status = wmi_query_block(WMID_GUID2, 0, &out);
2087 if (ACPI_FAILURE(status))
2088 return 0;
2089
2090 obj = (union acpi_object *) out.pointer;
2091 if (obj) {
2092 if (obj->type == ACPI_TYPE_BUFFER &&
2093 (obj->buffer.length == sizeof(u32) ||
2094 obj->buffer.length == sizeof(u64))) {
2095 devices = *((u32 *) obj->buffer.pointer);
2096 } else if (obj->type == ACPI_TYPE_INTEGER) {
2097 devices = (u32) obj->integer.value;
2098 }
2099 }
2100
2101 kfree(out.pointer);
2102 return devices;
2103}
2104
2105/*
2106 * Platform device
2107 */
2108static int acer_platform_probe(struct platform_device *device)
2109{
2110 int err;
2111
2112 if (has_cap(ACER_CAP_MAILLED)) {
2113 err = acer_led_init(&device->dev);
2114 if (err)
2115 goto error_mailled;
2116 }
2117
2118 if (has_cap(ACER_CAP_BRIGHTNESS)) {
2119 err = acer_backlight_init(&device->dev);
2120 if (err)
2121 goto error_brightness;
2122 }
2123
2124 err = acer_rfkill_init(&device->dev);
2125 if (err)
2126 goto error_rfkill;
2127
2128 return err;
2129
2130error_rfkill:
2131 if (has_cap(ACER_CAP_BRIGHTNESS))
2132 acer_backlight_exit();
2133error_brightness:
2134 if (has_cap(ACER_CAP_MAILLED))
2135 acer_led_exit();
2136error_mailled:
2137 return err;
2138}
2139
2140static int acer_platform_remove(struct platform_device *device)
2141{
2142 if (has_cap(ACER_CAP_MAILLED))
2143 acer_led_exit();
2144 if (has_cap(ACER_CAP_BRIGHTNESS))
2145 acer_backlight_exit();
2146
2147 acer_rfkill_exit();
2148 return 0;
2149}
2150
2151#ifdef CONFIG_PM_SLEEP
2152static int acer_suspend(struct device *dev)
2153{
2154 u32 value;
2155 struct acer_data *data = &interface->data;
2156
2157 if (!data)
2158 return -ENOMEM;
2159
2160 if (has_cap(ACER_CAP_MAILLED)) {
2161 get_u32(&value, ACER_CAP_MAILLED);
2162 set_u32(LED_OFF, ACER_CAP_MAILLED);
2163 data->mailled = value;
2164 }
2165
2166 if (has_cap(ACER_CAP_BRIGHTNESS)) {
2167 get_u32(&value, ACER_CAP_BRIGHTNESS);
2168 data->brightness = value;
2169 }
2170
2171 return 0;
2172}
2173
2174static int acer_resume(struct device *dev)
2175{
2176 struct acer_data *data = &interface->data;
2177
2178 if (!data)
2179 return -ENOMEM;
2180
2181 if (has_cap(ACER_CAP_MAILLED))
2182 set_u32(data->mailled, ACER_CAP_MAILLED);
2183
2184 if (has_cap(ACER_CAP_BRIGHTNESS))
2185 set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
2186
Olivier Deprez0e641232021-09-23 10:07:05 +02002187 if (acer_wmi_accel_dev)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002188 acer_gsensor_init();
2189
2190 return 0;
2191}
2192#else
2193#define acer_suspend NULL
2194#define acer_resume NULL
2195#endif
2196
2197static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
2198
2199static void acer_platform_shutdown(struct platform_device *device)
2200{
2201 struct acer_data *data = &interface->data;
2202
2203 if (!data)
2204 return;
2205
2206 if (has_cap(ACER_CAP_MAILLED))
2207 set_u32(LED_OFF, ACER_CAP_MAILLED);
2208}
2209
2210static struct platform_driver acer_platform_driver = {
2211 .driver = {
2212 .name = "acer-wmi",
2213 .pm = &acer_pm,
2214 },
2215 .probe = acer_platform_probe,
2216 .remove = acer_platform_remove,
2217 .shutdown = acer_platform_shutdown,
2218};
2219
2220static struct platform_device *acer_platform_device;
2221
2222static void remove_debugfs(void)
2223{
David Brazdil0f672f62019-12-10 10:32:29 +00002224 debugfs_remove_recursive(interface->debug.root);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002225}
2226
David Brazdil0f672f62019-12-10 10:32:29 +00002227static void __init create_debugfs(void)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002228{
2229 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002230
David Brazdil0f672f62019-12-10 10:32:29 +00002231 debugfs_create_u32("devices", S_IRUGO, interface->debug.root,
2232 &interface->debug.wmid_devices);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002233}
2234
2235static int __init acer_wmi_init(void)
2236{
2237 int err;
2238
2239 pr_info("Acer Laptop ACPI-WMI Extras\n");
2240
2241 if (dmi_check_system(acer_blacklist)) {
2242 pr_info("Blacklisted hardware detected - not loading\n");
2243 return -ENODEV;
2244 }
2245
2246 find_quirks();
2247
2248 /*
2249 * The AMW0_GUID1 wmi is not only found on Acer family but also other
2250 * machines like Lenovo, Fujitsu and Medion. In the past days,
2251 * acer-wmi driver handled those non-Acer machines by quirks list.
2252 * But actually acer-wmi driver was loaded on any machines that have
2253 * AMW0_GUID1. This behavior is strange because those machines should
2254 * be supported by appropriate wmi drivers. e.g. fujitsu-laptop,
2255 * ideapad-laptop. So, here checks the machine that has AMW0_GUID1
2256 * should be in Acer/Gateway/Packard Bell white list, or it's already
2257 * in the past quirk list.
2258 */
2259 if (wmi_has_guid(AMW0_GUID1) &&
2260 !dmi_check_system(amw0_whitelist) &&
2261 quirks == &quirk_unknown) {
2262 pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n");
2263 return -ENODEV;
2264 }
2265
2266 /*
2267 * Detect which ACPI-WMI interface we're using.
2268 */
2269 if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
2270 interface = &AMW0_V2_interface;
2271
2272 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
2273 interface = &wmid_interface;
2274
2275 if (wmi_has_guid(WMID_GUID3))
2276 interface = &wmid_v2_interface;
2277
2278 if (interface)
2279 dmi_walk(type_aa_dmi_decode, NULL);
2280
2281 if (wmi_has_guid(WMID_GUID2) && interface) {
2282 if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
2283 pr_err("Unable to detect available WMID devices\n");
2284 return -ENODEV;
2285 }
2286 /* WMID always provides brightness methods */
2287 interface->capability |= ACER_CAP_BRIGHTNESS;
Olivier Deprez0e641232021-09-23 10:07:05 +02002288 } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa && force_caps == -1) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002289 pr_err("No WMID device detection method found\n");
2290 return -ENODEV;
2291 }
2292
2293 if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) {
2294 interface = &AMW0_interface;
2295
2296 if (ACPI_FAILURE(AMW0_set_capabilities())) {
2297 pr_err("Unable to detect available AMW0 devices\n");
2298 return -ENODEV;
2299 }
2300 }
2301
2302 if (wmi_has_guid(AMW0_GUID1))
2303 AMW0_find_mailled();
2304
2305 if (!interface) {
2306 pr_err("No or unsupported WMI interface, unable to load\n");
2307 return -ENODEV;
2308 }
2309
2310 set_quirks();
2311
2312 if (dmi_check_system(video_vendor_dmi_table))
2313 acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
2314
2315 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
2316 interface->capability &= ~ACER_CAP_BRIGHTNESS;
2317
Olivier Deprez0e641232021-09-23 10:07:05 +02002318 if (wmi_has_guid(WMID_GUID3))
2319 interface->capability |= ACER_CAP_SET_FUNCTION_MODE;
2320
2321 if (force_caps != -1)
2322 interface->capability = force_caps;
2323
2324 if (wmi_has_guid(WMID_GUID3) &&
2325 (interface->capability & ACER_CAP_SET_FUNCTION_MODE)) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002326 if (ACPI_FAILURE(acer_wmi_enable_rf_button()))
2327 pr_warn("Cannot enable RF Button Driver\n");
2328
2329 if (ec_raw_mode) {
2330 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
2331 pr_err("Cannot enable EC raw mode\n");
2332 return -ENODEV;
2333 }
2334 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
2335 pr_err("Cannot enable Launch Manager mode\n");
2336 return -ENODEV;
2337 }
2338 } else if (ec_raw_mode) {
2339 pr_info("No WMID EC raw mode enable method\n");
2340 }
2341
2342 if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
2343 err = acer_wmi_input_setup();
2344 if (err)
2345 return err;
2346 err = acer_wmi_accel_setup();
2347 if (err && err != -ENODEV)
2348 pr_warn("Cannot enable accelerometer\n");
2349 }
2350
2351 err = platform_driver_register(&acer_platform_driver);
2352 if (err) {
2353 pr_err("Unable to register platform driver\n");
2354 goto error_platform_register;
2355 }
2356
2357 acer_platform_device = platform_device_alloc("acer-wmi", -1);
2358 if (!acer_platform_device) {
2359 err = -ENOMEM;
2360 goto error_device_alloc;
2361 }
2362
2363 err = platform_device_add(acer_platform_device);
2364 if (err)
2365 goto error_device_add;
2366
2367 if (wmi_has_guid(WMID_GUID2)) {
2368 interface->debug.wmid_devices = get_wmid_devices();
David Brazdil0f672f62019-12-10 10:32:29 +00002369 create_debugfs();
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002370 }
2371
2372 /* Override any initial settings with values from the commandline */
2373 acer_commandline_init();
2374
2375 return 0;
2376
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002377error_device_add:
2378 platform_device_put(acer_platform_device);
2379error_device_alloc:
2380 platform_driver_unregister(&acer_platform_driver);
2381error_platform_register:
2382 if (wmi_has_guid(ACERWMID_EVENT_GUID))
2383 acer_wmi_input_destroy();
Olivier Deprez0e641232021-09-23 10:07:05 +02002384 if (acer_wmi_accel_dev)
2385 input_unregister_device(acer_wmi_accel_dev);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002386
2387 return err;
2388}
2389
2390static void __exit acer_wmi_exit(void)
2391{
2392 if (wmi_has_guid(ACERWMID_EVENT_GUID))
2393 acer_wmi_input_destroy();
2394
Olivier Deprez0e641232021-09-23 10:07:05 +02002395 if (acer_wmi_accel_dev)
2396 input_unregister_device(acer_wmi_accel_dev);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002397
2398 remove_debugfs();
2399 platform_device_unregister(acer_platform_device);
2400 platform_driver_unregister(&acer_platform_driver);
2401
2402 pr_info("Acer Laptop WMI Extras unloaded\n");
2403 return;
2404}
2405
2406module_init(acer_wmi_init);
2407module_exit(acer_wmi_exit);