xref: /openbmc/linux/drivers/platform/x86/eeepc-wmi.c (revision bc40cce2)
1 /*
2  * Eee PC WMI hotkey driver
3  *
4  * Copyright(C) 2010 Intel Corporation.
5  * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
6  *
7  * Portions based on wistron_btns.c:
8  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26 
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28 
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <linux/input.h>
35 #include <linux/input/sparse-keymap.h>
36 #include <linux/fb.h>
37 #include <linux/backlight.h>
38 #include <linux/leds.h>
39 #include <linux/rfkill.h>
40 #include <linux/debugfs.h>
41 #include <linux/seq_file.h>
42 #include <linux/platform_device.h>
43 #include <acpi/acpi_bus.h>
44 #include <acpi/acpi_drivers.h>
45 
46 #define	EEEPC_WMI_FILE	"eeepc-wmi"
47 
48 MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
49 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
50 MODULE_LICENSE("GPL");
51 
52 #define EEEPC_ACPI_HID		"ASUS010" /* old _HID used in eeepc-laptop */
53 
54 #define EEEPC_WMI_EVENT_GUID	"ABBC0F72-8EA1-11D1-00A0-C90629100000"
55 #define EEEPC_WMI_MGMT_GUID	"97845ED0-4E6D-11DE-8A39-0800200C9A66"
56 
57 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
58 MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
59 
60 #define NOTIFY_BRNUP_MIN	0x11
61 #define NOTIFY_BRNUP_MAX	0x1f
62 #define NOTIFY_BRNDOWN_MIN	0x20
63 #define NOTIFY_BRNDOWN_MAX	0x2e
64 
65 #define EEEPC_WMI_METHODID_DEVS	0x53564544
66 #define EEEPC_WMI_METHODID_DSTS	0x53544344
67 #define EEEPC_WMI_METHODID_CFVS	0x53564643
68 
69 #define EEEPC_WMI_DEVID_BACKLIGHT	0x00050012
70 #define EEEPC_WMI_DEVID_TPDLED		0x00100011
71 #define EEEPC_WMI_DEVID_WLAN		0x00010011
72 #define EEEPC_WMI_DEVID_BLUETOOTH	0x00010013
73 #define EEEPC_WMI_DEVID_WWAN3G		0x00010019
74 
75 static const struct key_entry eeepc_wmi_keymap[] = {
76 	/* Sleep already handled via generic ACPI code */
77 	{ KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
78 	{ KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
79 	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
80 	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
81 	{ KE_KEY, 0x32, { KEY_MUTE } },
82 	{ KE_KEY, 0x5c, { KEY_F15 } },
83 	{ KE_KEY, 0x5d, { KEY_WLAN } },
84 	{ KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
85 	{ KE_KEY, 0x88, { KEY_WLAN } },
86 	{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
87 	{ KE_KEY, 0xe0, { KEY_PROG1 } },
88 	{ KE_KEY, 0xe1, { KEY_F14 } },
89 	{ KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
90 	{ KE_END, 0},
91 };
92 
93 struct bios_args {
94 	u32	dev_id;
95 	u32	ctrl_param;
96 };
97 
98 /*
99  * eeepc-wmi/    - debugfs root directory
100  *   dev_id      - current dev_id
101  *   ctrl_param  - current ctrl_param
102  *   devs        - call DEVS(dev_id, ctrl_param) and print result
103  *   dsts        - call DSTS(dev_id)  and print result
104  */
105 struct eeepc_wmi_debug {
106 	struct dentry *root;
107 	u32 dev_id;
108 	u32 ctrl_param;
109 };
110 
111 struct eeepc_wmi {
112 	struct input_dev *inputdev;
113 	struct backlight_device *backlight_device;
114 	struct platform_device *platform_device;
115 
116 	struct led_classdev tpd_led;
117 	int tpd_led_wk;
118 	struct workqueue_struct *led_workqueue;
119 	struct work_struct tpd_led_work;
120 
121 	struct rfkill *wlan_rfkill;
122 	struct rfkill *bluetooth_rfkill;
123 	struct rfkill *wwan3g_rfkill;
124 
125 	struct eeepc_wmi_debug debug;
126 };
127 
128 /* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
129 static struct platform_device *platform_device;
130 
131 static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
132 {
133 	int err;
134 
135 	eeepc->inputdev = input_allocate_device();
136 	if (!eeepc->inputdev)
137 		return -ENOMEM;
138 
139 	eeepc->inputdev->name = "Eee PC WMI hotkeys";
140 	eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
141 	eeepc->inputdev->id.bustype = BUS_HOST;
142 	eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
143 
144 	err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
145 	if (err)
146 		goto err_free_dev;
147 
148 	err = input_register_device(eeepc->inputdev);
149 	if (err)
150 		goto err_free_keymap;
151 
152 	return 0;
153 
154 err_free_keymap:
155 	sparse_keymap_free(eeepc->inputdev);
156 err_free_dev:
157 	input_free_device(eeepc->inputdev);
158 	return err;
159 }
160 
161 static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
162 {
163 	if (eeepc->inputdev) {
164 		sparse_keymap_free(eeepc->inputdev);
165 		input_unregister_device(eeepc->inputdev);
166 	}
167 
168 	eeepc->inputdev = NULL;
169 }
170 
171 static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
172 {
173 	struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
174 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
175 	union acpi_object *obj;
176 	acpi_status status;
177 	u32 tmp;
178 
179 	status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
180 			1, EEEPC_WMI_METHODID_DSTS, &input, &output);
181 
182 	if (ACPI_FAILURE(status))
183 		return status;
184 
185 	obj = (union acpi_object *)output.pointer;
186 	if (obj && obj->type == ACPI_TYPE_INTEGER)
187 		tmp = (u32)obj->integer.value;
188 	else
189 		tmp = 0;
190 
191 	if (retval)
192 		*retval = tmp;
193 
194 	kfree(obj);
195 
196 	return status;
197 
198 }
199 
200 static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
201 					  u32 *retval)
202 {
203 	struct bios_args args = {
204 		.dev_id = dev_id,
205 		.ctrl_param = ctrl_param,
206 	};
207 	struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
208 	acpi_status status;
209 
210 	if (!retval) {
211 		status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
212 					     EEEPC_WMI_METHODID_DEVS,
213 					     &input, NULL);
214 	} else {
215 		struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
216 		union acpi_object *obj;
217 		u32 tmp;
218 
219 		status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
220 					     EEEPC_WMI_METHODID_DEVS,
221 					     &input, &output);
222 
223 		if (ACPI_FAILURE(status))
224 			return status;
225 
226 		obj = (union acpi_object *)output.pointer;
227 		if (obj && obj->type == ACPI_TYPE_INTEGER)
228 			tmp = (u32)obj->integer.value;
229 		else
230 			tmp = 0;
231 
232 		*retval = tmp;
233 
234 		kfree(obj);
235 	}
236 
237 	return status;
238 }
239 
240 /*
241  * LEDs
242  */
243 /*
244  * These functions actually update the LED's, and are called from a
245  * workqueue. By doing this as separate work rather than when the LED
246  * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
247  * potentially bad time, such as a timer interrupt.
248  */
249 static void tpd_led_update(struct work_struct *work)
250 {
251 	int ctrl_param;
252 	struct eeepc_wmi *eeepc;
253 
254 	eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
255 
256 	ctrl_param = eeepc->tpd_led_wk;
257 	eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
258 }
259 
260 static void tpd_led_set(struct led_classdev *led_cdev,
261 			enum led_brightness value)
262 {
263 	struct eeepc_wmi *eeepc;
264 
265 	eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
266 
267 	eeepc->tpd_led_wk = !!value;
268 	queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
269 }
270 
271 static int read_tpd_state(struct eeepc_wmi *eeepc)
272 {
273 	u32 retval;
274 	acpi_status status;
275 
276 	status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &retval);
277 
278 	if (ACPI_FAILURE(status))
279 		return -1;
280 	else if (!retval || retval == 0x00060000)
281 		/*
282 		 * if touchpad led is present, DSTS will set some bits,
283 		 * usually 0x00020000.
284 		 * 0x00060000 means that the device is not supported
285 		 */
286 		return -ENODEV;
287 	else
288 		/* Status is stored in the first bit */
289 		return retval & 0x1;
290 }
291 
292 static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
293 {
294 	struct eeepc_wmi *eeepc;
295 
296 	eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
297 
298 	return read_tpd_state(eeepc);
299 }
300 
301 static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
302 {
303 	int rv;
304 
305 	if (read_tpd_state(eeepc) < 0)
306 		return 0;
307 
308 	eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
309 	if (!eeepc->led_workqueue)
310 		return -ENOMEM;
311 	INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
312 
313 	eeepc->tpd_led.name = "eeepc::touchpad";
314 	eeepc->tpd_led.brightness_set = tpd_led_set;
315 	eeepc->tpd_led.brightness_get = tpd_led_get;
316 	eeepc->tpd_led.max_brightness = 1;
317 
318 	rv = led_classdev_register(&eeepc->platform_device->dev,
319 				   &eeepc->tpd_led);
320 	if (rv) {
321 		destroy_workqueue(eeepc->led_workqueue);
322 		return rv;
323 	}
324 
325 	return 0;
326 }
327 
328 static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
329 {
330 	if (eeepc->tpd_led.dev)
331 		led_classdev_unregister(&eeepc->tpd_led);
332 	if (eeepc->led_workqueue)
333 		destroy_workqueue(eeepc->led_workqueue);
334 }
335 
336 /*
337  * Rfkill devices
338  */
339 static int eeepc_rfkill_set(void *data, bool blocked)
340 {
341 	int dev_id = (unsigned long)data;
342 	u32 ctrl_param = !blocked;
343 
344 	return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
345 }
346 
347 static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
348 {
349 	int dev_id = (unsigned long)data;
350 	u32 retval;
351 	acpi_status status;
352 
353 	status = eeepc_wmi_get_devstate(dev_id, &retval);
354 
355 	if (ACPI_FAILURE(status))
356 		return ;
357 
358 	rfkill_set_sw_state(rfkill, !(retval & 0x1));
359 }
360 
361 static const struct rfkill_ops eeepc_rfkill_ops = {
362 	.set_block = eeepc_rfkill_set,
363 	.query = eeepc_rfkill_query,
364 };
365 
366 static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
367 			    struct rfkill **rfkill,
368 			    const char *name,
369 			    enum rfkill_type type, int dev_id)
370 {
371 	int result;
372 	u32 retval;
373 	acpi_status status;
374 
375 	status = eeepc_wmi_get_devstate(dev_id, &retval);
376 
377 	if (ACPI_FAILURE(status))
378 		return -1;
379 
380 	/* If the device is present, DSTS will always set some bits
381 	 * 0x00070000 - 1110000000000000000 - device supported
382 	 * 0x00060000 - 1100000000000000000 - not supported
383 	 * 0x00020000 - 0100000000000000000 - device supported
384 	 * 0x00010000 - 0010000000000000000 - not supported / special mode ?
385 	 */
386 	if (!retval || retval == 0x00060000)
387 		return -ENODEV;
388 
389 	*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
390 			       &eeepc_rfkill_ops, (void *)(long)dev_id);
391 
392 	if (!*rfkill)
393 		return -EINVAL;
394 
395 	rfkill_init_sw_state(*rfkill, !(retval & 0x1));
396 	result = rfkill_register(*rfkill);
397 	if (result) {
398 		rfkill_destroy(*rfkill);
399 		*rfkill = NULL;
400 		return result;
401 	}
402 	return 0;
403 }
404 
405 static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
406 {
407 	if (eeepc->wlan_rfkill) {
408 		rfkill_unregister(eeepc->wlan_rfkill);
409 		rfkill_destroy(eeepc->wlan_rfkill);
410 		eeepc->wlan_rfkill = NULL;
411 	}
412 	if (eeepc->bluetooth_rfkill) {
413 		rfkill_unregister(eeepc->bluetooth_rfkill);
414 		rfkill_destroy(eeepc->bluetooth_rfkill);
415 		eeepc->bluetooth_rfkill = NULL;
416 	}
417 	if (eeepc->wwan3g_rfkill) {
418 		rfkill_unregister(eeepc->wwan3g_rfkill);
419 		rfkill_destroy(eeepc->wwan3g_rfkill);
420 		eeepc->wwan3g_rfkill = NULL;
421 	}
422 }
423 
424 static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
425 {
426 	int result = 0;
427 
428 	result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
429 				  "eeepc-wlan", RFKILL_TYPE_WLAN,
430 				  EEEPC_WMI_DEVID_WLAN);
431 
432 	if (result && result != -ENODEV)
433 		goto exit;
434 
435 	result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
436 				  "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
437 				  EEEPC_WMI_DEVID_BLUETOOTH);
438 
439 	if (result && result != -ENODEV)
440 		goto exit;
441 
442 	result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
443 				  "eeepc-wwan3g", RFKILL_TYPE_WWAN,
444 				  EEEPC_WMI_DEVID_WWAN3G);
445 
446 	if (result && result != -ENODEV)
447 		goto exit;
448 
449 exit:
450 	if (result && result != -ENODEV)
451 		eeepc_wmi_rfkill_exit(eeepc);
452 
453 	if (result == -ENODEV)
454 		result = 0;
455 
456 	return result;
457 }
458 
459 /*
460  * Backlight
461  */
462 static int read_brightness(struct backlight_device *bd)
463 {
464 	u32 retval;
465 	acpi_status status;
466 
467 	status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval);
468 
469 	if (ACPI_FAILURE(status))
470 		return -1;
471 	else
472 		return retval & 0xFF;
473 }
474 
475 static int update_bl_status(struct backlight_device *bd)
476 {
477 
478 	u32 ctrl_param;
479 	acpi_status status;
480 
481 	ctrl_param = bd->props.brightness;
482 
483 	status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
484 					ctrl_param, NULL);
485 
486 	if (ACPI_FAILURE(status))
487 		return -1;
488 	else
489 		return 0;
490 }
491 
492 static const struct backlight_ops eeepc_wmi_bl_ops = {
493 	.get_brightness = read_brightness,
494 	.update_status = update_bl_status,
495 };
496 
497 static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
498 {
499 	struct backlight_device *bd = eeepc->backlight_device;
500 	int old = bd->props.brightness;
501 	int new = old;
502 
503 	if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
504 		new = code - NOTIFY_BRNUP_MIN + 1;
505 	else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
506 		new = code - NOTIFY_BRNDOWN_MIN;
507 
508 	bd->props.brightness = new;
509 	backlight_update_status(bd);
510 	backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
511 
512 	return old;
513 }
514 
515 static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
516 {
517 	struct backlight_device *bd;
518 	struct backlight_properties props;
519 
520 	memset(&props, 0, sizeof(struct backlight_properties));
521 	props.max_brightness = 15;
522 	bd = backlight_device_register(EEEPC_WMI_FILE,
523 				       &eeepc->platform_device->dev, eeepc,
524 				       &eeepc_wmi_bl_ops, &props);
525 	if (IS_ERR(bd)) {
526 		pr_err("Could not register backlight device\n");
527 		return PTR_ERR(bd);
528 	}
529 
530 	eeepc->backlight_device = bd;
531 
532 	bd->props.brightness = read_brightness(bd);
533 	bd->props.power = FB_BLANK_UNBLANK;
534 	backlight_update_status(bd);
535 
536 	return 0;
537 }
538 
539 static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
540 {
541 	if (eeepc->backlight_device)
542 		backlight_device_unregister(eeepc->backlight_device);
543 
544 	eeepc->backlight_device = NULL;
545 }
546 
547 static void eeepc_wmi_notify(u32 value, void *context)
548 {
549 	struct eeepc_wmi *eeepc = context;
550 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
551 	union acpi_object *obj;
552 	acpi_status status;
553 	int code;
554 	int orig_code;
555 
556 	status = wmi_get_event_data(value, &response);
557 	if (status != AE_OK) {
558 		pr_err("bad event status 0x%x\n", status);
559 		return;
560 	}
561 
562 	obj = (union acpi_object *)response.pointer;
563 
564 	if (obj && obj->type == ACPI_TYPE_INTEGER) {
565 		code = obj->integer.value;
566 		orig_code = code;
567 
568 		if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
569 			code = NOTIFY_BRNUP_MIN;
570 		else if (code >= NOTIFY_BRNDOWN_MIN &&
571 			 code <= NOTIFY_BRNDOWN_MAX)
572 			code = NOTIFY_BRNDOWN_MIN;
573 
574 		if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
575 			if (!acpi_video_backlight_support())
576 				eeepc_wmi_backlight_notify(eeepc, orig_code);
577 		}
578 
579 		if (!sparse_keymap_report_event(eeepc->inputdev,
580 						code, 1, true))
581 			pr_info("Unknown key %x pressed\n", code);
582 	}
583 
584 	kfree(obj);
585 }
586 
587 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
588 			   const char *buf, size_t count)
589 {
590 	int value;
591 	struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
592 	acpi_status status;
593 
594 	if (!count || sscanf(buf, "%i", &value) != 1)
595 		return -EINVAL;
596 	if (value < 0 || value > 2)
597 		return -EINVAL;
598 
599 	status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
600 				     1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
601 
602 	if (ACPI_FAILURE(status))
603 		return -EIO;
604 	else
605 		return count;
606 }
607 
608 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
609 
610 static struct attribute *platform_attributes[] = {
611 	&dev_attr_cpufv.attr,
612 	NULL
613 };
614 
615 static struct attribute_group platform_attribute_group = {
616 	.attrs = platform_attributes
617 };
618 
619 static void eeepc_wmi_sysfs_exit(struct platform_device *device)
620 {
621 	sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
622 }
623 
624 static int eeepc_wmi_sysfs_init(struct platform_device *device)
625 {
626 	return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
627 }
628 
629 /*
630  * Platform device
631  */
632 static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
633 {
634 	int err;
635 
636 	eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
637 	if (!eeepc->platform_device)
638 		return -ENOMEM;
639 	platform_set_drvdata(eeepc->platform_device, eeepc);
640 
641 	err = platform_device_add(eeepc->platform_device);
642 	if (err)
643 		goto fail_platform_device;
644 
645 	err = eeepc_wmi_sysfs_init(eeepc->platform_device);
646 	if (err)
647 		goto fail_sysfs;
648 	return 0;
649 
650 fail_sysfs:
651 	platform_device_del(eeepc->platform_device);
652 fail_platform_device:
653 	platform_device_put(eeepc->platform_device);
654 	return err;
655 }
656 
657 static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
658 {
659 	eeepc_wmi_sysfs_exit(eeepc->platform_device);
660 	platform_device_unregister(eeepc->platform_device);
661 }
662 
663 /*
664  * debugfs
665  */
666 struct eeepc_wmi_debugfs_node {
667 	struct eeepc_wmi *eeepc;
668 	char *name;
669 	int (*show)(struct seq_file *m, void *data);
670 };
671 
672 static int show_dsts(struct seq_file *m, void *data)
673 {
674 	struct eeepc_wmi *eeepc = m->private;
675 	acpi_status status;
676 	u32 retval = -1;
677 
678 	status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
679 
680 	if (ACPI_FAILURE(status))
681 		return -EIO;
682 
683 	seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
684 
685 	return 0;
686 }
687 
688 static int show_devs(struct seq_file *m, void *data)
689 {
690 	struct eeepc_wmi *eeepc = m->private;
691 	acpi_status status;
692 	u32 retval = -1;
693 
694 	status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
695 					eeepc->debug.ctrl_param, &retval);
696 	if (ACPI_FAILURE(status))
697 		return -EIO;
698 
699 	seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
700 		   eeepc->debug.ctrl_param, retval);
701 
702 	return 0;
703 }
704 
705 static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
706 	{ NULL, "devs", show_devs },
707 	{ NULL, "dsts", show_dsts },
708 };
709 
710 static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
711 {
712 	struct eeepc_wmi_debugfs_node *node = inode->i_private;
713 
714 	return single_open(file, node->show, node->eeepc);
715 }
716 
717 static const struct file_operations eeepc_wmi_debugfs_io_ops = {
718 	.owner = THIS_MODULE,
719 	.open  = eeepc_wmi_debugfs_open,
720 	.read = seq_read,
721 	.llseek = seq_lseek,
722 	.release = single_release,
723 };
724 
725 static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
726 {
727 	debugfs_remove_recursive(eeepc->debug.root);
728 }
729 
730 static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
731 {
732 	struct dentry *dent;
733 	int i;
734 
735 	eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
736 	if (!eeepc->debug.root) {
737 		pr_err("failed to create debugfs directory");
738 		goto error_debugfs;
739 	}
740 
741 	dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
742 				  eeepc->debug.root, &eeepc->debug.dev_id);
743 	if (!dent)
744 		goto error_debugfs;
745 
746 	dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
747 				  eeepc->debug.root, &eeepc->debug.ctrl_param);
748 	if (!dent)
749 		goto error_debugfs;
750 
751 	for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
752 		struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
753 
754 		node->eeepc = eeepc;
755 		dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
756 					   eeepc->debug.root, node,
757 					   &eeepc_wmi_debugfs_io_ops);
758 		if (!dent) {
759 			pr_err("failed to create debug file: %s\n", node->name);
760 			goto error_debugfs;
761 		}
762 	}
763 
764 	return 0;
765 
766 error_debugfs:
767 	eeepc_wmi_debugfs_exit(eeepc);
768 	return -ENOMEM;
769 }
770 
771 /*
772  * WMI Driver
773  */
774 static struct platform_device * __init eeepc_wmi_add(void)
775 {
776 	struct eeepc_wmi *eeepc;
777 	acpi_status status;
778 	int err;
779 
780 	eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
781 	if (!eeepc)
782 		return ERR_PTR(-ENOMEM);
783 
784 	/*
785 	 * Register the platform device first.  It is used as a parent for the
786 	 * sub-devices below.
787 	 */
788 	err = eeepc_wmi_platform_init(eeepc);
789 	if (err)
790 		goto fail_platform;
791 
792 	err = eeepc_wmi_input_init(eeepc);
793 	if (err)
794 		goto fail_input;
795 
796 	err = eeepc_wmi_led_init(eeepc);
797 	if (err)
798 		goto fail_leds;
799 
800 	err = eeepc_wmi_rfkill_init(eeepc);
801 	if (err)
802 		goto fail_rfkill;
803 
804 	if (!acpi_video_backlight_support()) {
805 		err = eeepc_wmi_backlight_init(eeepc);
806 		if (err)
807 			goto fail_backlight;
808 	} else
809 		pr_info("Backlight controlled by ACPI video driver\n");
810 
811 	status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
812 					    eeepc_wmi_notify, eeepc);
813 	if (ACPI_FAILURE(status)) {
814 		pr_err("Unable to register notify handler - %d\n",
815 			status);
816 		err = -ENODEV;
817 		goto fail_wmi_handler;
818 	}
819 
820 	err = eeepc_wmi_debugfs_init(eeepc);
821 	if (err)
822 		goto fail_debugfs;
823 
824 	return eeepc->platform_device;
825 
826 fail_debugfs:
827 	wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
828 fail_wmi_handler:
829 	eeepc_wmi_backlight_exit(eeepc);
830 fail_backlight:
831 	eeepc_wmi_rfkill_exit(eeepc);
832 fail_rfkill:
833 	eeepc_wmi_led_exit(eeepc);
834 fail_leds:
835 	eeepc_wmi_input_exit(eeepc);
836 fail_input:
837 	eeepc_wmi_platform_exit(eeepc);
838 fail_platform:
839 	kfree(eeepc);
840 	return ERR_PTR(err);
841 }
842 
843 static int eeepc_wmi_remove(struct platform_device *device)
844 {
845 	struct eeepc_wmi *eeepc;
846 
847 	eeepc = platform_get_drvdata(device);
848 	wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
849 	eeepc_wmi_backlight_exit(eeepc);
850 	eeepc_wmi_input_exit(eeepc);
851 	eeepc_wmi_led_exit(eeepc);
852 	eeepc_wmi_rfkill_exit(eeepc);
853 	eeepc_wmi_debugfs_exit(eeepc);
854 	eeepc_wmi_platform_exit(eeepc);
855 
856 	kfree(eeepc);
857 	return 0;
858 }
859 
860 static struct platform_driver platform_driver = {
861 	.driver = {
862 		.name = EEEPC_WMI_FILE,
863 		.owner = THIS_MODULE,
864 	},
865 };
866 
867 static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
868 						 void *context, void **retval)
869 {
870 	pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
871 	*(bool *)context = true;
872 	return AE_CTRL_TERMINATE;
873 }
874 
875 static int __init eeepc_wmi_check_atkd(void)
876 {
877 	acpi_status status;
878 	bool found = false;
879 
880 	status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
881 				  &found, NULL);
882 
883 	if (ACPI_FAILURE(status) || !found)
884 		return 0;
885 	return -1;
886 }
887 
888 static int __init eeepc_wmi_init(void)
889 {
890 	int err;
891 
892 	if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
893 	    !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
894 		pr_warning("No known WMI GUID found\n");
895 		return -ENODEV;
896 	}
897 
898 	if (eeepc_wmi_check_atkd()) {
899 		pr_warning("WMI device present, but legacy ATKD device is also "
900 			   "present and enabled.");
901 		pr_warning("You probably booted with acpi_osi=\"Linux\" or "
902 			   "acpi_osi=\"!Windows 2009\"");
903 		pr_warning("Can't load eeepc-wmi, use default acpi_osi "
904 			   "(preferred) or eeepc-laptop");
905 		return -ENODEV;
906 	}
907 
908 	platform_device = eeepc_wmi_add();
909 	if (IS_ERR(platform_device)) {
910 		err = PTR_ERR(platform_device);
911 		goto fail_eeepc_wmi;
912 	}
913 
914 	err = platform_driver_register(&platform_driver);
915 	if (err) {
916 		pr_warning("Unable to register platform driver\n");
917 		goto fail_platform_driver;
918 	}
919 
920 	return 0;
921 
922 fail_platform_driver:
923 	eeepc_wmi_remove(platform_device);
924 fail_eeepc_wmi:
925 	return err;
926 }
927 
928 static void __exit eeepc_wmi_exit(void)
929 {
930 	eeepc_wmi_remove(platform_device);
931 	platform_driver_unregister(&platform_driver);
932 }
933 
934 module_init(eeepc_wmi_init);
935 module_exit(eeepc_wmi_exit);
936