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