diff options
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 200 |
2 files changed, 102 insertions, 99 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 4326f536f849..9b26574f1466 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -65,6 +65,7 @@ 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 INPUT_POLLDEV | ||
68 | select NEW_LEDS | 69 | select NEW_LEDS |
69 | select LEDS_CLASS | 70 | select LEDS_CLASS |
70 | help | 71 | help |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index d58ddcab601f..622630f051a5 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/dmi.h> | 21 | #include <linux/dmi.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input-polldev.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
@@ -28,23 +28,13 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/preempt.h> | 29 | #include <linux/preempt.h> |
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/timer.h> | ||
32 | #include <linux/types.h> | 31 | #include <linux/types.h> |
33 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
34 | #include <linux/leds.h> | 33 | #include <linux/leds.h> |
35 | 34 | ||
36 | /* | 35 | /* How often we poll keys - msecs */ |
37 | * Number of attempts to read data from queue per poll; | 36 | #define POLL_INTERVAL_DEFAULT 500 /* when idle */ |
38 | * the queue can hold up to 31 entries | 37 | #define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ |
39 | */ | ||
40 | #define MAX_POLL_ITERATIONS 64 | ||
41 | |||
42 | #define POLL_FREQUENCY 2 /* Number of polls per second when idle */ | ||
43 | #define POLL_FREQUENCY_BURST 10 /* Polls per second when a key was recently pressed */ | ||
44 | |||
45 | #if POLL_FREQUENCY_BURST > HZ | ||
46 | #error "POLL_FREQUENCY too high" | ||
47 | #endif | ||
48 | 38 | ||
49 | /* BIOS subsystem IDs */ | 39 | /* BIOS subsystem IDs */ |
50 | #define WIFI 0x35 | 40 | #define WIFI 0x35 |
@@ -973,66 +963,23 @@ static int __init select_keymap(void) | |||
973 | 963 | ||
974 | /* Input layer interface */ | 964 | /* Input layer interface */ |
975 | 965 | ||
976 | static struct input_dev *input_dev; | 966 | static struct input_polled_dev *wistron_idev; |
977 | 967 | static unsigned long jiffies_last_press; | |
978 | static int __devinit setup_input_dev(void) | 968 | static int wifi_enabled; |
979 | { | 969 | static int bluetooth_enabled; |
980 | const struct key_entry *key; | ||
981 | int error; | ||
982 | |||
983 | input_dev = input_allocate_device(); | ||
984 | if (!input_dev) | ||
985 | return -ENOMEM; | ||
986 | |||
987 | input_dev->name = "Wistron laptop buttons"; | ||
988 | input_dev->phys = "wistron/input0"; | ||
989 | input_dev->id.bustype = BUS_HOST; | ||
990 | input_dev->cdev.dev = &wistron_device->dev; | ||
991 | |||
992 | for (key = keymap; key->type != KE_END; key++) { | ||
993 | switch (key->type) { | ||
994 | case KE_KEY: | ||
995 | set_bit(EV_KEY, input_dev->evbit); | ||
996 | set_bit(key->keycode, input_dev->keybit); | ||
997 | break; | ||
998 | |||
999 | case KE_SW: | ||
1000 | set_bit(EV_SW, input_dev->evbit); | ||
1001 | set_bit(key->sw.code, input_dev->swbit); | ||
1002 | break; | ||
1003 | |||
1004 | default: | ||
1005 | ; | ||
1006 | } | ||
1007 | } | ||
1008 | |||
1009 | /* reads information flags on KE_END */ | ||
1010 | if (key->code & FE_UNTESTED) | ||
1011 | printk(KERN_WARNING "Untested laptop multimedia keys, " | ||
1012 | "please report success or failure to eric.piel" | ||
1013 | "@tremplin-utc.net\n"); | ||
1014 | |||
1015 | error = input_register_device(input_dev); | ||
1016 | if (error) { | ||
1017 | input_free_device(input_dev); | ||
1018 | return error; | ||
1019 | } | ||
1020 | |||
1021 | return 0; | ||
1022 | } | ||
1023 | 970 | ||
1024 | static void report_key(unsigned keycode) | 971 | static void report_key(struct input_dev *dev, unsigned int keycode) |
1025 | { | 972 | { |
1026 | input_report_key(input_dev, keycode, 1); | 973 | input_report_key(dev, keycode, 1); |
1027 | input_sync(input_dev); | 974 | input_sync(dev); |
1028 | input_report_key(input_dev, keycode, 0); | 975 | input_report_key(dev, keycode, 0); |
1029 | input_sync(input_dev); | 976 | input_sync(dev); |
1030 | } | 977 | } |
1031 | 978 | ||
1032 | static void report_switch(unsigned code, int value) | 979 | static void report_switch(struct input_dev *dev, unsigned int code, int value) |
1033 | { | 980 | { |
1034 | input_report_switch(input_dev, code, value); | 981 | input_report_switch(dev, code, value); |
1035 | input_sync(input_dev); | 982 | input_sync(dev); |
1036 | } | 983 | } |
1037 | 984 | ||
1038 | 985 | ||
@@ -1112,15 +1059,6 @@ static inline void wistron_led_resume(void) | |||
1112 | led_classdev_resume(&wistron_wifi_led); | 1059 | led_classdev_resume(&wistron_wifi_led); |
1113 | } | 1060 | } |
1114 | 1061 | ||
1115 | /* Driver core */ | ||
1116 | |||
1117 | static int wifi_enabled; | ||
1118 | static int bluetooth_enabled; | ||
1119 | |||
1120 | static void poll_bios(unsigned long); | ||
1121 | |||
1122 | static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0); | ||
1123 | |||
1124 | static void handle_key(u8 code) | 1062 | static void handle_key(u8 code) |
1125 | { | 1063 | { |
1126 | const struct key_entry *key; | 1064 | const struct key_entry *key; |
@@ -1129,11 +1067,12 @@ static void handle_key(u8 code) | |||
1129 | if (code == key->code) { | 1067 | if (code == key->code) { |
1130 | switch (key->type) { | 1068 | switch (key->type) { |
1131 | case KE_KEY: | 1069 | case KE_KEY: |
1132 | report_key(key->keycode); | 1070 | report_key(wistron_idev->input, key->keycode); |
1133 | break; | 1071 | break; |
1134 | 1072 | ||
1135 | case KE_SW: | 1073 | case KE_SW: |
1136 | report_switch(key->sw.code, key->sw.value); | 1074 | report_switch(wistron_idev->input, |
1075 | key->sw.code, key->sw.value); | ||
1137 | break; | 1076 | break; |
1138 | 1077 | ||
1139 | case KE_WIFI: | 1078 | case KE_WIFI: |
@@ -1152,19 +1091,19 @@ static void handle_key(u8 code) | |||
1152 | 1091 | ||
1153 | case KE_END: | 1092 | case KE_END: |
1154 | break; | 1093 | break; |
1094 | |||
1155 | default: | 1095 | default: |
1156 | BUG(); | 1096 | BUG(); |
1157 | } | 1097 | } |
1098 | jiffies_last_press = jiffies; | ||
1158 | return; | 1099 | return; |
1159 | } | 1100 | } |
1160 | } | 1101 | } |
1161 | printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); | 1102 | printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); |
1162 | } | 1103 | } |
1163 | 1104 | ||
1164 | static void poll_bios(unsigned long discard) | 1105 | static void poll_bios(bool discard) |
1165 | { | 1106 | { |
1166 | static unsigned long jiffies_last_press; | ||
1167 | unsigned long jiffies_now = jiffies; | ||
1168 | u8 qlen; | 1107 | u8 qlen; |
1169 | u16 val; | 1108 | u16 val; |
1170 | 1109 | ||
@@ -1173,24 +1112,85 @@ static void poll_bios(unsigned long discard) | |||
1173 | if (qlen == 0) | 1112 | if (qlen == 0) |
1174 | break; | 1113 | break; |
1175 | val = bios_pop_queue(); | 1114 | val = bios_pop_queue(); |
1176 | if (val != 0 && !discard) { | 1115 | if (val != 0 && !discard) |
1177 | handle_key((u8)val); | 1116 | handle_key((u8)val); |
1178 | jiffies_last_press = jiffies_now; | ||
1179 | } | ||
1180 | } | 1117 | } |
1118 | } | ||
1119 | |||
1120 | static void wistron_flush(struct input_polled_dev *dev) | ||
1121 | { | ||
1122 | /* Flush stale event queue */ | ||
1123 | poll_bios(true); | ||
1124 | } | ||
1181 | 1125 | ||
1182 | /* Increase precision if user is currently pressing keys (< 2s ago) */ | 1126 | static void wistron_poll(struct input_polled_dev *dev) |
1183 | if (time_after(jiffies_last_press, jiffies_now - (HZ * 2))) | 1127 | { |
1184 | mod_timer(&poll_timer, jiffies_now + HZ / POLL_FREQUENCY_BURST); | 1128 | poll_bios(false); |
1129 | |||
1130 | /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ | ||
1131 | if (time_before(jiffies, jiffies_last_press + 2 * HZ)) | ||
1132 | dev->poll_interval = POLL_INTERVAL_BURST; | ||
1185 | else | 1133 | else |
1186 | mod_timer(&poll_timer, jiffies_now + HZ / POLL_FREQUENCY); | 1134 | dev->poll_interval = POLL_INTERVAL_DEFAULT; |
1135 | } | ||
1136 | |||
1137 | static int __devinit setup_input_dev(void) | ||
1138 | { | ||
1139 | const struct key_entry *key; | ||
1140 | struct input_dev *input_dev; | ||
1141 | int error; | ||
1142 | |||
1143 | wistron_idev = input_allocate_polled_device(); | ||
1144 | if (!wistron_idev) | ||
1145 | return -ENOMEM; | ||
1146 | |||
1147 | wistron_idev->flush = wistron_flush; | ||
1148 | wistron_idev->poll = wistron_poll; | ||
1149 | wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; | ||
1150 | |||
1151 | input_dev = wistron_idev->input; | ||
1152 | input_dev->name = "Wistron laptop buttons"; | ||
1153 | input_dev->phys = "wistron/input0"; | ||
1154 | input_dev->id.bustype = BUS_HOST; | ||
1155 | input_dev->cdev.dev = &wistron_device->dev; | ||
1156 | |||
1157 | for (key = keymap; key->type != KE_END; key++) { | ||
1158 | switch (key->type) { | ||
1159 | case KE_KEY: | ||
1160 | set_bit(EV_KEY, input_dev->evbit); | ||
1161 | set_bit(key->keycode, input_dev->keybit); | ||
1162 | break; | ||
1163 | |||
1164 | case KE_SW: | ||
1165 | set_bit(EV_SW, input_dev->evbit); | ||
1166 | set_bit(key->sw.code, input_dev->swbit); | ||
1167 | break; | ||
1168 | |||
1169 | default: | ||
1170 | break; | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1174 | /* reads information flags on KE_END */ | ||
1175 | if (key->code & FE_UNTESTED) | ||
1176 | printk(KERN_WARNING "Untested laptop multimedia keys, " | ||
1177 | "please report success or failure to eric.piel" | ||
1178 | "@tremplin-utc.net\n"); | ||
1179 | |||
1180 | error = input_register_polled_device(wistron_idev); | ||
1181 | if (error) { | ||
1182 | input_free_polled_device(wistron_idev); | ||
1183 | return error; | ||
1184 | } | ||
1185 | |||
1186 | return 0; | ||
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | /* Driver core */ | ||
1190 | |||
1189 | static int __devinit wistron_probe(struct platform_device *dev) | 1191 | static int __devinit wistron_probe(struct platform_device *dev) |
1190 | { | 1192 | { |
1191 | int err = setup_input_dev(); | 1193 | int err; |
1192 | if (err) | ||
1193 | return err; | ||
1194 | 1194 | ||
1195 | bios_attach(); | 1195 | bios_attach(); |
1196 | cmos_address = bios_get_cmos_address(); | 1196 | cmos_address = bios_get_cmos_address(); |
@@ -1218,16 +1218,20 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | wistron_led_init(&dev->dev); | 1220 | wistron_led_init(&dev->dev); |
1221 | poll_bios(1); /* Flush stale event queue and arm timer */ | 1221 | err = setup_input_dev(); |
1222 | if (err) { | ||
1223 | bios_detach(); | ||
1224 | return err; | ||
1225 | } | ||
1222 | 1226 | ||
1223 | return 0; | 1227 | return 0; |
1224 | } | 1228 | } |
1225 | 1229 | ||
1226 | static int __devexit wistron_remove(struct platform_device *dev) | 1230 | static int __devexit wistron_remove(struct platform_device *dev) |
1227 | { | 1231 | { |
1228 | del_timer_sync(&poll_timer); | ||
1229 | wistron_led_remove(); | 1232 | wistron_led_remove(); |
1230 | input_unregister_device(input_dev); | 1233 | input_unregister_polled_device(wistron_idev); |
1234 | input_free_polled_device(wistron_idev); | ||
1231 | bios_detach(); | 1235 | bios_detach(); |
1232 | 1236 | ||
1233 | return 0; | 1237 | return 0; |
@@ -1236,8 +1240,6 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
1236 | #ifdef CONFIG_PM | 1240 | #ifdef CONFIG_PM |
1237 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1241 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) |
1238 | { | 1242 | { |
1239 | del_timer_sync(&poll_timer); | ||
1240 | |||
1241 | if (have_wifi) | 1243 | if (have_wifi) |
1242 | bios_set_state(WIFI, 0); | 1244 | bios_set_state(WIFI, 0); |
1243 | 1245 | ||
@@ -1257,7 +1259,7 @@ static int wistron_resume(struct platform_device *dev) | |||
1257 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1259 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1258 | 1260 | ||
1259 | wistron_led_resume(); | 1261 | wistron_led_resume(); |
1260 | poll_bios(1); | 1262 | poll_bios(true); |
1261 | 1263 | ||
1262 | return 0; | 1264 | return 0; |
1263 | } | 1265 | } |