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