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