diff options
author | Eric Piel <eric.piel@tremplin-utc.net> | 2007-05-21 00:46:31 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-07-10 00:35:17 -0400 |
commit | 389679d8faa38bb6d069d9e1805f15e3cb9a6d7f (patch) | |
tree | 7c53caf90abf1eec2720e204bc07d2fd7540285b | |
parent | a4da16d3838669d7fb096ea5d1e4917e5ca4dc16 (diff) |
Input: wistron - add LED support
Add support to wistron_btns for leds that come with the multimedia keys.
Mail and wifi leds are supported, on laptops which have them.
Depending on the laptop, wifi subsystem may control just the led, or both
the led and the wifi card. Wifi led interface is activated only for the
former type of laptops, as the latter type is already managed. Leds are
controled by the interface in /sys/class/leds.
Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r-- | drivers/input/misc/Kconfig | 5 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 88 |
2 files changed, 91 insertions, 2 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 88e29074ac90..4326f536f849 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -65,9 +65,12 @@ config INPUT_COBALT_BTNS | |||
65 | config INPUT_WISTRON_BTNS | 65 | config INPUT_WISTRON_BTNS |
66 | tristate "x86 Wistron laptop button interface" | 66 | tristate "x86 Wistron laptop button interface" |
67 | depends on X86 && !X86_64 | 67 | depends on X86 && !X86_64 |
68 | select NEW_LEDS | ||
69 | select LEDS_CLASS | ||
68 | help | 70 | help |
69 | Say Y here for support of Winstron laptop button interface, used on | 71 | Say Y here for support of Winstron laptop button interface, used on |
70 | laptops of various brands, including Acer and Fujitsu-Siemens. | 72 | laptops of various brands, including Acer and Fujitsu-Siemens. If |
73 | available, mail and wifi leds will be controlable via /sys/class/leds. | ||
71 | 74 | ||
72 | To compile this driver as a module, choose M here: the module will | 75 | To compile this driver as a module, choose M here: the module will |
73 | be called wistron_btns. | 76 | be called wistron_btns. |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 320262aa4c17..d58ddcab601f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/leds.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Number of attempts to read data from queue per poll; | 37 | * Number of attempts to read data from queue per poll; |
@@ -48,11 +49,12 @@ | |||
48 | /* BIOS subsystem IDs */ | 49 | /* BIOS subsystem IDs */ |
49 | #define WIFI 0x35 | 50 | #define WIFI 0x35 |
50 | #define BLUETOOTH 0x34 | 51 | #define BLUETOOTH 0x34 |
52 | #define MAIL_LED 0x31 | ||
51 | 53 | ||
52 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); | 54 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); |
53 | MODULE_DESCRIPTION("Wistron laptop button driver"); | 55 | MODULE_DESCRIPTION("Wistron laptop button driver"); |
54 | MODULE_LICENSE("GPL v2"); | 56 | MODULE_LICENSE("GPL v2"); |
55 | MODULE_VERSION("0.2"); | 57 | MODULE_VERSION("0.3"); |
56 | 58 | ||
57 | static int force; /* = 0; */ | 59 | static int force; /* = 0; */ |
58 | module_param(force, bool, 0); | 60 | module_param(force, bool, 0); |
@@ -253,6 +255,7 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
253 | static const struct key_entry *keymap; /* = NULL; Current key map */ | 255 | static const struct key_entry *keymap; /* = NULL; Current key map */ |
254 | static int have_wifi; | 256 | static int have_wifi; |
255 | static int have_bluetooth; | 257 | static int have_bluetooth; |
258 | static int have_leds; | ||
256 | 259 | ||
257 | static int __init dmi_matched(struct dmi_system_id *dmi) | 260 | static int __init dmi_matched(struct dmi_system_id *dmi) |
258 | { | 261 | { |
@@ -265,6 +268,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi) | |||
265 | else if (key->type == KE_BLUETOOTH) | 268 | else if (key->type == KE_BLUETOOTH) |
266 | have_bluetooth = 1; | 269 | have_bluetooth = 1; |
267 | } | 270 | } |
271 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | ||
272 | |||
268 | return 1; | 273 | return 1; |
269 | } | 274 | } |
270 | 275 | ||
@@ -1030,6 +1035,83 @@ static void report_switch(unsigned code, int value) | |||
1030 | input_sync(input_dev); | 1035 | input_sync(input_dev); |
1031 | } | 1036 | } |
1032 | 1037 | ||
1038 | |||
1039 | /* led management */ | ||
1040 | static void wistron_mail_led_set(struct led_classdev *led_cdev, | ||
1041 | enum led_brightness value) | ||
1042 | { | ||
1043 | bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); | ||
1044 | } | ||
1045 | |||
1046 | /* same as setting up wifi card, but for laptops on which the led is managed */ | ||
1047 | static void wistron_wifi_led_set(struct led_classdev *led_cdev, | ||
1048 | enum led_brightness value) | ||
1049 | { | ||
1050 | bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); | ||
1051 | } | ||
1052 | |||
1053 | static struct led_classdev wistron_mail_led = { | ||
1054 | .name = "mail:green", | ||
1055 | .brightness_set = wistron_mail_led_set, | ||
1056 | }; | ||
1057 | |||
1058 | static struct led_classdev wistron_wifi_led = { | ||
1059 | .name = "wifi:red", | ||
1060 | .brightness_set = wistron_wifi_led_set, | ||
1061 | }; | ||
1062 | |||
1063 | static void __devinit wistron_led_init(struct device *parent) | ||
1064 | { | ||
1065 | if (have_leds & FE_WIFI_LED) { | ||
1066 | u16 wifi = bios_get_default_setting(WIFI); | ||
1067 | if (wifi & 1) { | ||
1068 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | ||
1069 | if (led_classdev_register(parent, &wistron_wifi_led)) | ||
1070 | have_leds &= ~FE_WIFI_LED; | ||
1071 | else | ||
1072 | bios_set_state(WIFI, wistron_wifi_led.brightness); | ||
1073 | |||
1074 | } else | ||
1075 | have_leds &= ~FE_WIFI_LED; | ||
1076 | } | ||
1077 | |||
1078 | if (have_leds & FE_MAIL_LED) { | ||
1079 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | ||
1080 | wistron_mail_led.brightness = LED_OFF; | ||
1081 | if (led_classdev_register(parent, &wistron_mail_led)) | ||
1082 | have_leds &= ~FE_MAIL_LED; | ||
1083 | else | ||
1084 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | static void __devexit wistron_led_remove(void) | ||
1089 | { | ||
1090 | if (have_leds & FE_MAIL_LED) | ||
1091 | led_classdev_unregister(&wistron_mail_led); | ||
1092 | |||
1093 | if (have_leds & FE_WIFI_LED) | ||
1094 | led_classdev_unregister(&wistron_wifi_led); | ||
1095 | } | ||
1096 | |||
1097 | static inline void wistron_led_suspend(void) | ||
1098 | { | ||
1099 | if (have_leds & FE_MAIL_LED) | ||
1100 | led_classdev_suspend(&wistron_mail_led); | ||
1101 | |||
1102 | if (have_leds & FE_WIFI_LED) | ||
1103 | led_classdev_suspend(&wistron_wifi_led); | ||
1104 | } | ||
1105 | |||
1106 | static inline void wistron_led_resume(void) | ||
1107 | { | ||
1108 | if (have_leds & FE_MAIL_LED) | ||
1109 | led_classdev_resume(&wistron_mail_led); | ||
1110 | |||
1111 | if (have_leds & FE_WIFI_LED) | ||
1112 | led_classdev_resume(&wistron_wifi_led); | ||
1113 | } | ||
1114 | |||
1033 | /* Driver core */ | 1115 | /* Driver core */ |
1034 | 1116 | ||
1035 | static int wifi_enabled; | 1117 | static int wifi_enabled; |
@@ -1135,6 +1217,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1135 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1217 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1136 | } | 1218 | } |
1137 | 1219 | ||
1220 | wistron_led_init(&dev->dev); | ||
1138 | poll_bios(1); /* Flush stale event queue and arm timer */ | 1221 | poll_bios(1); /* Flush stale event queue and arm timer */ |
1139 | 1222 | ||
1140 | return 0; | 1223 | return 0; |
@@ -1143,6 +1226,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1143 | static int __devexit wistron_remove(struct platform_device *dev) | 1226 | static int __devexit wistron_remove(struct platform_device *dev) |
1144 | { | 1227 | { |
1145 | del_timer_sync(&poll_timer); | 1228 | del_timer_sync(&poll_timer); |
1229 | wistron_led_remove(); | ||
1146 | input_unregister_device(input_dev); | 1230 | input_unregister_device(input_dev); |
1147 | bios_detach(); | 1231 | bios_detach(); |
1148 | 1232 | ||
@@ -1160,6 +1244,7 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
1160 | if (have_bluetooth) | 1244 | if (have_bluetooth) |
1161 | bios_set_state(BLUETOOTH, 0); | 1245 | bios_set_state(BLUETOOTH, 0); |
1162 | 1246 | ||
1247 | wistron_led_suspend(); | ||
1163 | return 0; | 1248 | return 0; |
1164 | } | 1249 | } |
1165 | 1250 | ||
@@ -1171,6 +1256,7 @@ static int wistron_resume(struct platform_device *dev) | |||
1171 | if (have_bluetooth) | 1256 | if (have_bluetooth) |
1172 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1257 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1173 | 1258 | ||
1259 | wistron_led_resume(); | ||
1174 | poll_bios(1); | 1260 | poll_bios(1); |
1175 | 1261 | ||
1176 | return 0; | 1262 | return 0; |