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