aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;