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