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