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