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