2 * Eee PC WMI hotkey driver
4 * Copyright(C) 2010 Intel Corporation.
5 * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
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>
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.
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.
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
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
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>
46 #define EEEPC_WMI_FILE "eeepc-wmi"
48 MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
49 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
50 MODULE_LICENSE("GPL");
52 #define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */
54 #define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
55 #define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
57 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID
);
58 MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID
);
60 #define NOTIFY_BRNUP_MIN 0x11
61 #define NOTIFY_BRNUP_MAX 0x1f
62 #define NOTIFY_BRNDOWN_MIN 0x20
63 #define NOTIFY_BRNDOWN_MAX 0x2e
65 #define EEEPC_WMI_METHODID_DEVS 0x53564544
66 #define EEEPC_WMI_METHODID_DSTS 0x53544344
67 #define EEEPC_WMI_METHODID_CFVS 0x53564643
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
75 static const struct key_entry eeepc_wmi_keymap
[] = {
76 /* Sleep already handled via generic ACPI code */
77 { KE_KEY
, 0x5d, { KEY_WLAN
} },
78 { KE_KEY
, 0x32, { KEY_MUTE
} },
79 { KE_KEY
, 0x31, { KEY_VOLUMEDOWN
} },
80 { KE_KEY
, 0x30, { KEY_VOLUMEUP
} },
81 { KE_IGNORE
, NOTIFY_BRNDOWN_MIN
, { KEY_BRIGHTNESSDOWN
} },
82 { KE_IGNORE
, NOTIFY_BRNUP_MIN
, { KEY_BRIGHTNESSUP
} },
83 { KE_KEY
, 0xcc, { KEY_SWITCHVIDEOMODE
} },
84 { KE_KEY
, 0x6b, { KEY_F13
} }, /* Disable Touchpad */
85 { KE_KEY
, 0xe1, { KEY_F14
} },
86 { KE_KEY
, 0xe9, { KEY_DISPLAY_OFF
} },
87 { KE_KEY
, 0xe0, { KEY_PROG1
} },
88 { KE_KEY
, 0x5c, { KEY_F15
} },
98 * eeepc-wmi/ - debugfs root directory
99 * dev_id - current dev_id
100 * ctrl_param - current ctrl_param
101 * devs - call DEVS(dev_id, ctrl_param) and print result
102 * dsts - call DSTS(dev_id) and print result
104 struct eeepc_wmi_debug
{
111 struct input_dev
*inputdev
;
112 struct backlight_device
*backlight_device
;
113 struct platform_device
*platform_device
;
115 struct led_classdev tpd_led
;
117 struct workqueue_struct
*led_workqueue
;
118 struct work_struct tpd_led_work
;
120 struct rfkill
*wlan_rfkill
;
121 struct rfkill
*bluetooth_rfkill
;
122 struct rfkill
*wwan3g_rfkill
;
124 struct eeepc_wmi_debug debug
;
127 /* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
128 static struct platform_device
*platform_device
;
130 static int eeepc_wmi_input_init(struct eeepc_wmi
*eeepc
)
134 eeepc
->inputdev
= input_allocate_device();
135 if (!eeepc
->inputdev
)
138 eeepc
->inputdev
->name
= "Eee PC WMI hotkeys";
139 eeepc
->inputdev
->phys
= EEEPC_WMI_FILE
"/input0";
140 eeepc
->inputdev
->id
.bustype
= BUS_HOST
;
141 eeepc
->inputdev
->dev
.parent
= &eeepc
->platform_device
->dev
;
143 err
= sparse_keymap_setup(eeepc
->inputdev
, eeepc_wmi_keymap
, NULL
);
147 err
= input_register_device(eeepc
->inputdev
);
149 goto err_free_keymap
;
154 sparse_keymap_free(eeepc
->inputdev
);
156 input_free_device(eeepc
->inputdev
);
160 static void eeepc_wmi_input_exit(struct eeepc_wmi
*eeepc
)
162 if (eeepc
->inputdev
) {
163 sparse_keymap_free(eeepc
->inputdev
);
164 input_unregister_device(eeepc
->inputdev
);
167 eeepc
->inputdev
= NULL
;
170 static acpi_status
eeepc_wmi_get_devstate(u32 dev_id
, u32
*retval
)
172 struct acpi_buffer input
= { (acpi_size
)sizeof(u32
), &dev_id
};
173 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
174 union acpi_object
*obj
;
178 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
,
179 1, EEEPC_WMI_METHODID_DSTS
, &input
, &output
);
181 if (ACPI_FAILURE(status
))
184 obj
= (union acpi_object
*)output
.pointer
;
185 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
)
186 tmp
= (u32
)obj
->integer
.value
;
199 static acpi_status
eeepc_wmi_set_devstate(u32 dev_id
, u32 ctrl_param
,
202 struct bios_args args
= {
204 .ctrl_param
= ctrl_param
,
206 struct acpi_buffer input
= { (acpi_size
)sizeof(args
), &args
};
210 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
, 1,
211 EEEPC_WMI_METHODID_DEVS
,
214 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
215 union acpi_object
*obj
;
218 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
, 1,
219 EEEPC_WMI_METHODID_DEVS
,
222 if (ACPI_FAILURE(status
))
225 obj
= (union acpi_object
*)output
.pointer
;
226 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
)
227 tmp
= (u32
)obj
->integer
.value
;
243 * These functions actually update the LED's, and are called from a
244 * workqueue. By doing this as separate work rather than when the LED
245 * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
246 * potentially bad time, such as a timer interrupt.
248 static void tpd_led_update(struct work_struct
*work
)
251 struct eeepc_wmi
*eeepc
;
253 eeepc
= container_of(work
, struct eeepc_wmi
, tpd_led_work
);
255 ctrl_param
= eeepc
->tpd_led_wk
;
256 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED
, ctrl_param
, NULL
);
259 static void tpd_led_set(struct led_classdev
*led_cdev
,
260 enum led_brightness value
)
262 struct eeepc_wmi
*eeepc
;
264 eeepc
= container_of(led_cdev
, struct eeepc_wmi
, tpd_led
);
266 eeepc
->tpd_led_wk
= !!value
;
267 queue_work(eeepc
->led_workqueue
, &eeepc
->tpd_led_work
);
270 static int read_tpd_state(struct eeepc_wmi
*eeepc
)
275 status
= eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED
, &retval
);
277 if (ACPI_FAILURE(status
))
279 else if (!retval
|| retval
== 0x00060000)
281 * if touchpad led is present, DSTS will set some bits,
282 * usually 0x00020000.
283 * 0x00060000 means that the device is not supported
287 /* Status is stored in the first bit */
291 static enum led_brightness
tpd_led_get(struct led_classdev
*led_cdev
)
293 struct eeepc_wmi
*eeepc
;
295 eeepc
= container_of(led_cdev
, struct eeepc_wmi
, tpd_led
);
297 return read_tpd_state(eeepc
);
300 static int eeepc_wmi_led_init(struct eeepc_wmi
*eeepc
)
304 if (read_tpd_state(eeepc
) < 0)
307 eeepc
->led_workqueue
= create_singlethread_workqueue("led_workqueue");
308 if (!eeepc
->led_workqueue
)
310 INIT_WORK(&eeepc
->tpd_led_work
, tpd_led_update
);
312 eeepc
->tpd_led
.name
= "eeepc::touchpad";
313 eeepc
->tpd_led
.brightness_set
= tpd_led_set
;
314 eeepc
->tpd_led
.brightness_get
= tpd_led_get
;
315 eeepc
->tpd_led
.max_brightness
= 1;
317 rv
= led_classdev_register(&eeepc
->platform_device
->dev
,
320 destroy_workqueue(eeepc
->led_workqueue
);
327 static void eeepc_wmi_led_exit(struct eeepc_wmi
*eeepc
)
329 if (eeepc
->tpd_led
.dev
)
330 led_classdev_unregister(&eeepc
->tpd_led
);
331 if (eeepc
->led_workqueue
)
332 destroy_workqueue(eeepc
->led_workqueue
);
338 static int eeepc_rfkill_set(void *data
, bool blocked
)
340 int dev_id
= (unsigned long)data
;
341 u32 ctrl_param
= !blocked
;
343 return eeepc_wmi_set_devstate(dev_id
, ctrl_param
, NULL
);
346 static void eeepc_rfkill_query(struct rfkill
*rfkill
, void *data
)
348 int dev_id
= (unsigned long)data
;
352 status
= eeepc_wmi_get_devstate(dev_id
, &retval
);
354 if (ACPI_FAILURE(status
))
357 rfkill_set_sw_state(rfkill
, !(retval
& 0x1));
360 static const struct rfkill_ops eeepc_rfkill_ops
= {
361 .set_block
= eeepc_rfkill_set
,
362 .query
= eeepc_rfkill_query
,
365 static int eeepc_new_rfkill(struct eeepc_wmi
*eeepc
,
366 struct rfkill
**rfkill
,
368 enum rfkill_type type
, int dev_id
)
374 status
= eeepc_wmi_get_devstate(dev_id
, &retval
);
376 if (ACPI_FAILURE(status
))
379 /* If the device is present, DSTS will always set some bits
380 * 0x00070000 - 1110000000000000000 - device supported
381 * 0x00060000 - 1100000000000000000 - not supported
382 * 0x00020000 - 0100000000000000000 - device supported
383 * 0x00010000 - 0010000000000000000 - not supported / special mode ?
385 if (!retval
|| retval
== 0x00060000)
388 *rfkill
= rfkill_alloc(name
, &eeepc
->platform_device
->dev
, type
,
389 &eeepc_rfkill_ops
, (void *)(long)dev_id
);
394 rfkill_init_sw_state(*rfkill
, !(retval
& 0x1));
395 result
= rfkill_register(*rfkill
);
397 rfkill_destroy(*rfkill
);
404 static void eeepc_wmi_rfkill_exit(struct eeepc_wmi
*eeepc
)
406 if (eeepc
->wlan_rfkill
) {
407 rfkill_unregister(eeepc
->wlan_rfkill
);
408 rfkill_destroy(eeepc
->wlan_rfkill
);
409 eeepc
->wlan_rfkill
= NULL
;
411 if (eeepc
->bluetooth_rfkill
) {
412 rfkill_unregister(eeepc
->bluetooth_rfkill
);
413 rfkill_destroy(eeepc
->bluetooth_rfkill
);
414 eeepc
->bluetooth_rfkill
= NULL
;
416 if (eeepc
->wwan3g_rfkill
) {
417 rfkill_unregister(eeepc
->wwan3g_rfkill
);
418 rfkill_destroy(eeepc
->wwan3g_rfkill
);
419 eeepc
->wwan3g_rfkill
= NULL
;
423 static int eeepc_wmi_rfkill_init(struct eeepc_wmi
*eeepc
)
427 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wlan_rfkill
,
428 "eeepc-wlan", RFKILL_TYPE_WLAN
,
429 EEEPC_WMI_DEVID_WLAN
);
431 if (result
&& result
!= -ENODEV
)
434 result
= eeepc_new_rfkill(eeepc
, &eeepc
->bluetooth_rfkill
,
435 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH
,
436 EEEPC_WMI_DEVID_BLUETOOTH
);
438 if (result
&& result
!= -ENODEV
)
441 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wwan3g_rfkill
,
442 "eeepc-wwan3g", RFKILL_TYPE_WWAN
,
443 EEEPC_WMI_DEVID_WWAN3G
);
445 if (result
&& result
!= -ENODEV
)
449 if (result
&& result
!= -ENODEV
)
450 eeepc_wmi_rfkill_exit(eeepc
);
452 if (result
== -ENODEV
)
461 static int read_brightness(struct backlight_device
*bd
)
466 status
= eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT
, &retval
);
468 if (ACPI_FAILURE(status
))
471 return retval
& 0xFF;
474 static int update_bl_status(struct backlight_device
*bd
)
480 ctrl_param
= bd
->props
.brightness
;
482 status
= eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT
,
485 if (ACPI_FAILURE(status
))
491 static const struct backlight_ops eeepc_wmi_bl_ops
= {
492 .get_brightness
= read_brightness
,
493 .update_status
= update_bl_status
,
496 static int eeepc_wmi_backlight_notify(struct eeepc_wmi
*eeepc
, int code
)
498 struct backlight_device
*bd
= eeepc
->backlight_device
;
499 int old
= bd
->props
.brightness
;
502 if (code
>= NOTIFY_BRNUP_MIN
&& code
<= NOTIFY_BRNUP_MAX
)
503 new = code
- NOTIFY_BRNUP_MIN
+ 1;
504 else if (code
>= NOTIFY_BRNDOWN_MIN
&& code
<= NOTIFY_BRNDOWN_MAX
)
505 new = code
- NOTIFY_BRNDOWN_MIN
;
507 bd
->props
.brightness
= new;
508 backlight_update_status(bd
);
509 backlight_force_update(bd
, BACKLIGHT_UPDATE_HOTKEY
);
514 static int eeepc_wmi_backlight_init(struct eeepc_wmi
*eeepc
)
516 struct backlight_device
*bd
;
517 struct backlight_properties props
;
519 memset(&props
, 0, sizeof(struct backlight_properties
));
520 props
.max_brightness
= 15;
521 bd
= backlight_device_register(EEEPC_WMI_FILE
,
522 &eeepc
->platform_device
->dev
, eeepc
,
523 &eeepc_wmi_bl_ops
, &props
);
525 pr_err("Could not register backlight device\n");
529 eeepc
->backlight_device
= bd
;
531 bd
->props
.brightness
= read_brightness(bd
);
532 bd
->props
.power
= FB_BLANK_UNBLANK
;
533 backlight_update_status(bd
);
538 static void eeepc_wmi_backlight_exit(struct eeepc_wmi
*eeepc
)
540 if (eeepc
->backlight_device
)
541 backlight_device_unregister(eeepc
->backlight_device
);
543 eeepc
->backlight_device
= NULL
;
546 static void eeepc_wmi_notify(u32 value
, void *context
)
548 struct eeepc_wmi
*eeepc
= context
;
549 struct acpi_buffer response
= { ACPI_ALLOCATE_BUFFER
, NULL
};
550 union acpi_object
*obj
;
555 status
= wmi_get_event_data(value
, &response
);
556 if (status
!= AE_OK
) {
557 pr_err("bad event status 0x%x\n", status
);
561 obj
= (union acpi_object
*)response
.pointer
;
563 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
) {
564 code
= obj
->integer
.value
;
567 if (code
>= NOTIFY_BRNUP_MIN
&& code
<= NOTIFY_BRNUP_MAX
)
568 code
= NOTIFY_BRNUP_MIN
;
569 else if (code
>= NOTIFY_BRNDOWN_MIN
&&
570 code
<= NOTIFY_BRNDOWN_MAX
)
571 code
= NOTIFY_BRNDOWN_MIN
;
573 if (code
== NOTIFY_BRNUP_MIN
|| code
== NOTIFY_BRNDOWN_MIN
) {
574 if (!acpi_video_backlight_support())
575 eeepc_wmi_backlight_notify(eeepc
, orig_code
);
578 if (!sparse_keymap_report_event(eeepc
->inputdev
,
580 pr_info("Unknown key %x pressed\n", code
);
586 static ssize_t
store_cpufv(struct device
*dev
, struct device_attribute
*attr
,
587 const char *buf
, size_t count
)
590 struct acpi_buffer input
= { (acpi_size
)sizeof(value
), &value
};
593 if (!count
|| sscanf(buf
, "%i", &value
) != 1)
595 if (value
< 0 || value
> 2)
598 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
,
599 1, EEEPC_WMI_METHODID_CFVS
, &input
, NULL
);
601 if (ACPI_FAILURE(status
))
607 static DEVICE_ATTR(cpufv
, S_IRUGO
| S_IWUSR
, NULL
, store_cpufv
);
609 static struct attribute
*platform_attributes
[] = {
610 &dev_attr_cpufv
.attr
,
614 static struct attribute_group platform_attribute_group
= {
615 .attrs
= platform_attributes
618 static void eeepc_wmi_sysfs_exit(struct platform_device
*device
)
620 sysfs_remove_group(&device
->dev
.kobj
, &platform_attribute_group
);
623 static int eeepc_wmi_sysfs_init(struct platform_device
*device
)
625 return sysfs_create_group(&device
->dev
.kobj
, &platform_attribute_group
);
631 static int __init
eeepc_wmi_platform_init(struct eeepc_wmi
*eeepc
)
635 eeepc
->platform_device
= platform_device_alloc(EEEPC_WMI_FILE
, -1);
636 if (!eeepc
->platform_device
)
638 platform_set_drvdata(eeepc
->platform_device
, eeepc
);
640 err
= platform_device_add(eeepc
->platform_device
);
642 goto fail_platform_device
;
644 err
= eeepc_wmi_sysfs_init(eeepc
->platform_device
);
650 platform_device_del(eeepc
->platform_device
);
651 fail_platform_device
:
652 platform_device_put(eeepc
->platform_device
);
656 static void eeepc_wmi_platform_exit(struct eeepc_wmi
*eeepc
)
658 eeepc_wmi_sysfs_exit(eeepc
->platform_device
);
659 platform_device_unregister(eeepc
->platform_device
);
665 struct eeepc_wmi_debugfs_node
{
666 struct eeepc_wmi
*eeepc
;
668 int (*show
)(struct seq_file
*m
, void *data
);
671 static int show_dsts(struct seq_file
*m
, void *data
)
673 struct eeepc_wmi
*eeepc
= m
->private;
677 status
= eeepc_wmi_get_devstate(eeepc
->debug
.dev_id
, &retval
);
679 if (ACPI_FAILURE(status
))
682 seq_printf(m
, "DSTS(%x) = %x\n", eeepc
->debug
.dev_id
, retval
);
687 static int show_devs(struct seq_file
*m
, void *data
)
689 struct eeepc_wmi
*eeepc
= m
->private;
693 status
= eeepc_wmi_set_devstate(eeepc
->debug
.dev_id
,
694 eeepc
->debug
.ctrl_param
, &retval
);
695 if (ACPI_FAILURE(status
))
698 seq_printf(m
, "DEVS(%x, %x) = %x\n", eeepc
->debug
.dev_id
,
699 eeepc
->debug
.ctrl_param
, retval
);
704 static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files
[] = {
705 { NULL
, "devs", show_devs
},
706 { NULL
, "dsts", show_dsts
},
709 static int eeepc_wmi_debugfs_open(struct inode
*inode
, struct file
*file
)
711 struct eeepc_wmi_debugfs_node
*node
= inode
->i_private
;
713 return single_open(file
, node
->show
, node
->eeepc
);
716 static const struct file_operations eeepc_wmi_debugfs_io_ops
= {
717 .owner
= THIS_MODULE
,
718 .open
= eeepc_wmi_debugfs_open
,
721 .release
= single_release
,
724 static void eeepc_wmi_debugfs_exit(struct eeepc_wmi
*eeepc
)
726 debugfs_remove_recursive(eeepc
->debug
.root
);
729 static int eeepc_wmi_debugfs_init(struct eeepc_wmi
*eeepc
)
734 eeepc
->debug
.root
= debugfs_create_dir(EEEPC_WMI_FILE
, NULL
);
735 if (!eeepc
->debug
.root
) {
736 pr_err("failed to create debugfs directory");
740 dent
= debugfs_create_x32("dev_id", S_IRUGO
|S_IWUSR
,
741 eeepc
->debug
.root
, &eeepc
->debug
.dev_id
);
745 dent
= debugfs_create_x32("ctrl_param", S_IRUGO
|S_IWUSR
,
746 eeepc
->debug
.root
, &eeepc
->debug
.ctrl_param
);
750 for (i
= 0; i
< ARRAY_SIZE(eeepc_wmi_debug_files
); i
++) {
751 struct eeepc_wmi_debugfs_node
*node
= &eeepc_wmi_debug_files
[i
];
754 dent
= debugfs_create_file(node
->name
, S_IFREG
| S_IRUGO
,
755 eeepc
->debug
.root
, node
,
756 &eeepc_wmi_debugfs_io_ops
);
758 pr_err("failed to create debug file: %s\n", node
->name
);
766 eeepc_wmi_debugfs_exit(eeepc
);
773 static struct platform_device
* __init
eeepc_wmi_add(void)
775 struct eeepc_wmi
*eeepc
;
779 eeepc
= kzalloc(sizeof(struct eeepc_wmi
), GFP_KERNEL
);
781 return ERR_PTR(-ENOMEM
);
784 * Register the platform device first. It is used as a parent for the
787 err
= eeepc_wmi_platform_init(eeepc
);
791 err
= eeepc_wmi_input_init(eeepc
);
795 err
= eeepc_wmi_led_init(eeepc
);
799 err
= eeepc_wmi_rfkill_init(eeepc
);
803 if (!acpi_video_backlight_support()) {
804 err
= eeepc_wmi_backlight_init(eeepc
);
808 pr_info("Backlight controlled by ACPI video driver\n");
810 status
= wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID
,
811 eeepc_wmi_notify
, eeepc
);
812 if (ACPI_FAILURE(status
)) {
813 pr_err("Unable to register notify handler - %d\n",
816 goto fail_wmi_handler
;
819 err
= eeepc_wmi_debugfs_init(eeepc
);
823 return eeepc
->platform_device
;
826 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID
);
828 eeepc_wmi_backlight_exit(eeepc
);
830 eeepc_wmi_rfkill_exit(eeepc
);
832 eeepc_wmi_led_exit(eeepc
);
834 eeepc_wmi_input_exit(eeepc
);
836 eeepc_wmi_platform_exit(eeepc
);
842 static int eeepc_wmi_remove(struct platform_device
*device
)
844 struct eeepc_wmi
*eeepc
;
846 eeepc
= platform_get_drvdata(device
);
847 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID
);
848 eeepc_wmi_backlight_exit(eeepc
);
849 eeepc_wmi_input_exit(eeepc
);
850 eeepc_wmi_led_exit(eeepc
);
851 eeepc_wmi_rfkill_exit(eeepc
);
852 eeepc_wmi_debugfs_exit(eeepc
);
853 eeepc_wmi_platform_exit(eeepc
);
859 static struct platform_driver platform_driver
= {
861 .name
= EEEPC_WMI_FILE
,
862 .owner
= THIS_MODULE
,
866 static acpi_status __init
eeepc_wmi_parse_device(acpi_handle handle
, u32 level
,
867 void *context
, void **retval
)
869 pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID
);
870 *(bool *)context
= true;
871 return AE_CTRL_TERMINATE
;
874 static int __init
eeepc_wmi_check_atkd(void)
879 status
= acpi_get_devices(EEEPC_ACPI_HID
, eeepc_wmi_parse_device
,
882 if (ACPI_FAILURE(status
) || !found
)
887 static int __init
eeepc_wmi_init(void)
891 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID
) ||
892 !wmi_has_guid(EEEPC_WMI_MGMT_GUID
)) {
893 pr_warning("No known WMI GUID found\n");
897 if (eeepc_wmi_check_atkd()) {
898 pr_warning("WMI device present, but legacy ATKD device is also "
899 "present and enabled.");
900 pr_warning("You probably booted with acpi_osi=\"Linux\" or "
901 "acpi_osi=\"!Windows 2009\"");
902 pr_warning("Can't load eeepc-wmi, use default acpi_osi "
903 "(preferred) or eeepc-laptop");
907 platform_device
= eeepc_wmi_add();
908 if (IS_ERR(platform_device
)) {
909 err
= PTR_ERR(platform_device
);
913 err
= platform_driver_register(&platform_driver
);
915 pr_warning("Unable to register platform driver\n");
916 goto fail_platform_driver
;
921 fail_platform_driver
:
922 eeepc_wmi_remove(platform_device
);
927 static void __exit
eeepc_wmi_exit(void)
929 eeepc_wmi_remove(platform_device
);
930 platform_driver_unregister(&platform_driver
);
933 module_init(eeepc_wmi_init
);
934 module_exit(eeepc_wmi_exit
);