2 * eeepc-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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/types.h>
25 #include <linux/platform_device.h>
26 #include <linux/backlight.h>
28 #include <linux/hwmon.h>
29 #include <linux/hwmon-sysfs.h>
30 #include <acpi/acpi_drivers.h>
31 #include <acpi/acpi_bus.h>
32 #include <linux/uaccess.h>
33 #include <linux/input.h>
34 #include <linux/rfkill.h>
35 #include <linux/pci.h>
36 #include <linux/pci_hotplug.h>
37 #include <linux/leds.h>
39 #define EEEPC_LAPTOP_VERSION "0.1"
40 #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
41 #define EEEPC_LAPTOP_FILE "eeepc"
43 #define EEEPC_ACPI_CLASS "hotkey"
44 #define EEEPC_ACPI_DEVICE_NAME "Hotkey"
45 #define EEEPC_ACPI_HID "ASUS010"
47 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
48 MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
49 MODULE_LICENSE("GPL");
52 * Definitions for Asus EeePC
54 #define NOTIFY_BRN_MIN 0x20
55 #define NOTIFY_BRN_MAX 0x2f
58 DISABLE_ASL_WLAN = 0x0001,
59 DISABLE_ASL_BLUETOOTH = 0x0002,
60 DISABLE_ASL_IRDA = 0x0004,
61 DISABLE_ASL_CAMERA = 0x0008,
62 DISABLE_ASL_TV = 0x0010,
63 DISABLE_ASL_GPS = 0x0020,
64 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
65 DISABLE_ASL_MODEM = 0x0080,
66 DISABLE_ASL_CARDREADER = 0x0100,
67 DISABLE_ASL_3G = 0x0200,
68 DISABLE_ASL_WIMAX = 0x0400,
69 DISABLE_ASL_HWCF = 0x0800
86 CM_ASL_CPUTEMPERATURE,
99 CM_ASL_PANELPOWER, /*P901*/
103 static const char *cm_getv[] = {
104 "WLDG", "BTHG", NULL, NULL,
105 "CAMG", NULL, NULL, NULL,
106 NULL, "PBLG", NULL, NULL,
107 "CFVG", NULL, NULL, NULL,
108 "USBG", NULL, NULL, "MODG",
109 "CRDG", "M3GG", "WIMG", "HWCF",
110 "LIDG", "TYPE", "PBPG", "TPDG"
113 static const char *cm_setv[] = {
114 "WLDS", "BTHS", NULL, NULL,
115 "CAMS", NULL, NULL, NULL,
116 "SDSP", "PBLS", "HDPS", NULL,
117 "CFVS", NULL, NULL, NULL,
118 "USBG", NULL, NULL, "MODS",
119 "CRDS", "M3GS", "WIMS", NULL,
120 NULL, NULL, "PBPS", "TPDS"
129 enum { KE_KEY, KE_END };
131 static const struct key_entry eeepc_keymap[] = {
132 /* Sleep already handled via generic ACPI code */
133 {KE_KEY, 0x10, KEY_WLAN },
134 {KE_KEY, 0x11, KEY_WLAN },
135 {KE_KEY, 0x12, KEY_PROG1 },
136 {KE_KEY, 0x13, KEY_MUTE },
137 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
138 {KE_KEY, 0x15, KEY_VOLUMEUP },
139 {KE_KEY, 0x16, KEY_DISPLAY_OFF },
140 {KE_KEY, 0x1a, KEY_COFFEE },
141 {KE_KEY, 0x1b, KEY_ZOOM },
142 {KE_KEY, 0x1c, KEY_PROG2 },
143 {KE_KEY, 0x1d, KEY_PROG3 },
144 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
145 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
146 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
147 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
148 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
149 {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
150 {KE_KEY, 0x38, KEY_F14 },
156 * This is the main structure, we can use it to store useful information
158 struct eeepc_laptop {
159 acpi_handle handle; /* the handle of the acpi device */
160 u32 cm_supported; /* the control methods supported
162 u16 event_count[128]; /* count for each event */
164 struct platform_device *platform_device;
165 struct device *hwmon_device;
166 struct backlight_device *backlight_device;
168 struct input_dev *inputdev;
169 struct key_entry *keymap;
171 struct rfkill *wlan_rfkill;
172 struct rfkill *bluetooth_rfkill;
173 struct rfkill *wwan3g_rfkill;
174 struct rfkill *wimax_rfkill;
176 struct hotplug_slot *hotplug_slot;
177 struct mutex hotplug_lock;
179 struct led_classdev tpd_led;
181 struct workqueue_struct *led_workqueue;
182 struct work_struct tpd_led_work;
188 static int write_acpi_int(acpi_handle handle, const char *method, int val)
190 struct acpi_object_list params;
191 union acpi_object in_obj;
195 params.pointer = &in_obj;
196 in_obj.type = ACPI_TYPE_INTEGER;
197 in_obj.integer.value = val;
199 status = acpi_evaluate_object(handle, (char *)method, ¶ms, NULL);
200 return (status == AE_OK ? 0 : -1);
203 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
206 unsigned long long result;
208 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
209 if (ACPI_FAILURE(status)) {
218 static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
220 const char *method = cm_setv[cm];
224 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
227 if (write_acpi_int(eeepc->handle, method, value))
228 pr_warning("Error writing %s\n", method);
232 static int get_acpi(struct eeepc_laptop *eeepc, int cm)
234 const char *method = cm_getv[cm];
239 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
242 if (read_acpi_int(eeepc->handle, method, &value))
243 pr_warning("Error reading %s\n", method);
247 static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
250 const char *method = cm_setv[cm];
255 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
258 status = acpi_get_handle(eeepc->handle, (char *)method,
260 if (status != AE_OK) {
261 pr_warning("Error finding %s\n", method);
271 static int parse_arg(const char *buf, unsigned long count, int *val)
275 if (sscanf(buf, "%i", val) != 1)
280 static ssize_t store_sys_acpi(struct device *dev, int cm,
281 const char *buf, size_t count)
283 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
286 rv = parse_arg(buf, count, &value);
288 value = set_acpi(eeepc, cm, value);
294 static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
296 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
297 int value = get_acpi(eeepc, cm);
301 return sprintf(buf, "%d\n", value);
304 #define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
305 static ssize_t show_##_name(struct device *dev, \
306 struct device_attribute *attr, \
309 return show_sys_acpi(dev, _cm, buf); \
311 static ssize_t store_##_name(struct device *dev, \
312 struct device_attribute *attr, \
313 const char *buf, size_t count) \
315 return store_sys_acpi(dev, _cm, buf, count); \
317 static struct device_attribute dev_attr_##_name = { \
319 .name = __stringify(_name), \
321 .show = show_##_name, \
322 .store = store_##_name, \
325 EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
326 EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
327 EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
334 static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
336 c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
337 c->num = (c->cur >> 8) & 0xff;
339 if (c->cur < 0 || c->num <= 0 || c->num > 12)
344 static ssize_t show_available_cpufv(struct device *dev,
345 struct device_attribute *attr,
348 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
349 struct eeepc_cpufv c;
353 if (get_cpufv(eeepc, &c))
355 for (i = 0; i < c.num; i++)
356 len += sprintf(buf + len, "%d ", i);
357 len += sprintf(buf + len, "\n");
361 static ssize_t show_cpufv(struct device *dev,
362 struct device_attribute *attr,
365 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
366 struct eeepc_cpufv c;
368 if (get_cpufv(eeepc, &c))
370 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
373 static ssize_t store_cpufv(struct device *dev,
374 struct device_attribute *attr,
375 const char *buf, size_t count)
377 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
378 struct eeepc_cpufv c;
381 if (get_cpufv(eeepc, &c))
383 rv = parse_arg(buf, count, &value);
386 if (!rv || value < 0 || value >= c.num)
388 set_acpi(eeepc, CM_ASL_CPUFV, value);
392 static struct device_attribute dev_attr_cpufv = {
400 static struct device_attribute dev_attr_available_cpufv = {
402 .name = "available_cpufv",
404 .show = show_available_cpufv
407 static struct attribute *platform_attributes[] = {
408 &dev_attr_camera.attr,
409 &dev_attr_cardr.attr,
411 &dev_attr_cpufv.attr,
412 &dev_attr_available_cpufv.attr,
416 static struct attribute_group platform_attribute_group = {
417 .attrs = platform_attributes
420 static int eeepc_platform_init(struct eeepc_laptop *eeepc)
424 eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
425 if (!eeepc->platform_device)
427 platform_set_drvdata(eeepc->platform_device, eeepc);
429 result = platform_device_add(eeepc->platform_device);
431 goto fail_platform_device;
433 result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
434 &platform_attribute_group);
440 platform_device_del(eeepc->platform_device);
441 fail_platform_device:
442 platform_device_put(eeepc->platform_device);
446 static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
448 sysfs_remove_group(&eeepc->platform_device->dev.kobj,
449 &platform_attribute_group);
450 platform_device_unregister(eeepc->platform_device);
457 * These functions actually update the LED's, and are called from a
458 * workqueue. By doing this as separate work rather than when the LED
459 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
460 * potentially bad time, such as a timer interrupt.
462 static void tpd_led_update(struct work_struct *work)
464 struct eeepc_laptop *eeepc;
466 eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
468 set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
471 static void tpd_led_set(struct led_classdev *led_cdev,
472 enum led_brightness value)
474 struct eeepc_laptop *eeepc;
476 eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
478 eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
479 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
482 static int eeepc_led_init(struct eeepc_laptop *eeepc)
486 if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
489 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
490 if (!eeepc->led_workqueue)
492 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
494 eeepc->tpd_led.name = "eeepc::touchpad";
495 eeepc->tpd_led.brightness_set = tpd_led_set;
496 eeepc->tpd_led.max_brightness = 1;
498 rv = led_classdev_register(&eeepc->platform_device->dev,
501 destroy_workqueue(eeepc->led_workqueue);
508 static void eeepc_led_exit(struct eeepc_laptop *eeepc)
510 if (eeepc->tpd_led.dev)
511 led_classdev_unregister(&eeepc->tpd_led);
512 if (eeepc->led_workqueue)
513 destroy_workqueue(eeepc->led_workqueue);
518 * PCI hotplug (for wlan rfkill)
520 static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
522 if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
527 static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
531 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
533 if (eeepc->wlan_rfkill)
534 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
536 mutex_lock(&eeepc->hotplug_lock);
538 if (eeepc->hotplug_slot) {
539 bus = pci_find_bus(0, 1);
541 pr_warning("Unable to find PCI bus 1?\n");
546 dev = pci_get_slot(bus, 0);
548 /* Device already present */
552 dev = pci_scan_single_device(bus, 0);
554 pci_bus_assign_resources(bus);
555 if (pci_bus_add_device(dev))
556 pr_err("Unable to hotplug wifi\n");
559 dev = pci_get_slot(bus, 0);
561 pci_remove_bus_device(dev);
568 mutex_unlock(&eeepc->hotplug_lock);
571 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
573 struct eeepc_laptop *eeepc = data;
575 if (event != ACPI_NOTIFY_BUS_CHECK)
578 eeepc_rfkill_hotplug(eeepc);
581 static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
587 status = acpi_get_handle(NULL, node, &handle);
589 if (ACPI_SUCCESS(status)) {
590 status = acpi_install_notify_handler(handle,
594 if (ACPI_FAILURE(status))
595 pr_warning("Failed to register notify on %s\n", node);
602 static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
605 acpi_status status = AE_OK;
608 status = acpi_get_handle(NULL, node, &handle);
610 if (ACPI_SUCCESS(status)) {
611 status = acpi_remove_notify_handler(handle,
613 eeepc_rfkill_notify);
614 if (ACPI_FAILURE(status))
615 pr_err("Error removing rfkill notify handler %s\n",
620 static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
623 struct eeepc_laptop *eeepc = hotplug_slot->private;
624 int val = get_acpi(eeepc, CM_ASL_WLAN);
626 if (val == 1 || val == 0)
634 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
636 kfree(hotplug_slot->info);
640 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
641 .owner = THIS_MODULE,
642 .get_adapter_status = eeepc_get_adapter_status,
643 .get_power_status = eeepc_get_adapter_status,
646 static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
649 struct pci_bus *bus = pci_find_bus(0, 1);
652 pr_err("Unable to find wifi PCI bus\n");
656 eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
657 if (!eeepc->hotplug_slot)
660 eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
662 if (!eeepc->hotplug_slot->info)
665 eeepc->hotplug_slot->private = eeepc;
666 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
667 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
668 eeepc_get_adapter_status(eeepc->hotplug_slot,
669 &eeepc->hotplug_slot->info->adapter_status);
671 ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
673 pr_err("Unable to register hotplug slot - %d\n", ret);
680 kfree(eeepc->hotplug_slot->info);
682 kfree(eeepc->hotplug_slot);
683 eeepc->hotplug_slot = NULL;
691 static int eeepc_rfkill_set(void *data, bool blocked)
693 acpi_handle handle = data;
695 return write_acpi_int(handle, NULL, !blocked);
698 static const struct rfkill_ops eeepc_rfkill_ops = {
699 .set_block = eeepc_rfkill_set,
702 static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
703 struct rfkill **rfkill,
705 enum rfkill_type type, int cm)
710 result = acpi_setter_handle(eeepc, cm, &handle);
714 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
715 &eeepc_rfkill_ops, handle);
720 rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
721 result = rfkill_register(*rfkill);
723 rfkill_destroy(*rfkill);
730 static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
732 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
733 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
734 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
735 if (eeepc->wlan_rfkill) {
736 rfkill_unregister(eeepc->wlan_rfkill);
737 rfkill_destroy(eeepc->wlan_rfkill);
738 eeepc->wlan_rfkill = NULL;
741 * Refresh pci hotplug in case the rfkill state was changed after
742 * eeepc_unregister_rfkill_notifier()
744 eeepc_rfkill_hotplug(eeepc);
745 if (eeepc->hotplug_slot)
746 pci_hp_deregister(eeepc->hotplug_slot);
748 if (eeepc->bluetooth_rfkill) {
749 rfkill_unregister(eeepc->bluetooth_rfkill);
750 rfkill_destroy(eeepc->bluetooth_rfkill);
751 eeepc->bluetooth_rfkill = NULL;
753 if (eeepc->wwan3g_rfkill) {
754 rfkill_unregister(eeepc->wwan3g_rfkill);
755 rfkill_destroy(eeepc->wwan3g_rfkill);
756 eeepc->wwan3g_rfkill = NULL;
758 if (eeepc->wimax_rfkill) {
759 rfkill_unregister(eeepc->wimax_rfkill);
760 rfkill_destroy(eeepc->wimax_rfkill);
761 eeepc->wimax_rfkill = NULL;
765 static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
769 mutex_init(&eeepc->hotplug_lock);
771 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
772 "eeepc-wlan", RFKILL_TYPE_WLAN,
775 if (result && result != -ENODEV)
778 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
779 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
782 if (result && result != -ENODEV)
785 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
786 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
789 if (result && result != -ENODEV)
792 result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
793 "eeepc-wimax", RFKILL_TYPE_WIMAX,
796 if (result && result != -ENODEV)
799 result = eeepc_setup_pci_hotplug(eeepc);
801 * If we get -EBUSY then something else is handling the PCI hotplug -
802 * don't fail in this case
804 if (result == -EBUSY)
807 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
808 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
809 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
811 * Refresh pci hotplug in case the rfkill state was changed during
814 eeepc_rfkill_hotplug(eeepc);
817 if (result && result != -ENODEV)
818 eeepc_rfkill_exit(eeepc);
823 * Platform driver - hibernate/resume callbacks
825 static int eeepc_hotk_thaw(struct device *device)
827 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
829 if (eeepc->wlan_rfkill) {
833 * Work around bios bug - acpi _PTS turns off the wireless led
834 * during suspend. Normally it restores it on resume, but
835 * we should kick it ourselves in case hibernation is aborted.
837 wlan = get_acpi(eeepc, CM_ASL_WLAN);
838 set_acpi(eeepc, CM_ASL_WLAN, wlan);
844 static int eeepc_hotk_restore(struct device *device)
846 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
848 /* Refresh both wlan rfkill state and pci hotplug */
849 if (eeepc->wlan_rfkill)
850 eeepc_rfkill_hotplug(eeepc);
852 if (eeepc->bluetooth_rfkill)
853 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
854 get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
855 if (eeepc->wwan3g_rfkill)
856 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
857 get_acpi(eeepc, CM_ASL_3G) != 1);
858 if (eeepc->wimax_rfkill)
859 rfkill_set_sw_state(eeepc->wimax_rfkill,
860 get_acpi(eeepc, CM_ASL_WIMAX) != 1);
865 static const struct dev_pm_ops eeepc_pm_ops = {
866 .thaw = eeepc_hotk_thaw,
867 .restore = eeepc_hotk_restore,
870 static struct platform_driver platform_driver = {
872 .name = EEEPC_LAPTOP_FILE,
873 .owner = THIS_MODULE,
882 #define EEEPC_EC_SC00 0x61
883 #define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
884 #define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
885 #define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
887 #define EEEPC_EC_SFB0 0xD0
888 #define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
890 static int eeepc_get_fan_pwm(void)
894 ec_read(EEEPC_EC_FAN_PWM, &value);
895 return value * 255 / 100;
898 static void eeepc_set_fan_pwm(int value)
900 value = SENSORS_LIMIT(value, 0, 255);
901 value = value * 100 / 255;
902 ec_write(EEEPC_EC_FAN_PWM, value);
905 static int eeepc_get_fan_rpm(void)
910 ec_read(EEEPC_EC_FAN_HRPM, &high);
911 ec_read(EEEPC_EC_FAN_LRPM, &low);
912 return high << 8 | low;
915 static int eeepc_get_fan_ctrl(void)
919 ec_read(EEEPC_EC_FAN_CTRL, &value);
921 return 1; /* manual */
923 return 2; /* automatic */
926 static void eeepc_set_fan_ctrl(int manual)
930 ec_read(EEEPC_EC_FAN_CTRL, &value);
935 ec_write(EEEPC_EC_FAN_CTRL, value);
938 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
942 rv = parse_arg(buf, count, &value);
948 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
950 return sprintf(buf, "%d\n", get());
953 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
954 static ssize_t show_##_name(struct device *dev, \
955 struct device_attribute *attr, \
958 return show_sys_hwmon(_set, buf); \
960 static ssize_t store_##_name(struct device *dev, \
961 struct device_attribute *attr, \
962 const char *buf, size_t count) \
964 return store_sys_hwmon(_get, buf, count); \
966 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
968 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
969 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
970 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
971 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
972 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
975 show_name(struct device *dev, struct device_attribute *attr, char *buf)
977 return sprintf(buf, "eeepc\n");
979 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
981 static struct attribute *hwmon_attributes[] = {
982 &sensor_dev_attr_pwm1.dev_attr.attr,
983 &sensor_dev_attr_fan1_input.dev_attr.attr,
984 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
985 &sensor_dev_attr_name.dev_attr.attr,
989 static struct attribute_group hwmon_attribute_group = {
990 .attrs = hwmon_attributes
993 static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc)
995 struct device *hwmon;
997 hwmon = eeepc->hwmon_device;
1000 sysfs_remove_group(&hwmon->kobj,
1001 &hwmon_attribute_group);
1002 hwmon_device_unregister(hwmon);
1003 eeepc->hwmon_device = NULL;
1006 static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
1008 struct device *hwmon;
1011 hwmon = hwmon_device_register(&eeepc->platform_device->dev);
1012 if (IS_ERR(hwmon)) {
1013 pr_err("Could not register eeepc hwmon device\n");
1014 eeepc->hwmon_device = NULL;
1015 return PTR_ERR(hwmon);
1017 eeepc->hwmon_device = hwmon;
1018 result = sysfs_create_group(&hwmon->kobj,
1019 &hwmon_attribute_group);
1021 eeepc_hwmon_exit(eeepc);
1028 static int read_brightness(struct backlight_device *bd)
1030 struct eeepc_laptop *eeepc = bl_get_data(bd);
1032 return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1035 static int set_brightness(struct backlight_device *bd, int value)
1037 struct eeepc_laptop *eeepc = bl_get_data(bd);
1039 return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1042 static int update_bl_status(struct backlight_device *bd)
1044 return set_brightness(bd, bd->props.brightness);
1047 static struct backlight_ops eeepcbl_ops = {
1048 .get_brightness = read_brightness,
1049 .update_status = update_bl_status,
1052 static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1054 struct backlight_device *bd = eeepc->backlight_device;
1055 int old = bd->props.brightness;
1057 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1062 static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1064 struct backlight_device *bd;
1066 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1067 &eeepc->platform_device->dev,
1068 eeepc, &eeepcbl_ops);
1070 pr_err("Could not register eeepc backlight device\n");
1071 eeepc->backlight_device = NULL;
1074 eeepc->backlight_device = bd;
1075 bd->props.max_brightness = 15;
1076 bd->props.brightness = read_brightness(bd);
1077 bd->props.power = FB_BLANK_UNBLANK;
1078 backlight_update_status(bd);
1082 static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1084 if (eeepc->backlight_device)
1085 backlight_device_unregister(eeepc->backlight_device);
1086 eeepc->backlight_device = NULL;
1091 * Input device (i.e. hotkeys)
1093 static struct key_entry *eeepc_get_entry_by_scancode(
1094 struct eeepc_laptop *eeepc,
1097 struct key_entry *key;
1099 for (key = eeepc->keymap; key->type != KE_END; key++)
1100 if (code == key->code)
1106 static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1108 static struct key_entry *key;
1110 key = eeepc_get_entry_by_scancode(eeepc, event);
1112 switch (key->type) {
1114 input_report_key(eeepc->inputdev, key->keycode,
1116 input_sync(eeepc->inputdev);
1117 input_report_key(eeepc->inputdev, key->keycode,
1119 input_sync(eeepc->inputdev);
1125 static struct key_entry *eeepc_get_entry_by_keycode(
1126 struct eeepc_laptop *eeepc, int code)
1128 struct key_entry *key;
1130 for (key = eeepc->keymap; key->type != KE_END; key++)
1131 if (code == key->keycode && key->type == KE_KEY)
1137 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1139 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1140 struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
1142 if (key && key->type == KE_KEY) {
1143 *keycode = key->keycode;
1150 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
1152 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1153 struct key_entry *key;
1156 if (keycode < 0 || keycode > KEY_MAX)
1159 key = eeepc_get_entry_by_scancode(eeepc, scancode);
1160 if (key && key->type == KE_KEY) {
1161 old_keycode = key->keycode;
1162 key->keycode = keycode;
1163 set_bit(keycode, dev->keybit);
1164 if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
1165 clear_bit(old_keycode, dev->keybit);
1172 static int eeepc_input_init(struct eeepc_laptop *eeepc)
1174 const struct key_entry *key;
1177 eeepc->inputdev = input_allocate_device();
1178 if (!eeepc->inputdev) {
1179 pr_info("Unable to allocate input device\n");
1182 eeepc->inputdev->name = "Asus EeePC extra buttons";
1183 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
1184 eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
1185 eeepc->inputdev->id.bustype = BUS_HOST;
1186 eeepc->inputdev->getkeycode = eeepc_getkeycode;
1187 eeepc->inputdev->setkeycode = eeepc_setkeycode;
1188 input_set_drvdata(eeepc->inputdev, eeepc);
1190 eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
1192 for (key = eeepc_keymap; key->type != KE_END; key++) {
1193 switch (key->type) {
1195 set_bit(EV_KEY, eeepc->inputdev->evbit);
1196 set_bit(key->keycode, eeepc->inputdev->keybit);
1200 result = input_register_device(eeepc->inputdev);
1202 pr_info("Unable to register input device\n");
1203 input_free_device(eeepc->inputdev);
1209 static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1211 if (eeepc->inputdev) {
1212 input_unregister_device(eeepc->inputdev);
1213 kfree(eeepc->keymap);
1220 static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1222 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1225 if (event > ACPI_MAX_SYS_NOTIFY)
1227 count = eeepc->event_count[event % 128]++;
1228 acpi_bus_generate_proc_event(device, event, count);
1229 acpi_bus_generate_netlink_event(device->pnp.device_class,
1230 dev_name(&device->dev), event,
1233 /* Brightness events are special */
1234 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1236 /* Ignore them completely if the acpi video driver is used */
1237 if (eeepc->backlight_device != NULL) {
1238 int old_brightness, new_brightness;
1240 /* Update the backlight device. */
1241 old_brightness = eeepc_backlight_notify(eeepc);
1243 /* Convert event to keypress (obsolescent hack) */
1244 new_brightness = event - NOTIFY_BRN_MIN;
1246 if (new_brightness < old_brightness) {
1247 event = NOTIFY_BRN_MIN; /* brightness down */
1248 } else if (new_brightness > old_brightness) {
1249 event = NOTIFY_BRN_MAX; /* brightness up */
1252 * no change in brightness - already at min/max,
1253 * event will be desired value (or else ignored)
1256 eeepc_input_notify(eeepc, event);
1259 /* Everything else is a bona-fide keypress event */
1260 eeepc_input_notify(eeepc, event);
1264 static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1268 /* Some BIOSes do not report cm although it is avaliable.
1269 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1270 if (!(eeepc->cm_supported & (1 << cm))
1271 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1272 pr_info("%s (%x) not reported by BIOS,"
1273 " enabling anyway\n", name, 1 << cm);
1274 eeepc->cm_supported |= 1 << cm;
1278 static void cmsg_quirks(struct eeepc_laptop *eeepc)
1280 cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1281 cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1282 cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1283 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1286 static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
1287 struct acpi_device *device)
1289 unsigned int init_flags;
1292 result = acpi_bus_get_status(device);
1295 if (!device->status.present) {
1296 pr_err("Hotkey device not present, aborting\n");
1300 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1301 pr_notice("Hotkey init flags 0x%x\n", init_flags);
1303 if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1304 pr_err("Hotkey initialization failed\n");
1308 /* get control methods supported */
1309 if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1310 pr_err("Get control methods supported failed\n");
1314 pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1319 static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
1322 * If the following call to set_acpi() fails, it's because there's no
1323 * camera so we can ignore the error.
1325 if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1326 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1329 static bool eeepc_device_present;
1331 static int __devinit eeepc_acpi_add(struct acpi_device *device)
1333 struct eeepc_laptop *eeepc;
1336 pr_notice(EEEPC_LAPTOP_NAME "\n");
1337 eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1340 eeepc->handle = device->handle;
1341 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1342 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1343 device->driver_data = eeepc;
1345 result = eeepc_acpi_init(eeepc, device);
1348 eeepc_enable_camera(eeepc);
1351 * Register the platform device first. It is used as a parent for the
1352 * sub-devices below.
1354 * Note that if there are multiple instances of this ACPI device it
1355 * will bail out, because the platform device is registered with a
1356 * fixed name. Of course it doesn't make sense to have more than one,
1357 * and machine-specific scripts find the fixed name convenient. But
1358 * It's also good for us to exclude multiple instances because both
1359 * our hwmon and our wlan rfkill subdevice use global ACPI objects
1360 * (the EC and the wlan PCI slot respectively).
1362 result = eeepc_platform_init(eeepc);
1366 if (!acpi_video_backlight_support()) {
1367 result = eeepc_backlight_init(eeepc);
1369 goto fail_backlight;
1371 pr_info("Backlight controlled by ACPI video driver\n");
1373 result = eeepc_input_init(eeepc);
1377 result = eeepc_hwmon_init(eeepc);
1381 result = eeepc_led_init(eeepc);
1385 result = eeepc_rfkill_init(eeepc);
1389 eeepc_device_present = true;
1393 eeepc_led_exit(eeepc);
1395 eeepc_hwmon_exit(eeepc);
1397 eeepc_input_exit(eeepc);
1399 eeepc_backlight_exit(eeepc);
1401 eeepc_platform_exit(eeepc);
1408 static int eeepc_acpi_remove(struct acpi_device *device, int type)
1410 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1412 eeepc_backlight_exit(eeepc);
1413 eeepc_rfkill_exit(eeepc);
1414 eeepc_input_exit(eeepc);
1415 eeepc_hwmon_exit(eeepc);
1416 eeepc_led_exit(eeepc);
1417 eeepc_platform_exit(eeepc);
1424 static const struct acpi_device_id eeepc_device_ids[] = {
1425 {EEEPC_ACPI_HID, 0},
1428 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1430 static struct acpi_driver eeepc_acpi_driver = {
1431 .name = EEEPC_LAPTOP_NAME,
1432 .class = EEEPC_ACPI_CLASS,
1433 .owner = THIS_MODULE,
1434 .ids = eeepc_device_ids,
1435 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1437 .add = eeepc_acpi_add,
1438 .remove = eeepc_acpi_remove,
1439 .notify = eeepc_acpi_notify,
1444 static int __init eeepc_laptop_init(void)
1448 result = platform_driver_register(&platform_driver);
1452 result = acpi_bus_register_driver(&eeepc_acpi_driver);
1454 goto fail_acpi_driver;
1455 if (!eeepc_device_present) {
1457 goto fail_no_device;
1462 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1464 platform_driver_unregister(&platform_driver);
1468 static void __exit eeepc_laptop_exit(void)
1470 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1471 platform_driver_unregister(&platform_driver);
1474 module_init(eeepc_laptop_init);
1475 module_exit(eeepc_laptop_exit);