acer-wmi: Detect communication hot key number
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / platform / x86 / acer-wmi.c
1 /*
2  *  Acer WMI Laptop Extras
3  *
4  *  Copyright (C) 2007-2009     Carlos Corbacho <carlos@strangeworlds.co.uk>
5  *
6  *  Based on acer_acpi:
7  *    Copyright (C) 2005-2007   E.M. Smith
8  *    Copyright (C) 2007-2008   Carlos Corbacho <cathectic@gmail.com>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <linux/dmi.h>
32 #include <linux/fb.h>
33 #include <linux/backlight.h>
34 #include <linux/leds.h>
35 #include <linux/platform_device.h>
36 #include <linux/acpi.h>
37 #include <linux/i8042.h>
38 #include <linux/rfkill.h>
39 #include <linux/workqueue.h>
40 #include <linux/debugfs.h>
41 #include <linux/slab.h>
42 #include <linux/input.h>
43 #include <linux/input/sparse-keymap.h>
44
45 #include <acpi/acpi_drivers.h>
46
47 MODULE_AUTHOR("Carlos Corbacho");
48 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
49 MODULE_LICENSE("GPL");
50
51 /*
52  * Magic Number
53  * Meaning is unknown - this number is required for writing to ACPI for AMW0
54  * (it's also used in acerhk when directly accessing the BIOS)
55  */
56 #define ACER_AMW0_WRITE 0x9610
57
58 /*
59  * Bit masks for the AMW0 interface
60  */
61 #define ACER_AMW0_WIRELESS_MASK  0x35
62 #define ACER_AMW0_BLUETOOTH_MASK 0x34
63 #define ACER_AMW0_MAILLED_MASK   0x31
64
65 /*
66  * Method IDs for WMID interface
67  */
68 #define ACER_WMID_GET_WIRELESS_METHODID         1
69 #define ACER_WMID_GET_BLUETOOTH_METHODID        2
70 #define ACER_WMID_GET_BRIGHTNESS_METHODID       3
71 #define ACER_WMID_SET_WIRELESS_METHODID         4
72 #define ACER_WMID_SET_BLUETOOTH_METHODID        5
73 #define ACER_WMID_SET_BRIGHTNESS_METHODID       6
74 #define ACER_WMID_GET_THREEG_METHODID           10
75 #define ACER_WMID_SET_THREEG_METHODID           11
76
77 /*
78  * Acer ACPI method GUIDs
79  */
80 #define AMW0_GUID1              "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
81 #define AMW0_GUID2              "431F16ED-0C2B-444C-B267-27DEB140CF9C"
82 #define WMID_GUID1              "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
83 #define WMID_GUID2              "95764E09-FB56-4E83-B31A-37761F60994A"
84 #define WMID_GUID3              "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
85
86 /*
87  * Acer ACPI event GUIDs
88  */
89 #define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
90
91 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
92 MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
93 MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
94
95 enum acer_wmi_event_ids {
96         WMID_HOTKEY_EVENT = 0x1,
97 };
98
99 static const struct key_entry acer_wmi_keymap[] = {
100         {KE_KEY, 0x01, {KEY_WLAN} },     /* WiFi */
101         {KE_KEY, 0x03, {KEY_WLAN} },     /* WiFi */
102         {KE_KEY, 0x04, {KEY_WLAN} },     /* WiFi */
103         {KE_KEY, 0x12, {KEY_BLUETOOTH} },       /* BT */
104         {KE_KEY, 0x21, {KEY_PROG1} },    /* Backup */
105         {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
106         {KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
107         {KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
108         {KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
109         {KE_IGNORE, 0x41, {KEY_MUTE} },
110         {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
111         {KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },
112         {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
113         {KE_IGNORE, 0x4e, {KEY_NEXTSONG} },
114         {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
115         {KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },
116         {KE_IGNORE, 0x45, {KEY_STOP} },
117         {KE_IGNORE, 0x50, {KEY_STOP} },
118         {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
119         {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
120         {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
121         {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
122         {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
123         {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
124         {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
125         {KE_IGNORE, 0x81, {KEY_SLEEP} },
126         {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
127         {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
128         {KE_END, 0}
129 };
130
131 static struct input_dev *acer_wmi_input_dev;
132
133 struct event_return_value {
134         u8 function;
135         u8 key_num;
136         u16 device_state;
137         u32 reserved;
138 } __attribute__((packed));
139
140 /*
141  * GUID3 Get Device Status device flags
142  */
143 #define ACER_WMID3_GDS_WIRELESS         (1<<0)  /* WiFi */
144 #define ACER_WMID3_GDS_THREEG           (1<<6)  /* 3G */
145 #define ACER_WMID3_GDS_WIMAX            (1<<7)  /* WiMAX */
146 #define ACER_WMID3_GDS_BLUETOOTH        (1<<11) /* BT */
147
148 struct lm_input_params {
149         u8 function_num;        /* Function Number */
150         u16 commun_devices;     /* Communication type devices default status */
151         u16 devices;            /* Other type devices default status */
152         u8 lm_status;           /* Launch Manager Status */
153         u16 reserved;
154 } __attribute__((packed));
155
156 struct lm_return_value {
157         u8 error_code;          /* Error Code */
158         u8 ec_return_value;     /* EC Return Value */
159         u16 reserved;
160 } __attribute__((packed));
161
162 struct wmid3_gds_input_param {  /* Get Device Status input parameter */
163         u8 function_num;        /* Function Number */
164         u8 hotkey_number;       /* Hotkey Number */
165         u16 devices;            /* Get Device */
166 } __attribute__((packed));
167
168 struct wmid3_gds_return_value { /* Get Device Status return value*/
169         u8 error_code;          /* Error Code */
170         u8 ec_return_value;     /* EC Return Value */
171         u16 devices;            /* Current Device Status */
172         u32 reserved;
173 } __attribute__((packed));
174
175 struct hotkey_function_type_aa {
176         u8 type;
177         u8 length;
178         u16 handle;
179         u16 commun_func_bitmap;
180         u16 application_func_bitmap;
181         u16 media_func_bitmap;
182         u16 display_func_bitmap;
183         u16 others_func_bitmap;
184         u8 commun_fn_key_number;
185 } __attribute__((packed));
186
187 /*
188  * Interface capability flags
189  */
190 #define ACER_CAP_MAILLED                (1<<0)
191 #define ACER_CAP_WIRELESS               (1<<1)
192 #define ACER_CAP_BLUETOOTH              (1<<2)
193 #define ACER_CAP_BRIGHTNESS             (1<<3)
194 #define ACER_CAP_THREEG                 (1<<4)
195 #define ACER_CAP_ANY                    (0xFFFFFFFF)
196
197 /*
198  * Interface type flags
199  */
200 enum interface_flags {
201         ACER_AMW0,
202         ACER_AMW0_V2,
203         ACER_WMID,
204         ACER_WMID_v2,
205 };
206
207 #define ACER_DEFAULT_WIRELESS  0
208 #define ACER_DEFAULT_BLUETOOTH 0
209 #define ACER_DEFAULT_MAILLED   0
210 #define ACER_DEFAULT_THREEG    0
211
212 static int max_brightness = 0xF;
213
214 static int mailled = -1;
215 static int brightness = -1;
216 static int threeg = -1;
217 static int force_series;
218 static bool ec_raw_mode;
219 static bool has_type_aa;
220 static u16 commun_func_bitmap;
221 static u8 commun_fn_key_number;
222
223 module_param(mailled, int, 0444);
224 module_param(brightness, int, 0444);
225 module_param(threeg, int, 0444);
226 module_param(force_series, int, 0444);
227 module_param(ec_raw_mode, bool, 0444);
228 MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
229 MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
230 MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
231 MODULE_PARM_DESC(force_series, "Force a different laptop series");
232 MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
233
234 struct acer_data {
235         int mailled;
236         int threeg;
237         int brightness;
238 };
239
240 struct acer_debug {
241         struct dentry *root;
242         struct dentry *devices;
243         u32 wmid_devices;
244 };
245
246 static struct rfkill *wireless_rfkill;
247 static struct rfkill *bluetooth_rfkill;
248 static struct rfkill *threeg_rfkill;
249 static bool rfkill_inited;
250
251 /* Each low-level interface must define at least some of the following */
252 struct wmi_interface {
253         /* The WMI device type */
254         u32 type;
255
256         /* The capabilities this interface provides */
257         u32 capability;
258
259         /* Private data for the current interface */
260         struct acer_data data;
261
262         /* debugfs entries associated with this interface */
263         struct acer_debug debug;
264 };
265
266 /* The static interface pointer, points to the currently detected interface */
267 static struct wmi_interface *interface;
268
269 /*
270  * Embedded Controller quirks
271  * Some laptops require us to directly access the EC to either enable or query
272  * features that are not available through WMI.
273  */
274
275 struct quirk_entry {
276         u8 wireless;
277         u8 mailled;
278         s8 brightness;
279         u8 bluetooth;
280 };
281
282 static struct quirk_entry *quirks;
283
284 static void set_quirks(void)
285 {
286         if (!interface)
287                 return;
288
289         if (quirks->mailled)
290                 interface->capability |= ACER_CAP_MAILLED;
291
292         if (quirks->brightness)
293                 interface->capability |= ACER_CAP_BRIGHTNESS;
294 }
295
296 static int dmi_matched(const struct dmi_system_id *dmi)
297 {
298         quirks = dmi->driver_data;
299         return 1;
300 }
301
302 static struct quirk_entry quirk_unknown = {
303 };
304
305 static struct quirk_entry quirk_acer_aspire_1520 = {
306         .brightness = -1,
307 };
308
309 static struct quirk_entry quirk_acer_travelmate_2490 = {
310         .mailled = 1,
311 };
312
313 /* This AMW0 laptop has no bluetooth */
314 static struct quirk_entry quirk_medion_md_98300 = {
315         .wireless = 1,
316 };
317
318 static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
319         .wireless = 2,
320 };
321
322 static struct quirk_entry quirk_lenovo_ideapad_s205 = {
323         .wireless = 3,
324 };
325
326 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
327 static struct dmi_system_id __devinitdata acer_blacklist[] = {
328         {
329                 .ident = "Acer Aspire One (SSD)",
330                 .matches = {
331                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
332                         DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
333                 },
334         },
335         {
336                 .ident = "Acer Aspire One (HDD)",
337                 .matches = {
338                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
339                         DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
340                 },
341         },
342         {}
343 };
344
345 static struct dmi_system_id acer_quirks[] = {
346         {
347                 .callback = dmi_matched,
348                 .ident = "Acer Aspire 1360",
349                 .matches = {
350                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
351                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
352                 },
353                 .driver_data = &quirk_acer_aspire_1520,
354         },
355         {
356                 .callback = dmi_matched,
357                 .ident = "Acer Aspire 1520",
358                 .matches = {
359                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
360                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),
361                 },
362                 .driver_data = &quirk_acer_aspire_1520,
363         },
364         {
365                 .callback = dmi_matched,
366                 .ident = "Acer Aspire 3100",
367                 .matches = {
368                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
369                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
370                 },
371                 .driver_data = &quirk_acer_travelmate_2490,
372         },
373         {
374                 .callback = dmi_matched,
375                 .ident = "Acer Aspire 3610",
376                 .matches = {
377                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
378                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),
379                 },
380                 .driver_data = &quirk_acer_travelmate_2490,
381         },
382         {
383                 .callback = dmi_matched,
384                 .ident = "Acer Aspire 5100",
385                 .matches = {
386                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
387                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
388                 },
389                 .driver_data = &quirk_acer_travelmate_2490,
390         },
391         {
392                 .callback = dmi_matched,
393                 .ident = "Acer Aspire 5610",
394                 .matches = {
395                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
396                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
397                 },
398                 .driver_data = &quirk_acer_travelmate_2490,
399         },
400         {
401                 .callback = dmi_matched,
402                 .ident = "Acer Aspire 5630",
403                 .matches = {
404                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
405                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
406                 },
407                 .driver_data = &quirk_acer_travelmate_2490,
408         },
409         {
410                 .callback = dmi_matched,
411                 .ident = "Acer Aspire 5650",
412                 .matches = {
413                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
414                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
415                 },
416                 .driver_data = &quirk_acer_travelmate_2490,
417         },
418         {
419                 .callback = dmi_matched,
420                 .ident = "Acer Aspire 5680",
421                 .matches = {
422                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
423                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
424                 },
425                 .driver_data = &quirk_acer_travelmate_2490,
426         },
427         {
428                 .callback = dmi_matched,
429                 .ident = "Acer Aspire 9110",
430                 .matches = {
431                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
432                         DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
433                 },
434                 .driver_data = &quirk_acer_travelmate_2490,
435         },
436         {
437                 .callback = dmi_matched,
438                 .ident = "Acer TravelMate 2490",
439                 .matches = {
440                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
441                         DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
442                 },
443                 .driver_data = &quirk_acer_travelmate_2490,
444         },
445         {
446                 .callback = dmi_matched,
447                 .ident = "Acer TravelMate 4200",
448                 .matches = {
449                         DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
450                         DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"),
451                 },
452                 .driver_data = &quirk_acer_travelmate_2490,
453         },
454         {
455                 .callback = dmi_matched,
456                 .ident = "Fujitsu Siemens Amilo Li 1718",
457                 .matches = {
458                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
459                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),
460                 },
461                 .driver_data = &quirk_fujitsu_amilo_li_1718,
462         },
463         {
464                 .callback = dmi_matched,
465                 .ident = "Medion MD 98300",
466                 .matches = {
467                         DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
468                         DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"),
469                 },
470                 .driver_data = &quirk_medion_md_98300,
471         },
472         {
473                 .callback = dmi_matched,
474                 .ident = "Lenovo Ideapad S205",
475                 .matches = {
476                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
477                         DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
478                 },
479                 .driver_data = &quirk_lenovo_ideapad_s205,
480         },
481         {
482                 .callback = dmi_matched,
483                 .ident = "Lenovo 3000 N200",
484                 .matches = {
485                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
486                         DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
487                 },
488                 .driver_data = &quirk_fujitsu_amilo_li_1718,
489         },
490         {}
491 };
492
493 /* Find which quirks are needed for a particular vendor/ model pair */
494 static void find_quirks(void)
495 {
496         if (!force_series) {
497                 dmi_check_system(acer_quirks);
498         } else if (force_series == 2490) {
499                 quirks = &quirk_acer_travelmate_2490;
500         }
501
502         if (quirks == NULL)
503                 quirks = &quirk_unknown;
504
505         set_quirks();
506 }
507
508 /*
509  * General interface convenience methods
510  */
511
512 static bool has_cap(u32 cap)
513 {
514         if ((interface->capability & cap) != 0)
515                 return 1;
516
517         return 0;
518 }
519
520 /*
521  * AMW0 (V1) interface
522  */
523 struct wmab_args {
524         u32 eax;
525         u32 ebx;
526         u32 ecx;
527         u32 edx;
528 };
529
530 struct wmab_ret {
531         u32 eax;
532         u32 ebx;
533         u32 ecx;
534         u32 edx;
535         u32 eex;
536 };
537
538 static acpi_status wmab_execute(struct wmab_args *regbuf,
539 struct acpi_buffer *result)
540 {
541         struct acpi_buffer input;
542         acpi_status status;
543         input.length = sizeof(struct wmab_args);
544         input.pointer = (u8 *)regbuf;
545
546         status = wmi_evaluate_method(AMW0_GUID1, 1, 1, &input, result);
547
548         return status;
549 }
550
551 static acpi_status AMW0_get_u32(u32 *value, u32 cap)
552 {
553         int err;
554         u8 result;
555
556         switch (cap) {
557         case ACER_CAP_MAILLED:
558                 switch (quirks->mailled) {
559                 default:
560                         err = ec_read(0xA, &result);
561                         if (err)
562                                 return AE_ERROR;
563                         *value = (result >> 7) & 0x1;
564                         return AE_OK;
565                 }
566                 break;
567         case ACER_CAP_WIRELESS:
568                 switch (quirks->wireless) {
569                 case 1:
570                         err = ec_read(0x7B, &result);
571                         if (err)
572                                 return AE_ERROR;
573                         *value = result & 0x1;
574                         return AE_OK;
575                 case 2:
576                         err = ec_read(0x71, &result);
577                         if (err)
578                                 return AE_ERROR;
579                         *value = result & 0x1;
580                         return AE_OK;
581                 case 3:
582                         err = ec_read(0x78, &result);
583                         if (err)
584                                 return AE_ERROR;
585                         *value = result & 0x1;
586                         return AE_OK;
587                 default:
588                         err = ec_read(0xA, &result);
589                         if (err)
590                                 return AE_ERROR;
591                         *value = (result >> 2) & 0x1;
592                         return AE_OK;
593                 }
594                 break;
595         case ACER_CAP_BLUETOOTH:
596                 switch (quirks->bluetooth) {
597                 default:
598                         err = ec_read(0xA, &result);
599                         if (err)
600                                 return AE_ERROR;
601                         *value = (result >> 4) & 0x1;
602                         return AE_OK;
603                 }
604                 break;
605         case ACER_CAP_BRIGHTNESS:
606                 switch (quirks->brightness) {
607                 default:
608                         err = ec_read(0x83, &result);
609                         if (err)
610                                 return AE_ERROR;
611                         *value = result;
612                         return AE_OK;
613                 }
614                 break;
615         default:
616                 return AE_ERROR;
617         }
618         return AE_OK;
619 }
620
621 static acpi_status AMW0_set_u32(u32 value, u32 cap)
622 {
623         struct wmab_args args;
624
625         args.eax = ACER_AMW0_WRITE;
626         args.ebx = value ? (1<<8) : 0;
627         args.ecx = args.edx = 0;
628
629         switch (cap) {
630         case ACER_CAP_MAILLED:
631                 if (value > 1)
632                         return AE_BAD_PARAMETER;
633                 args.ebx |= ACER_AMW0_MAILLED_MASK;
634                 break;
635         case ACER_CAP_WIRELESS:
636                 if (value > 1)
637                         return AE_BAD_PARAMETER;
638                 args.ebx |= ACER_AMW0_WIRELESS_MASK;
639                 break;
640         case ACER_CAP_BLUETOOTH:
641                 if (value > 1)
642                         return AE_BAD_PARAMETER;
643                 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
644                 break;
645         case ACER_CAP_BRIGHTNESS:
646                 if (value > max_brightness)
647                         return AE_BAD_PARAMETER;
648                 switch (quirks->brightness) {
649                 default:
650                         return ec_write(0x83, value);
651                         break;
652                 }
653         default:
654                 return AE_ERROR;
655         }
656
657         /* Actually do the set */
658         return wmab_execute(&args, NULL);
659 }
660
661 static acpi_status AMW0_find_mailled(void)
662 {
663         struct wmab_args args;
664         struct wmab_ret ret;
665         acpi_status status = AE_OK;
666         struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
667         union acpi_object *obj;
668
669         args.eax = 0x86;
670         args.ebx = args.ecx = args.edx = 0;
671
672         status = wmab_execute(&args, &out);
673         if (ACPI_FAILURE(status))
674                 return status;
675
676         obj = (union acpi_object *) out.pointer;
677         if (obj && obj->type == ACPI_TYPE_BUFFER &&
678         obj->buffer.length == sizeof(struct wmab_ret)) {
679                 ret = *((struct wmab_ret *) obj->buffer.pointer);
680         } else {
681                 kfree(out.pointer);
682                 return AE_ERROR;
683         }
684
685         if (ret.eex & 0x1)
686                 interface->capability |= ACER_CAP_MAILLED;
687
688         kfree(out.pointer);
689
690         return AE_OK;
691 }
692
693 static int AMW0_set_cap_acpi_check_device_found;
694
695 static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
696         u32 level, void *context, void **retval)
697 {
698         AMW0_set_cap_acpi_check_device_found = 1;
699         return AE_OK;
700 }
701
702 static const struct acpi_device_id norfkill_ids[] = {
703         { "VPC2004", 0},
704         { "IBM0068", 0},
705         { "LEN0068", 0},
706         { "", 0},
707 };
708
709 static int AMW0_set_cap_acpi_check_device(void)
710 {
711         const struct acpi_device_id *id;
712
713         for (id = norfkill_ids; id->id[0]; id++)
714                 acpi_get_devices(id->id, AMW0_set_cap_acpi_check_device_cb,
715                                 NULL, NULL);
716         return AMW0_set_cap_acpi_check_device_found;
717 }
718
719 static acpi_status AMW0_set_capabilities(void)
720 {
721         struct wmab_args args;
722         struct wmab_ret ret;
723         acpi_status status;
724         struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
725         union acpi_object *obj;
726
727         /*
728          * On laptops with this strange GUID (non Acer), normal probing doesn't
729          * work.
730          */
731         if (wmi_has_guid(AMW0_GUID2)) {
732                 if ((quirks != &quirk_unknown) ||
733                     !AMW0_set_cap_acpi_check_device())
734                         interface->capability |= ACER_CAP_WIRELESS;
735                 return AE_OK;
736         }
737
738         args.eax = ACER_AMW0_WRITE;
739         args.ecx = args.edx = 0;
740
741         args.ebx = 0xa2 << 8;
742         args.ebx |= ACER_AMW0_WIRELESS_MASK;
743
744         status = wmab_execute(&args, &out);
745         if (ACPI_FAILURE(status))
746                 return status;
747
748         obj = out.pointer;
749         if (obj && obj->type == ACPI_TYPE_BUFFER &&
750         obj->buffer.length == sizeof(struct wmab_ret)) {
751                 ret = *((struct wmab_ret *) obj->buffer.pointer);
752         } else {
753                 status = AE_ERROR;
754                 goto out;
755         }
756
757         if (ret.eax & 0x1)
758                 interface->capability |= ACER_CAP_WIRELESS;
759
760         args.ebx = 2 << 8;
761         args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
762
763         /*
764          * It's ok to use existing buffer for next wmab_execute call.
765          * But we need to kfree(out.pointer) if next wmab_execute fail.
766          */
767         status = wmab_execute(&args, &out);
768         if (ACPI_FAILURE(status))
769                 goto out;
770
771         obj = (union acpi_object *) out.pointer;
772         if (obj && obj->type == ACPI_TYPE_BUFFER
773         && obj->buffer.length == sizeof(struct wmab_ret)) {
774                 ret = *((struct wmab_ret *) obj->buffer.pointer);
775         } else {
776                 status = AE_ERROR;
777                 goto out;
778         }
779
780         if (ret.eax & 0x1)
781                 interface->capability |= ACER_CAP_BLUETOOTH;
782
783         /*
784          * This appears to be safe to enable, since all Wistron based laptops
785          * appear to use the same EC register for brightness, even if they
786          * differ for wireless, etc
787          */
788         if (quirks->brightness >= 0)
789                 interface->capability |= ACER_CAP_BRIGHTNESS;
790
791         status = AE_OK;
792 out:
793         kfree(out.pointer);
794         return status;
795 }
796
797 static struct wmi_interface AMW0_interface = {
798         .type = ACER_AMW0,
799 };
800
801 static struct wmi_interface AMW0_V2_interface = {
802         .type = ACER_AMW0_V2,
803 };
804
805 /*
806  * New interface (The WMID interface)
807  */
808 static acpi_status
809 WMI_execute_u32(u32 method_id, u32 in, u32 *out)
810 {
811         struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
812         struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
813         union acpi_object *obj;
814         u32 tmp;
815         acpi_status status;
816
817         status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result);
818
819         if (ACPI_FAILURE(status))
820                 return status;
821
822         obj = (union acpi_object *) result.pointer;
823         if (obj && obj->type == ACPI_TYPE_BUFFER &&
824                 (obj->buffer.length == sizeof(u32) ||
825                 obj->buffer.length == sizeof(u64))) {
826                 tmp = *((u32 *) obj->buffer.pointer);
827         } else if (obj->type == ACPI_TYPE_INTEGER) {
828                 tmp = (u32) obj->integer.value;
829         } else {
830                 tmp = 0;
831         }
832
833         if (out)
834                 *out = tmp;
835
836         kfree(result.pointer);
837
838         return status;
839 }
840
841 static acpi_status WMID_get_u32(u32 *value, u32 cap)
842 {
843         acpi_status status;
844         u8 tmp;
845         u32 result, method_id = 0;
846
847         switch (cap) {
848         case ACER_CAP_WIRELESS:
849                 method_id = ACER_WMID_GET_WIRELESS_METHODID;
850                 break;
851         case ACER_CAP_BLUETOOTH:
852                 method_id = ACER_WMID_GET_BLUETOOTH_METHODID;
853                 break;
854         case ACER_CAP_BRIGHTNESS:
855                 method_id = ACER_WMID_GET_BRIGHTNESS_METHODID;
856                 break;
857         case ACER_CAP_THREEG:
858                 method_id = ACER_WMID_GET_THREEG_METHODID;
859                 break;
860         case ACER_CAP_MAILLED:
861                 if (quirks->mailled == 1) {
862                         ec_read(0x9f, &tmp);
863                         *value = tmp & 0x1;
864                         return 0;
865                 }
866         default:
867                 return AE_ERROR;
868         }
869         status = WMI_execute_u32(method_id, 0, &result);
870
871         if (ACPI_SUCCESS(status))
872                 *value = (u8)result;
873
874         return status;
875 }
876
877 static acpi_status WMID_set_u32(u32 value, u32 cap)
878 {
879         u32 method_id = 0;
880         char param;
881
882         switch (cap) {
883         case ACER_CAP_BRIGHTNESS:
884                 if (value > max_brightness)
885                         return AE_BAD_PARAMETER;
886                 method_id = ACER_WMID_SET_BRIGHTNESS_METHODID;
887                 break;
888         case ACER_CAP_WIRELESS:
889                 if (value > 1)
890                         return AE_BAD_PARAMETER;
891                 method_id = ACER_WMID_SET_WIRELESS_METHODID;
892                 break;
893         case ACER_CAP_BLUETOOTH:
894                 if (value > 1)
895                         return AE_BAD_PARAMETER;
896                 method_id = ACER_WMID_SET_BLUETOOTH_METHODID;
897                 break;
898         case ACER_CAP_THREEG:
899                 if (value > 1)
900                         return AE_BAD_PARAMETER;
901                 method_id = ACER_WMID_SET_THREEG_METHODID;
902                 break;
903         case ACER_CAP_MAILLED:
904                 if (value > 1)
905                         return AE_BAD_PARAMETER;
906                 if (quirks->mailled == 1) {
907                         param = value ? 0x92 : 0x93;
908                         i8042_lock_chip();
909                         i8042_command(&param, 0x1059);
910                         i8042_unlock_chip();
911                         return 0;
912                 }
913                 break;
914         default:
915                 return AE_ERROR;
916         }
917         return WMI_execute_u32(method_id, (u32)value, NULL);
918 }
919
920 static acpi_status wmid3_get_device_status(u32 *value, u16 device)
921 {
922         struct wmid3_gds_return_value return_value;
923         acpi_status status;
924         union acpi_object *obj;
925         struct wmid3_gds_input_param params = {
926                 .function_num = 0x1,
927                 .hotkey_number = commun_fn_key_number,
928                 .devices = device,
929         };
930         struct acpi_buffer input = {
931                 sizeof(struct wmid3_gds_input_param),
932                 &params
933         };
934         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
935
936         status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
937         if (ACPI_FAILURE(status))
938                 return status;
939
940         obj = output.pointer;
941
942         if (!obj)
943                 return AE_ERROR;
944         else if (obj->type != ACPI_TYPE_BUFFER) {
945                 kfree(obj);
946                 return AE_ERROR;
947         }
948         if (obj->buffer.length != 8) {
949                 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
950                 kfree(obj);
951                 return AE_ERROR;
952         }
953
954         return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
955         kfree(obj);
956
957         if (return_value.error_code || return_value.ec_return_value)
958                 pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
959                         device,
960                         return_value.error_code,
961                         return_value.ec_return_value);
962         else
963                 *value = !!(return_value.devices & device);
964
965         return status;
966 }
967
968 static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
969 {
970         u16 device;
971
972         switch (cap) {
973         case ACER_CAP_WIRELESS:
974                 device = ACER_WMID3_GDS_WIRELESS;
975                 break;
976         case ACER_CAP_BLUETOOTH:
977                 device = ACER_WMID3_GDS_BLUETOOTH;
978                 break;
979         case ACER_CAP_THREEG:
980                 device = ACER_WMID3_GDS_THREEG;
981                 break;
982         default:
983                 return AE_ERROR;
984         }
985         return wmid3_get_device_status(value, device);
986 }
987
988 static acpi_status wmid3_set_device_status(u32 value, u16 device)
989 {
990         struct wmid3_gds_return_value return_value;
991         acpi_status status;
992         union acpi_object *obj;
993         u16 devices;
994         struct wmid3_gds_input_param params = {
995                 .function_num = 0x1,
996                 .hotkey_number = commun_fn_key_number,
997                 .devices = commun_func_bitmap,
998         };
999         struct acpi_buffer input = {
1000                 sizeof(struct wmid3_gds_input_param),
1001                 &params
1002         };
1003         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1004         struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1005
1006         status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1007         if (ACPI_FAILURE(status))
1008                 return status;
1009
1010         obj = output.pointer;
1011
1012         if (!obj)
1013                 return AE_ERROR;
1014         else if (obj->type != ACPI_TYPE_BUFFER) {
1015                 kfree(obj);
1016                 return AE_ERROR;
1017         }
1018         if (obj->buffer.length != 8) {
1019                 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1020                 kfree(obj);
1021                 return AE_ERROR;
1022         }
1023
1024         return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1025         kfree(obj);
1026
1027         if (return_value.error_code || return_value.ec_return_value) {
1028                 pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",
1029                         return_value.error_code,
1030                         return_value.ec_return_value);
1031                 return status;
1032         }
1033
1034         devices = return_value.devices;
1035         params.function_num = 0x2;
1036         params.hotkey_number = commun_fn_key_number;
1037         params.devices = (value) ? (devices | device) : (devices & ~device);
1038
1039         status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1040         if (ACPI_FAILURE(status))
1041                 return status;
1042
1043         obj = output2.pointer;
1044
1045         if (!obj)
1046                 return AE_ERROR;
1047         else if (obj->type != ACPI_TYPE_BUFFER) {
1048                 kfree(obj);
1049                 return AE_ERROR;
1050         }
1051         if (obj->buffer.length != 4) {
1052                 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1053                 kfree(obj);
1054                 return AE_ERROR;
1055         }
1056
1057         return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1058         kfree(obj);
1059
1060         if (return_value.error_code || return_value.ec_return_value)
1061                 pr_warn("Set Device Status failed: 0x%x - 0x%x\n",
1062                         return_value.error_code,
1063                         return_value.ec_return_value);
1064
1065         return status;
1066 }
1067
1068 static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1069 {
1070         u16 device;
1071
1072         switch (cap) {
1073         case ACER_CAP_WIRELESS:
1074                 device = ACER_WMID3_GDS_WIRELESS;
1075                 break;
1076         case ACER_CAP_BLUETOOTH:
1077                 device = ACER_WMID3_GDS_BLUETOOTH;
1078                 break;
1079         case ACER_CAP_THREEG:
1080                 device = ACER_WMID3_GDS_THREEG;
1081                 break;
1082         default:
1083                 return AE_ERROR;
1084         }
1085         return wmid3_set_device_status(value, device);
1086 }
1087
1088 static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
1089 {
1090         struct hotkey_function_type_aa *type_aa;
1091
1092         /* We are looking for OEM-specific Type AAh */
1093         if (header->type != 0xAA)
1094                 return;
1095
1096         has_type_aa = true;
1097         type_aa = (struct hotkey_function_type_aa *) header;
1098
1099         pr_info("Function bitmap for Communication Button: 0x%x\n",
1100                 type_aa->commun_func_bitmap);
1101         commun_func_bitmap = type_aa->commun_func_bitmap;
1102
1103         if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
1104                 interface->capability |= ACER_CAP_WIRELESS;
1105         if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
1106                 interface->capability |= ACER_CAP_THREEG;
1107         if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
1108                 interface->capability |= ACER_CAP_BLUETOOTH;
1109
1110         commun_fn_key_number = type_aa->commun_fn_key_number;
1111 }
1112
1113 static acpi_status WMID_set_capabilities(void)
1114 {
1115         struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1116         union acpi_object *obj;
1117         acpi_status status;
1118         u32 devices;
1119
1120         status = wmi_query_block(WMID_GUID2, 1, &out);
1121         if (ACPI_FAILURE(status))
1122                 return status;
1123
1124         obj = (union acpi_object *) out.pointer;
1125         if (obj && obj->type == ACPI_TYPE_BUFFER &&
1126                 (obj->buffer.length == sizeof(u32) ||
1127                 obj->buffer.length == sizeof(u64))) {
1128                 devices = *((u32 *) obj->buffer.pointer);
1129         } else if (obj->type == ACPI_TYPE_INTEGER) {
1130                 devices = (u32) obj->integer.value;
1131         } else {
1132                 kfree(out.pointer);
1133                 return AE_ERROR;
1134         }
1135
1136         pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
1137         if (devices & 0x07)
1138                 interface->capability |= ACER_CAP_WIRELESS;
1139         if (devices & 0x40)
1140                 interface->capability |= ACER_CAP_THREEG;
1141         if (devices & 0x10)
1142                 interface->capability |= ACER_CAP_BLUETOOTH;
1143
1144         if (!(devices & 0x20))
1145                 max_brightness = 0x9;
1146
1147         kfree(out.pointer);
1148         return status;
1149 }
1150
1151 static struct wmi_interface wmid_interface = {
1152         .type = ACER_WMID,
1153 };
1154
1155 static struct wmi_interface wmid_v2_interface = {
1156         .type = ACER_WMID_v2,
1157 };
1158
1159 /*
1160  * Generic Device (interface-independent)
1161  */
1162
1163 static acpi_status get_u32(u32 *value, u32 cap)
1164 {
1165         acpi_status status = AE_ERROR;
1166
1167         switch (interface->type) {
1168         case ACER_AMW0:
1169                 status = AMW0_get_u32(value, cap);
1170                 break;
1171         case ACER_AMW0_V2:
1172                 if (cap == ACER_CAP_MAILLED) {
1173                         status = AMW0_get_u32(value, cap);
1174                         break;
1175                 }
1176         case ACER_WMID:
1177                 status = WMID_get_u32(value, cap);
1178                 break;
1179         case ACER_WMID_v2:
1180                 if (cap & (ACER_CAP_WIRELESS |
1181                            ACER_CAP_BLUETOOTH |
1182                            ACER_CAP_THREEG))
1183                         status = wmid_v2_get_u32(value, cap);
1184                 else if (wmi_has_guid(WMID_GUID2))
1185                         status = WMID_get_u32(value, cap);
1186                 break;
1187         }
1188
1189         return status;
1190 }
1191
1192 static acpi_status set_u32(u32 value, u32 cap)
1193 {
1194         acpi_status status;
1195
1196         if (interface->capability & cap) {
1197                 switch (interface->type) {
1198                 case ACER_AMW0:
1199                         return AMW0_set_u32(value, cap);
1200                 case ACER_AMW0_V2:
1201                         if (cap == ACER_CAP_MAILLED)
1202                                 return AMW0_set_u32(value, cap);
1203
1204                         /*
1205                          * On some models, some WMID methods don't toggle
1206                          * properly. For those cases, we want to run the AMW0
1207                          * method afterwards to be certain we've really toggled
1208                          * the device state.
1209                          */
1210                         if (cap == ACER_CAP_WIRELESS ||
1211                                 cap == ACER_CAP_BLUETOOTH) {
1212                                 status = WMID_set_u32(value, cap);
1213                                 if (ACPI_FAILURE(status))
1214                                         return status;
1215
1216                                 return AMW0_set_u32(value, cap);
1217                         }
1218                 case ACER_WMID:
1219                         return WMID_set_u32(value, cap);
1220                 case ACER_WMID_v2:
1221                         if (cap & (ACER_CAP_WIRELESS |
1222                                    ACER_CAP_BLUETOOTH |
1223                                    ACER_CAP_THREEG))
1224                                 return wmid_v2_set_u32(value, cap);
1225                         else if (wmi_has_guid(WMID_GUID2))
1226                                 return WMID_set_u32(value, cap);
1227                 default:
1228                         return AE_BAD_PARAMETER;
1229                 }
1230         }
1231         return AE_BAD_PARAMETER;
1232 }
1233
1234 static void __init acer_commandline_init(void)
1235 {
1236         /*
1237          * These will all fail silently if the value given is invalid, or the
1238          * capability isn't available on the given interface
1239          */
1240         if (mailled >= 0)
1241                 set_u32(mailled, ACER_CAP_MAILLED);
1242         if (!has_type_aa && threeg >= 0)
1243                 set_u32(threeg, ACER_CAP_THREEG);
1244         if (brightness >= 0)
1245                 set_u32(brightness, ACER_CAP_BRIGHTNESS);
1246 }
1247
1248 /*
1249  * LED device (Mail LED only, no other LEDs known yet)
1250  */
1251 static void mail_led_set(struct led_classdev *led_cdev,
1252 enum led_brightness value)
1253 {
1254         set_u32(value, ACER_CAP_MAILLED);
1255 }
1256
1257 static struct led_classdev mail_led = {
1258         .name = "acer-wmi::mail",
1259         .brightness_set = mail_led_set,
1260 };
1261
1262 static int __devinit acer_led_init(struct device *dev)
1263 {
1264         return led_classdev_register(dev, &mail_led);
1265 }
1266
1267 static void acer_led_exit(void)
1268 {
1269         set_u32(LED_OFF, ACER_CAP_MAILLED);
1270         led_classdev_unregister(&mail_led);
1271 }
1272
1273 /*
1274  * Backlight device
1275  */
1276 static struct backlight_device *acer_backlight_device;
1277
1278 static int read_brightness(struct backlight_device *bd)
1279 {
1280         u32 value;
1281         get_u32(&value, ACER_CAP_BRIGHTNESS);
1282         return value;
1283 }
1284
1285 static int update_bl_status(struct backlight_device *bd)
1286 {
1287         int intensity = bd->props.brightness;
1288
1289         if (bd->props.power != FB_BLANK_UNBLANK)
1290                 intensity = 0;
1291         if (bd->props.fb_blank != FB_BLANK_UNBLANK)
1292                 intensity = 0;
1293
1294         set_u32(intensity, ACER_CAP_BRIGHTNESS);
1295
1296         return 0;
1297 }
1298
1299 static const struct backlight_ops acer_bl_ops = {
1300         .get_brightness = read_brightness,
1301         .update_status = update_bl_status,
1302 };
1303
1304 static int __devinit acer_backlight_init(struct device *dev)
1305 {
1306         struct backlight_properties props;
1307         struct backlight_device *bd;
1308
1309         memset(&props, 0, sizeof(struct backlight_properties));
1310         props.type = BACKLIGHT_PLATFORM;
1311         props.max_brightness = max_brightness;
1312         bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
1313                                        &props);
1314         if (IS_ERR(bd)) {
1315                 pr_err("Could not register Acer backlight device\n");
1316                 acer_backlight_device = NULL;
1317                 return PTR_ERR(bd);
1318         }
1319
1320         acer_backlight_device = bd;
1321
1322         bd->props.power = FB_BLANK_UNBLANK;
1323         bd->props.brightness = read_brightness(bd);
1324         backlight_update_status(bd);
1325         return 0;
1326 }
1327
1328 static void acer_backlight_exit(void)
1329 {
1330         backlight_device_unregister(acer_backlight_device);
1331 }
1332
1333 /*
1334  * Rfkill devices
1335  */
1336 static void acer_rfkill_update(struct work_struct *ignored);
1337 static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
1338 static void acer_rfkill_update(struct work_struct *ignored)
1339 {
1340         u32 state;
1341         acpi_status status;
1342
1343         if (has_cap(ACER_CAP_WIRELESS)) {
1344                 status = get_u32(&state, ACER_CAP_WIRELESS);
1345                 if (ACPI_SUCCESS(status)) {
1346                         if (quirks->wireless == 3)
1347                                 rfkill_set_hw_state(wireless_rfkill, !state);
1348                         else
1349                                 rfkill_set_sw_state(wireless_rfkill, !state);
1350                 }
1351         }
1352
1353         if (has_cap(ACER_CAP_BLUETOOTH)) {
1354                 status = get_u32(&state, ACER_CAP_BLUETOOTH);
1355                 if (ACPI_SUCCESS(status))
1356                         rfkill_set_sw_state(bluetooth_rfkill, !state);
1357         }
1358
1359         if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1360                 status = get_u32(&state, ACER_WMID3_GDS_THREEG);
1361                 if (ACPI_SUCCESS(status))
1362                         rfkill_set_sw_state(threeg_rfkill, !state);
1363         }
1364
1365         schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
1366 }
1367
1368 static int acer_rfkill_set(void *data, bool blocked)
1369 {
1370         acpi_status status;
1371         u32 cap = (unsigned long)data;
1372
1373         if (rfkill_inited) {
1374                 status = set_u32(!blocked, cap);
1375                 if (ACPI_FAILURE(status))
1376                         return -ENODEV;
1377         }
1378
1379         return 0;
1380 }
1381
1382 static const struct rfkill_ops acer_rfkill_ops = {
1383         .set_block = acer_rfkill_set,
1384 };
1385
1386 static struct rfkill *acer_rfkill_register(struct device *dev,
1387                                            enum rfkill_type type,
1388                                            char *name, u32 cap)
1389 {
1390         int err;
1391         struct rfkill *rfkill_dev;
1392         u32 state;
1393         acpi_status status;
1394
1395         rfkill_dev = rfkill_alloc(name, dev, type,
1396                                   &acer_rfkill_ops,
1397                                   (void *)(unsigned long)cap);
1398         if (!rfkill_dev)
1399                 return ERR_PTR(-ENOMEM);
1400
1401         status = get_u32(&state, cap);
1402
1403         err = rfkill_register(rfkill_dev);
1404         if (err) {
1405                 rfkill_destroy(rfkill_dev);
1406                 return ERR_PTR(err);
1407         }
1408
1409         if (ACPI_SUCCESS(status))
1410                 rfkill_set_sw_state(rfkill_dev, !state);
1411
1412         return rfkill_dev;
1413 }
1414
1415 static int acer_rfkill_init(struct device *dev)
1416 {
1417         int err;
1418
1419         if (has_cap(ACER_CAP_WIRELESS)) {
1420                 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
1421                         "acer-wireless", ACER_CAP_WIRELESS);
1422                 if (IS_ERR(wireless_rfkill)) {
1423                         err = PTR_ERR(wireless_rfkill);
1424                         goto error_wireless;
1425                 }
1426         }
1427
1428         if (has_cap(ACER_CAP_BLUETOOTH)) {
1429                 bluetooth_rfkill = acer_rfkill_register(dev,
1430                         RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
1431                         ACER_CAP_BLUETOOTH);
1432                 if (IS_ERR(bluetooth_rfkill)) {
1433                         err = PTR_ERR(bluetooth_rfkill);
1434                         goto error_bluetooth;
1435                 }
1436         }
1437
1438         if (has_cap(ACER_CAP_THREEG)) {
1439                 threeg_rfkill = acer_rfkill_register(dev,
1440                         RFKILL_TYPE_WWAN, "acer-threeg",
1441                         ACER_CAP_THREEG);
1442                 if (IS_ERR(threeg_rfkill)) {
1443                         err = PTR_ERR(threeg_rfkill);
1444                         goto error_threeg;
1445                 }
1446         }
1447
1448         rfkill_inited = true;
1449
1450         if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1451             has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1452                 schedule_delayed_work(&acer_rfkill_work,
1453                         round_jiffies_relative(HZ));
1454
1455         return 0;
1456
1457 error_threeg:
1458         if (has_cap(ACER_CAP_BLUETOOTH)) {
1459                 rfkill_unregister(bluetooth_rfkill);
1460                 rfkill_destroy(bluetooth_rfkill);
1461         }
1462 error_bluetooth:
1463         if (has_cap(ACER_CAP_WIRELESS)) {
1464                 rfkill_unregister(wireless_rfkill);
1465                 rfkill_destroy(wireless_rfkill);
1466         }
1467 error_wireless:
1468         return err;
1469 }
1470
1471 static void acer_rfkill_exit(void)
1472 {
1473         if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1474             has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1475                 cancel_delayed_work_sync(&acer_rfkill_work);
1476
1477         if (has_cap(ACER_CAP_WIRELESS)) {
1478                 rfkill_unregister(wireless_rfkill);
1479                 rfkill_destroy(wireless_rfkill);
1480         }
1481
1482         if (has_cap(ACER_CAP_BLUETOOTH)) {
1483                 rfkill_unregister(bluetooth_rfkill);
1484                 rfkill_destroy(bluetooth_rfkill);
1485         }
1486
1487         if (has_cap(ACER_CAP_THREEG)) {
1488                 rfkill_unregister(threeg_rfkill);
1489                 rfkill_destroy(threeg_rfkill);
1490         }
1491         return;
1492 }
1493
1494 /*
1495  * sysfs interface
1496  */
1497 static ssize_t show_bool_threeg(struct device *dev,
1498         struct device_attribute *attr, char *buf)
1499 {
1500         u32 result; \
1501         acpi_status status;
1502
1503         pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
1504                 current->comm);
1505         status = get_u32(&result, ACER_CAP_THREEG);
1506         if (ACPI_SUCCESS(status))
1507                 return sprintf(buf, "%u\n", result);
1508         return sprintf(buf, "Read error\n");
1509 }
1510
1511 static ssize_t set_bool_threeg(struct device *dev,
1512         struct device_attribute *attr, const char *buf, size_t count)
1513 {
1514         u32 tmp = simple_strtoul(buf, NULL, 10);
1515         acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
1516         pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
1517                 current->comm);
1518         if (ACPI_FAILURE(status))
1519                 return -EINVAL;
1520         return count;
1521 }
1522 static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1523         set_bool_threeg);
1524
1525 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1526         char *buf)
1527 {
1528         pr_info("This interface sysfs will be removed in 2012 - used by: %s\n",
1529                 current->comm);
1530         switch (interface->type) {
1531         case ACER_AMW0:
1532                 return sprintf(buf, "AMW0\n");
1533         case ACER_AMW0_V2:
1534                 return sprintf(buf, "AMW0 v2\n");
1535         case ACER_WMID:
1536                 return sprintf(buf, "WMID\n");
1537         case ACER_WMID_v2:
1538                 return sprintf(buf, "WMID v2\n");
1539         default:
1540                 return sprintf(buf, "Error!\n");
1541         }
1542 }
1543
1544 static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
1545
1546 static void acer_wmi_notify(u32 value, void *context)
1547 {
1548         struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1549         union acpi_object *obj;
1550         struct event_return_value return_value;
1551         acpi_status status;
1552         u16 device_state;
1553         const struct key_entry *key;
1554
1555         status = wmi_get_event_data(value, &response);
1556         if (status != AE_OK) {
1557                 pr_warn("bad event status 0x%x\n", status);
1558                 return;
1559         }
1560
1561         obj = (union acpi_object *)response.pointer;
1562
1563         if (!obj)
1564                 return;
1565         if (obj->type != ACPI_TYPE_BUFFER) {
1566                 pr_warn("Unknown response received %d\n", obj->type);
1567                 kfree(obj);
1568                 return;
1569         }
1570         if (obj->buffer.length != 8) {
1571                 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1572                 kfree(obj);
1573                 return;
1574         }
1575
1576         return_value = *((struct event_return_value *)obj->buffer.pointer);
1577         kfree(obj);
1578
1579         switch (return_value.function) {
1580         case WMID_HOTKEY_EVENT:
1581                 device_state = return_value.device_state;
1582                 pr_debug("device state: 0x%x\n", device_state);
1583
1584                 key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
1585                                                         return_value.key_num);
1586                 if (!key) {
1587                         pr_warn("Unknown key number - 0x%x\n",
1588                                 return_value.key_num);
1589                 } else {
1590                         switch (key->keycode) {
1591                         case KEY_WLAN:
1592                         case KEY_BLUETOOTH:
1593                                 if (has_cap(ACER_CAP_WIRELESS))
1594                                         rfkill_set_sw_state(wireless_rfkill,
1595                                                 !(device_state & ACER_WMID3_GDS_WIRELESS));
1596                                 if (has_cap(ACER_CAP_THREEG))
1597                                         rfkill_set_sw_state(threeg_rfkill,
1598                                                 !(device_state & ACER_WMID3_GDS_THREEG));
1599                                 if (has_cap(ACER_CAP_BLUETOOTH))
1600                                         rfkill_set_sw_state(bluetooth_rfkill,
1601                                                 !(device_state & ACER_WMID3_GDS_BLUETOOTH));
1602                                 break;
1603                         }
1604                         sparse_keymap_report_entry(acer_wmi_input_dev, key,
1605                                                    1, true);
1606                 }
1607                 break;
1608         default:
1609                 pr_warn("Unknown function number - %d - %d\n",
1610                         return_value.function, return_value.key_num);
1611                 break;
1612         }
1613 }
1614
1615 static acpi_status
1616 wmid3_set_lm_mode(struct lm_input_params *params,
1617                   struct lm_return_value *return_value)
1618 {
1619         acpi_status status;
1620         union acpi_object *obj;
1621
1622         struct acpi_buffer input = { sizeof(struct lm_input_params), params };
1623         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1624
1625         status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
1626         if (ACPI_FAILURE(status))
1627                 return status;
1628
1629         obj = output.pointer;
1630
1631         if (!obj)
1632                 return AE_ERROR;
1633         else if (obj->type != ACPI_TYPE_BUFFER) {
1634                 kfree(obj);
1635                 return AE_ERROR;
1636         }
1637         if (obj->buffer.length != 4) {
1638                 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1639                 kfree(obj);
1640                 return AE_ERROR;
1641         }
1642
1643         *return_value = *((struct lm_return_value *)obj->buffer.pointer);
1644         kfree(obj);
1645
1646         return status;
1647 }
1648
1649 static int acer_wmi_enable_ec_raw(void)
1650 {
1651         struct lm_return_value return_value;
1652         acpi_status status;
1653         struct lm_input_params params = {
1654                 .function_num = 0x1,
1655                 .commun_devices = 0xFFFF,
1656                 .devices = 0xFFFF,
1657                 .lm_status = 0x00,            /* Launch Manager Deactive */
1658         };
1659
1660         status = wmid3_set_lm_mode(&params, &return_value);
1661
1662         if (return_value.error_code || return_value.ec_return_value)
1663                 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1664                         return_value.error_code,
1665                         return_value.ec_return_value);
1666         else
1667                 pr_info("Enabled EC raw mode\n");
1668
1669         return status;
1670 }
1671
1672 static int acer_wmi_enable_lm(void)
1673 {
1674         struct lm_return_value return_value;
1675         acpi_status status;
1676         struct lm_input_params params = {
1677                 .function_num = 0x1,
1678                 .commun_devices = 0xFFFF,
1679                 .devices = 0xFFFF,
1680                 .lm_status = 0x01,            /* Launch Manager Active */
1681         };
1682
1683         status = wmid3_set_lm_mode(&params, &return_value);
1684
1685         if (return_value.error_code || return_value.ec_return_value)
1686                 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1687                         return_value.error_code,
1688                         return_value.ec_return_value);
1689
1690         return status;
1691 }
1692
1693 static int __init acer_wmi_input_setup(void)
1694 {
1695         acpi_status status;
1696         int err;
1697
1698         acer_wmi_input_dev = input_allocate_device();
1699         if (!acer_wmi_input_dev)
1700                 return -ENOMEM;
1701
1702         acer_wmi_input_dev->name = "Acer WMI hotkeys";
1703         acer_wmi_input_dev->phys = "wmi/input0";
1704         acer_wmi_input_dev->id.bustype = BUS_HOST;
1705
1706         err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
1707         if (err)
1708                 goto err_free_dev;
1709
1710         status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
1711                                                 acer_wmi_notify, NULL);
1712         if (ACPI_FAILURE(status)) {
1713                 err = -EIO;
1714                 goto err_free_keymap;
1715         }
1716
1717         err = input_register_device(acer_wmi_input_dev);
1718         if (err)
1719                 goto err_uninstall_notifier;
1720
1721         return 0;
1722
1723 err_uninstall_notifier:
1724         wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1725 err_free_keymap:
1726         sparse_keymap_free(acer_wmi_input_dev);
1727 err_free_dev:
1728         input_free_device(acer_wmi_input_dev);
1729         return err;
1730 }
1731
1732 static void acer_wmi_input_destroy(void)
1733 {
1734         wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1735         sparse_keymap_free(acer_wmi_input_dev);
1736         input_unregister_device(acer_wmi_input_dev);
1737 }
1738
1739 /*
1740  * debugfs functions
1741  */
1742 static u32 get_wmid_devices(void)
1743 {
1744         struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1745         union acpi_object *obj;
1746         acpi_status status;
1747         u32 devices = 0;
1748
1749         status = wmi_query_block(WMID_GUID2, 1, &out);
1750         if (ACPI_FAILURE(status))
1751                 return 0;
1752
1753         obj = (union acpi_object *) out.pointer;
1754         if (obj && obj->type == ACPI_TYPE_BUFFER &&
1755                 (obj->buffer.length == sizeof(u32) ||
1756                 obj->buffer.length == sizeof(u64))) {
1757                 devices = *((u32 *) obj->buffer.pointer);
1758         } else if (obj->type == ACPI_TYPE_INTEGER) {
1759                 devices = (u32) obj->integer.value;
1760         }
1761
1762         kfree(out.pointer);
1763         return devices;
1764 }
1765
1766 /*
1767  * Platform device
1768  */
1769 static int __devinit acer_platform_probe(struct platform_device *device)
1770 {
1771         int err;
1772
1773         if (has_cap(ACER_CAP_MAILLED)) {
1774                 err = acer_led_init(&device->dev);
1775                 if (err)
1776                         goto error_mailled;
1777         }
1778
1779         if (has_cap(ACER_CAP_BRIGHTNESS)) {
1780                 err = acer_backlight_init(&device->dev);
1781                 if (err)
1782                         goto error_brightness;
1783         }
1784
1785         err = acer_rfkill_init(&device->dev);
1786         if (err)
1787                 goto error_rfkill;
1788
1789         return err;
1790
1791 error_rfkill:
1792         if (has_cap(ACER_CAP_BRIGHTNESS))
1793                 acer_backlight_exit();
1794 error_brightness:
1795         if (has_cap(ACER_CAP_MAILLED))
1796                 acer_led_exit();
1797 error_mailled:
1798         return err;
1799 }
1800
1801 static int acer_platform_remove(struct platform_device *device)
1802 {
1803         if (has_cap(ACER_CAP_MAILLED))
1804                 acer_led_exit();
1805         if (has_cap(ACER_CAP_BRIGHTNESS))
1806                 acer_backlight_exit();
1807
1808         acer_rfkill_exit();
1809         return 0;
1810 }
1811
1812 static int acer_platform_suspend(struct platform_device *dev,
1813 pm_message_t state)
1814 {
1815         u32 value;
1816         struct acer_data *data = &interface->data;
1817
1818         if (!data)
1819                 return -ENOMEM;
1820
1821         if (has_cap(ACER_CAP_MAILLED)) {
1822                 get_u32(&value, ACER_CAP_MAILLED);
1823                 set_u32(LED_OFF, ACER_CAP_MAILLED);
1824                 data->mailled = value;
1825         }
1826
1827         if (has_cap(ACER_CAP_BRIGHTNESS)) {
1828                 get_u32(&value, ACER_CAP_BRIGHTNESS);
1829                 data->brightness = value;
1830         }
1831
1832         return 0;
1833 }
1834
1835 static int acer_platform_resume(struct platform_device *device)
1836 {
1837         struct acer_data *data = &interface->data;
1838
1839         if (!data)
1840                 return -ENOMEM;
1841
1842         if (has_cap(ACER_CAP_MAILLED))
1843                 set_u32(data->mailled, ACER_CAP_MAILLED);
1844
1845         if (has_cap(ACER_CAP_BRIGHTNESS))
1846                 set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
1847
1848         return 0;
1849 }
1850
1851 static void acer_platform_shutdown(struct platform_device *device)
1852 {
1853         struct acer_data *data = &interface->data;
1854
1855         if (!data)
1856                 return;
1857
1858         if (has_cap(ACER_CAP_MAILLED))
1859                 set_u32(LED_OFF, ACER_CAP_MAILLED);
1860 }
1861
1862 static struct platform_driver acer_platform_driver = {
1863         .driver = {
1864                 .name = "acer-wmi",
1865                 .owner = THIS_MODULE,
1866         },
1867         .probe = acer_platform_probe,
1868         .remove = acer_platform_remove,
1869         .suspend = acer_platform_suspend,
1870         .resume = acer_platform_resume,
1871         .shutdown = acer_platform_shutdown,
1872 };
1873
1874 static struct platform_device *acer_platform_device;
1875
1876 static int remove_sysfs(struct platform_device *device)
1877 {
1878         if (has_cap(ACER_CAP_THREEG))
1879                 device_remove_file(&device->dev, &dev_attr_threeg);
1880
1881         device_remove_file(&device->dev, &dev_attr_interface);
1882
1883         return 0;
1884 }
1885
1886 static int create_sysfs(void)
1887 {
1888         int retval = -ENOMEM;
1889
1890         if (has_cap(ACER_CAP_THREEG)) {
1891                 retval = device_create_file(&acer_platform_device->dev,
1892                         &dev_attr_threeg);
1893                 if (retval)
1894                         goto error_sysfs;
1895         }
1896
1897         retval = device_create_file(&acer_platform_device->dev,
1898                 &dev_attr_interface);
1899         if (retval)
1900                 goto error_sysfs;
1901
1902         return 0;
1903
1904 error_sysfs:
1905                 remove_sysfs(acer_platform_device);
1906         return retval;
1907 }
1908
1909 static void remove_debugfs(void)
1910 {
1911         debugfs_remove(interface->debug.devices);
1912         debugfs_remove(interface->debug.root);
1913 }
1914
1915 static int create_debugfs(void)
1916 {
1917         interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
1918         if (!interface->debug.root) {
1919                 pr_err("Failed to create debugfs directory");
1920                 return -ENOMEM;
1921         }
1922
1923         interface->debug.devices = debugfs_create_u32("devices", S_IRUGO,
1924                                         interface->debug.root,
1925                                         &interface->debug.wmid_devices);
1926         if (!interface->debug.devices)
1927                 goto error_debugfs;
1928
1929         return 0;
1930
1931 error_debugfs:
1932         remove_debugfs();
1933         return -ENOMEM;
1934 }
1935
1936 static int __init acer_wmi_init(void)
1937 {
1938         int err;
1939
1940         pr_info("Acer Laptop ACPI-WMI Extras\n");
1941
1942         if (dmi_check_system(acer_blacklist)) {
1943                 pr_info("Blacklisted hardware detected - not loading\n");
1944                 return -ENODEV;
1945         }
1946
1947         find_quirks();
1948
1949         /*
1950          * Detect which ACPI-WMI interface we're using.
1951          */
1952         if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1953                 interface = &AMW0_V2_interface;
1954
1955         if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1956                 interface = &wmid_interface;
1957
1958         if (wmi_has_guid(WMID_GUID3))
1959                 interface = &wmid_v2_interface;
1960
1961         if (interface)
1962                 dmi_walk(type_aa_dmi_decode, NULL);
1963
1964         if (wmi_has_guid(WMID_GUID2) && interface) {
1965                 if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
1966                         pr_err("Unable to detect available WMID devices\n");
1967                         return -ENODEV;
1968                 }
1969                 /* WMID always provides brightness methods */
1970                 interface->capability |= ACER_CAP_BRIGHTNESS;
1971         } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
1972                 pr_err("No WMID device detection method found\n");
1973                 return -ENODEV;
1974         }
1975
1976         if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) {
1977                 interface = &AMW0_interface;
1978
1979                 if (ACPI_FAILURE(AMW0_set_capabilities())) {
1980                         pr_err("Unable to detect available AMW0 devices\n");
1981                         return -ENODEV;
1982                 }
1983         }
1984
1985         if (wmi_has_guid(AMW0_GUID1))
1986                 AMW0_find_mailled();
1987
1988         if (!interface) {
1989                 pr_err("No or unsupported WMI interface, unable to load\n");
1990                 return -ENODEV;
1991         }
1992
1993         set_quirks();
1994
1995         if (acpi_video_backlight_support()) {
1996                 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1997                 pr_info("Brightness must be controlled by generic video driver\n");
1998         }
1999
2000         if (wmi_has_guid(WMID_GUID3)) {
2001                 if (ec_raw_mode) {
2002                         if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
2003                                 pr_err("Cannot enable EC raw mode\n");
2004                                 return -ENODEV;
2005                         }
2006                 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
2007                         pr_err("Cannot enable Launch Manager mode\n");
2008                         return -ENODEV;
2009                 }
2010         } else if (ec_raw_mode) {
2011                 pr_info("No WMID EC raw mode enable method\n");
2012         }
2013
2014         if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
2015                 err = acer_wmi_input_setup();
2016                 if (err)
2017                         return err;
2018         }
2019
2020         err = platform_driver_register(&acer_platform_driver);
2021         if (err) {
2022                 pr_err("Unable to register platform driver\n");
2023                 goto error_platform_register;
2024         }
2025
2026         acer_platform_device = platform_device_alloc("acer-wmi", -1);
2027         if (!acer_platform_device) {
2028                 err = -ENOMEM;
2029                 goto error_device_alloc;
2030         }
2031
2032         err = platform_device_add(acer_platform_device);
2033         if (err)
2034                 goto error_device_add;
2035
2036         err = create_sysfs();
2037         if (err)
2038                 goto error_create_sys;
2039
2040         if (wmi_has_guid(WMID_GUID2)) {
2041                 interface->debug.wmid_devices = get_wmid_devices();
2042                 err = create_debugfs();
2043                 if (err)
2044                         goto error_create_debugfs;
2045         }
2046
2047         /* Override any initial settings with values from the commandline */
2048         acer_commandline_init();
2049
2050         return 0;
2051
2052 error_create_debugfs:
2053         remove_sysfs(acer_platform_device);
2054 error_create_sys:
2055         platform_device_del(acer_platform_device);
2056 error_device_add:
2057         platform_device_put(acer_platform_device);
2058 error_device_alloc:
2059         platform_driver_unregister(&acer_platform_driver);
2060 error_platform_register:
2061         if (wmi_has_guid(ACERWMID_EVENT_GUID))
2062                 acer_wmi_input_destroy();
2063
2064         return err;
2065 }
2066
2067 static void __exit acer_wmi_exit(void)
2068 {
2069         if (wmi_has_guid(ACERWMID_EVENT_GUID))
2070                 acer_wmi_input_destroy();
2071
2072         remove_sysfs(acer_platform_device);
2073         remove_debugfs();
2074         platform_device_unregister(acer_platform_device);
2075         platform_driver_unregister(&acer_platform_driver);
2076
2077         pr_info("Acer Laptop WMI Extras unloaded\n");
2078         return;
2079 }
2080
2081 module_init(acer_wmi_init);
2082 module_exit(acer_wmi_exit);