27 #include <linux/kernel.h>
29 #include <linux/module.h>
31 #include <linux/string.h>
32 #include <linux/slab.h>
33 #include <linux/types.h>
38 #define POLL_INTERVAL_DEFAULT 500
39 #define POLL_INTERVAL_BURST 100
43 #define BLUETOOTH 0x34
55 static char *keymap_name;
57 MODULE_PARM_DESC(keymap,
"Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
63 static void __iomem *bios_entry_point;
64 static void __iomem *bios_code_map_base;
65 static void __iomem *bios_data_map_base;
67 static u8 cmos_address;
73 static void call_bios(
struct regs *
regs)
79 asm volatile (
"pushl %%ebp;"
83 :
"=a" (regs->
eax),
"=b" (regs->
ebx),
"=c" (regs->
ecx)
84 :
"0" (regs->
eax),
"1" (regs->
ebx),
"2" (regs->
ecx),
85 "m" (bios_entry_point),
"m" (bios_data_map_base)
86 :
"edx",
"edi",
"esi",
"memory");
94 { 0x42, 0x21, 0x55, 0x30 };
97 for (offset = 0; offset < 0x10000; offset += 0x10) {
99 sizeof(signature)) != 0)
105 static int __init map_bios(
void)
111 base =
ioremap(0xF0000, 0x10000);
112 offset = locate_wistron_bios(base);
119 entry_point =
readl(base + offset + 5);
121 "wistron_btns: BIOS signature found at %p, entry point %08X\n",
122 base + offset, entry_point);
124 if (entry_point >= 0xF0000) {
125 bios_code_map_base = base;
126 bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
129 bios_code_map_base =
ioremap(entry_point & ~0x3FFF, 0x4000);
130 if (bios_code_map_base ==
NULL) {
132 "wistron_btns: Can't map BIOS code at %08X\n",
133 entry_point & ~0x3FFF);
136 bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
139 bios_data_map_base =
ioremap(0x400, 0xc00);
140 if (bios_data_map_base ==
NULL) {
152 static inline void unmap_bios(
void)
160 static u16 bios_pop_queue(
void)
183 static void bios_detach(
void)
217 static void bios_set_state(
u8 subsys,
int enable)
223 regs.
ebx = (enable ? 0x0100 : 0x0000) | subsys;
229 #define KE_WIFI (KE_LAST + 1)
230 #define KE_BLUETOOTH (KE_LAST + 2)
232 #define FE_MAIL_LED 0x01
233 #define FE_WIFI_LED 0x02
234 #define FE_UNTESTED 0x80
236 static struct key_entry *keymap;
237 static bool have_wifi;
238 static bool have_bluetooth;
239 static int leds_present;
243 const struct key_entry *
key;
245 keymap = dmi->driver_data;
246 for (key = keymap; key->type !=
KE_END; key++) {
250 have_bluetooth =
true;
257 static struct key_entry keymap_empty[]
__initdata = {
261 static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
271 static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
281 static struct key_entry keymap_fujitsu_n3510[] __initdata = {
293 static struct key_entry keymap_wistron_ms2111[] __initdata = {
302 static struct key_entry keymap_wistron_md40100[] __initdata = {
311 static struct key_entry keymap_wistron_ms2141[] __initdata = {
324 static struct key_entry keymap_acer_aspire_1500[] __initdata = {
337 static struct key_entry keymap_acer_aspire_1600[] __initdata = {
353 static struct key_entry keymap_acer_aspire_5020[] __initdata = {
367 static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
380 static struct key_entry keymap_acer_travelmate_110[] __initdata = {
397 static struct key_entry keymap_acer_travelmate_300[] __initdata = {
413 static struct key_entry keymap_acer_travelmate_380[] __initdata = {
427 static struct key_entry keymap_acer_travelmate_220[] __initdata = {
437 static struct key_entry keymap_acer_travelmate_230[] __initdata = {
447 static struct key_entry keymap_acer_travelmate_240[] __initdata = {
461 static struct key_entry keymap_acer_travelmate_350[] __initdata = {
472 static struct key_entry keymap_acer_travelmate_360[] __initdata = {
487 static struct key_entry keymap_acer_travelmate_610[] __initdata = {
499 static struct key_entry keymap_acer_travelmate_630[] __initdata = {
515 static struct key_entry keymap_aopen_1559as[] __initdata = {
526 static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
537 static struct key_entry keymap_wistron_md2900[] __initdata = {
548 static struct key_entry keymap_wistron_md96500[] __initdata = {
569 static struct key_entry keymap_wistron_generic[] __initdata = {
605 static struct key_entry keymap_aopen_1557[] __initdata = {
619 static struct key_entry keymap_prestigio[] __initdata = {
641 .callback = dmi_matched,
646 .driver_data = keymap_fs_amilo_pro_v2000
650 .callback = dmi_matched,
655 .driver_data = keymap_fs_amilo_pro_v3505
659 .callback = dmi_matched,
664 .driver_data = keymap_fs_amilo_pro_v2000
668 .callback = dmi_matched,
673 .driver_data = keymap_fs_amilo_pro_v2000
677 .callback = dmi_matched,
682 .driver_data = keymap_fujitsu_n3510
686 .callback = dmi_matched,
691 .driver_data = keymap_acer_aspire_1500
695 .callback = dmi_matched,
700 .driver_data = keymap_acer_aspire_1600
704 .callback = dmi_matched,
709 .driver_data = keymap_acer_aspire_5020
713 .callback = dmi_matched,
718 .driver_data = keymap_acer_aspire_5020
722 .callback = dmi_matched,
727 .driver_data = keymap_acer_aspire_5020
731 .callback = dmi_matched,
736 .driver_data = keymap_acer_travelmate_2410
740 .callback = dmi_matched,
745 .driver_data = keymap_acer_travelmate_300
749 .callback = dmi_matched,
754 .driver_data = keymap_acer_travelmate_300
758 .callback = dmi_matched,
763 .driver_data = keymap_acer_travelmate_110
767 .callback = dmi_matched,
772 .driver_data = keymap_acer_travelmate_380
776 .callback = dmi_matched,
781 .driver_data = keymap_acer_travelmate_380
785 .callback = dmi_matched,
790 .driver_data = keymap_acer_travelmate_220
794 .callback = dmi_matched,
799 .driver_data = keymap_acer_travelmate_220
803 .callback = dmi_matched,
809 .driver_data = keymap_acer_travelmate_230
813 .callback = dmi_matched,
818 .driver_data = keymap_acer_travelmate_230
822 .callback = dmi_matched,
827 .driver_data = keymap_acer_travelmate_240
831 .callback = dmi_matched,
836 .driver_data = keymap_acer_travelmate_240
840 .callback = dmi_matched,
845 .driver_data = keymap_acer_travelmate_240
849 .callback = dmi_matched,
854 .driver_data = keymap_acer_travelmate_350
858 .callback = dmi_matched,
863 .driver_data = keymap_acer_travelmate_360
867 .callback = dmi_matched,
872 .driver_data = keymap_acer_travelmate_610
876 .callback = dmi_matched,
881 .driver_data = keymap_acer_travelmate_630
885 .callback = dmi_matched,
890 .driver_data = keymap_acer_travelmate_630
894 .callback = dmi_matched,
899 .driver_data = keymap_aopen_1559as
903 .callback = dmi_matched,
908 .driver_data = keymap_wistron_ms2111
912 .callback = dmi_matched,
917 .driver_data = keymap_wistron_md40100
921 .callback = dmi_matched,
926 .driver_data = keymap_wistron_md2900
930 .callback = dmi_matched,
935 .driver_data = keymap_fs_amilo_pro_v2000
939 .callback = dmi_matched,
944 .driver_data = keymap_wistron_md96500
948 .callback = dmi_matched,
953 .driver_data = keymap_wistron_md96500
957 .callback = dmi_matched,
962 .driver_data = keymap_fs_amilo_d88x0
966 .callback = dmi_matched,
971 .driver_data = keymap_fs_amilo_d88x0
977 static int __init copy_keymap(
void)
979 const struct key_entry *
key;
980 struct key_entry *new_keymap;
983 for (key = keymap; key->type !=
KE_END; key++)
986 new_keymap =
kmemdup(keymap, length *
sizeof(
struct key_entry),
996 static int __init select_keymap(
void)
999 if (keymap_name !=
NULL) {
1000 if (
strcmp (keymap_name,
"1557/MS2141") == 0)
1001 keymap = keymap_wistron_ms2141;
1002 else if (
strcmp (keymap_name,
"aopen1557") == 0)
1003 keymap = keymap_aopen_1557;
1004 else if (
strcmp (keymap_name,
"prestigio") == 0)
1005 keymap = keymap_prestigio;
1006 else if (
strcmp (keymap_name,
"generic") == 0)
1007 keymap = keymap_wistron_generic;
1013 if (keymap ==
NULL) {
1018 keymap = keymap_empty;
1021 return copy_keymap();
1026 static struct input_polled_dev *wistron_idev;
1027 static unsigned long jiffies_last_press;
1028 static bool wifi_enabled;
1029 static bool bluetooth_enabled;
1032 static void wistron_mail_led_set(
struct led_classdev *led_cdev,
1039 static void wistron_wifi_led_set(
struct led_classdev *led_cdev,
1046 .name =
"wistron:green:mail",
1047 .brightness_set = wistron_mail_led_set,
1051 .name =
"wistron:red:wifi",
1052 .brightness_set = wistron_wifi_led_set,
1058 u16 wifi = bios_get_default_setting(
WIFI);
1062 leds_present &= ~FE_WIFI_LED;
1067 leds_present &= ~FE_WIFI_LED;
1074 leds_present &= ~FE_MAIL_LED;
1080 static void __devexit wistron_led_remove(
void)
1082 if (leds_present & FE_MAIL_LED)
1085 if (leds_present & FE_WIFI_LED)
1089 static inline void wistron_led_suspend(
void)
1091 if (leds_present & FE_MAIL_LED)
1094 if (leds_present & FE_WIFI_LED)
1098 static inline void wistron_led_resume(
void)
1100 if (leds_present & FE_MAIL_LED)
1103 if (leds_present & FE_WIFI_LED)
1107 static void handle_key(
u8 code)
1109 const struct key_entry *key =
1110 sparse_keymap_entry_from_scancode(wistron_idev->input, code);
1113 switch (key->type) {
1116 wifi_enabled = !wifi_enabled;
1117 bios_set_state(
WIFI, wifi_enabled);
1122 if (have_bluetooth) {
1123 bluetooth_enabled = !bluetooth_enabled;
1124 bios_set_state(
BLUETOOTH, bluetooth_enabled);
1129 sparse_keymap_report_entry(wistron_idev->input,
1136 "wistron_btns: Unknown key code %02X\n", code);
1139 static void poll_bios(
bool discard)
1148 val = bios_pop_queue();
1149 if (val != 0 && !discard)
1150 handle_key((
u8)val);
1154 static void wistron_flush(
struct input_polled_dev *
dev)
1160 static void wistron_poll(
struct input_polled_dev *
dev)
1171 static int __devinit wistron_setup_keymap(
struct input_dev *dev,
1172 struct key_entry *
entry)
1174 switch (entry->type) {
1185 if (!have_bluetooth) {
1194 "please report success or failure to "
1202 static int __devinit setup_input_dev(
void)
1204 struct input_dev *input_dev;
1211 wistron_idev->open = wistron_flush;
1212 wistron_idev->poll = wistron_poll;
1215 input_dev = wistron_idev->input;
1216 input_dev->name =
"Wistron laptop buttons";
1217 input_dev->phys =
"wistron/input0";
1219 input_dev->dev.parent = &wistron_device->
dev;
1221 error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
1227 goto err_free_keymap;
1232 sparse_keymap_free(input_dev);
1245 cmos_address = bios_get_cmos_address();
1248 u16 wifi = bios_get_default_setting(
WIFI);
1250 wifi_enabled = wifi & 2;
1255 bios_set_state(
WIFI, wifi_enabled);
1258 if (have_bluetooth) {
1261 bluetooth_enabled = bt & 2;
1263 have_bluetooth =
false;
1266 bios_set_state(
BLUETOOTH, bluetooth_enabled);
1269 wistron_led_init(&dev->
dev);
1271 err = setup_input_dev();
1282 wistron_led_remove();
1284 sparse_keymap_free(wistron_idev->input);
1292 static int wistron_suspend(
struct device *dev)
1295 bios_set_state(
WIFI, 0);
1300 wistron_led_suspend();
1305 static int wistron_resume(
struct device *dev)
1308 bios_set_state(
WIFI, wifi_enabled);
1311 bios_set_state(
BLUETOOTH, bluetooth_enabled);
1313 wistron_led_resume();
1320 static const struct dev_pm_ops wistron_pm_ops = {
1322 .resume = wistron_resume,
1323 .poweroff = wistron_suspend,
1324 .restore = wistron_resume,
1330 .name =
"wistron-bios",
1333 .pm = &wistron_pm_ops,
1336 .probe = wistron_probe,
1340 static int __init wb_module_init(
void)
1344 err = select_keymap();
1350 goto err_free_keymap;
1354 goto err_unmap_bios;
1357 if (!wistron_device) {
1359 goto err_unregister_driver;
1364 goto err_free_device;
1370 err_unregister_driver:
1380 static void __exit wb_module_exit(
void)