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 <linux/slab.h>
31 #include <acpi/acpi_drivers.h>
32 #include <acpi/acpi_bus.h>
33 #include <linux/uaccess.h>
34 #include <linux/input.h>
35 #include <linux/input/sparse-keymap.h>
36 #include <linux/rfkill.h>
37 #include <linux/pci.h>
38 #include <linux/pci_hotplug.h>
39 #include <linux/leds.h>
40 #include <linux/dmi.h>
42 #define EEEPC_LAPTOP_VERSION "0.1"
43 #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
44 #define EEEPC_LAPTOP_FILE "eeepc"
46 #define EEEPC_ACPI_CLASS "hotkey"
47 #define EEEPC_ACPI_DEVICE_NAME "Hotkey"
48 #define EEEPC_ACPI_HID "ASUS010"
50 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
51 MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME
);
52 MODULE_LICENSE("GPL");
54 static bool hotplug_disabled
;
56 module_param(hotplug_disabled
, bool, 0444);
57 MODULE_PARM_DESC(hotplug_disabled
,
58 "Disable hotplug for wireless device. "
59 "If your laptop need that, please report to "
60 "acpi4asus-user@lists.sourceforge.net.");
63 * Definitions for Asus EeePC
65 #define NOTIFY_BRN_MIN 0x20
66 #define NOTIFY_BRN_MAX 0x2f
69 DISABLE_ASL_WLAN
= 0x0001,
70 DISABLE_ASL_BLUETOOTH
= 0x0002,
71 DISABLE_ASL_IRDA
= 0x0004,
72 DISABLE_ASL_CAMERA
= 0x0008,
73 DISABLE_ASL_TV
= 0x0010,
74 DISABLE_ASL_GPS
= 0x0020,
75 DISABLE_ASL_DISPLAYSWITCH
= 0x0040,
76 DISABLE_ASL_MODEM
= 0x0080,
77 DISABLE_ASL_CARDREADER
= 0x0100,
78 DISABLE_ASL_3G
= 0x0200,
79 DISABLE_ASL_WIMAX
= 0x0400,
80 DISABLE_ASL_HWCF
= 0x0800
97 CM_ASL_CPUTEMPERATURE
,
110 CM_ASL_PANELPOWER
, /*P901*/
114 static const char *cm_getv
[] = {
115 "WLDG", "BTHG", NULL
, NULL
,
116 "CAMG", NULL
, NULL
, NULL
,
117 NULL
, "PBLG", NULL
, NULL
,
118 "CFVG", NULL
, NULL
, NULL
,
119 "USBG", NULL
, NULL
, "MODG",
120 "CRDG", "M3GG", "WIMG", "HWCF",
121 "LIDG", "TYPE", "PBPG", "TPDG"
124 static const char *cm_setv
[] = {
125 "WLDS", "BTHS", NULL
, NULL
,
126 "CAMS", NULL
, NULL
, NULL
,
127 "SDSP", "PBLS", "HDPS", NULL
,
128 "CFVS", NULL
, NULL
, NULL
,
129 "USBG", NULL
, NULL
, "MODS",
130 "CRDS", "M3GS", "WIMS", NULL
,
131 NULL
, NULL
, "PBPS", "TPDS"
134 static const struct key_entry eeepc_keymap
[] = {
135 { KE_KEY
, 0x10, { KEY_WLAN
} },
136 { KE_KEY
, 0x11, { KEY_WLAN
} },
137 { KE_KEY
, 0x12, { KEY_PROG1
} },
138 { KE_KEY
, 0x13, { KEY_MUTE
} },
139 { KE_KEY
, 0x14, { KEY_VOLUMEDOWN
} },
140 { KE_KEY
, 0x15, { KEY_VOLUMEUP
} },
141 { KE_KEY
, 0x16, { KEY_DISPLAY_OFF
} },
142 { KE_KEY
, 0x1a, { KEY_COFFEE
} },
143 { KE_KEY
, 0x1b, { KEY_ZOOM
} },
144 { KE_KEY
, 0x1c, { KEY_PROG2
} },
145 { KE_KEY
, 0x1d, { KEY_PROG3
} },
146 { KE_KEY
, NOTIFY_BRN_MIN
, { KEY_BRIGHTNESSDOWN
} },
147 { KE_KEY
, NOTIFY_BRN_MAX
, { KEY_BRIGHTNESSUP
} },
148 { KE_KEY
, 0x30, { KEY_SWITCHVIDEOMODE
} },
149 { KE_KEY
, 0x31, { KEY_SWITCHVIDEOMODE
} },
150 { KE_KEY
, 0x32, { KEY_SWITCHVIDEOMODE
} },
151 { KE_KEY
, 0x37, { KEY_F13
} }, /* Disable Touchpad */
152 { KE_KEY
, 0x38, { KEY_F14
} },
157 * This is the main structure, we can use it to store useful information
159 struct eeepc_laptop
{
160 acpi_handle handle
; /* the handle of the acpi device */
161 u32 cm_supported
; /* the control methods supported
164 bool hotplug_disabled
;
165 u16 event_count
[128]; /* count for each event */
167 struct platform_device
*platform_device
;
168 struct acpi_device
*device
; /* the device we are in */
169 struct device
*hwmon_device
;
170 struct backlight_device
*backlight_device
;
172 struct input_dev
*inputdev
;
174 struct rfkill
*wlan_rfkill
;
175 struct rfkill
*bluetooth_rfkill
;
176 struct rfkill
*wwan3g_rfkill
;
177 struct rfkill
*wimax_rfkill
;
179 struct hotplug_slot
*hotplug_slot
;
180 struct mutex hotplug_lock
;
182 struct led_classdev tpd_led
;
184 struct workqueue_struct
*led_workqueue
;
185 struct work_struct tpd_led_work
;
191 static int write_acpi_int(acpi_handle handle
, const char *method
, int val
)
193 struct acpi_object_list params
;
194 union acpi_object in_obj
;
198 params
.pointer
= &in_obj
;
199 in_obj
.type
= ACPI_TYPE_INTEGER
;
200 in_obj
.integer
.value
= val
;
202 status
= acpi_evaluate_object(handle
, (char *)method
, ¶ms
, NULL
);
203 return (status
== AE_OK
? 0 : -1);
206 static int read_acpi_int(acpi_handle handle
, const char *method
, int *val
)
209 unsigned long long result
;
211 status
= acpi_evaluate_integer(handle
, (char *)method
, NULL
, &result
);
212 if (ACPI_FAILURE(status
)) {
221 static int set_acpi(struct eeepc_laptop
*eeepc
, int cm
, int value
)
223 const char *method
= cm_setv
[cm
];
227 if ((eeepc
->cm_supported
& (0x1 << cm
)) == 0)
230 if (write_acpi_int(eeepc
->handle
, method
, value
))
231 pr_warn("Error writing %s\n", method
);
235 static int get_acpi(struct eeepc_laptop
*eeepc
, int cm
)
237 const char *method
= cm_getv
[cm
];
242 if ((eeepc
->cm_supported
& (0x1 << cm
)) == 0)
245 if (read_acpi_int(eeepc
->handle
, method
, &value
))
246 pr_warn("Error reading %s\n", method
);
250 static int acpi_setter_handle(struct eeepc_laptop
*eeepc
, int cm
,
253 const char *method
= cm_setv
[cm
];
258 if ((eeepc
->cm_supported
& (0x1 << cm
)) == 0)
261 status
= acpi_get_handle(eeepc
->handle
, (char *)method
,
263 if (status
!= AE_OK
) {
264 pr_warn("Error finding %s\n", method
);
274 static int parse_arg(const char *buf
, unsigned long count
, int *val
)
278 if (sscanf(buf
, "%i", val
) != 1)
283 static ssize_t
store_sys_acpi(struct device
*dev
, int cm
,
284 const char *buf
, size_t count
)
286 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
289 rv
= parse_arg(buf
, count
, &value
);
291 value
= set_acpi(eeepc
, cm
, value
);
297 static ssize_t
show_sys_acpi(struct device
*dev
, int cm
, char *buf
)
299 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
300 int value
= get_acpi(eeepc
, cm
);
304 return sprintf(buf
, "%d\n", value
);
307 #define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
308 static ssize_t show_##_name(struct device *dev, \
309 struct device_attribute *attr, \
312 return show_sys_acpi(dev, _cm, buf); \
314 static ssize_t store_##_name(struct device *dev, \
315 struct device_attribute *attr, \
316 const char *buf, size_t count) \
318 return store_sys_acpi(dev, _cm, buf, count); \
320 static struct device_attribute dev_attr_##_name = { \
322 .name = __stringify(_name), \
324 .show = show_##_name, \
325 .store = store_##_name, \
328 EEEPC_CREATE_DEVICE_ATTR(camera
, 0644, CM_ASL_CAMERA
);
329 EEEPC_CREATE_DEVICE_ATTR(cardr
, 0644, CM_ASL_CARDREADER
);
330 EEEPC_CREATE_DEVICE_ATTR(disp
, 0200, CM_ASL_DISPLAYSWITCH
);
337 static int get_cpufv(struct eeepc_laptop
*eeepc
, struct eeepc_cpufv
*c
)
339 c
->cur
= get_acpi(eeepc
, CM_ASL_CPUFV
);
340 c
->num
= (c
->cur
>> 8) & 0xff;
342 if (c
->cur
< 0 || c
->num
<= 0 || c
->num
> 12)
347 static ssize_t
show_available_cpufv(struct device
*dev
,
348 struct device_attribute
*attr
,
351 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
352 struct eeepc_cpufv c
;
356 if (get_cpufv(eeepc
, &c
))
358 for (i
= 0; i
< c
.num
; i
++)
359 len
+= sprintf(buf
+ len
, "%d ", i
);
360 len
+= sprintf(buf
+ len
, "\n");
364 static ssize_t
show_cpufv(struct device
*dev
,
365 struct device_attribute
*attr
,
368 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
369 struct eeepc_cpufv c
;
371 if (get_cpufv(eeepc
, &c
))
373 return sprintf(buf
, "%#x\n", (c
.num
<< 8) | c
.cur
);
376 static ssize_t
store_cpufv(struct device
*dev
,
377 struct device_attribute
*attr
,
378 const char *buf
, size_t count
)
380 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
381 struct eeepc_cpufv c
;
384 if (eeepc
->cpufv_disabled
)
386 if (get_cpufv(eeepc
, &c
))
388 rv
= parse_arg(buf
, count
, &value
);
391 if (!rv
|| value
< 0 || value
>= c
.num
)
393 set_acpi(eeepc
, CM_ASL_CPUFV
, value
);
397 static ssize_t
show_cpufv_disabled(struct device
*dev
,
398 struct device_attribute
*attr
,
401 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
403 return sprintf(buf
, "%d\n", eeepc
->cpufv_disabled
);
406 static ssize_t
store_cpufv_disabled(struct device
*dev
,
407 struct device_attribute
*attr
,
408 const char *buf
, size_t count
)
410 struct eeepc_laptop
*eeepc
= dev_get_drvdata(dev
);
413 rv
= parse_arg(buf
, count
, &value
);
419 if (eeepc
->cpufv_disabled
)
420 pr_warn("cpufv enabled (not officially supported "
422 eeepc
->cpufv_disabled
= false;
432 static struct device_attribute dev_attr_cpufv
= {
440 static struct device_attribute dev_attr_available_cpufv
= {
442 .name
= "available_cpufv",
444 .show
= show_available_cpufv
447 static struct device_attribute dev_attr_cpufv_disabled
= {
449 .name
= "cpufv_disabled",
451 .show
= show_cpufv_disabled
,
452 .store
= store_cpufv_disabled
456 static struct attribute
*platform_attributes
[] = {
457 &dev_attr_camera
.attr
,
458 &dev_attr_cardr
.attr
,
460 &dev_attr_cpufv
.attr
,
461 &dev_attr_available_cpufv
.attr
,
462 &dev_attr_cpufv_disabled
.attr
,
466 static struct attribute_group platform_attribute_group
= {
467 .attrs
= platform_attributes
470 static int eeepc_platform_init(struct eeepc_laptop
*eeepc
)
474 eeepc
->platform_device
= platform_device_alloc(EEEPC_LAPTOP_FILE
, -1);
475 if (!eeepc
->platform_device
)
477 platform_set_drvdata(eeepc
->platform_device
, eeepc
);
479 result
= platform_device_add(eeepc
->platform_device
);
481 goto fail_platform_device
;
483 result
= sysfs_create_group(&eeepc
->platform_device
->dev
.kobj
,
484 &platform_attribute_group
);
490 platform_device_del(eeepc
->platform_device
);
491 fail_platform_device
:
492 platform_device_put(eeepc
->platform_device
);
496 static void eeepc_platform_exit(struct eeepc_laptop
*eeepc
)
498 sysfs_remove_group(&eeepc
->platform_device
->dev
.kobj
,
499 &platform_attribute_group
);
500 platform_device_unregister(eeepc
->platform_device
);
507 * These functions actually update the LED's, and are called from a
508 * workqueue. By doing this as separate work rather than when the LED
509 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
510 * potentially bad time, such as a timer interrupt.
512 static void tpd_led_update(struct work_struct
*work
)
514 struct eeepc_laptop
*eeepc
;
516 eeepc
= container_of(work
, struct eeepc_laptop
, tpd_led_work
);
518 set_acpi(eeepc
, CM_ASL_TPD
, eeepc
->tpd_led_wk
);
521 static void tpd_led_set(struct led_classdev
*led_cdev
,
522 enum led_brightness value
)
524 struct eeepc_laptop
*eeepc
;
526 eeepc
= container_of(led_cdev
, struct eeepc_laptop
, tpd_led
);
528 eeepc
->tpd_led_wk
= (value
> 0) ? 1 : 0;
529 queue_work(eeepc
->led_workqueue
, &eeepc
->tpd_led_work
);
532 static enum led_brightness
tpd_led_get(struct led_classdev
*led_cdev
)
534 struct eeepc_laptop
*eeepc
;
536 eeepc
= container_of(led_cdev
, struct eeepc_laptop
, tpd_led
);
538 return get_acpi(eeepc
, CM_ASL_TPD
);
541 static int eeepc_led_init(struct eeepc_laptop
*eeepc
)
545 if (get_acpi(eeepc
, CM_ASL_TPD
) == -ENODEV
)
548 eeepc
->led_workqueue
= create_singlethread_workqueue("led_workqueue");
549 if (!eeepc
->led_workqueue
)
551 INIT_WORK(&eeepc
->tpd_led_work
, tpd_led_update
);
553 eeepc
->tpd_led
.name
= "eeepc::touchpad";
554 eeepc
->tpd_led
.brightness_set
= tpd_led_set
;
555 if (get_acpi(eeepc
, CM_ASL_TPD
) >= 0) /* if method is available */
556 eeepc
->tpd_led
.brightness_get
= tpd_led_get
;
557 eeepc
->tpd_led
.max_brightness
= 1;
559 rv
= led_classdev_register(&eeepc
->platform_device
->dev
,
562 destroy_workqueue(eeepc
->led_workqueue
);
569 static void eeepc_led_exit(struct eeepc_laptop
*eeepc
)
571 if (!IS_ERR_OR_NULL(eeepc
->tpd_led
.dev
))
572 led_classdev_unregister(&eeepc
->tpd_led
);
573 if (eeepc
->led_workqueue
)
574 destroy_workqueue(eeepc
->led_workqueue
);
579 * PCI hotplug (for wlan rfkill)
581 static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop
*eeepc
)
583 if (get_acpi(eeepc
, CM_ASL_WLAN
) == 1)
588 static void eeepc_rfkill_hotplug(struct eeepc_laptop
*eeepc
, acpi_handle handle
)
590 struct pci_dev
*port
;
593 bool blocked
= eeepc_wlan_rfkill_blocked(eeepc
);
597 if (eeepc
->wlan_rfkill
)
598 rfkill_set_sw_state(eeepc
->wlan_rfkill
, blocked
);
600 mutex_lock(&eeepc
->hotplug_lock
);
602 if (eeepc
->hotplug_slot
) {
603 port
= acpi_get_pci_dev(handle
);
605 pr_warning("Unable to find port\n");
609 bus
= port
->subordinate
;
612 pr_warn("Unable to find PCI bus 1?\n");
616 if (pci_bus_read_config_dword(bus
, 0, PCI_VENDOR_ID
, &l
)) {
617 pr_err("Unable to read PCI config space?\n");
621 absent
= (l
== 0xffffffff);
623 if (blocked
!= absent
) {
624 pr_warn("BIOS says wireless lan is %s, "
625 "but the pci device is %s\n",
626 blocked
? "blocked" : "unblocked",
627 absent
? "absent" : "present");
628 pr_warn("skipped wireless hotplug as probably "
629 "inappropriate for this model\n");
634 dev
= pci_get_slot(bus
, 0);
636 /* Device already present */
640 dev
= pci_scan_single_device(bus
, 0);
642 pci_bus_assign_resources(bus
);
643 if (pci_bus_add_device(dev
))
644 pr_err("Unable to hotplug wifi\n");
647 dev
= pci_get_slot(bus
, 0);
649 pci_stop_and_remove_bus_device(dev
);
658 mutex_unlock(&eeepc
->hotplug_lock
);
661 static void eeepc_rfkill_hotplug_update(struct eeepc_laptop
*eeepc
, char *node
)
663 acpi_status status
= AE_OK
;
666 status
= acpi_get_handle(NULL
, node
, &handle
);
668 if (ACPI_SUCCESS(status
))
669 eeepc_rfkill_hotplug(eeepc
, handle
);
672 static void eeepc_rfkill_notify(acpi_handle handle
, u32 event
, void *data
)
674 struct eeepc_laptop
*eeepc
= data
;
676 if (event
!= ACPI_NOTIFY_BUS_CHECK
)
679 eeepc_rfkill_hotplug(eeepc
, handle
);
682 static int eeepc_register_rfkill_notifier(struct eeepc_laptop
*eeepc
,
688 status
= acpi_get_handle(NULL
, node
, &handle
);
690 if (ACPI_SUCCESS(status
)) {
691 status
= acpi_install_notify_handler(handle
,
695 if (ACPI_FAILURE(status
))
696 pr_warn("Failed to register notify on %s\n", node
);
699 * Refresh pci hotplug in case the rfkill state was
700 * changed during setup.
702 eeepc_rfkill_hotplug(eeepc
, handle
);
709 static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop
*eeepc
,
712 acpi_status status
= AE_OK
;
715 status
= acpi_get_handle(NULL
, node
, &handle
);
717 if (ACPI_SUCCESS(status
)) {
718 status
= acpi_remove_notify_handler(handle
,
720 eeepc_rfkill_notify
);
721 if (ACPI_FAILURE(status
))
722 pr_err("Error removing rfkill notify handler %s\n",
725 * Refresh pci hotplug in case the rfkill
726 * state was changed after
727 * eeepc_unregister_rfkill_notifier()
729 eeepc_rfkill_hotplug(eeepc
, handle
);
733 static int eeepc_get_adapter_status(struct hotplug_slot
*hotplug_slot
,
736 struct eeepc_laptop
*eeepc
= hotplug_slot
->private;
737 int val
= get_acpi(eeepc
, CM_ASL_WLAN
);
739 if (val
== 1 || val
== 0)
747 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot
*hotplug_slot
)
749 kfree(hotplug_slot
->info
);
753 static struct hotplug_slot_ops eeepc_hotplug_slot_ops
= {
754 .owner
= THIS_MODULE
,
755 .get_adapter_status
= eeepc_get_adapter_status
,
756 .get_power_status
= eeepc_get_adapter_status
,
759 static int eeepc_setup_pci_hotplug(struct eeepc_laptop
*eeepc
)
762 struct pci_bus
*bus
= pci_find_bus(0, 1);
765 pr_err("Unable to find wifi PCI bus\n");
769 eeepc
->hotplug_slot
= kzalloc(sizeof(struct hotplug_slot
), GFP_KERNEL
);
770 if (!eeepc
->hotplug_slot
)
773 eeepc
->hotplug_slot
->info
= kzalloc(sizeof(struct hotplug_slot_info
),
775 if (!eeepc
->hotplug_slot
->info
)
778 eeepc
->hotplug_slot
->private = eeepc
;
779 eeepc
->hotplug_slot
->release
= &eeepc_cleanup_pci_hotplug
;
780 eeepc
->hotplug_slot
->ops
= &eeepc_hotplug_slot_ops
;
781 eeepc_get_adapter_status(eeepc
->hotplug_slot
,
782 &eeepc
->hotplug_slot
->info
->adapter_status
);
784 ret
= pci_hp_register(eeepc
->hotplug_slot
, bus
, 0, "eeepc-wifi");
786 pr_err("Unable to register hotplug slot - %d\n", ret
);
793 kfree(eeepc
->hotplug_slot
->info
);
795 kfree(eeepc
->hotplug_slot
);
796 eeepc
->hotplug_slot
= NULL
;
804 static int eeepc_rfkill_set(void *data
, bool blocked
)
806 acpi_handle handle
= data
;
808 return write_acpi_int(handle
, NULL
, !blocked
);
811 static const struct rfkill_ops eeepc_rfkill_ops
= {
812 .set_block
= eeepc_rfkill_set
,
815 static int eeepc_new_rfkill(struct eeepc_laptop
*eeepc
,
816 struct rfkill
**rfkill
,
818 enum rfkill_type type
, int cm
)
823 result
= acpi_setter_handle(eeepc
, cm
, &handle
);
827 *rfkill
= rfkill_alloc(name
, &eeepc
->platform_device
->dev
, type
,
828 &eeepc_rfkill_ops
, handle
);
833 rfkill_init_sw_state(*rfkill
, get_acpi(eeepc
, cm
) != 1);
834 result
= rfkill_register(*rfkill
);
836 rfkill_destroy(*rfkill
);
843 static void eeepc_rfkill_exit(struct eeepc_laptop
*eeepc
)
845 eeepc_unregister_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P5");
846 eeepc_unregister_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P6");
847 eeepc_unregister_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P7");
848 if (eeepc
->wlan_rfkill
) {
849 rfkill_unregister(eeepc
->wlan_rfkill
);
850 rfkill_destroy(eeepc
->wlan_rfkill
);
851 eeepc
->wlan_rfkill
= NULL
;
854 if (eeepc
->hotplug_slot
)
855 pci_hp_deregister(eeepc
->hotplug_slot
);
857 if (eeepc
->bluetooth_rfkill
) {
858 rfkill_unregister(eeepc
->bluetooth_rfkill
);
859 rfkill_destroy(eeepc
->bluetooth_rfkill
);
860 eeepc
->bluetooth_rfkill
= NULL
;
862 if (eeepc
->wwan3g_rfkill
) {
863 rfkill_unregister(eeepc
->wwan3g_rfkill
);
864 rfkill_destroy(eeepc
->wwan3g_rfkill
);
865 eeepc
->wwan3g_rfkill
= NULL
;
867 if (eeepc
->wimax_rfkill
) {
868 rfkill_unregister(eeepc
->wimax_rfkill
);
869 rfkill_destroy(eeepc
->wimax_rfkill
);
870 eeepc
->wimax_rfkill
= NULL
;
874 static int eeepc_rfkill_init(struct eeepc_laptop
*eeepc
)
878 mutex_init(&eeepc
->hotplug_lock
);
880 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wlan_rfkill
,
881 "eeepc-wlan", RFKILL_TYPE_WLAN
,
884 if (result
&& result
!= -ENODEV
)
887 result
= eeepc_new_rfkill(eeepc
, &eeepc
->bluetooth_rfkill
,
888 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH
,
891 if (result
&& result
!= -ENODEV
)
894 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wwan3g_rfkill
,
895 "eeepc-wwan3g", RFKILL_TYPE_WWAN
,
898 if (result
&& result
!= -ENODEV
)
901 result
= eeepc_new_rfkill(eeepc
, &eeepc
->wimax_rfkill
,
902 "eeepc-wimax", RFKILL_TYPE_WIMAX
,
905 if (result
&& result
!= -ENODEV
)
908 if (eeepc
->hotplug_disabled
)
911 result
= eeepc_setup_pci_hotplug(eeepc
);
913 * If we get -EBUSY then something else is handling the PCI hotplug -
914 * don't fail in this case
916 if (result
== -EBUSY
)
919 eeepc_register_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P5");
920 eeepc_register_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P6");
921 eeepc_register_rfkill_notifier(eeepc
, "\\_SB.PCI0.P0P7");
924 if (result
&& result
!= -ENODEV
)
925 eeepc_rfkill_exit(eeepc
);
930 * Platform driver - hibernate/resume callbacks
932 static int eeepc_hotk_thaw(struct device
*device
)
934 struct eeepc_laptop
*eeepc
= dev_get_drvdata(device
);
936 if (eeepc
->wlan_rfkill
) {
940 * Work around bios bug - acpi _PTS turns off the wireless led
941 * during suspend. Normally it restores it on resume, but
942 * we should kick it ourselves in case hibernation is aborted.
944 wlan
= get_acpi(eeepc
, CM_ASL_WLAN
);
945 set_acpi(eeepc
, CM_ASL_WLAN
, wlan
);
951 static int eeepc_hotk_restore(struct device
*device
)
953 struct eeepc_laptop
*eeepc
= dev_get_drvdata(device
);
955 /* Refresh both wlan rfkill state and pci hotplug */
956 if (eeepc
->wlan_rfkill
) {
957 eeepc_rfkill_hotplug_update(eeepc
, "\\_SB.PCI0.P0P5");
958 eeepc_rfkill_hotplug_update(eeepc
, "\\_SB.PCI0.P0P6");
959 eeepc_rfkill_hotplug_update(eeepc
, "\\_SB.PCI0.P0P7");
962 if (eeepc
->bluetooth_rfkill
)
963 rfkill_set_sw_state(eeepc
->bluetooth_rfkill
,
964 get_acpi(eeepc
, CM_ASL_BLUETOOTH
) != 1);
965 if (eeepc
->wwan3g_rfkill
)
966 rfkill_set_sw_state(eeepc
->wwan3g_rfkill
,
967 get_acpi(eeepc
, CM_ASL_3G
) != 1);
968 if (eeepc
->wimax_rfkill
)
969 rfkill_set_sw_state(eeepc
->wimax_rfkill
,
970 get_acpi(eeepc
, CM_ASL_WIMAX
) != 1);
975 static const struct dev_pm_ops eeepc_pm_ops
= {
976 .thaw
= eeepc_hotk_thaw
,
977 .restore
= eeepc_hotk_restore
,
980 static struct platform_driver platform_driver
= {
982 .name
= EEEPC_LAPTOP_FILE
,
983 .owner
= THIS_MODULE
,
992 #define EEEPC_EC_SC00 0x61
993 #define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
994 #define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
995 #define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
997 #define EEEPC_EC_SFB0 0xD0
998 #define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
1000 static int eeepc_get_fan_pwm(void)
1004 ec_read(EEEPC_EC_FAN_PWM
, &value
);
1005 return value
* 255 / 100;
1008 static void eeepc_set_fan_pwm(int value
)
1010 value
= clamp_val(value
, 0, 255);
1011 value
= value
* 100 / 255;
1012 ec_write(EEEPC_EC_FAN_PWM
, value
);
1015 static int eeepc_get_fan_rpm(void)
1020 ec_read(EEEPC_EC_FAN_HRPM
, &high
);
1021 ec_read(EEEPC_EC_FAN_LRPM
, &low
);
1022 return high
<< 8 | low
;
1025 static int eeepc_get_fan_ctrl(void)
1029 ec_read(EEEPC_EC_FAN_CTRL
, &value
);
1031 return 1; /* manual */
1033 return 2; /* automatic */
1036 static void eeepc_set_fan_ctrl(int manual
)
1040 ec_read(EEEPC_EC_FAN_CTRL
, &value
);
1045 ec_write(EEEPC_EC_FAN_CTRL
, value
);
1048 static ssize_t
store_sys_hwmon(void (*set
)(int), const char *buf
, size_t count
)
1052 rv
= parse_arg(buf
, count
, &value
);
1058 static ssize_t
show_sys_hwmon(int (*get
)(void), char *buf
)
1060 return sprintf(buf
, "%d\n", get());
1063 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
1064 static ssize_t show_##_name(struct device *dev, \
1065 struct device_attribute *attr, \
1068 return show_sys_hwmon(_set, buf); \
1070 static ssize_t store_##_name(struct device *dev, \
1071 struct device_attribute *attr, \
1072 const char *buf, size_t count) \
1074 return store_sys_hwmon(_get, buf, count); \
1076 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
1078 EEEPC_CREATE_SENSOR_ATTR(fan1_input
, S_IRUGO
, eeepc_get_fan_rpm
, NULL
);
1079 EEEPC_CREATE_SENSOR_ATTR(pwm1
, S_IRUGO
| S_IWUSR
,
1080 eeepc_get_fan_pwm
, eeepc_set_fan_pwm
);
1081 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable
, S_IRUGO
| S_IWUSR
,
1082 eeepc_get_fan_ctrl
, eeepc_set_fan_ctrl
);
1085 show_name(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
1087 return sprintf(buf
, "eeepc\n");
1089 static SENSOR_DEVICE_ATTR(name
, S_IRUGO
, show_name
, NULL
, 0);
1091 static struct attribute
*hwmon_attributes
[] = {
1092 &sensor_dev_attr_pwm1
.dev_attr
.attr
,
1093 &sensor_dev_attr_fan1_input
.dev_attr
.attr
,
1094 &sensor_dev_attr_pwm1_enable
.dev_attr
.attr
,
1095 &sensor_dev_attr_name
.dev_attr
.attr
,
1099 static struct attribute_group hwmon_attribute_group
= {
1100 .attrs
= hwmon_attributes
1103 static void eeepc_hwmon_exit(struct eeepc_laptop
*eeepc
)
1105 struct device
*hwmon
;
1107 hwmon
= eeepc
->hwmon_device
;
1110 sysfs_remove_group(&hwmon
->kobj
,
1111 &hwmon_attribute_group
);
1112 hwmon_device_unregister(hwmon
);
1113 eeepc
->hwmon_device
= NULL
;
1116 static int eeepc_hwmon_init(struct eeepc_laptop
*eeepc
)
1118 struct device
*hwmon
;
1121 hwmon
= hwmon_device_register(&eeepc
->platform_device
->dev
);
1122 if (IS_ERR(hwmon
)) {
1123 pr_err("Could not register eeepc hwmon device\n");
1124 eeepc
->hwmon_device
= NULL
;
1125 return PTR_ERR(hwmon
);
1127 eeepc
->hwmon_device
= hwmon
;
1128 result
= sysfs_create_group(&hwmon
->kobj
,
1129 &hwmon_attribute_group
);
1131 eeepc_hwmon_exit(eeepc
);
1138 static int read_brightness(struct backlight_device
*bd
)
1140 struct eeepc_laptop
*eeepc
= bl_get_data(bd
);
1142 return get_acpi(eeepc
, CM_ASL_PANELBRIGHT
);
1145 static int set_brightness(struct backlight_device
*bd
, int value
)
1147 struct eeepc_laptop
*eeepc
= bl_get_data(bd
);
1149 return set_acpi(eeepc
, CM_ASL_PANELBRIGHT
, value
);
1152 static int update_bl_status(struct backlight_device
*bd
)
1154 return set_brightness(bd
, bd
->props
.brightness
);
1157 static const struct backlight_ops eeepcbl_ops
= {
1158 .get_brightness
= read_brightness
,
1159 .update_status
= update_bl_status
,
1162 static int eeepc_backlight_notify(struct eeepc_laptop
*eeepc
)
1164 struct backlight_device
*bd
= eeepc
->backlight_device
;
1165 int old
= bd
->props
.brightness
;
1167 backlight_force_update(bd
, BACKLIGHT_UPDATE_HOTKEY
);
1172 static int eeepc_backlight_init(struct eeepc_laptop
*eeepc
)
1174 struct backlight_properties props
;
1175 struct backlight_device
*bd
;
1177 memset(&props
, 0, sizeof(struct backlight_properties
));
1178 props
.type
= BACKLIGHT_PLATFORM
;
1179 props
.max_brightness
= 15;
1180 bd
= backlight_device_register(EEEPC_LAPTOP_FILE
,
1181 &eeepc
->platform_device
->dev
, eeepc
,
1182 &eeepcbl_ops
, &props
);
1184 pr_err("Could not register eeepc backlight device\n");
1185 eeepc
->backlight_device
= NULL
;
1188 eeepc
->backlight_device
= bd
;
1189 bd
->props
.brightness
= read_brightness(bd
);
1190 bd
->props
.power
= FB_BLANK_UNBLANK
;
1191 backlight_update_status(bd
);
1195 static void eeepc_backlight_exit(struct eeepc_laptop
*eeepc
)
1197 if (eeepc
->backlight_device
)
1198 backlight_device_unregister(eeepc
->backlight_device
);
1199 eeepc
->backlight_device
= NULL
;
1204 * Input device (i.e. hotkeys)
1206 static int eeepc_input_init(struct eeepc_laptop
*eeepc
)
1208 struct input_dev
*input
;
1211 input
= input_allocate_device();
1213 pr_info("Unable to allocate input device\n");
1217 input
->name
= "Asus EeePC extra buttons";
1218 input
->phys
= EEEPC_LAPTOP_FILE
"/input0";
1219 input
->id
.bustype
= BUS_HOST
;
1220 input
->dev
.parent
= &eeepc
->platform_device
->dev
;
1222 error
= sparse_keymap_setup(input
, eeepc_keymap
, NULL
);
1224 pr_err("Unable to setup input device keymap\n");
1228 error
= input_register_device(input
);
1230 pr_err("Unable to register input device\n");
1231 goto err_free_keymap
;
1234 eeepc
->inputdev
= input
;
1238 sparse_keymap_free(input
);
1240 input_free_device(input
);
1244 static void eeepc_input_exit(struct eeepc_laptop
*eeepc
)
1246 if (eeepc
->inputdev
) {
1247 sparse_keymap_free(eeepc
->inputdev
);
1248 input_unregister_device(eeepc
->inputdev
);
1250 eeepc
->inputdev
= NULL
;
1256 static void eeepc_input_notify(struct eeepc_laptop
*eeepc
, int event
)
1258 if (!eeepc
->inputdev
)
1260 if (!sparse_keymap_report_event(eeepc
->inputdev
, event
, 1, true))
1261 pr_info("Unknown key %x pressed\n", event
);
1264 static void eeepc_acpi_notify(struct acpi_device
*device
, u32 event
)
1266 struct eeepc_laptop
*eeepc
= acpi_driver_data(device
);
1269 if (event
> ACPI_MAX_SYS_NOTIFY
)
1271 count
= eeepc
->event_count
[event
% 128]++;
1272 acpi_bus_generate_netlink_event(device
->pnp
.device_class
,
1273 dev_name(&device
->dev
), event
,
1276 /* Brightness events are special */
1277 if (event
>= NOTIFY_BRN_MIN
&& event
<= NOTIFY_BRN_MAX
) {
1279 /* Ignore them completely if the acpi video driver is used */
1280 if (eeepc
->backlight_device
!= NULL
) {
1281 int old_brightness
, new_brightness
;
1283 /* Update the backlight device. */
1284 old_brightness
= eeepc_backlight_notify(eeepc
);
1286 /* Convert event to keypress (obsolescent hack) */
1287 new_brightness
= event
- NOTIFY_BRN_MIN
;
1289 if (new_brightness
< old_brightness
) {
1290 event
= NOTIFY_BRN_MIN
; /* brightness down */
1291 } else if (new_brightness
> old_brightness
) {
1292 event
= NOTIFY_BRN_MAX
; /* brightness up */
1295 * no change in brightness - already at min/max,
1296 * event will be desired value (or else ignored)
1299 eeepc_input_notify(eeepc
, event
);
1302 /* Everything else is a bona-fide keypress event */
1303 eeepc_input_notify(eeepc
, event
);
1307 static void eeepc_dmi_check(struct eeepc_laptop
*eeepc
)
1311 model
= dmi_get_system_info(DMI_PRODUCT_NAME
);
1316 * Blacklist for setting cpufv (cpu speed).
1318 * EeePC 4G ("701") implements CFVS, but it is not supported
1319 * by the pre-installed OS, and the original option to change it
1320 * in the BIOS setup screen was removed in later versions.
1322 * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1323 * this applies to all "701" models (4G/4G Surf/2G Surf).
1325 * So Asus made a deliberate decision not to support it on this model.
1326 * We have several reports that using it can cause the system to hang
1328 * The hang has also been reported on a "702" (Model name "8G"?).
1330 * We avoid dmi_check_system() / dmi_match(), because they use
1331 * substring matching. We don't want to affect the "701SD"
1332 * and "701SDX" models, because they do support S.H.E.
1334 if (strcmp(model
, "701") == 0 || strcmp(model
, "702") == 0) {
1335 eeepc
->cpufv_disabled
= true;
1336 pr_info("model %s does not officially support setting cpu "
1338 pr_info("cpufv disabled to avoid instability\n");
1342 * Blacklist for wlan hotplug
1344 * Eeepc 1005HA doesn't work like others models and don't need the
1345 * hotplug code. In fact, current hotplug code seems to unplug another
1348 if (strcmp(model
, "1005HA") == 0 || strcmp(model
, "1201N") == 0 ||
1349 strcmp(model
, "1005PE") == 0) {
1350 eeepc
->hotplug_disabled
= true;
1351 pr_info("wlan hotplug disabled\n");
1355 static void cmsg_quirk(struct eeepc_laptop
*eeepc
, int cm
, const char *name
)
1359 /* Some BIOSes do not report cm although it is available.
1360 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1361 if (!(eeepc
->cm_supported
& (1 << cm
))
1362 && !read_acpi_int(eeepc
->handle
, cm_getv
[cm
], &dummy
)) {
1363 pr_info("%s (%x) not reported by BIOS,"
1364 " enabling anyway\n", name
, 1 << cm
);
1365 eeepc
->cm_supported
|= 1 << cm
;
1369 static void cmsg_quirks(struct eeepc_laptop
*eeepc
)
1371 cmsg_quirk(eeepc
, CM_ASL_LID
, "LID");
1372 cmsg_quirk(eeepc
, CM_ASL_TYPE
, "TYPE");
1373 cmsg_quirk(eeepc
, CM_ASL_PANELPOWER
, "PANELPOWER");
1374 cmsg_quirk(eeepc
, CM_ASL_TPD
, "TPD");
1377 static int eeepc_acpi_init(struct eeepc_laptop
*eeepc
)
1379 unsigned int init_flags
;
1382 result
= acpi_bus_get_status(eeepc
->device
);
1385 if (!eeepc
->device
->status
.present
) {
1386 pr_err("Hotkey device not present, aborting\n");
1390 init_flags
= DISABLE_ASL_WLAN
| DISABLE_ASL_DISPLAYSWITCH
;
1391 pr_notice("Hotkey init flags 0x%x\n", init_flags
);
1393 if (write_acpi_int(eeepc
->handle
, "INIT", init_flags
)) {
1394 pr_err("Hotkey initialization failed\n");
1398 /* get control methods supported */
1399 if (read_acpi_int(eeepc
->handle
, "CMSG", &eeepc
->cm_supported
)) {
1400 pr_err("Get control methods supported failed\n");
1404 pr_info("Get control methods supported: 0x%x\n", eeepc
->cm_supported
);
1409 static void eeepc_enable_camera(struct eeepc_laptop
*eeepc
)
1412 * If the following call to set_acpi() fails, it's because there's no
1413 * camera so we can ignore the error.
1415 if (get_acpi(eeepc
, CM_ASL_CAMERA
) == 0)
1416 set_acpi(eeepc
, CM_ASL_CAMERA
, 1);
1419 static bool eeepc_device_present
;
1421 static int eeepc_acpi_add(struct acpi_device
*device
)
1423 struct eeepc_laptop
*eeepc
;
1426 pr_notice(EEEPC_LAPTOP_NAME
"\n");
1427 eeepc
= kzalloc(sizeof(struct eeepc_laptop
), GFP_KERNEL
);
1430 eeepc
->handle
= device
->handle
;
1431 strcpy(acpi_device_name(device
), EEEPC_ACPI_DEVICE_NAME
);
1432 strcpy(acpi_device_class(device
), EEEPC_ACPI_CLASS
);
1433 device
->driver_data
= eeepc
;
1434 eeepc
->device
= device
;
1436 eeepc
->hotplug_disabled
= hotplug_disabled
;
1438 eeepc_dmi_check(eeepc
);
1440 result
= eeepc_acpi_init(eeepc
);
1443 eeepc_enable_camera(eeepc
);
1446 * Register the platform device first. It is used as a parent for the
1447 * sub-devices below.
1449 * Note that if there are multiple instances of this ACPI device it
1450 * will bail out, because the platform device is registered with a
1451 * fixed name. Of course it doesn't make sense to have more than one,
1452 * and machine-specific scripts find the fixed name convenient. But
1453 * It's also good for us to exclude multiple instances because both
1454 * our hwmon and our wlan rfkill subdevice use global ACPI objects
1455 * (the EC and the wlan PCI slot respectively).
1457 result
= eeepc_platform_init(eeepc
);
1461 if (!acpi_video_backlight_support()) {
1462 result
= eeepc_backlight_init(eeepc
);
1464 goto fail_backlight
;
1466 pr_info("Backlight controlled by ACPI video driver\n");
1468 result
= eeepc_input_init(eeepc
);
1472 result
= eeepc_hwmon_init(eeepc
);
1476 result
= eeepc_led_init(eeepc
);
1480 result
= eeepc_rfkill_init(eeepc
);
1484 eeepc_device_present
= true;
1488 eeepc_led_exit(eeepc
);
1490 eeepc_hwmon_exit(eeepc
);
1492 eeepc_input_exit(eeepc
);
1494 eeepc_backlight_exit(eeepc
);
1496 eeepc_platform_exit(eeepc
);
1503 static int eeepc_acpi_remove(struct acpi_device
*device
)
1505 struct eeepc_laptop
*eeepc
= acpi_driver_data(device
);
1507 eeepc_backlight_exit(eeepc
);
1508 eeepc_rfkill_exit(eeepc
);
1509 eeepc_input_exit(eeepc
);
1510 eeepc_hwmon_exit(eeepc
);
1511 eeepc_led_exit(eeepc
);
1512 eeepc_platform_exit(eeepc
);
1519 static const struct acpi_device_id eeepc_device_ids
[] = {
1520 {EEEPC_ACPI_HID
, 0},
1523 MODULE_DEVICE_TABLE(acpi
, eeepc_device_ids
);
1525 static struct acpi_driver eeepc_acpi_driver
= {
1526 .name
= EEEPC_LAPTOP_NAME
,
1527 .class = EEEPC_ACPI_CLASS
,
1528 .owner
= THIS_MODULE
,
1529 .ids
= eeepc_device_ids
,
1530 .flags
= ACPI_DRIVER_ALL_NOTIFY_EVENTS
,
1532 .add
= eeepc_acpi_add
,
1533 .remove
= eeepc_acpi_remove
,
1534 .notify
= eeepc_acpi_notify
,
1539 static int __init
eeepc_laptop_init(void)
1543 result
= platform_driver_register(&platform_driver
);
1547 result
= acpi_bus_register_driver(&eeepc_acpi_driver
);
1549 goto fail_acpi_driver
;
1551 if (!eeepc_device_present
) {
1553 goto fail_no_device
;
1559 acpi_bus_unregister_driver(&eeepc_acpi_driver
);
1561 platform_driver_unregister(&platform_driver
);
1565 static void __exit
eeepc_laptop_exit(void)
1567 acpi_bus_unregister_driver(&eeepc_acpi_driver
);
1568 platform_driver_unregister(&platform_driver
);
1571 module_init(eeepc_laptop_init
);
1572 module_exit(eeepc_laptop_exit
);