diff options
author | Corentin Chary <corentincj@iksaif.net> | 2009-12-03 02:44:52 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-09 15:54:30 -0500 |
commit | 3c0eb510697dbbb53674c72544350624a04ab5b4 (patch) | |
tree | 83f5c09da8363e5c10f662f54970e618c0427ffb /drivers/platform/x86/eeepc-laptop.c | |
parent | edf624522757adec8ceb83a4b97747eba645c454 (diff) |
eeepc-laptop: add touchpad led
This led can be found on Eeepc 1005 series.
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 2c65a3772968..91304342f8b6 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | 36 | #include <linux/pci_hotplug.h> |
37 | #include <linux/leds.h> | ||
37 | 38 | ||
38 | #define EEEPC_LAPTOP_VERSION "0.1" | 39 | #define EEEPC_LAPTOP_VERSION "0.1" |
39 | 40 | ||
@@ -507,6 +508,39 @@ static struct attribute_group platform_attribute_group = { | |||
507 | }; | 508 | }; |
508 | 509 | ||
509 | /* | 510 | /* |
511 | * LEDs | ||
512 | */ | ||
513 | /* | ||
514 | * These functions actually update the LED's, and are called from a | ||
515 | * workqueue. By doing this as separate work rather than when the LED | ||
516 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a | ||
517 | * potentially bad time, such as a timer interrupt. | ||
518 | */ | ||
519 | static int tpd_led_wk; | ||
520 | |||
521 | static void tpd_led_update(struct work_struct *ignored) | ||
522 | { | ||
523 | int value = tpd_led_wk; | ||
524 | set_acpi(CM_ASL_TPD, value); | ||
525 | } | ||
526 | |||
527 | static struct workqueue_struct *led_workqueue; | ||
528 | static DECLARE_WORK(tpd_led_work, tpd_led_update); | ||
529 | |||
530 | static void tpd_led_set(struct led_classdev *led_cdev, | ||
531 | enum led_brightness value) | ||
532 | { | ||
533 | tpd_led_wk = (value > 0) ? 1 : 0; | ||
534 | queue_work(led_workqueue, &tpd_led_work); | ||
535 | } | ||
536 | |||
537 | static struct led_classdev tpd_led = { | ||
538 | .name = "eeepc::touchpad", | ||
539 | .brightness_set = tpd_led_set, | ||
540 | .max_brightness = 1 | ||
541 | }; | ||
542 | |||
543 | /* | ||
510 | * Hotkey functions | 544 | * Hotkey functions |
511 | */ | 545 | */ |
512 | static struct key_entry *eepc_get_entry_by_scancode(int code) | 546 | static struct key_entry *eepc_get_entry_by_scancode(int code) |
@@ -1034,6 +1068,14 @@ static void eeepc_hwmon_exit(void) | |||
1034 | eeepc_hwmon_device = NULL; | 1068 | eeepc_hwmon_device = NULL; |
1035 | } | 1069 | } |
1036 | 1070 | ||
1071 | static void eeepc_led_exit(void) | ||
1072 | { | ||
1073 | if (led_workqueue) | ||
1074 | destroy_workqueue(led_workqueue); | ||
1075 | if (tpd_led.dev) | ||
1076 | led_classdev_unregister(&tpd_led); | ||
1077 | } | ||
1078 | |||
1037 | static int eeepc_new_rfkill(struct rfkill **rfkill, | 1079 | static int eeepc_new_rfkill(struct rfkill **rfkill, |
1038 | const char *name, struct device *dev, | 1080 | const char *name, struct device *dev, |
1039 | enum rfkill_type type, int cm) | 1081 | enum rfkill_type type, int cm) |
@@ -1190,6 +1232,24 @@ static int eeepc_input_init(struct device *dev) | |||
1190 | return 0; | 1232 | return 0; |
1191 | } | 1233 | } |
1192 | 1234 | ||
1235 | static int eeepc_led_init(struct device *dev) | ||
1236 | { | ||
1237 | int rv; | ||
1238 | |||
1239 | if (get_acpi(CM_ASL_TPD) == -ENODEV) | ||
1240 | return 0; | ||
1241 | |||
1242 | rv = led_classdev_register(dev, &tpd_led); | ||
1243 | if (rv) | ||
1244 | return rv; | ||
1245 | |||
1246 | led_workqueue = create_singlethread_workqueue("led_workqueue"); | ||
1247 | if (!led_workqueue) | ||
1248 | return -ENOMEM; | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1193 | static int __devinit eeepc_hotk_add(struct acpi_device *device) | 1253 | static int __devinit eeepc_hotk_add(struct acpi_device *device) |
1194 | { | 1254 | { |
1195 | struct device *dev; | 1255 | struct device *dev; |
@@ -1248,6 +1308,10 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device) | |||
1248 | if (result) | 1308 | if (result) |
1249 | goto fail_hwmon; | 1309 | goto fail_hwmon; |
1250 | 1310 | ||
1311 | result = eeepc_led_init(dev); | ||
1312 | if (result) | ||
1313 | goto fail_led; | ||
1314 | |||
1251 | result = eeepc_rfkill_init(dev); | 1315 | result = eeepc_rfkill_init(dev); |
1252 | if (result) | 1316 | if (result) |
1253 | goto fail_rfkill; | 1317 | goto fail_rfkill; |
@@ -1255,6 +1319,8 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device) | |||
1255 | return 0; | 1319 | return 0; |
1256 | 1320 | ||
1257 | fail_rfkill: | 1321 | fail_rfkill: |
1322 | eeepc_led_exit(); | ||
1323 | fail_led: | ||
1258 | eeepc_hwmon_exit(); | 1324 | eeepc_hwmon_exit(); |
1259 | fail_hwmon: | 1325 | fail_hwmon: |
1260 | eeepc_input_exit(); | 1326 | eeepc_input_exit(); |
@@ -1284,6 +1350,7 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
1284 | eeepc_rfkill_exit(); | 1350 | eeepc_rfkill_exit(); |
1285 | eeepc_input_exit(); | 1351 | eeepc_input_exit(); |
1286 | eeepc_hwmon_exit(); | 1352 | eeepc_hwmon_exit(); |
1353 | eeepc_led_exit(); | ||
1287 | sysfs_remove_group(&platform_device->dev.kobj, | 1354 | sysfs_remove_group(&platform_device->dev.kobj, |
1288 | &platform_attribute_group); | 1355 | &platform_attribute_group); |
1289 | platform_device_unregister(platform_device); | 1356 | platform_device_unregister(platform_device); |