2 * eepc-laptop.c - Asus Eee PC extras
4 * Based on asus_acpi.c as patched for the Eee PC by Asus:
5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
6 * Based on eee.c from eeepc-linux
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/types.h>
23 #include <linux/platform_device.h>
24 #include <linux/backlight.h>
26 #include <linux/hwmon.h>
27 #include <linux/hwmon-sysfs.h>
28 #include <acpi/acpi_drivers.h>
29 #include <acpi/acpi_bus.h>
30 #include <linux/uaccess.h>
31 #include <linux/input.h>
32 #include <linux/rfkill.h>
33 #include <linux/pci.h>
35 #define EEEPC_LAPTOP_VERSION "0.1"
37 #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
38 #define EEEPC_HOTK_FILE "eeepc"
39 #define EEEPC_HOTK_CLASS "hotkey"
40 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
41 #define EEEPC_HOTK_HID "ASUS010"
43 #define EEEPC_LOG EEEPC_HOTK_FILE ": "
44 #define EEEPC_ERR KERN_ERR EEEPC_LOG
45 #define EEEPC_WARNING KERN_WARNING EEEPC_LOG
46 #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
47 #define EEEPC_INFO KERN_INFO EEEPC_LOG
50 * Definitions for Asus EeePC
52 #define NOTIFY_WLAN_ON 0x10
53 #define NOTIFY_BRN_MIN 0x20
54 #define NOTIFY_BRN_MAX 0x2f
57 DISABLE_ASL_WLAN = 0x0001,
58 DISABLE_ASL_BLUETOOTH = 0x0002,
59 DISABLE_ASL_IRDA = 0x0004,
60 DISABLE_ASL_CAMERA = 0x0008,
61 DISABLE_ASL_TV = 0x0010,
62 DISABLE_ASL_GPS = 0x0020,
63 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
64 DISABLE_ASL_MODEM = 0x0080,
65 DISABLE_ASL_CARDREADER = 0x0100,
66 DISABLE_ASL_3G = 0x0200,
67 DISABLE_ASL_WIMAX = 0x0400,
68 DISABLE_ASL_HWCF = 0x0800
85 CM_ASL_CPUTEMPERATURE,
98 CM_ASL_PANELPOWER, /*P901*/
102 static const char *cm_getv[] = {
103 "WLDG", "BTHG", NULL, NULL,
104 "CAMG", NULL, NULL, NULL,
105 NULL, "PBLG", NULL, NULL,
106 "CFVG", NULL, NULL, NULL,
107 "USBG", NULL, NULL, "MODG",
108 "CRDG", "M3GG", "WIMG", "HWCF",
109 "LIDG", "TYPE", "PBPG", "TPDG"
112 static const char *cm_setv[] = {
113 "WLDS", "BTHS", NULL, NULL,
114 "CAMS", NULL, NULL, NULL,
115 "SDSP", "PBLS", "HDPS", NULL,
116 "CFVS", NULL, NULL, NULL,
117 "USBG", NULL, NULL, "MODS",
118 "CRDS", "M3GS", "WIMS", NULL,
119 NULL, NULL, "PBPS", "TPDS"
122 #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
124 #define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
125 #define EEEPC_EC_SC02 0x63
126 #define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
127 #define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
128 #define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
129 #define EEEPC_EC_SFB3 0xD3
132 * This is the main structure, we can use it to store useful information
133 * about the hotk device
136 struct acpi_device *device; /* the device we are in */
137 acpi_handle handle; /* the handle of the hotk device */
138 u32 cm_supported; /* the control methods supported
140 uint init_flag; /* Init flags */
141 u16 event_count[128]; /* count for each event */
142 struct input_dev *inputdev;
144 struct rfkill *eeepc_wlan_rfkill;
145 struct rfkill *eeepc_bluetooth_rfkill;
148 /* The actual device the driver binds to */
149 static struct eeepc_hotk *ehotk;
151 /* Platform device/driver */
152 static struct platform_driver platform_driver = {
154 .name = EEEPC_HOTK_FILE,
155 .owner = THIS_MODULE,
159 static struct platform_device *platform_device;
167 enum { KE_KEY, KE_END };
169 static struct key_entry eeepc_keymap[] = {
170 /* Sleep already handled via generic ACPI code */
171 {KE_KEY, 0x10, KEY_WLAN },
172 {KE_KEY, 0x11, KEY_WLAN },
173 {KE_KEY, 0x12, KEY_PROG1 },
174 {KE_KEY, 0x13, KEY_MUTE },
175 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
176 {KE_KEY, 0x15, KEY_VOLUMEUP },
177 {KE_KEY, 0x1a, KEY_COFFEE },
178 {KE_KEY, 0x1b, KEY_ZOOM },
179 {KE_KEY, 0x1c, KEY_PROG2 },
180 {KE_KEY, 0x1d, KEY_PROG3 },
181 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
182 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
183 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
184 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
185 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
190 * The hotkey driver declaration
192 static int eeepc_hotk_add(struct acpi_device *device);
193 static int eeepc_hotk_remove(struct acpi_device *device, int type);
194 static int eeepc_hotk_resume(struct acpi_device *device);
195 static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
197 static const struct acpi_device_id eeepc_device_ids[] = {
201 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
203 static struct acpi_driver eeepc_hotk_driver = {
204 .name = EEEPC_HOTK_NAME,
205 .class = EEEPC_HOTK_CLASS,
206 .ids = eeepc_device_ids,
207 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
209 .add = eeepc_hotk_add,
210 .remove = eeepc_hotk_remove,
211 .resume = eeepc_hotk_resume,
212 .notify = eeepc_hotk_notify,
216 /* The backlight device /sys/class/backlight */
217 static struct backlight_device *eeepc_backlight_device;
219 /* The hwmon device */
220 static struct device *eeepc_hwmon_device;
223 * The backlight class declaration
225 static int read_brightness(struct backlight_device *bd);
226 static int update_bl_status(struct backlight_device *bd);
227 static struct backlight_ops eeepcbl_ops = {
228 .get_brightness = read_brightness,
229 .update_status = update_bl_status,
232 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
233 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
234 MODULE_LICENSE("GPL");
239 static int write_acpi_int(acpi_handle handle, const char *method, int val,
240 struct acpi_buffer *output)
242 struct acpi_object_list params;
243 union acpi_object in_obj;
247 params.pointer = &in_obj;
248 in_obj.type = ACPI_TYPE_INTEGER;
249 in_obj.integer.value = val;
251 status = acpi_evaluate_object(handle, (char *)method, ¶ms, output);
252 return (status == AE_OK ? 0 : -1);
255 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
258 unsigned long long result;
260 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
261 if (ACPI_FAILURE(status)) {
270 static int set_acpi(int cm, int value)
272 if (ehotk->cm_supported & (0x1 << cm)) {
273 const char *method = cm_setv[cm];
276 if (write_acpi_int(ehotk->handle, method, value, NULL))
277 printk(EEEPC_WARNING "Error writing %s\n", method);
282 static int get_acpi(int cm)
285 if ((ehotk->cm_supported & (0x1 << cm))) {
286 const char *method = cm_getv[cm];
289 if (read_acpi_int(ehotk->handle, method, &value))
290 printk(EEEPC_WARNING "Error reading %s\n", method);
298 static int read_brightness(struct backlight_device *bd)
300 return get_acpi(CM_ASL_PANELBRIGHT);
303 static int set_brightness(struct backlight_device *bd, int value)
305 value = max(0, min(15, value));
306 return set_acpi(CM_ASL_PANELBRIGHT, value);
309 static int update_bl_status(struct backlight_device *bd)
311 return set_brightness(bd, bd->props.brightness);
318 static bool eeepc_wlan_rfkill_blocked(void)
320 if (get_acpi(CM_ASL_WLAN) == 1)
325 static int eeepc_rfkill_set(void *data, bool blocked)
327 unsigned long asl = (unsigned long)data;
328 return set_acpi(asl, !blocked);
331 static const struct rfkill_ops eeepc_rfkill_ops = {
332 .set_block = eeepc_rfkill_set,
335 static void __init eeepc_enable_camera(void)
338 * If the following call to set_acpi() fails, it's because there's no
339 * camera so we can ignore the error.
341 set_acpi(CM_ASL_CAMERA, 1);
347 static int parse_arg(const char *buf, unsigned long count, int *val)
351 if (sscanf(buf, "%i", val) != 1)
356 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
360 rv = parse_arg(buf, count, &value);
366 static ssize_t show_sys_acpi(int cm, char *buf)
368 return sprintf(buf, "%d\n", get_acpi(cm));
371 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
372 static ssize_t show_##_name(struct device *dev, \
373 struct device_attribute *attr, \
376 return show_sys_acpi(_cm, buf); \
378 static ssize_t store_##_name(struct device *dev, \
379 struct device_attribute *attr, \
380 const char *buf, size_t count) \
382 return store_sys_acpi(_cm, buf, count); \
384 static struct device_attribute dev_attr_##_name = { \
386 .name = __stringify(_name), \
388 .show = show_##_name, \
389 .store = store_##_name, \
392 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
393 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
394 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
395 EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV);
397 static struct attribute *platform_attributes[] = {
398 &dev_attr_camera.attr,
399 &dev_attr_cardr.attr,
401 &dev_attr_cpufv.attr,
405 static struct attribute_group platform_attribute_group = {
406 .attrs = platform_attributes
412 static struct key_entry *eepc_get_entry_by_scancode(int code)
414 struct key_entry *key;
416 for (key = eeepc_keymap; key->type != KE_END; key++)
417 if (code == key->code)
423 static struct key_entry *eepc_get_entry_by_keycode(int code)
425 struct key_entry *key;
427 for (key = eeepc_keymap; key->type != KE_END; key++)
428 if (code == key->keycode && key->type == KE_KEY)
434 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
436 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
438 if (key && key->type == KE_KEY) {
439 *keycode = key->keycode;
446 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
448 struct key_entry *key;
451 if (keycode < 0 || keycode > KEY_MAX)
454 key = eepc_get_entry_by_scancode(scancode);
455 if (key && key->type == KE_KEY) {
456 old_keycode = key->keycode;
457 key->keycode = keycode;
458 set_bit(keycode, dev->keybit);
459 if (!eepc_get_entry_by_keycode(old_keycode))
460 clear_bit(old_keycode, dev->keybit);
467 static int eeepc_hotk_check(void)
469 const struct key_entry *key;
470 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
473 result = acpi_bus_get_status(ehotk->device);
476 if (ehotk->device->status.present) {
477 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
479 printk(EEEPC_ERR "Hotkey initialization failed\n");
482 printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
485 /* get control methods supported */
486 if (read_acpi_int(ehotk->handle, "CMSG"
487 , &ehotk->cm_supported)) {
489 "Get control methods supported failed\n");
493 "Get control methods supported: 0x%x\n",
494 ehotk->cm_supported);
496 ehotk->inputdev = input_allocate_device();
497 if (!ehotk->inputdev) {
498 printk(EEEPC_INFO "Unable to allocate input device\n");
501 ehotk->inputdev->name = "Asus EeePC extra buttons";
502 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
503 ehotk->inputdev->id.bustype = BUS_HOST;
504 ehotk->inputdev->getkeycode = eeepc_getkeycode;
505 ehotk->inputdev->setkeycode = eeepc_setkeycode;
507 for (key = eeepc_keymap; key->type != KE_END; key++) {
510 set_bit(EV_KEY, ehotk->inputdev->evbit);
511 set_bit(key->keycode, ehotk->inputdev->keybit);
515 result = input_register_device(ehotk->inputdev);
517 printk(EEEPC_INFO "Unable to register input device\n");
518 input_free_device(ehotk->inputdev);
522 printk(EEEPC_ERR "Hotkey device not present, aborting\n");
528 static int notify_brn(void)
530 /* returns the *previous* brightness, or -1 */
531 struct backlight_device *bd = eeepc_backlight_device;
533 int old = bd->props.brightness;
534 bd->props.brightness = read_brightness(bd);
540 static void eeepc_rfkill_hotplug(void)
543 struct pci_bus *bus = pci_find_bus(0, 1);
547 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
551 blocked = eeepc_wlan_rfkill_blocked();
553 dev = pci_get_slot(bus, 0);
555 /* Device already present */
559 dev = pci_scan_single_device(bus, 0);
561 pci_bus_assign_resources(bus);
562 if (pci_bus_add_device(dev))
563 printk(EEEPC_ERR "Unable to hotplug wifi\n");
566 dev = pci_get_slot(bus, 0);
568 pci_remove_bus_device(dev);
573 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
576 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
578 if (event != ACPI_NOTIFY_BUS_CHECK)
581 eeepc_rfkill_hotplug();
584 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
586 static struct key_entry *key;
592 if (event > ACPI_MAX_SYS_NOTIFY)
594 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
596 count = ehotk->event_count[event % 128]++;
597 acpi_bus_generate_proc_event(ehotk->device, event, count);
598 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
599 dev_name(&ehotk->device->dev), event,
601 if (ehotk->inputdev) {
602 if (brn != -ENODEV) {
603 /* brightness-change events need special
604 * handling for conversion to key events
609 brn += NOTIFY_BRN_MIN;
611 event = NOTIFY_BRN_MIN; /* brightness down */
612 else if (event > brn)
613 event = NOTIFY_BRN_MIN + 2; /* ... up */
615 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
617 key = eepc_get_entry_by_scancode(event);
621 input_report_key(ehotk->inputdev, key->keycode,
623 input_sync(ehotk->inputdev);
624 input_report_key(ehotk->inputdev, key->keycode,
626 input_sync(ehotk->inputdev);
633 static int eeepc_register_rfkill_notifier(char *node)
635 acpi_status status = AE_OK;
638 status = acpi_get_handle(NULL, node, &handle);
640 if (ACPI_SUCCESS(status)) {
641 status = acpi_install_notify_handler(handle,
645 if (ACPI_FAILURE(status))
647 "Failed to register notify on %s\n", node);
654 static void eeepc_unregister_rfkill_notifier(char *node)
656 acpi_status status = AE_OK;
659 status = acpi_get_handle(NULL, node, &handle);
661 if (ACPI_SUCCESS(status)) {
662 status = acpi_remove_notify_handler(handle,
664 eeepc_rfkill_notify);
665 if (ACPI_FAILURE(status))
667 "Error removing rfkill notify handler %s\n",
672 static int eeepc_hotk_add(struct acpi_device *device)
678 printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
679 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
682 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
683 ehotk->handle = device->handle;
684 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
685 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
686 device->driver_data = ehotk;
687 ehotk->device = device;
688 result = eeepc_hotk_check();
692 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
693 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
695 if (get_acpi(CM_ASL_WLAN) != -1) {
696 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
700 (void *)CM_ASL_WLAN);
702 if (!ehotk->eeepc_wlan_rfkill)
705 rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
706 get_acpi(CM_ASL_WLAN) != 1);
707 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
712 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
713 ehotk->eeepc_bluetooth_rfkill =
714 rfkill_alloc("eeepc-bluetooth",
716 RFKILL_TYPE_BLUETOOTH,
718 (void *)CM_ASL_BLUETOOTH);
720 if (!ehotk->eeepc_bluetooth_rfkill)
723 rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
724 get_acpi(CM_ASL_BLUETOOTH) != 1);
725 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
733 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
734 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
736 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
737 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
738 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
746 static int eeepc_hotk_remove(struct acpi_device *device, int type)
748 if (!device || !acpi_driver_data(device))
751 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
752 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
758 static int eeepc_hotk_resume(struct acpi_device *device)
760 if (ehotk->eeepc_wlan_rfkill) {
763 /* Workaround - it seems that _PTS disables the wireless
764 without notification or changing the value read by WLAN.
765 Normally this is fine because the correct value is restored
766 from the non-volatile storage on resume, but we need to do
767 it ourself if case suspend is aborted, or we lose wireless.
769 wlan = get_acpi(CM_ASL_WLAN);
770 set_acpi(CM_ASL_WLAN, wlan);
772 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
775 eeepc_rfkill_hotplug();
778 if (ehotk->eeepc_bluetooth_rfkill)
779 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
780 get_acpi(CM_ASL_BLUETOOTH) != 1);
788 static int eeepc_get_fan_pwm(void)
792 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
793 value = value * 255 / 100;
797 static void eeepc_set_fan_pwm(int value)
799 value = SENSORS_LIMIT(value, 0, 255);
800 value = value * 100 / 255;
801 ec_write(EEEPC_EC_SC02, value);
804 static int eeepc_get_fan_rpm(void)
809 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
810 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
811 return (high << 8 | low);
814 static int eeepc_get_fan_ctrl(void)
818 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
819 return ((value & 0x02 ? 1 : 0));
822 static void eeepc_set_fan_ctrl(int manual)
826 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
831 ec_write(EEEPC_EC_SFB3, value);
834 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
838 rv = parse_arg(buf, count, &value);
844 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
846 return sprintf(buf, "%d\n", get());
849 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
850 static ssize_t show_##_name(struct device *dev, \
851 struct device_attribute *attr, \
854 return show_sys_hwmon(_set, buf); \
856 static ssize_t store_##_name(struct device *dev, \
857 struct device_attribute *attr, \
858 const char *buf, size_t count) \
860 return store_sys_hwmon(_get, buf, count); \
862 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
864 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
865 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
866 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
867 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
868 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
871 show_name(struct device *dev, struct device_attribute *attr, char *buf)
873 return sprintf(buf, "eeepc\n");
875 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
877 static struct attribute *hwmon_attributes[] = {
878 &sensor_dev_attr_pwm1.dev_attr.attr,
879 &sensor_dev_attr_fan1_input.dev_attr.attr,
880 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
881 &sensor_dev_attr_name.dev_attr.attr,
885 static struct attribute_group hwmon_attribute_group = {
886 .attrs = hwmon_attributes
892 static void eeepc_backlight_exit(void)
894 if (eeepc_backlight_device)
895 backlight_device_unregister(eeepc_backlight_device);
896 eeepc_backlight_device = NULL;
899 static void eeepc_rfkill_exit(void)
901 if (ehotk->eeepc_wlan_rfkill)
902 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
903 if (ehotk->eeepc_bluetooth_rfkill)
904 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
907 static void eeepc_input_exit(void)
910 input_unregister_device(ehotk->inputdev);
913 static void eeepc_hwmon_exit(void)
915 struct device *hwmon;
917 hwmon = eeepc_hwmon_device;
920 sysfs_remove_group(&hwmon->kobj,
921 &hwmon_attribute_group);
922 hwmon_device_unregister(hwmon);
923 eeepc_hwmon_device = NULL;
926 static void __exit eeepc_laptop_exit(void)
928 eeepc_backlight_exit();
932 acpi_bus_unregister_driver(&eeepc_hotk_driver);
933 sysfs_remove_group(&platform_device->dev.kobj,
934 &platform_attribute_group);
935 platform_device_unregister(platform_device);
936 platform_driver_unregister(&platform_driver);
939 static int eeepc_backlight_init(struct device *dev)
941 struct backlight_device *bd;
943 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
947 "Could not register eeepc backlight device\n");
948 eeepc_backlight_device = NULL;
951 eeepc_backlight_device = bd;
952 bd->props.max_brightness = 15;
953 bd->props.brightness = read_brightness(NULL);
954 bd->props.power = FB_BLANK_UNBLANK;
955 backlight_update_status(bd);
959 static int eeepc_hwmon_init(struct device *dev)
961 struct device *hwmon;
964 hwmon = hwmon_device_register(dev);
967 "Could not register eeepc hwmon device\n");
968 eeepc_hwmon_device = NULL;
969 return PTR_ERR(hwmon);
971 eeepc_hwmon_device = hwmon;
972 result = sysfs_create_group(&hwmon->kobj,
973 &hwmon_attribute_group);
979 static int __init eeepc_laptop_init(void)
986 result = acpi_bus_register_driver(&eeepc_hotk_driver);
990 acpi_bus_unregister_driver(&eeepc_hotk_driver);
993 dev = acpi_get_physical_device(ehotk->device->handle);
995 if (!acpi_video_backlight_support()) {
996 result = eeepc_backlight_init(dev);
1000 printk(EEEPC_INFO "Backlight controlled by ACPI video "
1003 result = eeepc_hwmon_init(dev);
1007 eeepc_enable_camera();
1009 /* Register platform stuff */
1010 result = platform_driver_register(&platform_driver);
1012 goto fail_platform_driver;
1013 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1014 if (!platform_device) {
1016 goto fail_platform_device1;
1018 result = platform_device_add(platform_device);
1020 goto fail_platform_device2;
1021 result = sysfs_create_group(&platform_device->dev.kobj,
1022 &platform_attribute_group);
1027 platform_device_del(platform_device);
1028 fail_platform_device2:
1029 platform_device_put(platform_device);
1030 fail_platform_device1:
1031 platform_driver_unregister(&platform_driver);
1032 fail_platform_driver:
1035 eeepc_backlight_exit();
1038 eeepc_rfkill_exit();
1042 module_init(eeepc_laptop_init);
1043 module_exit(eeepc_laptop_exit);