15fc14680SDmitry Torokhov /* 25fc14680SDmitry Torokhov * Wistron laptop button driver 35fc14680SDmitry Torokhov * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 484b256a6SBernhard Rosenkraenzer * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> 5a5b0cc80SDmitry Torokhov * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> 65fc14680SDmitry Torokhov * 75fc14680SDmitry Torokhov * You can redistribute and/or modify this program under the terms of the 85fc14680SDmitry Torokhov * GNU General Public License version 2 as published by the Free Software 95fc14680SDmitry Torokhov * Foundation. 105fc14680SDmitry Torokhov * 115fc14680SDmitry Torokhov * This program is distributed in the hope that it will be useful, but 125fc14680SDmitry Torokhov * WITHOUT ANY WARRANTY; without even the implied warranty of 135fc14680SDmitry Torokhov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 145fc14680SDmitry Torokhov * Public License for more details. 155fc14680SDmitry Torokhov * 165fc14680SDmitry Torokhov * You should have received a copy of the GNU General Public License along 175fc14680SDmitry Torokhov * with this program; if not, write to the Free Software Foundation, Inc., 185fc14680SDmitry Torokhov * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA. 195fc14680SDmitry Torokhov */ 2053d5ed62SMatthew Wilcox #include <linux/io.h> 215fc14680SDmitry Torokhov #include <linux/dmi.h> 225fc14680SDmitry Torokhov #include <linux/init.h> 23c2554c91SDmitry Torokhov #include <linux/input-polldev.h> 245fc14680SDmitry Torokhov #include <linux/interrupt.h> 25a4da16d3SEric Piel #include <linux/jiffies.h> 265fc14680SDmitry Torokhov #include <linux/kernel.h> 275fc14680SDmitry Torokhov #include <linux/mc146818rtc.h> 285fc14680SDmitry Torokhov #include <linux/module.h> 295fc14680SDmitry Torokhov #include <linux/preempt.h> 305fc14680SDmitry Torokhov #include <linux/string.h> 315fc14680SDmitry Torokhov #include <linux/types.h> 32a5b0cc80SDmitry Torokhov #include <linux/platform_device.h> 33389679d8SEric Piel #include <linux/leds.h> 345fc14680SDmitry Torokhov 35c2554c91SDmitry Torokhov /* How often we poll keys - msecs */ 36c2554c91SDmitry Torokhov #define POLL_INTERVAL_DEFAULT 500 /* when idle */ 37c2554c91SDmitry Torokhov #define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ 385fc14680SDmitry Torokhov 3984b256a6SBernhard Rosenkraenzer /* BIOS subsystem IDs */ 4084b256a6SBernhard Rosenkraenzer #define WIFI 0x35 4184b256a6SBernhard Rosenkraenzer #define BLUETOOTH 0x34 42389679d8SEric Piel #define MAIL_LED 0x31 4384b256a6SBernhard Rosenkraenzer 445fc14680SDmitry Torokhov MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 455fc14680SDmitry Torokhov MODULE_DESCRIPTION("Wistron laptop button driver"); 465fc14680SDmitry Torokhov MODULE_LICENSE("GPL v2"); 47389679d8SEric Piel MODULE_VERSION("0.3"); 485fc14680SDmitry Torokhov 495fc14680SDmitry Torokhov static int force; /* = 0; */ 505fc14680SDmitry Torokhov module_param(force, bool, 0); 515fc14680SDmitry Torokhov MODULE_PARM_DESC(force, "Load even if computer is not in database"); 525fc14680SDmitry Torokhov 535fc14680SDmitry Torokhov static char *keymap_name; /* = NULL; */ 545fc14680SDmitry Torokhov module_param_named(keymap, keymap_name, charp, 0); 557b0a4cd7SEric Piel MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]"); 565fc14680SDmitry Torokhov 57a5b0cc80SDmitry Torokhov static struct platform_device *wistron_device; 58a5b0cc80SDmitry Torokhov 595fc14680SDmitry Torokhov /* BIOS interface implementation */ 605fc14680SDmitry Torokhov 615fc14680SDmitry Torokhov static void __iomem *bios_entry_point; /* BIOS routine entry point */ 625fc14680SDmitry Torokhov static void __iomem *bios_code_map_base; 635fc14680SDmitry Torokhov static void __iomem *bios_data_map_base; 645fc14680SDmitry Torokhov 655fc14680SDmitry Torokhov static u8 cmos_address; 665fc14680SDmitry Torokhov 675fc14680SDmitry Torokhov struct regs { 685fc14680SDmitry Torokhov u32 eax, ebx, ecx; 695fc14680SDmitry Torokhov }; 705fc14680SDmitry Torokhov 715fc14680SDmitry Torokhov static void call_bios(struct regs *regs) 725fc14680SDmitry Torokhov { 735fc14680SDmitry Torokhov unsigned long flags; 745fc14680SDmitry Torokhov 755fc14680SDmitry Torokhov preempt_disable(); 765fc14680SDmitry Torokhov local_irq_save(flags); 775fc14680SDmitry Torokhov asm volatile ("pushl %%ebp;" 785fc14680SDmitry Torokhov "movl %7, %%ebp;" 795fc14680SDmitry Torokhov "call *%6;" 805fc14680SDmitry Torokhov "popl %%ebp" 815fc14680SDmitry Torokhov : "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx) 825fc14680SDmitry Torokhov : "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx), 835fc14680SDmitry Torokhov "m" (bios_entry_point), "m" (bios_data_map_base) 845fc14680SDmitry Torokhov : "edx", "edi", "esi", "memory"); 855fc14680SDmitry Torokhov local_irq_restore(flags); 865fc14680SDmitry Torokhov preempt_enable(); 875fc14680SDmitry Torokhov } 885fc14680SDmitry Torokhov 89c28c3583SMiloslav Trmac static ssize_t __init locate_wistron_bios(void __iomem *base) 905fc14680SDmitry Torokhov { 91c7948989SAndrew Morton static unsigned char __initdata signature[] = 925fc14680SDmitry Torokhov { 0x42, 0x21, 0x55, 0x30 }; 93c28c3583SMiloslav Trmac ssize_t offset; 945fc14680SDmitry Torokhov 955fc14680SDmitry Torokhov for (offset = 0; offset < 0x10000; offset += 0x10) { 965fc14680SDmitry Torokhov if (check_signature(base + offset, signature, 975fc14680SDmitry Torokhov sizeof(signature)) != 0) 985fc14680SDmitry Torokhov return offset; 995fc14680SDmitry Torokhov } 1005fc14680SDmitry Torokhov return -1; 1015fc14680SDmitry Torokhov } 1025fc14680SDmitry Torokhov 1035fc14680SDmitry Torokhov static int __init map_bios(void) 1045fc14680SDmitry Torokhov { 1055fc14680SDmitry Torokhov void __iomem *base; 106c28c3583SMiloslav Trmac ssize_t offset; 1075fc14680SDmitry Torokhov u32 entry_point; 1085fc14680SDmitry Torokhov 1095fc14680SDmitry Torokhov base = ioremap(0xF0000, 0x10000); /* Can't fail */ 1105fc14680SDmitry Torokhov offset = locate_wistron_bios(base); 1115fc14680SDmitry Torokhov if (offset < 0) { 1125fc14680SDmitry Torokhov printk(KERN_ERR "wistron_btns: BIOS entry point not found\n"); 1135fc14680SDmitry Torokhov iounmap(base); 1145fc14680SDmitry Torokhov return -ENODEV; 1155fc14680SDmitry Torokhov } 1165fc14680SDmitry Torokhov 1175fc14680SDmitry Torokhov entry_point = readl(base + offset + 5); 1185fc14680SDmitry Torokhov printk(KERN_DEBUG 1195fc14680SDmitry Torokhov "wistron_btns: BIOS signature found at %p, entry point %08X\n", 1205fc14680SDmitry Torokhov base + offset, entry_point); 1215fc14680SDmitry Torokhov 1225fc14680SDmitry Torokhov if (entry_point >= 0xF0000) { 1235fc14680SDmitry Torokhov bios_code_map_base = base; 1245fc14680SDmitry Torokhov bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF); 1255fc14680SDmitry Torokhov } else { 1265fc14680SDmitry Torokhov iounmap(base); 1275fc14680SDmitry Torokhov bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000); 1285fc14680SDmitry Torokhov if (bios_code_map_base == NULL) { 1295fc14680SDmitry Torokhov printk(KERN_ERR 1305fc14680SDmitry Torokhov "wistron_btns: Can't map BIOS code at %08X\n", 1315fc14680SDmitry Torokhov entry_point & ~0x3FFF); 1325fc14680SDmitry Torokhov goto err; 1335fc14680SDmitry Torokhov } 1345fc14680SDmitry Torokhov bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF); 1355fc14680SDmitry Torokhov } 1365fc14680SDmitry Torokhov /* The Windows driver maps 0x10000 bytes, we keep only one page... */ 1375fc14680SDmitry Torokhov bios_data_map_base = ioremap(0x400, 0xc00); 1385fc14680SDmitry Torokhov if (bios_data_map_base == NULL) { 1395fc14680SDmitry Torokhov printk(KERN_ERR "wistron_btns: Can't map BIOS data\n"); 1405fc14680SDmitry Torokhov goto err_code; 1415fc14680SDmitry Torokhov } 1425fc14680SDmitry Torokhov return 0; 1435fc14680SDmitry Torokhov 1445fc14680SDmitry Torokhov err_code: 1455fc14680SDmitry Torokhov iounmap(bios_code_map_base); 1465fc14680SDmitry Torokhov err: 1475fc14680SDmitry Torokhov return -ENOMEM; 1485fc14680SDmitry Torokhov } 1495fc14680SDmitry Torokhov 15022a397e2SDmitry Torokhov static inline void unmap_bios(void) 1515fc14680SDmitry Torokhov { 1525fc14680SDmitry Torokhov iounmap(bios_code_map_base); 1535fc14680SDmitry Torokhov iounmap(bios_data_map_base); 1545fc14680SDmitry Torokhov } 1555fc14680SDmitry Torokhov 1565fc14680SDmitry Torokhov /* BIOS calls */ 1575fc14680SDmitry Torokhov 1585fc14680SDmitry Torokhov static u16 bios_pop_queue(void) 1595fc14680SDmitry Torokhov { 1605fc14680SDmitry Torokhov struct regs regs; 1615fc14680SDmitry Torokhov 1625fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 1635fc14680SDmitry Torokhov regs.eax = 0x9610; 1645fc14680SDmitry Torokhov regs.ebx = 0x061C; 1655fc14680SDmitry Torokhov regs.ecx = 0x0000; 1665fc14680SDmitry Torokhov call_bios(®s); 1675fc14680SDmitry Torokhov 1685fc14680SDmitry Torokhov return regs.eax; 1695fc14680SDmitry Torokhov } 1705fc14680SDmitry Torokhov 171e7c3aad5SDmitry Torokhov static void __devinit bios_attach(void) 1725fc14680SDmitry Torokhov { 1735fc14680SDmitry Torokhov struct regs regs; 1745fc14680SDmitry Torokhov 1755fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 1765fc14680SDmitry Torokhov regs.eax = 0x9610; 1775fc14680SDmitry Torokhov regs.ebx = 0x012E; 1785fc14680SDmitry Torokhov call_bios(®s); 1795fc14680SDmitry Torokhov } 1805fc14680SDmitry Torokhov 18122a397e2SDmitry Torokhov static void bios_detach(void) 1825fc14680SDmitry Torokhov { 1835fc14680SDmitry Torokhov struct regs regs; 1845fc14680SDmitry Torokhov 1855fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 1865fc14680SDmitry Torokhov regs.eax = 0x9610; 1875fc14680SDmitry Torokhov regs.ebx = 0x002E; 1885fc14680SDmitry Torokhov call_bios(®s); 1895fc14680SDmitry Torokhov } 1905fc14680SDmitry Torokhov 191e7c3aad5SDmitry Torokhov static u8 __devinit bios_get_cmos_address(void) 1925fc14680SDmitry Torokhov { 1935fc14680SDmitry Torokhov struct regs regs; 1945fc14680SDmitry Torokhov 1955fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 1965fc14680SDmitry Torokhov regs.eax = 0x9610; 1975fc14680SDmitry Torokhov regs.ebx = 0x051C; 1985fc14680SDmitry Torokhov call_bios(®s); 1995fc14680SDmitry Torokhov 2005fc14680SDmitry Torokhov return regs.ecx; 2015fc14680SDmitry Torokhov } 2025fc14680SDmitry Torokhov 203e7c3aad5SDmitry Torokhov static u16 __devinit bios_get_default_setting(u8 subsys) 2045fc14680SDmitry Torokhov { 2055fc14680SDmitry Torokhov struct regs regs; 2065fc14680SDmitry Torokhov 2075fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 2085fc14680SDmitry Torokhov regs.eax = 0x9610; 20984b256a6SBernhard Rosenkraenzer regs.ebx = 0x0200 | subsys; 2105fc14680SDmitry Torokhov call_bios(®s); 2115fc14680SDmitry Torokhov 2125fc14680SDmitry Torokhov return regs.eax; 2135fc14680SDmitry Torokhov } 2145fc14680SDmitry Torokhov 21584b256a6SBernhard Rosenkraenzer static void bios_set_state(u8 subsys, int enable) 2165fc14680SDmitry Torokhov { 2175fc14680SDmitry Torokhov struct regs regs; 2185fc14680SDmitry Torokhov 2195fc14680SDmitry Torokhov memset(®s, 0, sizeof (regs)); 2205fc14680SDmitry Torokhov regs.eax = 0x9610; 22184b256a6SBernhard Rosenkraenzer regs.ebx = (enable ? 0x0100 : 0x0000) | subsys; 2225fc14680SDmitry Torokhov call_bios(®s); 2235fc14680SDmitry Torokhov } 2245fc14680SDmitry Torokhov 2255fc14680SDmitry Torokhov /* Hardware database */ 2265fc14680SDmitry Torokhov 2275fc14680SDmitry Torokhov struct key_entry { 2285fc14680SDmitry Torokhov char type; /* See KE_* below */ 2295fc14680SDmitry Torokhov u8 code; 2306480e2a2SEric Piel union { 2316480e2a2SEric Piel u16 keycode; /* For KE_KEY */ 2326480e2a2SEric Piel struct { /* For KE_SW */ 2336480e2a2SEric Piel u8 code; 2346480e2a2SEric Piel u8 value; 2356480e2a2SEric Piel } sw; 2366480e2a2SEric Piel }; 2375fc14680SDmitry Torokhov }; 2385fc14680SDmitry Torokhov 2396480e2a2SEric Piel enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; 2406480e2a2SEric Piel 2416480e2a2SEric Piel #define FE_MAIL_LED 0x01 2426480e2a2SEric Piel #define FE_WIFI_LED 0x02 2436480e2a2SEric Piel #define FE_UNTESTED 0x80 2445fc14680SDmitry Torokhov 245d63219a1SDmitry Torokhov static struct key_entry *keymap; /* = NULL; Current key map */ 24667dbe83aSDmitry Torokhov static bool have_wifi; 24767dbe83aSDmitry Torokhov static bool have_bluetooth; 24867dbe83aSDmitry Torokhov static int leds_present; /* bitmask of leds present */ 2495fc14680SDmitry Torokhov 2501855256cSJeff Garzik static int __init dmi_matched(const struct dmi_system_id *dmi) 2515fc14680SDmitry Torokhov { 2525fc14680SDmitry Torokhov const struct key_entry *key; 2535fc14680SDmitry Torokhov 2545fc14680SDmitry Torokhov keymap = dmi->driver_data; 2555fc14680SDmitry Torokhov for (key = keymap; key->type != KE_END; key++) { 256cde45f19SReiner Herrmann if (key->type == KE_WIFI) 25767dbe83aSDmitry Torokhov have_wifi = true; 258cde45f19SReiner Herrmann else if (key->type == KE_BLUETOOTH) 25967dbe83aSDmitry Torokhov have_bluetooth = true; 2605fc14680SDmitry Torokhov } 26167dbe83aSDmitry Torokhov leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); 262389679d8SEric Piel 2635fc14680SDmitry Torokhov return 1; 2645fc14680SDmitry Torokhov } 2655fc14680SDmitry Torokhov 26655d29c98SEric Piel static struct key_entry keymap_empty[] __initdata = { 2675fc14680SDmitry Torokhov { KE_END, 0 } 2685fc14680SDmitry Torokhov }; 2695fc14680SDmitry Torokhov 27055d29c98SEric Piel static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { 2716480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 2726480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 2736480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 2746480e2a2SEric Piel { KE_WIFI, 0x30 }, 2756480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 2766480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 2775fc14680SDmitry Torokhov { KE_END, 0 } 2785fc14680SDmitry Torokhov }; 2795fc14680SDmitry Torokhov 28034a7c48cSRemi Herilier static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { 28134a7c48cSRemi Herilier { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ 28234a7c48cSRemi Herilier { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ 28334a7c48cSRemi Herilier { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ 28434a7c48cSRemi Herilier { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ 28534a7c48cSRemi Herilier { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ 28634a7c48cSRemi Herilier { KE_WIFI, 0x78 }, /* satelite dish button */ 28734a7c48cSRemi Herilier { KE_END, 0 } 28834a7c48cSRemi Herilier }; 28934a7c48cSRemi Herilier 29055d29c98SEric Piel static struct key_entry keymap_fujitsu_n3510[] __initdata = { 2916480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 2926480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 2936480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 2946480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 2956480e2a2SEric Piel { KE_KEY, 0x71, {KEY_STOPCD} }, 2966480e2a2SEric Piel { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, 2976480e2a2SEric Piel { KE_KEY, 0x74, {KEY_REWIND} }, 2986480e2a2SEric Piel { KE_KEY, 0x78, {KEY_FORWARD} }, 299e2aa507aSJohn Reed Riley { KE_END, 0 } 300e2aa507aSJohn Reed Riley }; 301e2aa507aSJohn Reed Riley 30255d29c98SEric Piel static struct key_entry keymap_wistron_ms2111[] __initdata = { 3036480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3046480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3056480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 3066480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3076480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3086480e2a2SEric Piel { KE_END, FE_MAIL_LED } 3096480e2a2SEric Piel }; 3106480e2a2SEric Piel 31155d29c98SEric Piel static struct key_entry keymap_wistron_md40100[] __initdata = { 3126480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3136480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 3146480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3156480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3166480e2a2SEric Piel { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 3176480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 3189000195bSFrank de Lange }; 3199000195bSFrank de Lange 32055d29c98SEric Piel static struct key_entry keymap_wistron_ms2141[] __initdata = { 3216480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3226480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3236480e2a2SEric Piel { KE_WIFI, 0x30 }, 3246480e2a2SEric Piel { KE_KEY, 0x22, {KEY_REWIND} }, 3256480e2a2SEric Piel { KE_KEY, 0x23, {KEY_FORWARD} }, 3266480e2a2SEric Piel { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 3276480e2a2SEric Piel { KE_KEY, 0x25, {KEY_STOPCD} }, 3286480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3296480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3305fc14680SDmitry Torokhov { KE_END, 0 } 3315fc14680SDmitry Torokhov }; 3325fc14680SDmitry Torokhov 33355d29c98SEric Piel static struct key_entry keymap_acer_aspire_1500[] __initdata = { 3346480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3356480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 3366480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3376480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3386480e2a2SEric Piel { KE_WIFI, 0x30 }, 3396480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3406480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3416480e2a2SEric Piel { KE_KEY, 0x49, {KEY_CONFIG} }, 3426480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 3436480e2a2SEric Piel { KE_END, FE_UNTESTED } 3446480e2a2SEric Piel }; 3456480e2a2SEric Piel 34655d29c98SEric Piel static struct key_entry keymap_acer_aspire_1600[] __initdata = { 3476480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3486480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 3496480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 3506480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3516480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3526480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 3536480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3546480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3556480e2a2SEric Piel { KE_KEY, 0x49, {KEY_CONFIG} }, 3566480e2a2SEric Piel { KE_WIFI, 0x30 }, 3576480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 3586480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 3596480e2a2SEric Piel }; 3606480e2a2SEric Piel 3616480e2a2SEric Piel /* 3020 has been tested */ 36255d29c98SEric Piel static struct key_entry keymap_acer_aspire_5020[] __initdata = { 3636480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3646480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 3656480e2a2SEric Piel { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 3666480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3676480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3686480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3696480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3706480e2a2SEric Piel { KE_KEY, 0x6a, {KEY_CONFIG} }, 3716480e2a2SEric Piel { KE_WIFI, 0x30 }, 3726480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 3736480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 3746480e2a2SEric Piel }; 3756480e2a2SEric Piel 37655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_2410[] __initdata = { 3776480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3786480e2a2SEric Piel { KE_KEY, 0x6d, {KEY_POWER} }, 3796480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3806480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3816480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3826480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 3836480e2a2SEric Piel { KE_KEY, 0x6a, {KEY_CONFIG} }, 3846480e2a2SEric Piel { KE_WIFI, 0x30 }, 3856480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 3866480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 3876480e2a2SEric Piel }; 3886480e2a2SEric Piel 38955d29c98SEric Piel static struct key_entry keymap_acer_travelmate_110[] __initdata = { 3906480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 3916480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 3926480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 3936480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 3946480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 3956480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 3966480e2a2SEric Piel { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 3976480e2a2SEric Piel { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 3986480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 3996480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 4006480e2a2SEric Piel { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ 4016480e2a2SEric Piel { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ 4026480e2a2SEric Piel { KE_WIFI, 0x30 }, 4036480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 4046480e2a2SEric Piel }; 4056480e2a2SEric Piel 40655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_300[] __initdata = { 4076480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4086480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4096480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 4106480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 4116480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4126480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4136480e2a2SEric Piel { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 4146480e2a2SEric Piel { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 4156480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 4166480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 4176480e2a2SEric Piel { KE_WIFI, 0x30 }, 4186480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 4196480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 4206480e2a2SEric Piel }; 4216480e2a2SEric Piel 42255d29c98SEric Piel static struct key_entry keymap_acer_travelmate_380[] __initdata = { 4236480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4246480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4256480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */ 4266480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4276480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4286480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 4296480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 4306480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 4316480e2a2SEric Piel { KE_WIFI, 0x30 }, 4326480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 4336480e2a2SEric Piel }; 4346480e2a2SEric Piel 4356480e2a2SEric Piel /* unusual map */ 43655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_220[] __initdata = { 4376480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4386480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4396480e2a2SEric Piel { KE_KEY, 0x11, {KEY_MAIL} }, 4406480e2a2SEric Piel { KE_KEY, 0x12, {KEY_WWW} }, 4416480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG2} }, 4426480e2a2SEric Piel { KE_KEY, 0x31, {KEY_PROG1} }, 4436480e2a2SEric Piel { KE_END, FE_WIFI_LED | FE_UNTESTED } 4446480e2a2SEric Piel }; 4456480e2a2SEric Piel 44655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_230[] __initdata = { 4476480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4486480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4496480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4506480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4516480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 4526480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 4536480e2a2SEric Piel { KE_END, FE_WIFI_LED | FE_UNTESTED } 45484b256a6SBernhard Rosenkraenzer }; 45584b256a6SBernhard Rosenkraenzer 45655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_240[] __initdata = { 4576480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4586480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4596480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 4606480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 4616480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 4626480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 4636480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4646480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4656480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 4666480e2a2SEric Piel { KE_WIFI, 0x30 }, 4676480e2a2SEric Piel { KE_END, FE_UNTESTED } 4686480e2a2SEric Piel }; 4696480e2a2SEric Piel 47055d29c98SEric Piel static struct key_entry keymap_acer_travelmate_350[] __initdata = { 4716480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4726480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4736480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4746480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4756480e2a2SEric Piel { KE_KEY, 0x13, {KEY_MAIL} }, 4766480e2a2SEric Piel { KE_KEY, 0x14, {KEY_PROG3} }, 4776480e2a2SEric Piel { KE_KEY, 0x15, {KEY_WWW} }, 4786480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 4796480e2a2SEric Piel }; 4806480e2a2SEric Piel 48155d29c98SEric Piel static struct key_entry keymap_acer_travelmate_360[] __initdata = { 4826480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4836480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4846480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 4856480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 4866480e2a2SEric Piel { KE_KEY, 0x13, {KEY_MAIL} }, 4876480e2a2SEric Piel { KE_KEY, 0x14, {KEY_PROG3} }, 4886480e2a2SEric Piel { KE_KEY, 0x15, {KEY_WWW} }, 4896480e2a2SEric Piel { KE_KEY, 0x40, {KEY_WLAN} }, 4906480e2a2SEric Piel { KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */ 49174a89c96SAshutosh Naik }; 49274a89c96SAshutosh Naik 493bc413c95SEric Piel /* Wifi subsystem only activates the led. Therefore we need to pass 494bc413c95SEric Piel * wifi event as a normal key, then userspace can really change the wifi state. 495bc413c95SEric Piel * TODO we need to export led state to userspace (wifi and mail) */ 49655d29c98SEric Piel static struct key_entry keymap_acer_travelmate_610[] __initdata = { 4976480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 4986480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 4996480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 500fd013ce8SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5016480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 5026480e2a2SEric Piel { KE_KEY, 0x14, {KEY_MAIL} }, 5036480e2a2SEric Piel { KE_KEY, 0x15, {KEY_WWW} }, 5046480e2a2SEric Piel { KE_KEY, 0x40, {KEY_WLAN} }, 5056480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_WIFI_LED } 5066480e2a2SEric Piel }; 5076480e2a2SEric Piel 50855d29c98SEric Piel static struct key_entry keymap_acer_travelmate_630[] __initdata = { 5096480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5106480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 5116480e2a2SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 5126480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */ 5136480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5146480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5156480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 5166480e2a2SEric Piel { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 5176480e2a2SEric Piel { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 5186480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5196480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5206480e2a2SEric Piel { KE_WIFI, 0x30 }, 5216480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 522bc413c95SEric Piel }; 523bc413c95SEric Piel 52455d29c98SEric Piel static struct key_entry keymap_aopen_1559as[] __initdata = { 5256480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5266480e2a2SEric Piel { KE_KEY, 0x06, {KEY_PROG3} }, 5276480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5286480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5296480e2a2SEric Piel { KE_WIFI, 0x30 }, 5306480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5316480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5329000195bSFrank de Lange { KE_END, 0 }, 533e107b8eeSmasc@theaterzentrum.at }; 534e107b8eeSmasc@theaterzentrum.at 53555d29c98SEric Piel static struct key_entry keymap_fs_amilo_d88x0[] __initdata = { 5366480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5376480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 5386480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5396480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5406480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5416480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5426480e2a2SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 5436480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 5446480e2a2SEric Piel }; 5456480e2a2SEric Piel 54655d29c98SEric Piel static struct key_entry keymap_wistron_md2900[] __initdata = { 5476480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5486480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 5496480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5506480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5516480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5526480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5536480e2a2SEric Piel { KE_WIFI, 0x30 }, 5546480e2a2SEric Piel { KE_END, FE_MAIL_LED | FE_UNTESTED } 5556480e2a2SEric Piel }; 5566480e2a2SEric Piel 55755d29c98SEric Piel static struct key_entry keymap_wistron_md96500[] __initdata = { 5586480e2a2SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5596480e2a2SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 5606480e2a2SEric Piel { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 5616480e2a2SEric Piel { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 5626480e2a2SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 5636480e2a2SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5646480e2a2SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5656480e2a2SEric Piel { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 5666480e2a2SEric Piel { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 5676480e2a2SEric Piel { KE_KEY, 0x22, {KEY_REWIND} }, 5686480e2a2SEric Piel { KE_KEY, 0x23, {KEY_FORWARD} }, 5696480e2a2SEric Piel { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 5706480e2a2SEric Piel { KE_KEY, 0x25, {KEY_STOPCD} }, 5716480e2a2SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5726480e2a2SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5736480e2a2SEric Piel { KE_WIFI, 0x30 }, 5746480e2a2SEric Piel { KE_BLUETOOTH, 0x44 }, 5756480e2a2SEric Piel { KE_END, FE_UNTESTED } 5765809d537SMichael Leun }; 5775809d537SMichael Leun 57855d29c98SEric Piel static struct key_entry keymap_wistron_generic[] __initdata = { 5797b0a4cd7SEric Piel { KE_KEY, 0x01, {KEY_HELP} }, 5807b0a4cd7SEric Piel { KE_KEY, 0x02, {KEY_CONFIG} }, 5817b0a4cd7SEric Piel { KE_KEY, 0x03, {KEY_POWER} }, 5827b0a4cd7SEric Piel { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 5837b0a4cd7SEric Piel { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 5847b0a4cd7SEric Piel { KE_KEY, 0x08, {KEY_MUTE} }, 5857b0a4cd7SEric Piel { KE_KEY, 0x11, {KEY_PROG1} }, 5867b0a4cd7SEric Piel { KE_KEY, 0x12, {KEY_PROG2} }, 5877b0a4cd7SEric Piel { KE_KEY, 0x13, {KEY_PROG3} }, 5887b0a4cd7SEric Piel { KE_KEY, 0x14, {KEY_MAIL} }, 5897b0a4cd7SEric Piel { KE_KEY, 0x15, {KEY_WWW} }, 5907b0a4cd7SEric Piel { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 5917b0a4cd7SEric Piel { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 5927b0a4cd7SEric Piel { KE_KEY, 0x22, {KEY_REWIND} }, 5937b0a4cd7SEric Piel { KE_KEY, 0x23, {KEY_FORWARD} }, 5947b0a4cd7SEric Piel { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 5957b0a4cd7SEric Piel { KE_KEY, 0x25, {KEY_STOPCD} }, 5967b0a4cd7SEric Piel { KE_KEY, 0x31, {KEY_MAIL} }, 5977b0a4cd7SEric Piel { KE_KEY, 0x36, {KEY_WWW} }, 5987b0a4cd7SEric Piel { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 5997b0a4cd7SEric Piel { KE_KEY, 0x40, {KEY_WLAN} }, 6007b0a4cd7SEric Piel { KE_KEY, 0x49, {KEY_CONFIG} }, 6017b0a4cd7SEric Piel { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ 6027b0a4cd7SEric Piel { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ 6037b0a4cd7SEric Piel { KE_KEY, 0x6a, {KEY_CONFIG} }, 6047b0a4cd7SEric Piel { KE_KEY, 0x6d, {KEY_POWER} }, 6057b0a4cd7SEric Piel { KE_KEY, 0x71, {KEY_STOPCD} }, 6067b0a4cd7SEric Piel { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, 6077b0a4cd7SEric Piel { KE_KEY, 0x74, {KEY_REWIND} }, 6087b0a4cd7SEric Piel { KE_KEY, 0x78, {KEY_FORWARD} }, 6097b0a4cd7SEric Piel { KE_WIFI, 0x30 }, 6107b0a4cd7SEric Piel { KE_BLUETOOTH, 0x44 }, 6117b0a4cd7SEric Piel { KE_END, 0 } 6127b0a4cd7SEric Piel }; 6137b0a4cd7SEric Piel 61485927b0dSDmitry Torokhov static struct key_entry keymap_aopen_1557[] __initdata = { 61585927b0dSDmitry Torokhov { KE_KEY, 0x01, {KEY_HELP} }, 61685927b0dSDmitry Torokhov { KE_KEY, 0x11, {KEY_PROG1} }, 61785927b0dSDmitry Torokhov { KE_KEY, 0x12, {KEY_PROG2} }, 61885927b0dSDmitry Torokhov { KE_WIFI, 0x30 }, 61985927b0dSDmitry Torokhov { KE_KEY, 0x22, {KEY_REWIND} }, 62085927b0dSDmitry Torokhov { KE_KEY, 0x23, {KEY_FORWARD} }, 62185927b0dSDmitry Torokhov { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 62285927b0dSDmitry Torokhov { KE_KEY, 0x25, {KEY_STOPCD} }, 62385927b0dSDmitry Torokhov { KE_KEY, 0x31, {KEY_MAIL} }, 62485927b0dSDmitry Torokhov { KE_KEY, 0x36, {KEY_WWW} }, 62585927b0dSDmitry Torokhov { KE_END, 0 } 62685927b0dSDmitry Torokhov }; 62785927b0dSDmitry Torokhov 62819493478STJ static struct key_entry keymap_prestigio[] __initdata = { 62919493478STJ { KE_KEY, 0x11, {KEY_PROG1} }, 63019493478STJ { KE_KEY, 0x12, {KEY_PROG2} }, 63119493478STJ { KE_WIFI, 0x30 }, 63219493478STJ { KE_KEY, 0x22, {KEY_REWIND} }, 63319493478STJ { KE_KEY, 0x23, {KEY_FORWARD} }, 63419493478STJ { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 63519493478STJ { KE_KEY, 0x25, {KEY_STOPCD} }, 63619493478STJ { KE_KEY, 0x31, {KEY_MAIL} }, 63719493478STJ { KE_KEY, 0x36, {KEY_WWW} }, 63819493478STJ { KE_END, 0 } 63919493478STJ }; 64019493478STJ 64119493478STJ 6425fc14680SDmitry Torokhov /* 6435fc14680SDmitry Torokhov * If your machine is not here (which is currently rather likely), please send 6445fc14680SDmitry Torokhov * a list of buttons and their key codes (reported when loading this module 6455fc14680SDmitry Torokhov * with force=1) and the output of dmidecode to $MODULE_AUTHOR. 6465fc14680SDmitry Torokhov */ 647c7948989SAndrew Morton static struct dmi_system_id dmi_ids[] __initdata = { 6485fc14680SDmitry Torokhov { 6495fc14680SDmitry Torokhov .callback = dmi_matched, 6505fc14680SDmitry Torokhov .ident = "Fujitsu-Siemens Amilo Pro V2000", 6515fc14680SDmitry Torokhov .matches = { 6525fc14680SDmitry Torokhov DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 6535fc14680SDmitry Torokhov DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), 6545fc14680SDmitry Torokhov }, 6555fc14680SDmitry Torokhov .driver_data = keymap_fs_amilo_pro_v2000 6565fc14680SDmitry Torokhov }, 65784b256a6SBernhard Rosenkraenzer { 65884b256a6SBernhard Rosenkraenzer .callback = dmi_matched, 65934a7c48cSRemi Herilier .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", 66034a7c48cSRemi Herilier .matches = { 66134a7c48cSRemi Herilier DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 66234a7c48cSRemi Herilier DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), 66334a7c48cSRemi Herilier }, 66434a7c48cSRemi Herilier .driver_data = keymap_fs_amilo_pro_v3505 66534a7c48cSRemi Herilier }, 66634a7c48cSRemi Herilier { 66734a7c48cSRemi Herilier .callback = dmi_matched, 6688a1b1708SStefan Rompf .ident = "Fujitsu-Siemens Amilo M7400", 6698a1b1708SStefan Rompf .matches = { 6708a1b1708SStefan Rompf DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 6718a1b1708SStefan Rompf DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), 6728a1b1708SStefan Rompf }, 6738a1b1708SStefan Rompf .driver_data = keymap_fs_amilo_pro_v2000 6748a1b1708SStefan Rompf }, 6758a1b1708SStefan Rompf { 6768a1b1708SStefan Rompf .callback = dmi_matched, 677e705cee4SGiuseppe Mazzotta .ident = "Maxdata Pro 7000 DX", 678e705cee4SGiuseppe Mazzotta .matches = { 679e705cee4SGiuseppe Mazzotta DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), 680e705cee4SGiuseppe Mazzotta DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), 681e705cee4SGiuseppe Mazzotta }, 682e705cee4SGiuseppe Mazzotta .driver_data = keymap_fs_amilo_pro_v2000 683e705cee4SGiuseppe Mazzotta }, 684e705cee4SGiuseppe Mazzotta { 685e705cee4SGiuseppe Mazzotta .callback = dmi_matched, 686e2aa507aSJohn Reed Riley .ident = "Fujitsu N3510", 687e2aa507aSJohn Reed Riley .matches = { 688e2aa507aSJohn Reed Riley DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 689e2aa507aSJohn Reed Riley DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), 690e2aa507aSJohn Reed Riley }, 691e2aa507aSJohn Reed Riley .driver_data = keymap_fujitsu_n3510 692e2aa507aSJohn Reed Riley }, 693e2aa507aSJohn Reed Riley { 694e2aa507aSJohn Reed Riley .callback = dmi_matched, 69584b256a6SBernhard Rosenkraenzer .ident = "Acer Aspire 1500", 69684b256a6SBernhard Rosenkraenzer .matches = { 69784b256a6SBernhard Rosenkraenzer DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 69884b256a6SBernhard Rosenkraenzer DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), 69984b256a6SBernhard Rosenkraenzer }, 70084b256a6SBernhard Rosenkraenzer .driver_data = keymap_acer_aspire_1500 70184b256a6SBernhard Rosenkraenzer }, 70274a89c96SAshutosh Naik { 70374a89c96SAshutosh Naik .callback = dmi_matched, 7046480e2a2SEric Piel .ident = "Acer Aspire 1600", 7056480e2a2SEric Piel .matches = { 7066480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7076480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), 7086480e2a2SEric Piel }, 7096480e2a2SEric Piel .driver_data = keymap_acer_aspire_1600 7106480e2a2SEric Piel }, 7116480e2a2SEric Piel { 7126480e2a2SEric Piel .callback = dmi_matched, 7136480e2a2SEric Piel .ident = "Acer Aspire 3020", 7146480e2a2SEric Piel .matches = { 7156480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7166480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), 7176480e2a2SEric Piel }, 7186480e2a2SEric Piel .driver_data = keymap_acer_aspire_5020 7196480e2a2SEric Piel }, 7206480e2a2SEric Piel { 7216480e2a2SEric Piel .callback = dmi_matched, 7226480e2a2SEric Piel .ident = "Acer Aspire 5020", 7236480e2a2SEric Piel .matches = { 7246480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7256480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), 7266480e2a2SEric Piel }, 7276480e2a2SEric Piel .driver_data = keymap_acer_aspire_5020 7286480e2a2SEric Piel }, 7296480e2a2SEric Piel { 7306480e2a2SEric Piel .callback = dmi_matched, 7316480e2a2SEric Piel .ident = "Acer TravelMate 2100", 7326480e2a2SEric Piel .matches = { 7336480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7346480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), 7356480e2a2SEric Piel }, 7366480e2a2SEric Piel .driver_data = keymap_acer_aspire_5020 7376480e2a2SEric Piel }, 7386480e2a2SEric Piel { 7396480e2a2SEric Piel .callback = dmi_matched, 7406480e2a2SEric Piel .ident = "Acer TravelMate 2410", 7416480e2a2SEric Piel .matches = { 7426480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7436480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), 7446480e2a2SEric Piel }, 7456480e2a2SEric Piel .driver_data = keymap_acer_travelmate_2410 7466480e2a2SEric Piel }, 7476480e2a2SEric Piel { 7486480e2a2SEric Piel .callback = dmi_matched, 7496480e2a2SEric Piel .ident = "Acer TravelMate C300", 7506480e2a2SEric Piel .matches = { 7516480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7526480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), 7536480e2a2SEric Piel }, 7546480e2a2SEric Piel .driver_data = keymap_acer_travelmate_300 7556480e2a2SEric Piel }, 7566480e2a2SEric Piel { 7576480e2a2SEric Piel .callback = dmi_matched, 7586480e2a2SEric Piel .ident = "Acer TravelMate C100", 7596480e2a2SEric Piel .matches = { 7606480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7616480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), 7626480e2a2SEric Piel }, 7636480e2a2SEric Piel .driver_data = keymap_acer_travelmate_300 7646480e2a2SEric Piel }, 7656480e2a2SEric Piel { 7666480e2a2SEric Piel .callback = dmi_matched, 7676480e2a2SEric Piel .ident = "Acer TravelMate C110", 7686480e2a2SEric Piel .matches = { 7696480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7706480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), 7716480e2a2SEric Piel }, 7726480e2a2SEric Piel .driver_data = keymap_acer_travelmate_110 7736480e2a2SEric Piel }, 7746480e2a2SEric Piel { 7756480e2a2SEric Piel .callback = dmi_matched, 7766480e2a2SEric Piel .ident = "Acer TravelMate 380", 7776480e2a2SEric Piel .matches = { 7786480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7796480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), 7806480e2a2SEric Piel }, 7816480e2a2SEric Piel .driver_data = keymap_acer_travelmate_380 7826480e2a2SEric Piel }, 7836480e2a2SEric Piel { 7846480e2a2SEric Piel .callback = dmi_matched, 7856480e2a2SEric Piel .ident = "Acer TravelMate 370", 7866480e2a2SEric Piel .matches = { 7876480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7886480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), 7896480e2a2SEric Piel }, 7906480e2a2SEric Piel .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ 7916480e2a2SEric Piel }, 7926480e2a2SEric Piel { 7936480e2a2SEric Piel .callback = dmi_matched, 7946480e2a2SEric Piel .ident = "Acer TravelMate 220", 7956480e2a2SEric Piel .matches = { 7966480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 7976480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), 7986480e2a2SEric Piel }, 7996480e2a2SEric Piel .driver_data = keymap_acer_travelmate_220 8006480e2a2SEric Piel }, 8016480e2a2SEric Piel { 8026480e2a2SEric Piel .callback = dmi_matched, 8036480e2a2SEric Piel .ident = "Acer TravelMate 260", 8046480e2a2SEric Piel .matches = { 8056480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8066480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), 8076480e2a2SEric Piel }, 8086480e2a2SEric Piel .driver_data = keymap_acer_travelmate_220 8096480e2a2SEric Piel }, 8106480e2a2SEric Piel { 8116480e2a2SEric Piel .callback = dmi_matched, 8126480e2a2SEric Piel .ident = "Acer TravelMate 230", 8136480e2a2SEric Piel .matches = { 8146480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8156480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), 8166480e2a2SEric Piel /* acerhk looks for "TravelMate F4..." ?! */ 8176480e2a2SEric Piel }, 8186480e2a2SEric Piel .driver_data = keymap_acer_travelmate_230 8196480e2a2SEric Piel }, 8206480e2a2SEric Piel { 8216480e2a2SEric Piel .callback = dmi_matched, 8226480e2a2SEric Piel .ident = "Acer TravelMate 280", 8236480e2a2SEric Piel .matches = { 8246480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8256480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), 8266480e2a2SEric Piel }, 8276480e2a2SEric Piel .driver_data = keymap_acer_travelmate_230 8286480e2a2SEric Piel }, 8296480e2a2SEric Piel { 8306480e2a2SEric Piel .callback = dmi_matched, 83174a89c96SAshutosh Naik .ident = "Acer TravelMate 240", 83274a89c96SAshutosh Naik .matches = { 83374a89c96SAshutosh Naik DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 83474a89c96SAshutosh Naik DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), 83574a89c96SAshutosh Naik }, 83674a89c96SAshutosh Naik .driver_data = keymap_acer_travelmate_240 83774a89c96SAshutosh Naik }, 838e107b8eeSmasc@theaterzentrum.at { 839bb088590SAshutosh Naik .callback = dmi_matched, 8406480e2a2SEric Piel .ident = "Acer TravelMate 250", 8416480e2a2SEric Piel .matches = { 8426480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8436480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), 8446480e2a2SEric Piel }, 8456480e2a2SEric Piel .driver_data = keymap_acer_travelmate_240 8466480e2a2SEric Piel }, 8476480e2a2SEric Piel { 8486480e2a2SEric Piel .callback = dmi_matched, 849bb088590SAshutosh Naik .ident = "Acer TravelMate 2424NWXCi", 850bb088590SAshutosh Naik .matches = { 851bb088590SAshutosh Naik DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 852bb088590SAshutosh Naik DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), 853bb088590SAshutosh Naik }, 854bb088590SAshutosh Naik .driver_data = keymap_acer_travelmate_240 855bb088590SAshutosh Naik }, 856bb088590SAshutosh Naik { 857e107b8eeSmasc@theaterzentrum.at .callback = dmi_matched, 8586480e2a2SEric Piel .ident = "Acer TravelMate 350", 8596480e2a2SEric Piel .matches = { 8606480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8616480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), 8626480e2a2SEric Piel }, 8636480e2a2SEric Piel .driver_data = keymap_acer_travelmate_350 8646480e2a2SEric Piel }, 8656480e2a2SEric Piel { 8666480e2a2SEric Piel .callback = dmi_matched, 8676480e2a2SEric Piel .ident = "Acer TravelMate 360", 8686480e2a2SEric Piel .matches = { 8696480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8706480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), 8716480e2a2SEric Piel }, 8726480e2a2SEric Piel .driver_data = keymap_acer_travelmate_360 8736480e2a2SEric Piel }, 8746480e2a2SEric Piel { 8756480e2a2SEric Piel .callback = dmi_matched, 876bc413c95SEric Piel .ident = "Acer TravelMate 610", 877bc413c95SEric Piel .matches = { 878bc413c95SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "ACER"), 879bc413c95SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), 880bc413c95SEric Piel }, 881bc413c95SEric Piel .driver_data = keymap_acer_travelmate_610 882bc413c95SEric Piel }, 883bc413c95SEric Piel { 884bc413c95SEric Piel .callback = dmi_matched, 8856480e2a2SEric Piel .ident = "Acer TravelMate 620", 8866480e2a2SEric Piel .matches = { 8876480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8886480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), 8896480e2a2SEric Piel }, 8906480e2a2SEric Piel .driver_data = keymap_acer_travelmate_630 8916480e2a2SEric Piel }, 8926480e2a2SEric Piel { 8936480e2a2SEric Piel .callback = dmi_matched, 8946480e2a2SEric Piel .ident = "Acer TravelMate 630", 8956480e2a2SEric Piel .matches = { 8966480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 8976480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), 8986480e2a2SEric Piel }, 8996480e2a2SEric Piel .driver_data = keymap_acer_travelmate_630 9006480e2a2SEric Piel }, 9016480e2a2SEric Piel { 9026480e2a2SEric Piel .callback = dmi_matched, 903e107b8eeSmasc@theaterzentrum.at .ident = "AOpen 1559AS", 904e107b8eeSmasc@theaterzentrum.at .matches = { 905e107b8eeSmasc@theaterzentrum.at DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), 906e107b8eeSmasc@theaterzentrum.at DMI_MATCH(DMI_BOARD_NAME, "E2U"), 907e107b8eeSmasc@theaterzentrum.at }, 908e107b8eeSmasc@theaterzentrum.at .driver_data = keymap_aopen_1559as 909e107b8eeSmasc@theaterzentrum.at }, 9109000195bSFrank de Lange { 9119000195bSFrank de Lange .callback = dmi_matched, 9129000195bSFrank de Lange .ident = "Medion MD 9783", 9139000195bSFrank de Lange .matches = { 9149000195bSFrank de Lange DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 9159000195bSFrank de Lange DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), 9169000195bSFrank de Lange }, 9179000195bSFrank de Lange .driver_data = keymap_wistron_ms2111 9189000195bSFrank de Lange }, 9195809d537SMichael Leun { 9205809d537SMichael Leun .callback = dmi_matched, 9216480e2a2SEric Piel .ident = "Medion MD 40100", 9226480e2a2SEric Piel .matches = { 9236480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 9246480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), 9256480e2a2SEric Piel }, 9266480e2a2SEric Piel .driver_data = keymap_wistron_md40100 9276480e2a2SEric Piel }, 9286480e2a2SEric Piel { 9296480e2a2SEric Piel .callback = dmi_matched, 9306480e2a2SEric Piel .ident = "Medion MD 2900", 9316480e2a2SEric Piel .matches = { 9326480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 9336480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), 9346480e2a2SEric Piel }, 9356480e2a2SEric Piel .driver_data = keymap_wistron_md2900 9366480e2a2SEric Piel }, 9376480e2a2SEric Piel { 9386480e2a2SEric Piel .callback = dmi_matched, 9393bfb0a7eSSebastian Frei .ident = "Medion MD 42200", 9403bfb0a7eSSebastian Frei .matches = { 9413bfb0a7eSSebastian Frei DMI_MATCH(DMI_SYS_VENDOR, "Medion"), 9423bfb0a7eSSebastian Frei DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), 9433bfb0a7eSSebastian Frei }, 9443bfb0a7eSSebastian Frei .driver_data = keymap_fs_amilo_pro_v2000 9453bfb0a7eSSebastian Frei }, 9463bfb0a7eSSebastian Frei { 9473bfb0a7eSSebastian Frei .callback = dmi_matched, 9486480e2a2SEric Piel .ident = "Medion MD 96500", 9496480e2a2SEric Piel .matches = { 9506480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 9516480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), 9526480e2a2SEric Piel }, 9536480e2a2SEric Piel .driver_data = keymap_wistron_md96500 9546480e2a2SEric Piel }, 9556480e2a2SEric Piel { 9566480e2a2SEric Piel .callback = dmi_matched, 9576480e2a2SEric Piel .ident = "Medion MD 95400", 9586480e2a2SEric Piel .matches = { 9596480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 9606480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), 9616480e2a2SEric Piel }, 9626480e2a2SEric Piel .driver_data = keymap_wistron_md96500 9636480e2a2SEric Piel }, 9646480e2a2SEric Piel { 9656480e2a2SEric Piel .callback = dmi_matched, 9666480e2a2SEric Piel .ident = "Fujitsu Siemens Amilo D7820", 9676480e2a2SEric Piel .matches = { 9686480e2a2SEric Piel DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ 9696480e2a2SEric Piel DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), 9706480e2a2SEric Piel }, 9716480e2a2SEric Piel .driver_data = keymap_fs_amilo_d88x0 9726480e2a2SEric Piel }, 9736480e2a2SEric Piel { 9746480e2a2SEric Piel .callback = dmi_matched, 9755809d537SMichael Leun .ident = "Fujitsu Siemens Amilo D88x0", 9765809d537SMichael Leun .matches = { 9775809d537SMichael Leun DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 9785809d537SMichael Leun DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), 9795809d537SMichael Leun }, 9805809d537SMichael Leun .driver_data = keymap_fs_amilo_d88x0 9815809d537SMichael Leun }, 98281f0a91eSAl Viro { NULL, } 9835fc14680SDmitry Torokhov }; 9845fc14680SDmitry Torokhov 98555d29c98SEric Piel /* Copy the good keymap, as the original ones are free'd */ 98655d29c98SEric Piel static int __init copy_keymap(void) 98755d29c98SEric Piel { 98855d29c98SEric Piel const struct key_entry *key; 98955d29c98SEric Piel struct key_entry *new_keymap; 99055d29c98SEric Piel unsigned int length = 1; 99155d29c98SEric Piel 99255d29c98SEric Piel for (key = keymap; key->type != KE_END; key++) 99355d29c98SEric Piel length++; 99455d29c98SEric Piel 99555d29c98SEric Piel new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); 99655d29c98SEric Piel if (!new_keymap) 99755d29c98SEric Piel return -ENOMEM; 99855d29c98SEric Piel 99955d29c98SEric Piel memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); 100055d29c98SEric Piel keymap = new_keymap; 100155d29c98SEric Piel 100255d29c98SEric Piel return 0; 100355d29c98SEric Piel } 100455d29c98SEric Piel 10055fc14680SDmitry Torokhov static int __init select_keymap(void) 10065fc14680SDmitry Torokhov { 10077b0a4cd7SEric Piel dmi_check_system(dmi_ids); 10085fc14680SDmitry Torokhov if (keymap_name != NULL) { 10095fc14680SDmitry Torokhov if (strcmp (keymap_name, "1557/MS2141") == 0) 10105fc14680SDmitry Torokhov keymap = keymap_wistron_ms2141; 101185927b0dSDmitry Torokhov else if (strcmp (keymap_name, "aopen1557") == 0) 101285927b0dSDmitry Torokhov keymap = keymap_aopen_1557; 101319493478STJ else if (strcmp (keymap_name, "prestigio") == 0) 101419493478STJ keymap = keymap_prestigio; 10157b0a4cd7SEric Piel else if (strcmp (keymap_name, "generic") == 0) 10167b0a4cd7SEric Piel keymap = keymap_wistron_generic; 10175fc14680SDmitry Torokhov else { 10185fc14680SDmitry Torokhov printk(KERN_ERR "wistron_btns: Keymap unknown\n"); 10195fc14680SDmitry Torokhov return -EINVAL; 10205fc14680SDmitry Torokhov } 10215fc14680SDmitry Torokhov } 10225fc14680SDmitry Torokhov if (keymap == NULL) { 10235fc14680SDmitry Torokhov if (!force) { 10245fc14680SDmitry Torokhov printk(KERN_ERR "wistron_btns: System unknown\n"); 10255fc14680SDmitry Torokhov return -ENODEV; 10265fc14680SDmitry Torokhov } 10275fc14680SDmitry Torokhov keymap = keymap_empty; 10285fc14680SDmitry Torokhov } 102955d29c98SEric Piel 103055d29c98SEric Piel return copy_keymap(); 10315fc14680SDmitry Torokhov } 10325fc14680SDmitry Torokhov 10335fc14680SDmitry Torokhov /* Input layer interface */ 10345fc14680SDmitry Torokhov 1035c2554c91SDmitry Torokhov static struct input_polled_dev *wistron_idev; 1036c2554c91SDmitry Torokhov static unsigned long jiffies_last_press; 103767dbe83aSDmitry Torokhov static bool wifi_enabled; 103867dbe83aSDmitry Torokhov static bool bluetooth_enabled; 10395fc14680SDmitry Torokhov 1040c2554c91SDmitry Torokhov static void report_key(struct input_dev *dev, unsigned int keycode) 10415fc14680SDmitry Torokhov { 1042c2554c91SDmitry Torokhov input_report_key(dev, keycode, 1); 1043c2554c91SDmitry Torokhov input_sync(dev); 1044c2554c91SDmitry Torokhov input_report_key(dev, keycode, 0); 1045c2554c91SDmitry Torokhov input_sync(dev); 10465fc14680SDmitry Torokhov } 10475fc14680SDmitry Torokhov 1048c2554c91SDmitry Torokhov static void report_switch(struct input_dev *dev, unsigned int code, int value) 10495fc14680SDmitry Torokhov { 1050c2554c91SDmitry Torokhov input_report_switch(dev, code, value); 1051c2554c91SDmitry Torokhov input_sync(dev); 10526480e2a2SEric Piel } 10536480e2a2SEric Piel 1054389679d8SEric Piel 1055389679d8SEric Piel /* led management */ 1056389679d8SEric Piel static void wistron_mail_led_set(struct led_classdev *led_cdev, 1057389679d8SEric Piel enum led_brightness value) 1058389679d8SEric Piel { 1059389679d8SEric Piel bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); 1060389679d8SEric Piel } 1061389679d8SEric Piel 1062389679d8SEric Piel /* same as setting up wifi card, but for laptops on which the led is managed */ 1063389679d8SEric Piel static void wistron_wifi_led_set(struct led_classdev *led_cdev, 1064389679d8SEric Piel enum led_brightness value) 1065389679d8SEric Piel { 1066389679d8SEric Piel bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); 1067389679d8SEric Piel } 1068389679d8SEric Piel 1069389679d8SEric Piel static struct led_classdev wistron_mail_led = { 10706c152beeSRichard Purdie .name = "wistron:green:mail", 1071389679d8SEric Piel .brightness_set = wistron_mail_led_set, 1072389679d8SEric Piel }; 1073389679d8SEric Piel 1074389679d8SEric Piel static struct led_classdev wistron_wifi_led = { 10756c152beeSRichard Purdie .name = "wistron:red:wifi", 1076389679d8SEric Piel .brightness_set = wistron_wifi_led_set, 1077389679d8SEric Piel }; 1078389679d8SEric Piel 1079389679d8SEric Piel static void __devinit wistron_led_init(struct device *parent) 1080389679d8SEric Piel { 108167dbe83aSDmitry Torokhov if (leds_present & FE_WIFI_LED) { 1082389679d8SEric Piel u16 wifi = bios_get_default_setting(WIFI); 1083389679d8SEric Piel if (wifi & 1) { 1084389679d8SEric Piel wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; 1085389679d8SEric Piel if (led_classdev_register(parent, &wistron_wifi_led)) 108667dbe83aSDmitry Torokhov leds_present &= ~FE_WIFI_LED; 1087389679d8SEric Piel else 1088389679d8SEric Piel bios_set_state(WIFI, wistron_wifi_led.brightness); 1089389679d8SEric Piel 1090389679d8SEric Piel } else 109167dbe83aSDmitry Torokhov leds_present &= ~FE_WIFI_LED; 1092389679d8SEric Piel } 1093389679d8SEric Piel 109467dbe83aSDmitry Torokhov if (leds_present & FE_MAIL_LED) { 1095389679d8SEric Piel /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ 1096389679d8SEric Piel wistron_mail_led.brightness = LED_OFF; 1097389679d8SEric Piel if (led_classdev_register(parent, &wistron_mail_led)) 109867dbe83aSDmitry Torokhov leds_present &= ~FE_MAIL_LED; 1099389679d8SEric Piel else 1100389679d8SEric Piel bios_set_state(MAIL_LED, wistron_mail_led.brightness); 1101389679d8SEric Piel } 1102389679d8SEric Piel } 1103389679d8SEric Piel 1104389679d8SEric Piel static void __devexit wistron_led_remove(void) 1105389679d8SEric Piel { 110667dbe83aSDmitry Torokhov if (leds_present & FE_MAIL_LED) 1107389679d8SEric Piel led_classdev_unregister(&wistron_mail_led); 1108389679d8SEric Piel 110967dbe83aSDmitry Torokhov if (leds_present & FE_WIFI_LED) 1110389679d8SEric Piel led_classdev_unregister(&wistron_wifi_led); 1111389679d8SEric Piel } 1112389679d8SEric Piel 1113389679d8SEric Piel static inline void wistron_led_suspend(void) 1114389679d8SEric Piel { 111567dbe83aSDmitry Torokhov if (leds_present & FE_MAIL_LED) 1116389679d8SEric Piel led_classdev_suspend(&wistron_mail_led); 1117389679d8SEric Piel 111867dbe83aSDmitry Torokhov if (leds_present & FE_WIFI_LED) 1119389679d8SEric Piel led_classdev_suspend(&wistron_wifi_led); 1120389679d8SEric Piel } 1121389679d8SEric Piel 1122389679d8SEric Piel static inline void wistron_led_resume(void) 1123389679d8SEric Piel { 112467dbe83aSDmitry Torokhov if (leds_present & FE_MAIL_LED) 1125389679d8SEric Piel led_classdev_resume(&wistron_mail_led); 1126389679d8SEric Piel 112767dbe83aSDmitry Torokhov if (leds_present & FE_WIFI_LED) 1128389679d8SEric Piel led_classdev_resume(&wistron_wifi_led); 1129389679d8SEric Piel } 1130389679d8SEric Piel 1131d63219a1SDmitry Torokhov static struct key_entry *wistron_get_entry_by_scancode(int code) 1132d63219a1SDmitry Torokhov { 1133d63219a1SDmitry Torokhov struct key_entry *key; 1134d63219a1SDmitry Torokhov 1135d63219a1SDmitry Torokhov for (key = keymap; key->type != KE_END; key++) 1136d63219a1SDmitry Torokhov if (code == key->code) 1137d63219a1SDmitry Torokhov return key; 1138d63219a1SDmitry Torokhov 1139d63219a1SDmitry Torokhov return NULL; 1140d63219a1SDmitry Torokhov } 1141d63219a1SDmitry Torokhov 1142d63219a1SDmitry Torokhov static struct key_entry *wistron_get_entry_by_keycode(int keycode) 1143d63219a1SDmitry Torokhov { 1144d63219a1SDmitry Torokhov struct key_entry *key; 1145d63219a1SDmitry Torokhov 1146d63219a1SDmitry Torokhov for (key = keymap; key->type != KE_END; key++) 1147d63219a1SDmitry Torokhov if (key->type == KE_KEY && keycode == key->keycode) 1148d63219a1SDmitry Torokhov return key; 1149d63219a1SDmitry Torokhov 1150d63219a1SDmitry Torokhov return NULL; 1151d63219a1SDmitry Torokhov } 1152d63219a1SDmitry Torokhov 11535fc14680SDmitry Torokhov static void handle_key(u8 code) 11545fc14680SDmitry Torokhov { 1155d63219a1SDmitry Torokhov const struct key_entry *key = wistron_get_entry_by_scancode(code); 11565fc14680SDmitry Torokhov 1157d63219a1SDmitry Torokhov if (key) { 11585fc14680SDmitry Torokhov switch (key->type) { 11595fc14680SDmitry Torokhov case KE_KEY: 1160c2554c91SDmitry Torokhov report_key(wistron_idev->input, key->keycode); 11615fc14680SDmitry Torokhov break; 11625fc14680SDmitry Torokhov 11636480e2a2SEric Piel case KE_SW: 1164c2554c91SDmitry Torokhov report_switch(wistron_idev->input, 1165c2554c91SDmitry Torokhov key->sw.code, key->sw.value); 11666480e2a2SEric Piel break; 11676480e2a2SEric Piel 11685fc14680SDmitry Torokhov case KE_WIFI: 11695fc14680SDmitry Torokhov if (have_wifi) { 11705fc14680SDmitry Torokhov wifi_enabled = !wifi_enabled; 117184b256a6SBernhard Rosenkraenzer bios_set_state(WIFI, wifi_enabled); 117284b256a6SBernhard Rosenkraenzer } 117384b256a6SBernhard Rosenkraenzer break; 117484b256a6SBernhard Rosenkraenzer 117584b256a6SBernhard Rosenkraenzer case KE_BLUETOOTH: 117684b256a6SBernhard Rosenkraenzer if (have_bluetooth) { 117784b256a6SBernhard Rosenkraenzer bluetooth_enabled = !bluetooth_enabled; 117884b256a6SBernhard Rosenkraenzer bios_set_state(BLUETOOTH, bluetooth_enabled); 11795fc14680SDmitry Torokhov } 11805fc14680SDmitry Torokhov break; 11815fc14680SDmitry Torokhov 11825fc14680SDmitry Torokhov default: 11835fc14680SDmitry Torokhov BUG(); 11845fc14680SDmitry Torokhov } 1185c2554c91SDmitry Torokhov jiffies_last_press = jiffies; 1186d63219a1SDmitry Torokhov } else 1187d63219a1SDmitry Torokhov printk(KERN_NOTICE 1188d63219a1SDmitry Torokhov "wistron_btns: Unknown key code %02X\n", code); 11895fc14680SDmitry Torokhov } 11905fc14680SDmitry Torokhov 1191c2554c91SDmitry Torokhov static void poll_bios(bool discard) 11925fc14680SDmitry Torokhov { 11935fc14680SDmitry Torokhov u8 qlen; 11945fc14680SDmitry Torokhov u16 val; 11955fc14680SDmitry Torokhov 11965fc14680SDmitry Torokhov for (;;) { 11975fc14680SDmitry Torokhov qlen = CMOS_READ(cmos_address); 11985fc14680SDmitry Torokhov if (qlen == 0) 11995fc14680SDmitry Torokhov break; 12005fc14680SDmitry Torokhov val = bios_pop_queue(); 1201c2554c91SDmitry Torokhov if (val != 0 && !discard) 12025fc14680SDmitry Torokhov handle_key((u8)val); 1203a4da16d3SEric Piel } 12045fc14680SDmitry Torokhov } 12055fc14680SDmitry Torokhov 1206c2554c91SDmitry Torokhov static void wistron_flush(struct input_polled_dev *dev) 1207c2554c91SDmitry Torokhov { 1208c2554c91SDmitry Torokhov /* Flush stale event queue */ 1209c2554c91SDmitry Torokhov poll_bios(true); 12105fc14680SDmitry Torokhov } 12115fc14680SDmitry Torokhov 1212c2554c91SDmitry Torokhov static void wistron_poll(struct input_polled_dev *dev) 1213c2554c91SDmitry Torokhov { 1214c2554c91SDmitry Torokhov poll_bios(false); 1215c2554c91SDmitry Torokhov 1216c2554c91SDmitry Torokhov /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ 1217c2554c91SDmitry Torokhov if (time_before(jiffies, jiffies_last_press + 2 * HZ)) 1218c2554c91SDmitry Torokhov dev->poll_interval = POLL_INTERVAL_BURST; 1219c2554c91SDmitry Torokhov else 1220c2554c91SDmitry Torokhov dev->poll_interval = POLL_INTERVAL_DEFAULT; 1221c2554c91SDmitry Torokhov } 1222c2554c91SDmitry Torokhov 1223d63219a1SDmitry Torokhov static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) 1224d63219a1SDmitry Torokhov { 1225d63219a1SDmitry Torokhov const struct key_entry *key = wistron_get_entry_by_scancode(scancode); 1226d63219a1SDmitry Torokhov 1227d63219a1SDmitry Torokhov if (key && key->type == KE_KEY) { 1228d63219a1SDmitry Torokhov *keycode = key->keycode; 1229d63219a1SDmitry Torokhov return 0; 1230d63219a1SDmitry Torokhov } 1231d63219a1SDmitry Torokhov 1232d63219a1SDmitry Torokhov return -EINVAL; 1233d63219a1SDmitry Torokhov } 1234d63219a1SDmitry Torokhov 1235d63219a1SDmitry Torokhov static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) 1236d63219a1SDmitry Torokhov { 1237d63219a1SDmitry Torokhov struct key_entry *key; 1238d63219a1SDmitry Torokhov int old_keycode; 1239d63219a1SDmitry Torokhov 1240d63219a1SDmitry Torokhov if (keycode < 0 || keycode > KEY_MAX) 1241d63219a1SDmitry Torokhov return -EINVAL; 1242d63219a1SDmitry Torokhov 1243d63219a1SDmitry Torokhov key = wistron_get_entry_by_scancode(scancode); 1244d63219a1SDmitry Torokhov if (key && key->type == KE_KEY) { 1245d63219a1SDmitry Torokhov old_keycode = key->keycode; 1246d63219a1SDmitry Torokhov key->keycode = keycode; 1247d63219a1SDmitry Torokhov set_bit(keycode, dev->keybit); 1248d63219a1SDmitry Torokhov if (!wistron_get_entry_by_keycode(old_keycode)) 1249d63219a1SDmitry Torokhov clear_bit(old_keycode, dev->keybit); 1250d63219a1SDmitry Torokhov return 0; 1251d63219a1SDmitry Torokhov } 1252d63219a1SDmitry Torokhov 1253d63219a1SDmitry Torokhov return -EINVAL; 1254d63219a1SDmitry Torokhov } 1255d63219a1SDmitry Torokhov 1256c2554c91SDmitry Torokhov static int __devinit setup_input_dev(void) 1257c2554c91SDmitry Torokhov { 1258a8944037SÉric Piel struct key_entry *key; 1259c2554c91SDmitry Torokhov struct input_dev *input_dev; 1260c2554c91SDmitry Torokhov int error; 1261c2554c91SDmitry Torokhov 1262c2554c91SDmitry Torokhov wistron_idev = input_allocate_polled_device(); 1263c2554c91SDmitry Torokhov if (!wistron_idev) 1264c2554c91SDmitry Torokhov return -ENOMEM; 1265c2554c91SDmitry Torokhov 1266c2554c91SDmitry Torokhov wistron_idev->flush = wistron_flush; 1267c2554c91SDmitry Torokhov wistron_idev->poll = wistron_poll; 1268c2554c91SDmitry Torokhov wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; 1269c2554c91SDmitry Torokhov 1270c2554c91SDmitry Torokhov input_dev = wistron_idev->input; 1271c2554c91SDmitry Torokhov input_dev->name = "Wistron laptop buttons"; 1272c2554c91SDmitry Torokhov input_dev->phys = "wistron/input0"; 1273c2554c91SDmitry Torokhov input_dev->id.bustype = BUS_HOST; 1274d63219a1SDmitry Torokhov input_dev->dev.parent = &wistron_device->dev; 1275d63219a1SDmitry Torokhov 1276d63219a1SDmitry Torokhov input_dev->getkeycode = wistron_getkeycode; 1277d63219a1SDmitry Torokhov input_dev->setkeycode = wistron_setkeycode; 1278c2554c91SDmitry Torokhov 1279c2554c91SDmitry Torokhov for (key = keymap; key->type != KE_END; key++) { 1280c2554c91SDmitry Torokhov switch (key->type) { 1281c2554c91SDmitry Torokhov case KE_KEY: 1282c2554c91SDmitry Torokhov set_bit(EV_KEY, input_dev->evbit); 1283c2554c91SDmitry Torokhov set_bit(key->keycode, input_dev->keybit); 1284c2554c91SDmitry Torokhov break; 1285c2554c91SDmitry Torokhov 1286c2554c91SDmitry Torokhov case KE_SW: 1287c2554c91SDmitry Torokhov set_bit(EV_SW, input_dev->evbit); 1288c2554c91SDmitry Torokhov set_bit(key->sw.code, input_dev->swbit); 1289c2554c91SDmitry Torokhov break; 1290c2554c91SDmitry Torokhov 1291a8944037SÉric Piel /* if wifi or bluetooth are not available, create normal keys */ 1292a8944037SÉric Piel case KE_WIFI: 1293a8944037SÉric Piel if (!have_wifi) { 1294a8944037SÉric Piel key->type = KE_KEY; 1295a8944037SÉric Piel key->keycode = KEY_WLAN; 1296a8944037SÉric Piel key--; 1297a8944037SÉric Piel } 1298a8944037SÉric Piel break; 1299a8944037SÉric Piel 1300a8944037SÉric Piel case KE_BLUETOOTH: 1301a8944037SÉric Piel if (!have_bluetooth) { 1302a8944037SÉric Piel key->type = KE_KEY; 1303a8944037SÉric Piel key->keycode = KEY_BLUETOOTH; 1304a8944037SÉric Piel key--; 1305a8944037SÉric Piel } 1306a8944037SÉric Piel break; 1307a8944037SÉric Piel 1308c2554c91SDmitry Torokhov default: 1309c2554c91SDmitry Torokhov break; 1310c2554c91SDmitry Torokhov } 1311c2554c91SDmitry Torokhov } 1312c2554c91SDmitry Torokhov 1313c2554c91SDmitry Torokhov /* reads information flags on KE_END */ 1314c2554c91SDmitry Torokhov if (key->code & FE_UNTESTED) 1315c2554c91SDmitry Torokhov printk(KERN_WARNING "Untested laptop multimedia keys, " 1316c2554c91SDmitry Torokhov "please report success or failure to eric.piel" 1317c2554c91SDmitry Torokhov "@tremplin-utc.net\n"); 1318c2554c91SDmitry Torokhov 1319c2554c91SDmitry Torokhov error = input_register_polled_device(wistron_idev); 1320c2554c91SDmitry Torokhov if (error) { 1321c2554c91SDmitry Torokhov input_free_polled_device(wistron_idev); 1322c2554c91SDmitry Torokhov return error; 1323c2554c91SDmitry Torokhov } 1324c2554c91SDmitry Torokhov 1325c2554c91SDmitry Torokhov return 0; 1326c2554c91SDmitry Torokhov } 1327c2554c91SDmitry Torokhov 1328c2554c91SDmitry Torokhov /* Driver core */ 1329c2554c91SDmitry Torokhov 1330e7c3aad5SDmitry Torokhov static int __devinit wistron_probe(struct platform_device *dev) 1331e7c3aad5SDmitry Torokhov { 1332c2554c91SDmitry Torokhov int err; 1333e7c3aad5SDmitry Torokhov 1334e7c3aad5SDmitry Torokhov bios_attach(); 1335e7c3aad5SDmitry Torokhov cmos_address = bios_get_cmos_address(); 1336e7c3aad5SDmitry Torokhov 1337e7c3aad5SDmitry Torokhov if (have_wifi) { 1338e7c3aad5SDmitry Torokhov u16 wifi = bios_get_default_setting(WIFI); 1339e7c3aad5SDmitry Torokhov if (wifi & 1) 134067dbe83aSDmitry Torokhov wifi_enabled = wifi & 2; 1341e7c3aad5SDmitry Torokhov else 1342e7c3aad5SDmitry Torokhov have_wifi = 0; 1343e7c3aad5SDmitry Torokhov 1344e7c3aad5SDmitry Torokhov if (have_wifi) 1345e7c3aad5SDmitry Torokhov bios_set_state(WIFI, wifi_enabled); 1346e7c3aad5SDmitry Torokhov } 1347e7c3aad5SDmitry Torokhov 1348e7c3aad5SDmitry Torokhov if (have_bluetooth) { 1349e7c3aad5SDmitry Torokhov u16 bt = bios_get_default_setting(BLUETOOTH); 1350e7c3aad5SDmitry Torokhov if (bt & 1) 135167dbe83aSDmitry Torokhov bluetooth_enabled = bt & 2; 1352e7c3aad5SDmitry Torokhov else 135367dbe83aSDmitry Torokhov have_bluetooth = false; 1354e7c3aad5SDmitry Torokhov 1355e7c3aad5SDmitry Torokhov if (have_bluetooth) 1356e7c3aad5SDmitry Torokhov bios_set_state(BLUETOOTH, bluetooth_enabled); 1357e7c3aad5SDmitry Torokhov } 1358e7c3aad5SDmitry Torokhov 1359389679d8SEric Piel wistron_led_init(&dev->dev); 136067dbe83aSDmitry Torokhov 1361c2554c91SDmitry Torokhov err = setup_input_dev(); 1362c2554c91SDmitry Torokhov if (err) { 1363c2554c91SDmitry Torokhov bios_detach(); 1364c2554c91SDmitry Torokhov return err; 1365c2554c91SDmitry Torokhov } 1366e7c3aad5SDmitry Torokhov 1367e7c3aad5SDmitry Torokhov return 0; 1368e7c3aad5SDmitry Torokhov } 1369e7c3aad5SDmitry Torokhov 1370e7c3aad5SDmitry Torokhov static int __devexit wistron_remove(struct platform_device *dev) 1371e7c3aad5SDmitry Torokhov { 1372389679d8SEric Piel wistron_led_remove(); 1373c2554c91SDmitry Torokhov input_unregister_polled_device(wistron_idev); 1374c2554c91SDmitry Torokhov input_free_polled_device(wistron_idev); 1375e7c3aad5SDmitry Torokhov bios_detach(); 1376e7c3aad5SDmitry Torokhov 1377e7c3aad5SDmitry Torokhov return 0; 1378e7c3aad5SDmitry Torokhov } 1379e7c3aad5SDmitry Torokhov 1380e7c3aad5SDmitry Torokhov #ifdef CONFIG_PM 138167dbe83aSDmitry Torokhov static int wistron_suspend(struct device *dev) 1382a5b0cc80SDmitry Torokhov { 1383e753b650SMiloslav Trmac if (have_wifi) 1384e753b650SMiloslav Trmac bios_set_state(WIFI, 0); 1385e753b650SMiloslav Trmac 1386e753b650SMiloslav Trmac if (have_bluetooth) 1387e753b650SMiloslav Trmac bios_set_state(BLUETOOTH, 0); 1388e753b650SMiloslav Trmac 1389389679d8SEric Piel wistron_led_suspend(); 139067dbe83aSDmitry Torokhov 1391a5b0cc80SDmitry Torokhov return 0; 1392a5b0cc80SDmitry Torokhov } 1393a5b0cc80SDmitry Torokhov 139467dbe83aSDmitry Torokhov static int wistron_resume(struct device *dev) 1395a5b0cc80SDmitry Torokhov { 1396a5b0cc80SDmitry Torokhov if (have_wifi) 1397a5b0cc80SDmitry Torokhov bios_set_state(WIFI, wifi_enabled); 1398a5b0cc80SDmitry Torokhov 1399a5b0cc80SDmitry Torokhov if (have_bluetooth) 1400a5b0cc80SDmitry Torokhov bios_set_state(BLUETOOTH, bluetooth_enabled); 1401a5b0cc80SDmitry Torokhov 1402389679d8SEric Piel wistron_led_resume(); 140367dbe83aSDmitry Torokhov 1404c2554c91SDmitry Torokhov poll_bios(true); 1405a5b0cc80SDmitry Torokhov 1406a5b0cc80SDmitry Torokhov return 0; 1407a5b0cc80SDmitry Torokhov } 140867dbe83aSDmitry Torokhov 140967dbe83aSDmitry Torokhov static const struct dev_pm_ops wistron_pm_ops = { 141067dbe83aSDmitry Torokhov .suspend = wistron_suspend, 141167dbe83aSDmitry Torokhov .resume = wistron_resume, 141267dbe83aSDmitry Torokhov .poweroff = wistron_suspend, 141367dbe83aSDmitry Torokhov .restore = wistron_resume, 141467dbe83aSDmitry Torokhov }; 1415e7c3aad5SDmitry Torokhov #endif 1416a5b0cc80SDmitry Torokhov 1417a5b0cc80SDmitry Torokhov static struct platform_driver wistron_driver = { 1418a5b0cc80SDmitry Torokhov .driver = { 1419a5b0cc80SDmitry Torokhov .name = "wistron-bios", 1420e7c3aad5SDmitry Torokhov .owner = THIS_MODULE, 142167dbe83aSDmitry Torokhov #if CONFIG_PM 142267dbe83aSDmitry Torokhov .pm = &wistron_pm_ops, 142367dbe83aSDmitry Torokhov #endif 1424a5b0cc80SDmitry Torokhov }, 1425e7c3aad5SDmitry Torokhov .probe = wistron_probe, 1426e7c3aad5SDmitry Torokhov .remove = __devexit_p(wistron_remove), 1427a5b0cc80SDmitry Torokhov }; 1428a5b0cc80SDmitry Torokhov 14295fc14680SDmitry Torokhov static int __init wb_module_init(void) 14305fc14680SDmitry Torokhov { 14315fc14680SDmitry Torokhov int err; 14325fc14680SDmitry Torokhov 14335fc14680SDmitry Torokhov err = select_keymap(); 14345fc14680SDmitry Torokhov if (err) 14355fc14680SDmitry Torokhov return err; 143622a397e2SDmitry Torokhov 14375fc14680SDmitry Torokhov err = map_bios(); 14385fc14680SDmitry Torokhov if (err) 14395fc14680SDmitry Torokhov return err; 144022a397e2SDmitry Torokhov 1441a5b0cc80SDmitry Torokhov err = platform_driver_register(&wistron_driver); 1442a5b0cc80SDmitry Torokhov if (err) 1443e7c3aad5SDmitry Torokhov goto err_unmap_bios; 1444a5b0cc80SDmitry Torokhov 1445e7c3aad5SDmitry Torokhov wistron_device = platform_device_alloc("wistron-bios", -1); 1446e7c3aad5SDmitry Torokhov if (!wistron_device) { 1447e7c3aad5SDmitry Torokhov err = -ENOMEM; 1448a5b0cc80SDmitry Torokhov goto err_unregister_driver; 1449a5b0cc80SDmitry Torokhov } 1450a5b0cc80SDmitry Torokhov 1451e7c3aad5SDmitry Torokhov err = platform_device_add(wistron_device); 1452a5b0cc80SDmitry Torokhov if (err) 1453e7c3aad5SDmitry Torokhov goto err_free_device; 14545fc14680SDmitry Torokhov 14555fc14680SDmitry Torokhov return 0; 1456a5b0cc80SDmitry Torokhov 1457e7c3aad5SDmitry Torokhov err_free_device: 1458e7c3aad5SDmitry Torokhov platform_device_put(wistron_device); 1459a5b0cc80SDmitry Torokhov err_unregister_driver: 1460a5b0cc80SDmitry Torokhov platform_driver_unregister(&wistron_driver); 1461e7c3aad5SDmitry Torokhov err_unmap_bios: 1462a5b0cc80SDmitry Torokhov unmap_bios(); 1463a5b0cc80SDmitry Torokhov 1464a5b0cc80SDmitry Torokhov return err; 14655fc14680SDmitry Torokhov } 14665fc14680SDmitry Torokhov 14675fc14680SDmitry Torokhov static void __exit wb_module_exit(void) 14685fc14680SDmitry Torokhov { 1469a5b0cc80SDmitry Torokhov platform_device_unregister(wistron_device); 1470a5b0cc80SDmitry Torokhov platform_driver_unregister(&wistron_driver); 14715fc14680SDmitry Torokhov unmap_bios(); 147255d29c98SEric Piel kfree(keymap); 14735fc14680SDmitry Torokhov } 14745fc14680SDmitry Torokhov 14755fc14680SDmitry Torokhov module_init(wb_module_init); 14765fc14680SDmitry Torokhov module_exit(wb_module_exit); 1477