acer-wmi.c revision 1d1fc8a75fec3a2b29cc5864d45c5d03048f62e0
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 acpi_status AMW0_set_capabilities(void)
683{
684	struct wmab_args args;
685	struct wmab_ret ret;
686	acpi_status status;
687	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
688	union acpi_object *obj;
689
690	/*
691	 * On laptops with this strange GUID (non Acer), normal probing doesn't
692	 * work.
693	 */
694	if (wmi_has_guid(AMW0_GUID2)) {
695		interface->capability |= ACER_CAP_WIRELESS;
696		return AE_OK;
697	}
698
699	args.eax = ACER_AMW0_WRITE;
700	args.ecx = args.edx = 0;
701
702	args.ebx = 0xa2 << 8;
703	args.ebx |= ACER_AMW0_WIRELESS_MASK;
704
705	status = wmab_execute(&args, &out);
706	if (ACPI_FAILURE(status))
707		return status;
708
709	obj = out.pointer;
710	if (obj && obj->type == ACPI_TYPE_BUFFER &&
711	obj->buffer.length == sizeof(struct wmab_ret)) {
712		ret = *((struct wmab_ret *) obj->buffer.pointer);
713	} else {
714		status = AE_ERROR;
715		goto out;
716	}
717
718	if (ret.eax & 0x1)
719		interface->capability |= ACER_CAP_WIRELESS;
720
721	args.ebx = 2 << 8;
722	args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
723
724	/*
725	 * It's ok to use existing buffer for next wmab_execute call.
726	 * But we need to kfree(out.pointer) if next wmab_execute fail.
727	 */
728	status = wmab_execute(&args, &out);
729	if (ACPI_FAILURE(status))
730		goto out;
731
732	obj = (union acpi_object *) out.pointer;
733	if (obj && obj->type == ACPI_TYPE_BUFFER
734	&& obj->buffer.length == sizeof(struct wmab_ret)) {
735		ret = *((struct wmab_ret *) obj->buffer.pointer);
736	} else {
737		status = AE_ERROR;
738		goto out;
739	}
740
741	if (ret.eax & 0x1)
742		interface->capability |= ACER_CAP_BLUETOOTH;
743
744	/*
745	 * This appears to be safe to enable, since all Wistron based laptops
746	 * appear to use the same EC register for brightness, even if they
747	 * differ for wireless, etc
748	 */
749	if (quirks->brightness >= 0)
750		interface->capability |= ACER_CAP_BRIGHTNESS;
751
752	status = AE_OK;
753out:
754	kfree(out.pointer);
755	return status;
756}
757
758static struct wmi_interface AMW0_interface = {
759	.type = ACER_AMW0,
760};
761
762static struct wmi_interface AMW0_V2_interface = {
763	.type = ACER_AMW0_V2,
764};
765
766/*
767 * New interface (The WMID interface)
768 */
769static acpi_status
770WMI_execute_u32(u32 method_id, u32 in, u32 *out)
771{
772	struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
773	struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
774	union acpi_object *obj;
775	u32 tmp;
776	acpi_status status;
777
778	status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result);
779
780	if (ACPI_FAILURE(status))
781		return status;
782
783	obj = (union acpi_object *) result.pointer;
784	if (obj && obj->type == ACPI_TYPE_BUFFER &&
785		(obj->buffer.length == sizeof(u32) ||
786		obj->buffer.length == sizeof(u64))) {
787		tmp = *((u32 *) obj->buffer.pointer);
788	} else if (obj->type == ACPI_TYPE_INTEGER) {
789		tmp = (u32) obj->integer.value;
790	} else {
791		tmp = 0;
792	}
793
794	if (out)
795		*out = tmp;
796
797	kfree(result.pointer);
798
799	return status;
800}
801
802static acpi_status WMID_get_u32(u32 *value, u32 cap,
803struct wmi_interface *iface)
804{
805	acpi_status status;
806	u8 tmp;
807	u32 result, method_id = 0;
808
809	switch (cap) {
810	case ACER_CAP_WIRELESS:
811		method_id = ACER_WMID_GET_WIRELESS_METHODID;
812		break;
813	case ACER_CAP_BLUETOOTH:
814		method_id = ACER_WMID_GET_BLUETOOTH_METHODID;
815		break;
816	case ACER_CAP_BRIGHTNESS:
817		method_id = ACER_WMID_GET_BRIGHTNESS_METHODID;
818		break;
819	case ACER_CAP_THREEG:
820		method_id = ACER_WMID_GET_THREEG_METHODID;
821		break;
822	case ACER_CAP_MAILLED:
823		if (quirks->mailled == 1) {
824			ec_read(0x9f, &tmp);
825			*value = tmp & 0x1;
826			return 0;
827		}
828	default:
829		return AE_ERROR;
830	}
831	status = WMI_execute_u32(method_id, 0, &result);
832
833	if (ACPI_SUCCESS(status))
834		*value = (u8)result;
835
836	return status;
837}
838
839static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
840{
841	u32 method_id = 0;
842	char param;
843
844	switch (cap) {
845	case ACER_CAP_BRIGHTNESS:
846		if (value > max_brightness)
847			return AE_BAD_PARAMETER;
848		method_id = ACER_WMID_SET_BRIGHTNESS_METHODID;
849		break;
850	case ACER_CAP_WIRELESS:
851		if (value > 1)
852			return AE_BAD_PARAMETER;
853		method_id = ACER_WMID_SET_WIRELESS_METHODID;
854		break;
855	case ACER_CAP_BLUETOOTH:
856		if (value > 1)
857			return AE_BAD_PARAMETER;
858		method_id = ACER_WMID_SET_BLUETOOTH_METHODID;
859		break;
860	case ACER_CAP_THREEG:
861		if (value > 1)
862			return AE_BAD_PARAMETER;
863		method_id = ACER_WMID_SET_THREEG_METHODID;
864		break;
865	case ACER_CAP_MAILLED:
866		if (value > 1)
867			return AE_BAD_PARAMETER;
868		if (quirks->mailled == 1) {
869			param = value ? 0x92 : 0x93;
870			i8042_lock_chip();
871			i8042_command(&param, 0x1059);
872			i8042_unlock_chip();
873			return 0;
874		}
875		break;
876	default:
877		return AE_ERROR;
878	}
879	return WMI_execute_u32(method_id, (u32)value, NULL);
880}
881
882static acpi_status wmid3_get_device_status(u32 *value, u16 device)
883{
884	struct wmid3_gds_return_value return_value;
885	acpi_status status;
886	union acpi_object *obj;
887	struct wmid3_gds_input_param params = {
888		.function_num = 0x1,
889		.hotkey_number = 0x01,
890		.devices = device,
891	};
892	struct acpi_buffer input = {
893		sizeof(struct wmid3_gds_input_param),
894		&params
895	};
896	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
897
898	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
899	if (ACPI_FAILURE(status))
900		return status;
901
902	obj = output.pointer;
903
904	if (!obj)
905		return AE_ERROR;
906	else if (obj->type != ACPI_TYPE_BUFFER) {
907		kfree(obj);
908		return AE_ERROR;
909	}
910	if (obj->buffer.length != 8) {
911		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
912		kfree(obj);
913		return AE_ERROR;
914	}
915
916	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
917	kfree(obj);
918
919	if (return_value.error_code || return_value.ec_return_value)
920		pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
921			device,
922			return_value.error_code,
923			return_value.ec_return_value);
924	else
925		*value = !!(return_value.devices & device);
926
927	return status;
928}
929
930static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
931{
932	u16 device;
933
934	switch (cap) {
935	case ACER_CAP_WIRELESS:
936		device = ACER_WMID3_GDS_WIRELESS;
937		break;
938	case ACER_CAP_BLUETOOTH:
939		device = ACER_WMID3_GDS_BLUETOOTH;
940		break;
941	case ACER_CAP_THREEG:
942		device = ACER_WMID3_GDS_THREEG;
943		break;
944	default:
945		return AE_ERROR;
946	}
947	return wmid3_get_device_status(value, device);
948}
949
950static acpi_status wmid3_set_device_status(u32 value, u16 device)
951{
952	struct wmid3_gds_return_value return_value;
953	acpi_status status;
954	union acpi_object *obj;
955	u16 devices;
956	struct wmid3_gds_input_param params = {
957		.function_num = 0x1,
958		.hotkey_number = 0x01,
959		.devices = commun_func_bitmap,
960	};
961	struct acpi_buffer input = {
962		sizeof(struct wmid3_gds_input_param),
963		&params
964	};
965	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
966	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
967
968	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
969	if (ACPI_FAILURE(status))
970		return status;
971
972	obj = output.pointer;
973
974	if (!obj)
975		return AE_ERROR;
976	else if (obj->type != ACPI_TYPE_BUFFER) {
977		kfree(obj);
978		return AE_ERROR;
979	}
980	if (obj->buffer.length != 8) {
981		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
982		kfree(obj);
983		return AE_ERROR;
984	}
985
986	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
987	kfree(obj);
988
989	if (return_value.error_code || return_value.ec_return_value) {
990		pr_warning("Get Current Device Status failed: "
991			"0x%x - 0x%x\n", return_value.error_code,
992			return_value.ec_return_value);
993		return status;
994	}
995
996	devices = return_value.devices;
997	params.function_num = 0x2;
998	params.hotkey_number = 0x01;
999	params.devices = (value) ? (devices | device) : (devices & ~device);
1000
1001	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1002	if (ACPI_FAILURE(status))
1003		return status;
1004
1005	obj = output2.pointer;
1006
1007	if (!obj)
1008		return AE_ERROR;
1009	else if (obj->type != ACPI_TYPE_BUFFER) {
1010		kfree(obj);
1011		return AE_ERROR;
1012	}
1013	if (obj->buffer.length != 4) {
1014		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1015		kfree(obj);
1016		return AE_ERROR;
1017	}
1018
1019	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1020	kfree(obj);
1021
1022	if (return_value.error_code || return_value.ec_return_value)
1023		pr_warning("Set Device Status failed: "
1024			"0x%x - 0x%x\n", return_value.error_code,
1025			return_value.ec_return_value);
1026
1027	return status;
1028}
1029
1030static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1031{
1032	u16 device;
1033
1034	switch (cap) {
1035	case ACER_CAP_WIRELESS:
1036		device = ACER_WMID3_GDS_WIRELESS;
1037		break;
1038	case ACER_CAP_BLUETOOTH:
1039		device = ACER_WMID3_GDS_BLUETOOTH;
1040		break;
1041	case ACER_CAP_THREEG:
1042		device = ACER_WMID3_GDS_THREEG;
1043		break;
1044	default:
1045		return AE_ERROR;
1046	}
1047	return wmid3_set_device_status(value, device);
1048}
1049
1050static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
1051{
1052	struct hotkey_function_type_aa *type_aa;
1053
1054	/* We are looking for OEM-specific Type AAh */
1055	if (header->type != 0xAA)
1056		return;
1057
1058	has_type_aa = true;
1059	type_aa = (struct hotkey_function_type_aa *) header;
1060
1061	pr_info("Function bitmap for Communication Button: 0x%x\n",
1062		type_aa->commun_func_bitmap);
1063	commun_func_bitmap = type_aa->commun_func_bitmap;
1064
1065	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
1066		interface->capability |= ACER_CAP_WIRELESS;
1067	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
1068		interface->capability |= ACER_CAP_THREEG;
1069	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
1070		interface->capability |= ACER_CAP_BLUETOOTH;
1071}
1072
1073static acpi_status WMID_set_capabilities(void)
1074{
1075	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1076	union acpi_object *obj;
1077	acpi_status status;
1078	u32 devices;
1079
1080	status = wmi_query_block(WMID_GUID2, 1, &out);
1081	if (ACPI_FAILURE(status))
1082		return status;
1083
1084	obj = (union acpi_object *) out.pointer;
1085	if (obj && obj->type == ACPI_TYPE_BUFFER &&
1086		(obj->buffer.length == sizeof(u32) ||
1087		obj->buffer.length == sizeof(u64))) {
1088		devices = *((u32 *) obj->buffer.pointer);
1089	} else if (obj->type == ACPI_TYPE_INTEGER) {
1090		devices = (u32) obj->integer.value;
1091	} else {
1092		kfree(out.pointer);
1093		return AE_ERROR;
1094	}
1095
1096	pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
1097	if (devices & 0x07)
1098		interface->capability |= ACER_CAP_WIRELESS;
1099	if (devices & 0x40)
1100		interface->capability |= ACER_CAP_THREEG;
1101	if (devices & 0x10)
1102		interface->capability |= ACER_CAP_BLUETOOTH;
1103
1104	if (!(devices & 0x20))
1105		max_brightness = 0x9;
1106
1107	kfree(out.pointer);
1108	return status;
1109}
1110
1111static struct wmi_interface wmid_interface = {
1112	.type = ACER_WMID,
1113};
1114
1115static struct wmi_interface wmid_v2_interface = {
1116	.type = ACER_WMID_v2,
1117};
1118
1119/*
1120 * Generic Device (interface-independent)
1121 */
1122
1123static acpi_status get_u32(u32 *value, u32 cap)
1124{
1125	acpi_status status = AE_ERROR;
1126
1127	switch (interface->type) {
1128	case ACER_AMW0:
1129		status = AMW0_get_u32(value, cap, interface);
1130		break;
1131	case ACER_AMW0_V2:
1132		if (cap == ACER_CAP_MAILLED) {
1133			status = AMW0_get_u32(value, cap, interface);
1134			break;
1135		}
1136	case ACER_WMID:
1137		status = WMID_get_u32(value, cap, interface);
1138		break;
1139	case ACER_WMID_v2:
1140		if (cap & (ACER_CAP_WIRELESS |
1141			   ACER_CAP_BLUETOOTH |
1142			   ACER_CAP_THREEG))
1143			status = wmid_v2_get_u32(value, cap);
1144		else if (wmi_has_guid(WMID_GUID2))
1145			status = WMID_get_u32(value, cap, interface);
1146		break;
1147	}
1148
1149	return status;
1150}
1151
1152static acpi_status set_u32(u32 value, u32 cap)
1153{
1154	acpi_status status;
1155
1156	if (interface->capability & cap) {
1157		switch (interface->type) {
1158		case ACER_AMW0:
1159			return AMW0_set_u32(value, cap, interface);
1160		case ACER_AMW0_V2:
1161			if (cap == ACER_CAP_MAILLED)
1162				return AMW0_set_u32(value, cap, interface);
1163
1164			/*
1165			 * On some models, some WMID methods don't toggle
1166			 * properly. For those cases, we want to run the AMW0
1167			 * method afterwards to be certain we've really toggled
1168			 * the device state.
1169			 */
1170			if (cap == ACER_CAP_WIRELESS ||
1171				cap == ACER_CAP_BLUETOOTH) {
1172				status = WMID_set_u32(value, cap, interface);
1173				if (ACPI_FAILURE(status))
1174					return status;
1175
1176				return AMW0_set_u32(value, cap, interface);
1177			}
1178		case ACER_WMID:
1179			return WMID_set_u32(value, cap, interface);
1180		case ACER_WMID_v2:
1181			if (cap & (ACER_CAP_WIRELESS |
1182				   ACER_CAP_BLUETOOTH |
1183				   ACER_CAP_THREEG))
1184				return wmid_v2_set_u32(value, cap);
1185			else if (wmi_has_guid(WMID_GUID2))
1186				return WMID_set_u32(value, cap, interface);
1187		default:
1188			return AE_BAD_PARAMETER;
1189		}
1190	}
1191	return AE_BAD_PARAMETER;
1192}
1193
1194static void __init acer_commandline_init(void)
1195{
1196	/*
1197	 * These will all fail silently if the value given is invalid, or the
1198	 * capability isn't available on the given interface
1199	 */
1200	if (mailled >= 0)
1201		set_u32(mailled, ACER_CAP_MAILLED);
1202	if (!has_type_aa && threeg >= 0)
1203		set_u32(threeg, ACER_CAP_THREEG);
1204	if (brightness >= 0)
1205		set_u32(brightness, ACER_CAP_BRIGHTNESS);
1206}
1207
1208/*
1209 * LED device (Mail LED only, no other LEDs known yet)
1210 */
1211static void mail_led_set(struct led_classdev *led_cdev,
1212enum led_brightness value)
1213{
1214	set_u32(value, ACER_CAP_MAILLED);
1215}
1216
1217static struct led_classdev mail_led = {
1218	.name = "acer-wmi::mail",
1219	.brightness_set = mail_led_set,
1220};
1221
1222static int __devinit acer_led_init(struct device *dev)
1223{
1224	return led_classdev_register(dev, &mail_led);
1225}
1226
1227static void acer_led_exit(void)
1228{
1229	set_u32(LED_OFF, ACER_CAP_MAILLED);
1230	led_classdev_unregister(&mail_led);
1231}
1232
1233/*
1234 * Backlight device
1235 */
1236static struct backlight_device *acer_backlight_device;
1237
1238static int read_brightness(struct backlight_device *bd)
1239{
1240	u32 value;
1241	get_u32(&value, ACER_CAP_BRIGHTNESS);
1242	return value;
1243}
1244
1245static int update_bl_status(struct backlight_device *bd)
1246{
1247	int intensity = bd->props.brightness;
1248
1249	if (bd->props.power != FB_BLANK_UNBLANK)
1250		intensity = 0;
1251	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
1252		intensity = 0;
1253
1254	set_u32(intensity, ACER_CAP_BRIGHTNESS);
1255
1256	return 0;
1257}
1258
1259static const struct backlight_ops acer_bl_ops = {
1260	.get_brightness = read_brightness,
1261	.update_status = update_bl_status,
1262};
1263
1264static int __devinit acer_backlight_init(struct device *dev)
1265{
1266	struct backlight_properties props;
1267	struct backlight_device *bd;
1268
1269	memset(&props, 0, sizeof(struct backlight_properties));
1270	props.type = BACKLIGHT_PLATFORM;
1271	props.max_brightness = max_brightness;
1272	bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
1273				       &props);
1274	if (IS_ERR(bd)) {
1275		pr_err("Could not register Acer backlight device\n");
1276		acer_backlight_device = NULL;
1277		return PTR_ERR(bd);
1278	}
1279
1280	acer_backlight_device = bd;
1281
1282	bd->props.power = FB_BLANK_UNBLANK;
1283	bd->props.brightness = read_brightness(bd);
1284	backlight_update_status(bd);
1285	return 0;
1286}
1287
1288static void acer_backlight_exit(void)
1289{
1290	backlight_device_unregister(acer_backlight_device);
1291}
1292
1293/*
1294 * Rfkill devices
1295 */
1296static void acer_rfkill_update(struct work_struct *ignored);
1297static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
1298static void acer_rfkill_update(struct work_struct *ignored)
1299{
1300	u32 state;
1301	acpi_status status;
1302
1303	if (has_cap(ACER_CAP_WIRELESS)) {
1304		status = get_u32(&state, ACER_CAP_WIRELESS);
1305		if (ACPI_SUCCESS(status)) {
1306			if (quirks->wireless == 3)
1307				rfkill_set_hw_state(wireless_rfkill, !state);
1308			else
1309				rfkill_set_sw_state(wireless_rfkill, !state);
1310		}
1311	}
1312
1313	if (has_cap(ACER_CAP_BLUETOOTH)) {
1314		status = get_u32(&state, ACER_CAP_BLUETOOTH);
1315		if (ACPI_SUCCESS(status))
1316			rfkill_set_sw_state(bluetooth_rfkill, !state);
1317	}
1318
1319	if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1320		status = get_u32(&state, ACER_WMID3_GDS_THREEG);
1321		if (ACPI_SUCCESS(status))
1322			rfkill_set_sw_state(threeg_rfkill, !state);
1323	}
1324
1325	schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
1326}
1327
1328static int acer_rfkill_set(void *data, bool blocked)
1329{
1330	acpi_status status;
1331	u32 cap = (unsigned long)data;
1332
1333	if (rfkill_inited) {
1334		status = set_u32(!blocked, cap);
1335		if (ACPI_FAILURE(status))
1336			return -ENODEV;
1337	}
1338
1339	return 0;
1340}
1341
1342static const struct rfkill_ops acer_rfkill_ops = {
1343	.set_block = acer_rfkill_set,
1344};
1345
1346static struct rfkill *acer_rfkill_register(struct device *dev,
1347					   enum rfkill_type type,
1348					   char *name, u32 cap)
1349{
1350	int err;
1351	struct rfkill *rfkill_dev;
1352	u32 state;
1353	acpi_status status;
1354
1355	rfkill_dev = rfkill_alloc(name, dev, type,
1356				  &acer_rfkill_ops,
1357				  (void *)(unsigned long)cap);
1358	if (!rfkill_dev)
1359		return ERR_PTR(-ENOMEM);
1360
1361	status = get_u32(&state, cap);
1362
1363	err = rfkill_register(rfkill_dev);
1364	if (err) {
1365		rfkill_destroy(rfkill_dev);
1366		return ERR_PTR(err);
1367	}
1368
1369	if (ACPI_SUCCESS(status))
1370		rfkill_set_sw_state(rfkill_dev, !state);
1371
1372	return rfkill_dev;
1373}
1374
1375static int acer_rfkill_init(struct device *dev)
1376{
1377	int err;
1378
1379	if (has_cap(ACER_CAP_WIRELESS)) {
1380		wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
1381			"acer-wireless", ACER_CAP_WIRELESS);
1382		if (IS_ERR(wireless_rfkill)) {
1383			err = PTR_ERR(wireless_rfkill);
1384			goto error_wireless;
1385		}
1386	}
1387
1388	if (has_cap(ACER_CAP_BLUETOOTH)) {
1389		bluetooth_rfkill = acer_rfkill_register(dev,
1390			RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
1391			ACER_CAP_BLUETOOTH);
1392		if (IS_ERR(bluetooth_rfkill)) {
1393			err = PTR_ERR(bluetooth_rfkill);
1394			goto error_bluetooth;
1395		}
1396	}
1397
1398	if (has_cap(ACER_CAP_THREEG)) {
1399		threeg_rfkill = acer_rfkill_register(dev,
1400			RFKILL_TYPE_WWAN, "acer-threeg",
1401			ACER_CAP_THREEG);
1402		if (IS_ERR(threeg_rfkill)) {
1403			err = PTR_ERR(threeg_rfkill);
1404			goto error_threeg;
1405		}
1406	}
1407
1408	rfkill_inited = true;
1409
1410	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1411	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1412		schedule_delayed_work(&acer_rfkill_work,
1413			round_jiffies_relative(HZ));
1414
1415	return 0;
1416
1417error_threeg:
1418	if (has_cap(ACER_CAP_BLUETOOTH)) {
1419		rfkill_unregister(bluetooth_rfkill);
1420		rfkill_destroy(bluetooth_rfkill);
1421	}
1422error_bluetooth:
1423	if (has_cap(ACER_CAP_WIRELESS)) {
1424		rfkill_unregister(wireless_rfkill);
1425		rfkill_destroy(wireless_rfkill);
1426	}
1427error_wireless:
1428	return err;
1429}
1430
1431static void acer_rfkill_exit(void)
1432{
1433	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1434	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1435		cancel_delayed_work_sync(&acer_rfkill_work);
1436
1437	if (has_cap(ACER_CAP_WIRELESS)) {
1438		rfkill_unregister(wireless_rfkill);
1439		rfkill_destroy(wireless_rfkill);
1440	}
1441
1442	if (has_cap(ACER_CAP_BLUETOOTH)) {
1443		rfkill_unregister(bluetooth_rfkill);
1444		rfkill_destroy(bluetooth_rfkill);
1445	}
1446
1447	if (has_cap(ACER_CAP_THREEG)) {
1448		rfkill_unregister(threeg_rfkill);
1449		rfkill_destroy(threeg_rfkill);
1450	}
1451	return;
1452}
1453
1454/*
1455 * sysfs interface
1456 */
1457static ssize_t show_bool_threeg(struct device *dev,
1458	struct device_attribute *attr, char *buf)
1459{
1460	u32 result; \
1461	acpi_status status;
1462
1463	pr_info("This threeg sysfs will be removed in 2012"
1464		" - used by: %s\n", current->comm);
1465	status = get_u32(&result, ACER_CAP_THREEG);
1466	if (ACPI_SUCCESS(status))
1467		return sprintf(buf, "%u\n", result);
1468	return sprintf(buf, "Read error\n");
1469}
1470
1471static ssize_t set_bool_threeg(struct device *dev,
1472	struct device_attribute *attr, const char *buf, size_t count)
1473{
1474	u32 tmp = simple_strtoul(buf, NULL, 10);
1475	acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
1476	pr_info("This threeg sysfs will be removed in 2012"
1477		" - used by: %s\n", current->comm);
1478	if (ACPI_FAILURE(status))
1479		return -EINVAL;
1480	return count;
1481}
1482static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1483	set_bool_threeg);
1484
1485static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1486	char *buf)
1487{
1488	pr_info("This interface sysfs will be removed in 2012"
1489		" - used by: %s\n", current->comm);
1490	switch (interface->type) {
1491	case ACER_AMW0:
1492		return sprintf(buf, "AMW0\n");
1493	case ACER_AMW0_V2:
1494		return sprintf(buf, "AMW0 v2\n");
1495	case ACER_WMID:
1496		return sprintf(buf, "WMID\n");
1497	case ACER_WMID_v2:
1498		return sprintf(buf, "WMID v2\n");
1499	default:
1500		return sprintf(buf, "Error!\n");
1501	}
1502}
1503
1504static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
1505
1506static void acer_wmi_notify(u32 value, void *context)
1507{
1508	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1509	union acpi_object *obj;
1510	struct event_return_value return_value;
1511	acpi_status status;
1512	u16 device_state;
1513	const struct key_entry *key;
1514
1515	status = wmi_get_event_data(value, &response);
1516	if (status != AE_OK) {
1517		pr_warn("bad event status 0x%x\n", status);
1518		return;
1519	}
1520
1521	obj = (union acpi_object *)response.pointer;
1522
1523	if (!obj)
1524		return;
1525	if (obj->type != ACPI_TYPE_BUFFER) {
1526		pr_warn("Unknown response received %d\n", obj->type);
1527		kfree(obj);
1528		return;
1529	}
1530	if (obj->buffer.length != 8) {
1531		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1532		kfree(obj);
1533		return;
1534	}
1535
1536	return_value = *((struct event_return_value *)obj->buffer.pointer);
1537	kfree(obj);
1538
1539	switch (return_value.function) {
1540	case WMID_HOTKEY_EVENT:
1541		device_state = return_value.device_state;
1542		pr_debug("device state: 0x%x\n", device_state);
1543
1544		key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
1545							return_value.key_num);
1546		if (!key) {
1547			pr_warn("Unknown key number - 0x%x\n",
1548				return_value.key_num);
1549		} else {
1550			switch (key->keycode) {
1551			case KEY_WLAN:
1552			case KEY_BLUETOOTH:
1553				if (has_cap(ACER_CAP_WIRELESS))
1554					rfkill_set_sw_state(wireless_rfkill,
1555						!(device_state & ACER_WMID3_GDS_WIRELESS));
1556				if (has_cap(ACER_CAP_THREEG))
1557					rfkill_set_sw_state(threeg_rfkill,
1558						!(device_state & ACER_WMID3_GDS_THREEG));
1559				if (has_cap(ACER_CAP_BLUETOOTH))
1560					rfkill_set_sw_state(bluetooth_rfkill,
1561						!(device_state & ACER_WMID3_GDS_BLUETOOTH));
1562				break;
1563			}
1564			sparse_keymap_report_entry(acer_wmi_input_dev, key,
1565						   1, true);
1566		}
1567		break;
1568	default:
1569		pr_warn("Unknown function number - %d - %d\n",
1570			return_value.function, return_value.key_num);
1571		break;
1572	}
1573}
1574
1575static acpi_status
1576wmid3_set_lm_mode(struct lm_input_params *params,
1577		  struct lm_return_value *return_value)
1578{
1579	acpi_status status;
1580	union acpi_object *obj;
1581
1582	struct acpi_buffer input = { sizeof(struct lm_input_params), params };
1583	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1584
1585	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
1586	if (ACPI_FAILURE(status))
1587		return status;
1588
1589	obj = output.pointer;
1590
1591	if (!obj)
1592		return AE_ERROR;
1593	else if (obj->type != ACPI_TYPE_BUFFER) {
1594		kfree(obj);
1595		return AE_ERROR;
1596	}
1597	if (obj->buffer.length != 4) {
1598		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1599		kfree(obj);
1600		return AE_ERROR;
1601	}
1602
1603	*return_value = *((struct lm_return_value *)obj->buffer.pointer);
1604	kfree(obj);
1605
1606	return status;
1607}
1608
1609static int acer_wmi_enable_ec_raw(void)
1610{
1611	struct lm_return_value return_value;
1612	acpi_status status;
1613	struct lm_input_params params = {
1614		.function_num = 0x1,
1615		.commun_devices = 0xFFFF,
1616		.devices = 0xFFFF,
1617		.lm_status = 0x00,            /* Launch Manager Deactive */
1618	};
1619
1620	status = wmid3_set_lm_mode(&params, &return_value);
1621
1622	if (return_value.error_code || return_value.ec_return_value)
1623		pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1624			return_value.error_code,
1625			return_value.ec_return_value);
1626	else
1627		pr_info("Enabled EC raw mode\n");
1628
1629	return status;
1630}
1631
1632static int acer_wmi_enable_lm(void)
1633{
1634	struct lm_return_value return_value;
1635	acpi_status status;
1636	struct lm_input_params params = {
1637		.function_num = 0x1,
1638		.commun_devices = 0xFFFF,
1639		.devices = 0xFFFF,
1640		.lm_status = 0x01,            /* Launch Manager Active */
1641	};
1642
1643	status = wmid3_set_lm_mode(&params, &return_value);
1644
1645	if (return_value.error_code || return_value.ec_return_value)
1646		pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1647			return_value.error_code,
1648			return_value.ec_return_value);
1649
1650	return status;
1651}
1652
1653static int __init acer_wmi_input_setup(void)
1654{
1655	acpi_status status;
1656	int err;
1657
1658	acer_wmi_input_dev = input_allocate_device();
1659	if (!acer_wmi_input_dev)
1660		return -ENOMEM;
1661
1662	acer_wmi_input_dev->name = "Acer WMI hotkeys";
1663	acer_wmi_input_dev->phys = "wmi/input0";
1664	acer_wmi_input_dev->id.bustype = BUS_HOST;
1665
1666	err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
1667	if (err)
1668		goto err_free_dev;
1669
1670	status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
1671						acer_wmi_notify, NULL);
1672	if (ACPI_FAILURE(status)) {
1673		err = -EIO;
1674		goto err_free_keymap;
1675	}
1676
1677	err = input_register_device(acer_wmi_input_dev);
1678	if (err)
1679		goto err_uninstall_notifier;
1680
1681	return 0;
1682
1683err_uninstall_notifier:
1684	wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1685err_free_keymap:
1686	sparse_keymap_free(acer_wmi_input_dev);
1687err_free_dev:
1688	input_free_device(acer_wmi_input_dev);
1689	return err;
1690}
1691
1692static void acer_wmi_input_destroy(void)
1693{
1694	wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1695	sparse_keymap_free(acer_wmi_input_dev);
1696	input_unregister_device(acer_wmi_input_dev);
1697}
1698
1699/*
1700 * debugfs functions
1701 */
1702static u32 get_wmid_devices(void)
1703{
1704	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1705	union acpi_object *obj;
1706	acpi_status status;
1707	u32 devices = 0;
1708
1709	status = wmi_query_block(WMID_GUID2, 1, &out);
1710	if (ACPI_FAILURE(status))
1711		return 0;
1712
1713	obj = (union acpi_object *) out.pointer;
1714	if (obj && obj->type == ACPI_TYPE_BUFFER &&
1715		(obj->buffer.length == sizeof(u32) ||
1716		obj->buffer.length == sizeof(u64))) {
1717		devices = *((u32 *) obj->buffer.pointer);
1718	} else if (obj->type == ACPI_TYPE_INTEGER) {
1719		devices = (u32) obj->integer.value;
1720	}
1721
1722	kfree(out.pointer);
1723	return devices;
1724}
1725
1726/*
1727 * Platform device
1728 */
1729static int __devinit acer_platform_probe(struct platform_device *device)
1730{
1731	int err;
1732
1733	if (has_cap(ACER_CAP_MAILLED)) {
1734		err = acer_led_init(&device->dev);
1735		if (err)
1736			goto error_mailled;
1737	}
1738
1739	if (has_cap(ACER_CAP_BRIGHTNESS)) {
1740		err = acer_backlight_init(&device->dev);
1741		if (err)
1742			goto error_brightness;
1743	}
1744
1745	err = acer_rfkill_init(&device->dev);
1746	if (err)
1747		goto error_rfkill;
1748
1749	return err;
1750
1751error_rfkill:
1752	if (has_cap(ACER_CAP_BRIGHTNESS))
1753		acer_backlight_exit();
1754error_brightness:
1755	if (has_cap(ACER_CAP_MAILLED))
1756		acer_led_exit();
1757error_mailled:
1758	return err;
1759}
1760
1761static int acer_platform_remove(struct platform_device *device)
1762{
1763	if (has_cap(ACER_CAP_MAILLED))
1764		acer_led_exit();
1765	if (has_cap(ACER_CAP_BRIGHTNESS))
1766		acer_backlight_exit();
1767
1768	acer_rfkill_exit();
1769	return 0;
1770}
1771
1772static int acer_platform_suspend(struct platform_device *dev,
1773pm_message_t state)
1774{
1775	u32 value;
1776	struct acer_data *data = &interface->data;
1777
1778	if (!data)
1779		return -ENOMEM;
1780
1781	if (has_cap(ACER_CAP_MAILLED)) {
1782		get_u32(&value, ACER_CAP_MAILLED);
1783		set_u32(LED_OFF, ACER_CAP_MAILLED);
1784		data->mailled = value;
1785	}
1786
1787	if (has_cap(ACER_CAP_BRIGHTNESS)) {
1788		get_u32(&value, ACER_CAP_BRIGHTNESS);
1789		data->brightness = value;
1790	}
1791
1792	return 0;
1793}
1794
1795static int acer_platform_resume(struct platform_device *device)
1796{
1797	struct acer_data *data = &interface->data;
1798
1799	if (!data)
1800		return -ENOMEM;
1801
1802	if (has_cap(ACER_CAP_MAILLED))
1803		set_u32(data->mailled, ACER_CAP_MAILLED);
1804
1805	if (has_cap(ACER_CAP_BRIGHTNESS))
1806		set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
1807
1808	return 0;
1809}
1810
1811static void acer_platform_shutdown(struct platform_device *device)
1812{
1813	struct acer_data *data = &interface->data;
1814
1815	if (!data)
1816		return;
1817
1818	if (has_cap(ACER_CAP_MAILLED))
1819		set_u32(LED_OFF, ACER_CAP_MAILLED);
1820}
1821
1822static struct platform_driver acer_platform_driver = {
1823	.driver = {
1824		.name = "acer-wmi",
1825		.owner = THIS_MODULE,
1826	},
1827	.probe = acer_platform_probe,
1828	.remove = acer_platform_remove,
1829	.suspend = acer_platform_suspend,
1830	.resume = acer_platform_resume,
1831	.shutdown = acer_platform_shutdown,
1832};
1833
1834static struct platform_device *acer_platform_device;
1835
1836static int remove_sysfs(struct platform_device *device)
1837{
1838	if (has_cap(ACER_CAP_THREEG))
1839		device_remove_file(&device->dev, &dev_attr_threeg);
1840
1841	device_remove_file(&device->dev, &dev_attr_interface);
1842
1843	return 0;
1844}
1845
1846static int create_sysfs(void)
1847{
1848	int retval = -ENOMEM;
1849
1850	if (has_cap(ACER_CAP_THREEG)) {
1851		retval = device_create_file(&acer_platform_device->dev,
1852			&dev_attr_threeg);
1853		if (retval)
1854			goto error_sysfs;
1855	}
1856
1857	retval = device_create_file(&acer_platform_device->dev,
1858		&dev_attr_interface);
1859	if (retval)
1860		goto error_sysfs;
1861
1862	return 0;
1863
1864error_sysfs:
1865		remove_sysfs(acer_platform_device);
1866	return retval;
1867}
1868
1869static void remove_debugfs(void)
1870{
1871	debugfs_remove(interface->debug.devices);
1872	debugfs_remove(interface->debug.root);
1873}
1874
1875static int create_debugfs(void)
1876{
1877	interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
1878	if (!interface->debug.root) {
1879		pr_err("Failed to create debugfs directory");
1880		return -ENOMEM;
1881	}
1882
1883	interface->debug.devices = debugfs_create_u32("devices", S_IRUGO,
1884					interface->debug.root,
1885					&interface->debug.wmid_devices);
1886	if (!interface->debug.devices)
1887		goto error_debugfs;
1888
1889	return 0;
1890
1891error_debugfs:
1892	remove_debugfs();
1893	return -ENOMEM;
1894}
1895
1896static int __init acer_wmi_init(void)
1897{
1898	int err;
1899
1900	pr_info("Acer Laptop ACPI-WMI Extras\n");
1901
1902	if (dmi_check_system(acer_blacklist)) {
1903		pr_info("Blacklisted hardware detected - not loading\n");
1904		return -ENODEV;
1905	}
1906
1907	find_quirks();
1908
1909	/*
1910	 * Detect which ACPI-WMI interface we're using.
1911	 */
1912	if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1913		interface = &AMW0_V2_interface;
1914
1915	if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1916		interface = &wmid_interface;
1917
1918	if (wmi_has_guid(WMID_GUID3))
1919		interface = &wmid_v2_interface;
1920
1921	if (interface)
1922		dmi_walk(type_aa_dmi_decode, NULL);
1923
1924	if (wmi_has_guid(WMID_GUID2) && interface) {
1925		if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
1926			pr_err("Unable to detect available WMID devices\n");
1927			return -ENODEV;
1928		}
1929		/* WMID always provides brightness methods */
1930		interface->capability |= ACER_CAP_BRIGHTNESS;
1931	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
1932		pr_err("No WMID device detection method found\n");
1933		return -ENODEV;
1934	}
1935
1936	if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) {
1937		interface = &AMW0_interface;
1938
1939		if (ACPI_FAILURE(AMW0_set_capabilities())) {
1940			pr_err("Unable to detect available AMW0 devices\n");
1941			return -ENODEV;
1942		}
1943	}
1944
1945	if (wmi_has_guid(AMW0_GUID1))
1946		AMW0_find_mailled();
1947
1948	if (!interface) {
1949		pr_err("No or unsupported WMI interface, unable to load\n");
1950		return -ENODEV;
1951	}
1952
1953	set_quirks();
1954
1955	if (acpi_video_backlight_support()) {
1956		interface->capability &= ~ACER_CAP_BRIGHTNESS;
1957		pr_info("Brightness must be controlled by "
1958		       "generic video driver\n");
1959	}
1960
1961	if (wmi_has_guid(WMID_GUID3)) {
1962		if (ec_raw_mode) {
1963			if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
1964				pr_err("Cannot enable EC raw mode\n");
1965				return -ENODEV;
1966			}
1967		} else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
1968			pr_err("Cannot enable Launch Manager mode\n");
1969			return -ENODEV;
1970		}
1971	} else if (ec_raw_mode) {
1972		pr_info("No WMID EC raw mode enable method\n");
1973	}
1974
1975	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
1976		err = acer_wmi_input_setup();
1977		if (err)
1978			return err;
1979	}
1980
1981	err = platform_driver_register(&acer_platform_driver);
1982	if (err) {
1983		pr_err("Unable to register platform driver.\n");
1984		goto error_platform_register;
1985	}
1986
1987	acer_platform_device = platform_device_alloc("acer-wmi", -1);
1988	if (!acer_platform_device) {
1989		err = -ENOMEM;
1990		goto error_device_alloc;
1991	}
1992
1993	err = platform_device_add(acer_platform_device);
1994	if (err)
1995		goto error_device_add;
1996
1997	err = create_sysfs();
1998	if (err)
1999		goto error_create_sys;
2000
2001	if (wmi_has_guid(WMID_GUID2)) {
2002		interface->debug.wmid_devices = get_wmid_devices();
2003		err = create_debugfs();
2004		if (err)
2005			goto error_create_debugfs;
2006	}
2007
2008	/* Override any initial settings with values from the commandline */
2009	acer_commandline_init();
2010
2011	return 0;
2012
2013error_create_debugfs:
2014	remove_sysfs(acer_platform_device);
2015error_create_sys:
2016	platform_device_del(acer_platform_device);
2017error_device_add:
2018	platform_device_put(acer_platform_device);
2019error_device_alloc:
2020	platform_driver_unregister(&acer_platform_driver);
2021error_platform_register:
2022	if (wmi_has_guid(ACERWMID_EVENT_GUID))
2023		acer_wmi_input_destroy();
2024
2025	return err;
2026}
2027
2028static void __exit acer_wmi_exit(void)
2029{
2030	if (wmi_has_guid(ACERWMID_EVENT_GUID))
2031		acer_wmi_input_destroy();
2032
2033	remove_sysfs(acer_platform_device);
2034	remove_debugfs();
2035	platform_device_unregister(acer_platform_device);
2036	platform_driver_unregister(&acer_platform_driver);
2037
2038	pr_info("Acer Laptop WMI Extras unloaded\n");
2039	return;
2040}
2041
2042module_init(acer_wmi_init);
2043module_exit(acer_wmi_exit);
2044