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_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
53 #define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
55 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID
);
56 MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID
);
58 #define NOTIFY_BRNUP_MIN 0x11
59 #define NOTIFY_BRNUP_MAX 0x1f
60 #define NOTIFY_BRNDOWN_MIN 0x20
61 #define NOTIFY_BRNDOWN_MAX 0x2e
63 #define EEEPC_WMI_METHODID_DEVS 0x53564544
64 #define EEEPC_WMI_METHODID_DSTS 0x53544344
65 #define EEEPC_WMI_METHODID_CFVS 0x53564643
67 #define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
68 #define EEEPC_WMI_DEVID_TPDLED 0x00100011
69 #define EEEPC_WMI_DEVID_WLAN 0x00010011
70 #define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
71 #define EEEPC_WMI_DEVID_WWAN3G 0x00010019
73 static const struct key_entry eeepc_wmi_keymap
[] = {
74 /* Sleep already handled via generic ACPI code */
75 { KE_KEY
, 0x5d, { KEY_WLAN
} },
76 { KE_KEY
, 0x32, { KEY_MUTE
} },
77 { KE_KEY
, 0x31, { KEY_VOLUMEDOWN
} },
78 { KE_KEY
, 0x30, { KEY_VOLUMEUP
} },
79 { KE_IGNORE
, NOTIFY_BRNDOWN_MIN
, { KEY_BRIGHTNESSDOWN
} },
80 { KE_IGNORE
, NOTIFY_BRNUP_MIN
, { KEY_BRIGHTNESSUP
} },
81 { KE_KEY
, 0xcc, { KEY_SWITCHVIDEOMODE
} },
82 { KE_KEY
, 0x6b, { KEY_F13
} }, /* Disable Touchpad */
83 { KE_KEY
, 0xe1, { KEY_F14
} },
84 { KE_KEY
, 0xe9, { KEY_DISPLAY_OFF
} },
85 { KE_KEY
, 0xe0, { KEY_PROG1
} },
86 { KE_KEY
, 0x5c, { KEY_F15
} },
96 * eeepc-wmi/ - debugfs root directory
97 * dev_id - current dev_id
98 * ctrl_param - current ctrl_param
99 * devs - call DEVS(dev_id, ctrl_param) and print result
100 * dsts - call DSTS(dev_id) and print result
102 struct eeepc_wmi_debug
{
109 struct input_dev
*inputdev
;
110 struct backlight_device
*backlight_device
;
111 struct platform_device
*platform_device
;
113 struct led_classdev tpd_led
;
115 struct workqueue_struct
*led_workqueue
;
116 struct work_struct tpd_led_work
;
118 struct rfkill
*wlan_rfkill
;
119 struct rfkill
*bluetooth_rfkill
;
120 struct rfkill
*wwan3g_rfkill
;
122 struct eeepc_wmi_debug debug
;
125 /* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
126 static struct platform_device
*platform_device
;
128 static int eeepc_wmi_input_init(struct eeepc_wmi
*eeepc
)
132 eeepc
->inputdev
= input_allocate_device();
133 if (!eeepc
->inputdev
)
136 eeepc
->inputdev
->name
= "Eee PC WMI hotkeys";
137 eeepc
->inputdev
->phys
= EEEPC_WMI_FILE
"/input0";
138 eeepc
->inputdev
->id
.bustype
= BUS_HOST
;
139 eeepc
->inputdev
->dev
.parent
= &eeepc
->platform_device
->dev
;
141 err
= sparse_keymap_setup(eeepc
->inputdev
, eeepc_wmi_keymap
, NULL
);
145 err
= input_register_device(eeepc
->inputdev
);
147 goto err_free_keymap
;
152 sparse_keymap_free(eeepc
->inputdev
);
154 input_free_device(eeepc
->inputdev
);
158 static void eeepc_wmi_input_exit(struct eeepc_wmi
*eeepc
)
160 if (eeepc
->inputdev
) {
161 sparse_keymap_free(eeepc
->inputdev
);
162 input_unregister_device(eeepc
->inputdev
);
165 eeepc
->inputdev
= NULL
;
168 static acpi_status
eeepc_wmi_get_devstate(u32 dev_id
, u32
*retval
)
170 struct acpi_buffer input
= { (acpi_size
)sizeof(u32
), &dev_id
};
171 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
172 union acpi_object
*obj
;
176 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
,
177 1, EEEPC_WMI_METHODID_DSTS
, &input
, &output
);
179 if (ACPI_FAILURE(status
))
182 obj
= (union acpi_object
*)output
.pointer
;
183 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
)
184 tmp
= (u32
)obj
->integer
.value
;
197 static acpi_status
eeepc_wmi_set_devstate(u32 dev_id
, u32 ctrl_param
,
200 struct bios_args args
= {
202 .ctrl_param
= ctrl_param
,
204 struct acpi_buffer input
= { (acpi_size
)sizeof(args
), &args
};
208 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
, 1,
209 EEEPC_WMI_METHODID_DEVS
,
212 struct acpi_buffer output
= { ACPI_ALLOCATE_BUFFER
, NULL
};
213 union acpi_object
*obj
;
216 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
, 1,
217 EEEPC_WMI_METHODID_DEVS
,
220 if (ACPI_FAILURE(status
))
223 obj
= (union acpi_object
*)output
.pointer
;
224 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
)
225 tmp
= (u32
)obj
->integer
.value
;
241 * These functions actually update the LED's, and are called from a
242 * workqueue. By doing this as separate work rather than when the LED
243 * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
244 * potentially bad time, such as a timer interrupt.
246 static void tpd_led_update(struct work_struct
*work
)
249 struct eeepc_wmi
*eeepc
;
251 eeepc
= container_of(work
, struct eeepc_wmi
, tpd_led_work
);
253 ctrl_param
= eeepc
->tpd_led_wk
;
254 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED
, ctrl_param
, NULL
);
257 static void tpd_led_set(struct led_classdev
*led_cdev
,
258 enum led_brightness value
)
260 struct eeepc_wmi
*eeepc
;
262 eeepc
= container_of(led_cdev
, struct eeepc_wmi
, tpd_led
);
264 eeepc
->tpd_led_wk
= !!value
;
265 queue_work(eeepc
->led_workqueue
, &eeepc
->tpd_led_work
);
268 static int read_tpd_state(struct eeepc_wmi
*eeepc
)
273 status
= eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED
, &retval
);
275 if (ACPI_FAILURE(status
))
277 else if (!retval
|| retval
== 0x00060000)
279 * if touchpad led is present, DSTS will set some bits,
280 * usually 0x00020000.
281 * 0x00060000 means that the device is not supported
285 /* Status is stored in the first bit */
289 static enum led_brightness
tpd_led_get(struct led_classdev
*led_cdev
)
291 struct eeepc_wmi
*eeepc
;
293 eeepc
= container_of(led_cdev
, struct eeepc_wmi
, tpd_led
);
295 return read_tpd_state(eeepc
);
298 static int eeepc_wmi_led_init(struct eeepc_wmi
*eeepc
)
302 if (read_tpd_state(eeepc
) < 0)
305 eeepc
->led_workqueue
= create_singlethread_workqueue("led_workqueue");
306 if (!eeepc
->led_workqueue
)
308 INIT_WORK(&eeepc
->tpd_led_work
, tpd_led_update
);
310 eeepc
->tpd_led
.name
= "eeepc::touchpad";
311 eeepc
->tpd_led
.brightness_set
= tpd_led_set
;
312 eeepc
->tpd_led
.brightness_get
= tpd_led_get
;
313 eeepc
->tpd_led
.max_brightness
= 1;
315 rv
= led_classdev_register(&eeepc
->platform_device
->dev
,
318 destroy_workqueue(eeepc
->led_workqueue
);
325 static void eeepc_wmi_led_exit(struct eeepc_wmi
*eeepc
)
327 if (eeepc
->tpd_led
.dev
)
328 led_classdev_unregister(&eeepc
->tpd_led
);
329 if (eeepc
->led_workqueue
)
330 destroy_workqueue(eeepc
->led_workqueue
);
336 static int eeepc_rfkill_set(void *data
, bool blocked
)
338 int dev_id
= (unsigned long)data
;
339 u32 ctrl_param
= !blocked
;
341 return eeepc_wmi_set_devstate(dev_id
, ctrl_param
, NULL
);
344 static void eeepc_rfkill_query(struct rfkill
*rfkill
, void *data
)
346 int dev_id
= (unsigned long)data
;
350 status
= eeepc_wmi_get_devstate(dev_id
, &retval
);
352 if (ACPI_FAILURE(status
))
355 rfkill_set_sw_state(rfkill
, !(retval
& 0x1));
358 static const struct rfkill_ops eeepc_rfkill_ops
= {
359 .set_block
= eeepc_rfkill_set
,
360 .query
= eeepc_rfkill_query
,
363 static int eeepc_new_rfkill(struct eeepc_wmi
*eeepc
,
364 struct rfkill
**rfkill
,
366 enum rfkill_type type
, int dev_id
)
372 status
= eeepc_wmi_get_devstate(dev_id
, &retval
);
374 if (ACPI_FAILURE(status
))
377 /* If the device is present, DSTS will always set some bits
378 * 0x00070000 - 1110000000000000000 - device supported
379 * 0x00060000 - 1100000000000000000 - not supported
380 * 0x00020000 - 0100000000000000000 - device supported
381 * 0x00010000 - 0010000000000000000 - not supported / special mode ?
383 if (!retval
|| retval
== 0x00060000)
386 *rfkill
= rfkill_alloc(name
, &eeepc
->platform_device
->dev
, type
,
387 &eeepc_rfkill_ops
, (void *)(long)dev_id
);
392 rfkill_init_sw_state(*rfkill
, !(retval
& 0x1));
393 result
= rfkill_register(*rfkill
);
395 rfkill_destroy(*rfkill
);
402 static void eeepc_wmi_rfkill_exit(struct eeepc_wmi
*eeepc
)
404 if (eeepc
->wlan_rfkill
) {
405 rfkill_unregister(eeepc
->wlan_rfkill
);
406 rfkill_destroy(eeepc
->wlan_rfkill
);
407 eeepc
->wlan_rfkill
= NULL
;
409 if (eeepc
->bluetooth_rfkill
) {
410 rfkill_unregister(eeepc
->bluetooth_rfkill
);
411 rfkill_destroy(eeepc
->bluetooth_rfkill
);
412 eeepc
->bluetooth_rfkill
= NULL
;
414 if (eeepc
->wwan3g_rfkill
) {
415 rfkill_unregister(eeepc
->wwan3g_rfkill
);
416 rfkill_destroy(eeepc
->wwan3g_rfkill
);
417 eeepc
->wwan3g_rfkill
= NULL
;
421 static int eeepc_wmi_rfkill_init(struct eeepc_wmi
*eeepc
)
425 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wlan_rfkill
,
426 "eeepc-wlan", RFKILL_TYPE_WLAN
,
427 EEEPC_WMI_DEVID_WLAN
);
429 if (result
&& result
!= -ENODEV
)
432 result
= eeepc_new_rfkill(eeepc
, &eeepc
->bluetooth_rfkill
,
433 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH
,
434 EEEPC_WMI_DEVID_BLUETOOTH
);
436 if (result
&& result
!= -ENODEV
)
439 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wwan3g_rfkill
,
440 "eeepc-wwan3g", RFKILL_TYPE_WWAN
,
441 EEEPC_WMI_DEVID_WWAN3G
);
443 if (result
&& result
!= -ENODEV
)
447 if (result
&& result
!= -ENODEV
)
448 eeepc_wmi_rfkill_exit(eeepc
);
450 if (result
== -ENODEV
)
459 static int read_brightness(struct backlight_device
*bd
)
464 status
= eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT
, &retval
);
466 if (ACPI_FAILURE(status
))
469 return retval
& 0xFF;
472 static int update_bl_status(struct backlight_device
*bd
)
478 ctrl_param
= bd
->props
.brightness
;
480 status
= eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT
,
483 if (ACPI_FAILURE(status
))
489 static const struct backlight_ops eeepc_wmi_bl_ops
= {
490 .get_brightness
= read_brightness
,
491 .update_status
= update_bl_status
,
494 static int eeepc_wmi_backlight_notify(struct eeepc_wmi
*eeepc
, int code
)
496 struct backlight_device
*bd
= eeepc
->backlight_device
;
497 int old
= bd
->props
.brightness
;
500 if (code
>= NOTIFY_BRNUP_MIN
&& code
<= NOTIFY_BRNUP_MAX
)
501 new = code
- NOTIFY_BRNUP_MIN
+ 1;
502 else if (code
>= NOTIFY_BRNDOWN_MIN
&& code
<= NOTIFY_BRNDOWN_MAX
)
503 new = code
- NOTIFY_BRNDOWN_MIN
;
505 bd
->props
.brightness
= new;
506 backlight_update_status(bd
);
507 backlight_force_update(bd
, BACKLIGHT_UPDATE_HOTKEY
);
512 static int eeepc_wmi_backlight_init(struct eeepc_wmi
*eeepc
)
514 struct backlight_device
*bd
;
515 struct backlight_properties props
;
517 memset(&props
, 0, sizeof(struct backlight_properties
));
518 props
.max_brightness
= 15;
519 bd
= backlight_device_register(EEEPC_WMI_FILE
,
520 &eeepc
->platform_device
->dev
, eeepc
,
521 &eeepc_wmi_bl_ops
, &props
);
523 pr_err("Could not register backlight device\n");
527 eeepc
->backlight_device
= bd
;
529 bd
->props
.brightness
= read_brightness(bd
);
530 bd
->props
.power
= FB_BLANK_UNBLANK
;
531 backlight_update_status(bd
);
536 static void eeepc_wmi_backlight_exit(struct eeepc_wmi
*eeepc
)
538 if (eeepc
->backlight_device
)
539 backlight_device_unregister(eeepc
->backlight_device
);
541 eeepc
->backlight_device
= NULL
;
544 static void eeepc_wmi_notify(u32 value
, void *context
)
546 struct eeepc_wmi
*eeepc
= context
;
547 struct acpi_buffer response
= { ACPI_ALLOCATE_BUFFER
, NULL
};
548 union acpi_object
*obj
;
553 status
= wmi_get_event_data(value
, &response
);
554 if (status
!= AE_OK
) {
555 pr_err("bad event status 0x%x\n", status
);
559 obj
= (union acpi_object
*)response
.pointer
;
561 if (obj
&& obj
->type
== ACPI_TYPE_INTEGER
) {
562 code
= obj
->integer
.value
;
565 if (code
>= NOTIFY_BRNUP_MIN
&& code
<= NOTIFY_BRNUP_MAX
)
566 code
= NOTIFY_BRNUP_MIN
;
567 else if (code
>= NOTIFY_BRNDOWN_MIN
&&
568 code
<= NOTIFY_BRNDOWN_MAX
)
569 code
= NOTIFY_BRNDOWN_MIN
;
571 if (code
== NOTIFY_BRNUP_MIN
|| code
== NOTIFY_BRNDOWN_MIN
) {
572 if (!acpi_video_backlight_support())
573 eeepc_wmi_backlight_notify(eeepc
, orig_code
);
576 if (!sparse_keymap_report_event(eeepc
->inputdev
,
578 pr_info("Unknown key %x pressed\n", code
);
584 static ssize_t
store_cpufv(struct device
*dev
, struct device_attribute
*attr
,
585 const char *buf
, size_t count
)
588 struct acpi_buffer input
= { (acpi_size
)sizeof(value
), &value
};
591 if (!count
|| sscanf(buf
, "%i", &value
) != 1)
593 if (value
< 0 || value
> 2)
596 status
= wmi_evaluate_method(EEEPC_WMI_MGMT_GUID
,
597 1, EEEPC_WMI_METHODID_CFVS
, &input
, NULL
);
599 if (ACPI_FAILURE(status
))
605 static DEVICE_ATTR(cpufv
, S_IRUGO
| S_IWUSR
, NULL
, store_cpufv
);
607 static struct attribute
*platform_attributes
[] = {
608 &dev_attr_cpufv
.attr
,
612 static struct attribute_group platform_attribute_group
= {
613 .attrs
= platform_attributes
616 static void eeepc_wmi_sysfs_exit(struct platform_device
*device
)
618 sysfs_remove_group(&device
->dev
.kobj
, &platform_attribute_group
);
621 static int eeepc_wmi_sysfs_init(struct platform_device
*device
)
623 return sysfs_create_group(&device
->dev
.kobj
, &platform_attribute_group
);
629 static int __init
eeepc_wmi_platform_init(struct eeepc_wmi
*eeepc
)
633 eeepc
->platform_device
= platform_device_alloc(EEEPC_WMI_FILE
, -1);
634 if (!eeepc
->platform_device
)
636 platform_set_drvdata(eeepc
->platform_device
, eeepc
);
638 err
= platform_device_add(eeepc
->platform_device
);
640 goto fail_platform_device
;
642 err
= eeepc_wmi_sysfs_init(eeepc
->platform_device
);
648 platform_device_del(eeepc
->platform_device
);
649 fail_platform_device
:
650 platform_device_put(eeepc
->platform_device
);
654 static void eeepc_wmi_platform_exit(struct eeepc_wmi
*eeepc
)
656 eeepc_wmi_sysfs_exit(eeepc
->platform_device
);
657 platform_device_unregister(eeepc
->platform_device
);
663 struct eeepc_wmi_debugfs_node
{
664 struct eeepc_wmi
*eeepc
;
666 int (*show
)(struct seq_file
*m
, void *data
);
669 static int show_dsts(struct seq_file
*m
, void *data
)
671 struct eeepc_wmi
*eeepc
= m
->private;
675 status
= eeepc_wmi_get_devstate(eeepc
->debug
.dev_id
, &retval
);
677 if (ACPI_FAILURE(status
))
680 seq_printf(m
, "DSTS(%x) = %x\n", eeepc
->debug
.dev_id
, retval
);
685 static int show_devs(struct seq_file
*m
, void *data
)
687 struct eeepc_wmi
*eeepc
= m
->private;
691 status
= eeepc_wmi_set_devstate(eeepc
->debug
.dev_id
,
692 eeepc
->debug
.ctrl_param
, &retval
);
693 if (ACPI_FAILURE(status
))
696 seq_printf(m
, "DEVS(%x, %x) = %x\n", eeepc
->debug
.dev_id
,
697 eeepc
->debug
.ctrl_param
, retval
);
702 static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files
[] = {
703 { NULL
, "devs", show_devs
},
704 { NULL
, "dsts", show_dsts
},
707 static int eeepc_wmi_debugfs_open(struct inode
*inode
, struct file
*file
)
709 struct eeepc_wmi_debugfs_node
*node
= inode
->i_private
;
711 return single_open(file
, node
->show
, node
->eeepc
);
714 static const struct file_operations eeepc_wmi_debugfs_io_ops
= {
715 .owner
= THIS_MODULE
,
716 .open
= eeepc_wmi_debugfs_open
,
719 .release
= single_release
,
722 static void eeepc_wmi_debugfs_exit(struct eeepc_wmi
*eeepc
)
724 debugfs_remove_recursive(eeepc
->debug
.root
);
727 static int eeepc_wmi_debugfs_init(struct eeepc_wmi
*eeepc
)
732 eeepc
->debug
.root
= debugfs_create_dir(EEEPC_WMI_FILE
, NULL
);
733 if (!eeepc
->debug
.root
) {
734 pr_err("failed to create debugfs directory");
738 dent
= debugfs_create_x32("dev_id", S_IRUGO
|S_IWUSR
,
739 eeepc
->debug
.root
, &eeepc
->debug
.dev_id
);
743 dent
= debugfs_create_x32("ctrl_param", S_IRUGO
|S_IWUSR
,
744 eeepc
->debug
.root
, &eeepc
->debug
.ctrl_param
);
748 for (i
= 0; i
< ARRAY_SIZE(eeepc_wmi_debug_files
); i
++) {
749 struct eeepc_wmi_debugfs_node
*node
= &eeepc_wmi_debug_files
[i
];
752 dent
= debugfs_create_file(node
->name
, S_IFREG
| S_IRUGO
,
753 eeepc
->debug
.root
, node
,
754 &eeepc_wmi_debugfs_io_ops
);
756 pr_err("failed to create debug file: %s\n", node
->name
);
764 eeepc_wmi_debugfs_exit(eeepc
);
771 static struct platform_device
* __init
eeepc_wmi_add(void)
773 struct eeepc_wmi
*eeepc
;
777 eeepc
= kzalloc(sizeof(struct eeepc_wmi
), GFP_KERNEL
);
779 return ERR_PTR(-ENOMEM
);
782 * Register the platform device first. It is used as a parent for the
785 err
= eeepc_wmi_platform_init(eeepc
);
789 err
= eeepc_wmi_input_init(eeepc
);
793 err
= eeepc_wmi_led_init(eeepc
);
797 err
= eeepc_wmi_rfkill_init(eeepc
);
801 if (!acpi_video_backlight_support()) {
802 err
= eeepc_wmi_backlight_init(eeepc
);
806 pr_info("Backlight controlled by ACPI video driver\n");
808 status
= wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID
,
809 eeepc_wmi_notify
, eeepc
);
810 if (ACPI_FAILURE(status
)) {
811 pr_err("Unable to register notify handler - %d\n",
814 goto fail_wmi_handler
;
817 err
= eeepc_wmi_debugfs_init(eeepc
);
821 return eeepc
->platform_device
;
824 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID
);
826 eeepc_wmi_backlight_exit(eeepc
);
828 eeepc_wmi_rfkill_exit(eeepc
);
830 eeepc_wmi_led_exit(eeepc
);
832 eeepc_wmi_input_exit(eeepc
);
834 eeepc_wmi_platform_exit(eeepc
);
840 static int eeepc_wmi_remove(struct platform_device
*device
)
842 struct eeepc_wmi
*eeepc
;
844 eeepc
= platform_get_drvdata(device
);
845 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID
);
846 eeepc_wmi_backlight_exit(eeepc
);
847 eeepc_wmi_input_exit(eeepc
);
848 eeepc_wmi_led_exit(eeepc
);
849 eeepc_wmi_rfkill_exit(eeepc
);
850 eeepc_wmi_debugfs_exit(eeepc
);
851 eeepc_wmi_platform_exit(eeepc
);
857 static struct platform_driver platform_driver
= {
859 .name
= EEEPC_WMI_FILE
,
860 .owner
= THIS_MODULE
,
864 static int __init
eeepc_wmi_init(void)
868 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID
) ||
869 !wmi_has_guid(EEEPC_WMI_MGMT_GUID
)) {
870 pr_warning("No known WMI GUID found\n");
874 platform_device
= eeepc_wmi_add();
875 if (IS_ERR(platform_device
)) {
876 err
= PTR_ERR(platform_device
);
880 err
= platform_driver_register(&platform_driver
);
882 pr_warning("Unable to register platform driver\n");
883 goto fail_platform_driver
;
888 fail_platform_driver
:
889 eeepc_wmi_remove(platform_device
);
894 static void __exit
eeepc_wmi_exit(void)
896 eeepc_wmi_remove(platform_device
);
897 platform_driver_unregister(&platform_driver
);
900 module_init(eeepc_wmi_init
);
901 module_exit(eeepc_wmi_exit
);