aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Piel <eric.piel@tremplin-utc.net>2007-05-21 00:46:31 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-07-10 00:35:17 -0400
commit389679d8faa38bb6d069d9e1805f15e3cb9a6d7f (patch)
tree7c53caf90abf1eec2720e204bc07d2fd7540285b
parenta4da16d3838669d7fb096ea5d1e4917e5ca4dc16 (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/Kconfig5
-rw-r--r--drivers/input/misc/wistron_btns.c88
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
65config INPUT_WISTRON_BTNS 65config 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
52MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 54MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
53MODULE_DESCRIPTION("Wistron laptop button driver"); 55MODULE_DESCRIPTION("Wistron laptop button driver");
54MODULE_LICENSE("GPL v2"); 56MODULE_LICENSE("GPL v2");
55MODULE_VERSION("0.2"); 57MODULE_VERSION("0.3");
56 58
57static int force; /* = 0; */ 59static int force; /* = 0; */
58module_param(force, bool, 0); 60module_param(force, bool, 0);
@@ -253,6 +255,7 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
253static const struct key_entry *keymap; /* = NULL; Current key map */ 255static const struct key_entry *keymap; /* = NULL; Current key map */
254static int have_wifi; 256static int have_wifi;
255static int have_bluetooth; 257static int have_bluetooth;
258static int have_leds;
256 259
257static int __init dmi_matched(struct dmi_system_id *dmi) 260static 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 */
1040static 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 */
1047static 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
1053static struct led_classdev wistron_mail_led = {
1054 .name = "mail:green",
1055 .brightness_set = wistron_mail_led_set,
1056};
1057
1058static struct led_classdev wistron_wifi_led = {
1059 .name = "wifi:red",
1060 .brightness_set = wistron_wifi_led_set,
1061};
1062
1063static 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
1088static 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
1097static 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
1106static 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
1035static int wifi_enabled; 1117static 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)
1143static int __devexit wistron_remove(struct platform_device *dev) 1226static 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;