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