linux/drivers/input/misc/wistron_btns.c
<<
>>
Prefs
   1/*
   2 * Wistron laptop button driver
   3 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
   4 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
   5 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
   6 *
   7 * You can redistribute and/or modify this program under the terms of the
   8 * GNU General Public License version 2 as published by the Free Software
   9 * Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  14 * Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along
  17 * with this program; if not, write to the Free Software Foundation, Inc.,
  18 * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
  19 */
  20#include <linux/io.h>
  21#include <linux/dmi.h>
  22#include <linux/init.h>
  23#include <linux/input-polldev.h>
  24#include <linux/input/sparse-keymap.h>
  25#include <linux/interrupt.h>
  26#include <linux/jiffies.h>
  27#include <linux/kernel.h>
  28#include <linux/mc146818rtc.h>
  29#include <linux/module.h>
  30#include <linux/preempt.h>
  31#include <linux/string.h>
  32#include <linux/slab.h>
  33#include <linux/types.h>
  34#include <linux/platform_device.h>
  35#include <linux/leds.h>
  36
  37/* How often we poll keys - msecs */
  38#define POLL_INTERVAL_DEFAULT   500 /* when idle */
  39#define POLL_INTERVAL_BURST     100 /* when a key was recently pressed */
  40
  41/* BIOS subsystem IDs */
  42#define WIFI            0x35
  43#define BLUETOOTH       0x34
  44#define MAIL_LED        0x31
  45
  46MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
  47MODULE_DESCRIPTION("Wistron laptop button driver");
  48MODULE_LICENSE("GPL v2");
  49MODULE_VERSION("0.3");
  50
  51static bool force; /* = 0; */
  52module_param(force, bool, 0);
  53MODULE_PARM_DESC(force, "Load even if computer is not in database");
  54
  55static char *keymap_name; /* = NULL; */
  56module_param_named(keymap, keymap_name, charp, 0);
  57MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
  58
  59static struct platform_device *wistron_device;
  60
  61 /* BIOS interface implementation */
  62
  63static void __iomem *bios_entry_point; /* BIOS routine entry point */
  64static void __iomem *bios_code_map_base;
  65static void __iomem *bios_data_map_base;
  66
  67static u8 cmos_address;
  68
  69struct regs {
  70        u32 eax, ebx, ecx;
  71};
  72
  73static void call_bios(struct regs *regs)
  74{
  75        unsigned long flags;
  76
  77        preempt_disable();
  78        local_irq_save(flags);
  79        asm volatile ("pushl %%ebp;"
  80                      "movl %7, %%ebp;"
  81                      "call *%6;"
  82                      "popl %%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");
  87        local_irq_restore(flags);
  88        preempt_enable();
  89}
  90
  91static ssize_t __init locate_wistron_bios(void __iomem *base)
  92{
  93        static unsigned char __initdata signature[] =
  94                { 0x42, 0x21, 0x55, 0x30 };
  95        ssize_t offset;
  96
  97        for (offset = 0; offset < 0x10000; offset += 0x10) {
  98                if (check_signature(base + offset, signature,
  99                                    sizeof(signature)) != 0)
 100                        return offset;
 101        }
 102        return -1;
 103}
 104
 105static int __init map_bios(void)
 106{
 107        void __iomem *base;
 108        ssize_t offset;
 109        u32 entry_point;
 110
 111        base = ioremap(0xF0000, 0x10000); /* Can't fail */
 112        offset = locate_wistron_bios(base);
 113        if (offset < 0) {
 114                printk(KERN_ERR "wistron_btns: BIOS entry point not found\n");
 115                iounmap(base);
 116                return -ENODEV;
 117        }
 118
 119        entry_point = readl(base + offset + 5);
 120        printk(KERN_DEBUG
 121                "wistron_btns: BIOS signature found at %p, entry point %08X\n",
 122                base + offset, entry_point);
 123
 124        if (entry_point >= 0xF0000) {
 125                bios_code_map_base = base;
 126                bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
 127        } else {
 128                iounmap(base);
 129                bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000);
 130                if (bios_code_map_base == NULL) {
 131                        printk(KERN_ERR
 132                                "wistron_btns: Can't map BIOS code at %08X\n",
 133                                entry_point & ~0x3FFF);
 134                        goto err;
 135                }
 136                bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
 137        }
 138        /* The Windows driver maps 0x10000 bytes, we keep only one page... */
 139        bios_data_map_base = ioremap(0x400, 0xc00);
 140        if (bios_data_map_base == NULL) {
 141                printk(KERN_ERR "wistron_btns: Can't map BIOS data\n");
 142                goto err_code;
 143        }
 144        return 0;
 145
 146err_code:
 147        iounmap(bios_code_map_base);
 148err:
 149        return -ENOMEM;
 150}
 151
 152static inline void unmap_bios(void)
 153{
 154        iounmap(bios_code_map_base);
 155        iounmap(bios_data_map_base);
 156}
 157
 158 /* BIOS calls */
 159
 160static u16 bios_pop_queue(void)
 161{
 162        struct regs regs;
 163
 164        memset(&regs, 0, sizeof (regs));
 165        regs.eax = 0x9610;
 166        regs.ebx = 0x061C;
 167        regs.ecx = 0x0000;
 168        call_bios(&regs);
 169
 170        return regs.eax;
 171}
 172
 173static void bios_attach(void)
 174{
 175        struct regs regs;
 176
 177        memset(&regs, 0, sizeof (regs));
 178        regs.eax = 0x9610;
 179        regs.ebx = 0x012E;
 180        call_bios(&regs);
 181}
 182
 183static void bios_detach(void)
 184{
 185        struct regs regs;
 186
 187        memset(&regs, 0, sizeof (regs));
 188        regs.eax = 0x9610;
 189        regs.ebx = 0x002E;
 190        call_bios(&regs);
 191}
 192
 193static u8 bios_get_cmos_address(void)
 194{
 195        struct regs regs;
 196
 197        memset(&regs, 0, sizeof (regs));
 198        regs.eax = 0x9610;
 199        regs.ebx = 0x051C;
 200        call_bios(&regs);
 201
 202        return regs.ecx;
 203}
 204
 205static u16 bios_get_default_setting(u8 subsys)
 206{
 207        struct regs regs;
 208
 209        memset(&regs, 0, sizeof (regs));
 210        regs.eax = 0x9610;
 211        regs.ebx = 0x0200 | subsys;
 212        call_bios(&regs);
 213
 214        return regs.eax;
 215}
 216
 217static void bios_set_state(u8 subsys, int enable)
 218{
 219        struct regs regs;
 220
 221        memset(&regs, 0, sizeof (regs));
 222        regs.eax = 0x9610;
 223        regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
 224        call_bios(&regs);
 225}
 226
 227/* Hardware database */
 228
 229#define KE_WIFI         (KE_LAST + 1)
 230#define KE_BLUETOOTH    (KE_LAST + 2)
 231
 232#define FE_MAIL_LED 0x01
 233#define FE_WIFI_LED 0x02
 234#define FE_UNTESTED 0x80
 235
 236static struct key_entry *keymap; /* = NULL; Current key map */
 237static bool have_wifi;
 238static bool have_bluetooth;
 239static int leds_present;        /* bitmask of leds present */
 240
 241static int __init dmi_matched(const struct dmi_system_id *dmi)
 242{
 243        const struct key_entry *key;
 244
 245        keymap = dmi->driver_data;
 246        for (key = keymap; key->type != KE_END; key++) {
 247                if (key->type == KE_WIFI)
 248                        have_wifi = true;
 249                else if (key->type == KE_BLUETOOTH)
 250                        have_bluetooth = true;
 251        }
 252        leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED);
 253
 254        return 1;
 255}
 256
 257static struct key_entry keymap_empty[] __initdata = {
 258        { KE_END, 0 }
 259};
 260
 261static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
 262        { KE_KEY,  0x01, {KEY_HELP} },
 263        { KE_KEY,  0x11, {KEY_PROG1} },
 264        { KE_KEY,  0x12, {KEY_PROG2} },
 265        { KE_WIFI, 0x30 },
 266        { KE_KEY,  0x31, {KEY_MAIL} },
 267        { KE_KEY,  0x36, {KEY_WWW} },
 268        { KE_END,  0 }
 269};
 270
 271static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
 272        { KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */
 273        { KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
 274        { KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
 275        { KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
 276        { KE_KEY,       0x36, {KEY_WWW} },           /* www button */
 277        { KE_WIFI,      0x78 },                      /* satellite dish button */
 278        { KE_END,       0 }
 279};
 280
 281static struct key_entry keymap_fujitsu_n3510[] __initdata = {
 282        { KE_KEY, 0x11, {KEY_PROG1} },
 283        { KE_KEY, 0x12, {KEY_PROG2} },
 284        { KE_KEY, 0x36, {KEY_WWW} },
 285        { KE_KEY, 0x31, {KEY_MAIL} },
 286        { KE_KEY, 0x71, {KEY_STOPCD} },
 287        { KE_KEY, 0x72, {KEY_PLAYPAUSE} },
 288        { KE_KEY, 0x74, {KEY_REWIND} },
 289        { KE_KEY, 0x78, {KEY_FORWARD} },
 290        { KE_END, 0 }
 291};
 292
 293static struct key_entry keymap_wistron_ms2111[] __initdata = {
 294        { KE_KEY,  0x11, {KEY_PROG1} },
 295        { KE_KEY,  0x12, {KEY_PROG2} },
 296        { KE_KEY,  0x13, {KEY_PROG3} },
 297        { KE_KEY,  0x31, {KEY_MAIL} },
 298        { KE_KEY,  0x36, {KEY_WWW} },
 299        { KE_END, FE_MAIL_LED }
 300};
 301
 302static struct key_entry keymap_wistron_md40100[] __initdata = {
 303        { KE_KEY, 0x01, {KEY_HELP} },
 304        { KE_KEY, 0x02, {KEY_CONFIG} },
 305        { KE_KEY, 0x31, {KEY_MAIL} },
 306        { KE_KEY, 0x36, {KEY_WWW} },
 307        { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
 308        { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
 309};
 310
 311static struct key_entry keymap_wistron_ms2141[] __initdata = {
 312        { KE_KEY,  0x11, {KEY_PROG1} },
 313        { KE_KEY,  0x12, {KEY_PROG2} },
 314        { KE_WIFI, 0x30 },
 315        { KE_KEY,  0x22, {KEY_REWIND} },
 316        { KE_KEY,  0x23, {KEY_FORWARD} },
 317        { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
 318        { KE_KEY,  0x25, {KEY_STOPCD} },
 319        { KE_KEY,  0x31, {KEY_MAIL} },
 320        { KE_KEY,  0x36, {KEY_WWW} },
 321        { KE_END,  0 }
 322};
 323
 324static struct key_entry keymap_acer_aspire_1500[] __initdata = {
 325        { KE_KEY, 0x01, {KEY_HELP} },
 326        { KE_KEY, 0x03, {KEY_POWER} },
 327        { KE_KEY, 0x11, {KEY_PROG1} },
 328        { KE_KEY, 0x12, {KEY_PROG2} },
 329        { KE_WIFI, 0x30 },
 330        { KE_KEY, 0x31, {KEY_MAIL} },
 331        { KE_KEY, 0x36, {KEY_WWW} },
 332        { KE_KEY, 0x49, {KEY_CONFIG} },
 333        { KE_BLUETOOTH, 0x44 },
 334        { KE_END, FE_UNTESTED }
 335};
 336
 337static struct key_entry keymap_acer_aspire_1600[] __initdata = {
 338        { KE_KEY, 0x01, {KEY_HELP} },
 339        { KE_KEY, 0x03, {KEY_POWER} },
 340        { KE_KEY, 0x08, {KEY_MUTE} },
 341        { KE_KEY, 0x11, {KEY_PROG1} },
 342        { KE_KEY, 0x12, {KEY_PROG2} },
 343        { KE_KEY, 0x13, {KEY_PROG3} },
 344        { KE_KEY, 0x31, {KEY_MAIL} },
 345        { KE_KEY, 0x36, {KEY_WWW} },
 346        { KE_KEY, 0x49, {KEY_CONFIG} },
 347        { KE_WIFI, 0x30 },
 348        { KE_BLUETOOTH, 0x44 },
 349        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 350};
 351
 352/* 3020 has been tested */
 353static struct key_entry keymap_acer_aspire_5020[] __initdata = {
 354        { KE_KEY, 0x01, {KEY_HELP} },
 355        { KE_KEY, 0x03, {KEY_POWER} },
 356        { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
 357        { KE_KEY, 0x11, {KEY_PROG1} },
 358        { KE_KEY, 0x12, {KEY_PROG2} },
 359        { KE_KEY, 0x31, {KEY_MAIL} },
 360        { KE_KEY, 0x36, {KEY_WWW} },
 361        { KE_KEY, 0x6a, {KEY_CONFIG} },
 362        { KE_WIFI, 0x30 },
 363        { KE_BLUETOOTH, 0x44 },
 364        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 365};
 366
 367static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
 368        { KE_KEY, 0x01, {KEY_HELP} },
 369        { KE_KEY, 0x6d, {KEY_POWER} },
 370        { KE_KEY, 0x11, {KEY_PROG1} },
 371        { KE_KEY, 0x12, {KEY_PROG2} },
 372        { KE_KEY, 0x31, {KEY_MAIL} },
 373        { KE_KEY, 0x36, {KEY_WWW} },
 374        { KE_KEY, 0x6a, {KEY_CONFIG} },
 375        { KE_WIFI, 0x30 },
 376        { KE_BLUETOOTH, 0x44 },
 377        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 378};
 379
 380static struct key_entry keymap_acer_travelmate_110[] __initdata = {
 381        { KE_KEY, 0x01, {KEY_HELP} },
 382        { KE_KEY, 0x02, {KEY_CONFIG} },
 383        { KE_KEY, 0x03, {KEY_POWER} },
 384        { KE_KEY, 0x08, {KEY_MUTE} },
 385        { KE_KEY, 0x11, {KEY_PROG1} },
 386        { KE_KEY, 0x12, {KEY_PROG2} },
 387        { KE_KEY, 0x20, {KEY_VOLUMEUP} },
 388        { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
 389        { KE_KEY, 0x31, {KEY_MAIL} },
 390        { KE_KEY, 0x36, {KEY_WWW} },
 391        { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
 392        { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
 393        { KE_WIFI, 0x30 },
 394        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 395};
 396
 397static struct key_entry keymap_acer_travelmate_300[] __initdata = {
 398        { KE_KEY, 0x01, {KEY_HELP} },
 399        { KE_KEY, 0x02, {KEY_CONFIG} },
 400        { KE_KEY, 0x03, {KEY_POWER} },
 401        { KE_KEY, 0x08, {KEY_MUTE} },
 402        { KE_KEY, 0x11, {KEY_PROG1} },
 403        { KE_KEY, 0x12, {KEY_PROG2} },
 404        { KE_KEY, 0x20, {KEY_VOLUMEUP} },
 405        { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
 406        { KE_KEY, 0x31, {KEY_MAIL} },
 407        { KE_KEY, 0x36, {KEY_WWW} },
 408        { KE_WIFI, 0x30 },
 409        { KE_BLUETOOTH, 0x44 },
 410        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 411};
 412
 413static struct key_entry keymap_acer_travelmate_380[] __initdata = {
 414        { KE_KEY, 0x01, {KEY_HELP} },
 415        { KE_KEY, 0x02, {KEY_CONFIG} },
 416        { KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
 417        { KE_KEY, 0x11, {KEY_PROG1} },
 418        { KE_KEY, 0x12, {KEY_PROG2} },
 419        { KE_KEY, 0x13, {KEY_PROG3} },
 420        { KE_KEY, 0x31, {KEY_MAIL} },
 421        { KE_KEY, 0x36, {KEY_WWW} },
 422        { KE_WIFI, 0x30 },
 423        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 424};
 425
 426/* unusual map */
 427static struct key_entry keymap_acer_travelmate_220[] __initdata = {
 428        { KE_KEY, 0x01, {KEY_HELP} },
 429        { KE_KEY, 0x02, {KEY_CONFIG} },
 430        { KE_KEY, 0x11, {KEY_MAIL} },
 431        { KE_KEY, 0x12, {KEY_WWW} },
 432        { KE_KEY, 0x13, {KEY_PROG2} },
 433        { KE_KEY, 0x31, {KEY_PROG1} },
 434        { KE_END, FE_WIFI_LED | FE_UNTESTED }
 435};
 436
 437static struct key_entry keymap_acer_travelmate_230[] __initdata = {
 438        { KE_KEY, 0x01, {KEY_HELP} },
 439        { KE_KEY, 0x02, {KEY_CONFIG} },
 440        { KE_KEY, 0x11, {KEY_PROG1} },
 441        { KE_KEY, 0x12, {KEY_PROG2} },
 442        { KE_KEY, 0x31, {KEY_MAIL} },
 443        { KE_KEY, 0x36, {KEY_WWW} },
 444        { KE_END, FE_WIFI_LED | FE_UNTESTED }
 445};
 446
 447static struct key_entry keymap_acer_travelmate_240[] __initdata = {
 448        { KE_KEY, 0x01, {KEY_HELP} },
 449        { KE_KEY, 0x02, {KEY_CONFIG} },
 450        { KE_KEY, 0x03, {KEY_POWER} },
 451        { KE_KEY, 0x08, {KEY_MUTE} },
 452        { KE_KEY, 0x31, {KEY_MAIL} },
 453        { KE_KEY, 0x36, {KEY_WWW} },
 454        { KE_KEY, 0x11, {KEY_PROG1} },
 455        { KE_KEY, 0x12, {KEY_PROG2} },
 456        { KE_BLUETOOTH, 0x44 },
 457        { KE_WIFI, 0x30 },
 458        { KE_END, FE_UNTESTED }
 459};
 460
 461static struct key_entry keymap_acer_travelmate_350[] __initdata = {
 462        { KE_KEY, 0x01, {KEY_HELP} },
 463        { KE_KEY, 0x02, {KEY_CONFIG} },
 464        { KE_KEY, 0x11, {KEY_PROG1} },
 465        { KE_KEY, 0x12, {KEY_PROG2} },
 466        { KE_KEY, 0x13, {KEY_MAIL} },
 467        { KE_KEY, 0x14, {KEY_PROG3} },
 468        { KE_KEY, 0x15, {KEY_WWW} },
 469        { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
 470};
 471
 472static struct key_entry keymap_acer_travelmate_360[] __initdata = {
 473        { KE_KEY, 0x01, {KEY_HELP} },
 474        { KE_KEY, 0x02, {KEY_CONFIG} },
 475        { KE_KEY, 0x11, {KEY_PROG1} },
 476        { KE_KEY, 0x12, {KEY_PROG2} },
 477        { KE_KEY, 0x13, {KEY_MAIL} },
 478        { KE_KEY, 0x14, {KEY_PROG3} },
 479        { KE_KEY, 0x15, {KEY_WWW} },
 480        { KE_KEY, 0x40, {KEY_WLAN} },
 481        { KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
 482};
 483
 484/* Wifi subsystem only activates the led. Therefore we need to pass
 485 * wifi event as a normal key, then userspace can really change the wifi state.
 486 * TODO we need to export led state to userspace (wifi and mail) */
 487static struct key_entry keymap_acer_travelmate_610[] __initdata = {
 488        { KE_KEY, 0x01, {KEY_HELP} },
 489        { KE_KEY, 0x02, {KEY_CONFIG} },
 490        { KE_KEY, 0x11, {KEY_PROG1} },
 491        { KE_KEY, 0x12, {KEY_PROG2} },
 492        { KE_KEY, 0x13, {KEY_PROG3} },
 493        { KE_KEY, 0x14, {KEY_MAIL} },
 494        { KE_KEY, 0x15, {KEY_WWW} },
 495        { KE_KEY, 0x40, {KEY_WLAN} },
 496        { KE_END, FE_MAIL_LED | FE_WIFI_LED }
 497};
 498
 499static struct key_entry keymap_acer_travelmate_630[] __initdata = {
 500        { KE_KEY, 0x01, {KEY_HELP} },
 501        { KE_KEY, 0x02, {KEY_CONFIG} },
 502        { KE_KEY, 0x03, {KEY_POWER} },
 503        { KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
 504        { KE_KEY, 0x11, {KEY_PROG1} },
 505        { KE_KEY, 0x12, {KEY_PROG2} },
 506        { KE_KEY, 0x13, {KEY_PROG3} },
 507        { KE_KEY, 0x20, {KEY_VOLUMEUP} },
 508        { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
 509        { KE_KEY, 0x31, {KEY_MAIL} },
 510        { KE_KEY, 0x36, {KEY_WWW} },
 511        { KE_WIFI, 0x30 },
 512        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 513};
 514
 515static struct key_entry keymap_aopen_1559as[] __initdata = {
 516        { KE_KEY,  0x01, {KEY_HELP} },
 517        { KE_KEY,  0x06, {KEY_PROG3} },
 518        { KE_KEY,  0x11, {KEY_PROG1} },
 519        { KE_KEY,  0x12, {KEY_PROG2} },
 520        { KE_WIFI, 0x30 },
 521        { KE_KEY,  0x31, {KEY_MAIL} },
 522        { KE_KEY,  0x36, {KEY_WWW} },
 523        { KE_END,  0 },
 524};
 525
 526static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
 527        { KE_KEY, 0x01, {KEY_HELP} },
 528        { KE_KEY, 0x08, {KEY_MUTE} },
 529        { KE_KEY, 0x31, {KEY_MAIL} },
 530        { KE_KEY, 0x36, {KEY_WWW} },
 531        { KE_KEY, 0x11, {KEY_PROG1} },
 532        { KE_KEY, 0x12, {KEY_PROG2} },
 533        { KE_KEY, 0x13, {KEY_PROG3} },
 534        { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
 535};
 536
 537static struct key_entry keymap_wistron_md2900[] __initdata = {
 538        { KE_KEY, 0x01, {KEY_HELP} },
 539        { KE_KEY, 0x02, {KEY_CONFIG} },
 540        { KE_KEY, 0x11, {KEY_PROG1} },
 541        { KE_KEY, 0x12, {KEY_PROG2} },
 542        { KE_KEY, 0x31, {KEY_MAIL} },
 543        { KE_KEY, 0x36, {KEY_WWW} },
 544        { KE_WIFI, 0x30 },
 545        { KE_END, FE_MAIL_LED | FE_UNTESTED }
 546};
 547
 548static struct key_entry keymap_wistron_md96500[] __initdata = {
 549        { KE_KEY, 0x01, {KEY_HELP} },
 550        { KE_KEY, 0x02, {KEY_CONFIG} },
 551        { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
 552        { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
 553        { KE_KEY, 0x08, {KEY_MUTE} },
 554        { KE_KEY, 0x11, {KEY_PROG1} },
 555        { KE_KEY, 0x12, {KEY_PROG2} },
 556        { KE_KEY, 0x20, {KEY_VOLUMEUP} },
 557        { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
 558        { KE_KEY, 0x22, {KEY_REWIND} },
 559        { KE_KEY, 0x23, {KEY_FORWARD} },
 560        { KE_KEY, 0x24, {KEY_PLAYPAUSE} },
 561        { KE_KEY, 0x25, {KEY_STOPCD} },
 562        { KE_KEY, 0x31, {KEY_MAIL} },
 563        { KE_KEY, 0x36, {KEY_WWW} },
 564        { KE_WIFI, 0x30 },
 565        { KE_BLUETOOTH, 0x44 },
 566        { KE_END, FE_UNTESTED }
 567};
 568
 569static struct key_entry keymap_wistron_generic[] __initdata = {
 570        { KE_KEY, 0x01, {KEY_HELP} },
 571        { KE_KEY, 0x02, {KEY_CONFIG} },
 572        { KE_KEY, 0x03, {KEY_POWER} },
 573        { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
 574        { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
 575        { KE_KEY, 0x08, {KEY_MUTE} },
 576        { KE_KEY, 0x11, {KEY_PROG1} },
 577        { KE_KEY, 0x12, {KEY_PROG2} },
 578        { KE_KEY, 0x13, {KEY_PROG3} },
 579        { KE_KEY, 0x14, {KEY_MAIL} },
 580        { KE_KEY, 0x15, {KEY_WWW} },
 581        { KE_KEY, 0x20, {KEY_VOLUMEUP} },
 582        { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
 583        { KE_KEY, 0x22, {KEY_REWIND} },
 584        { KE_KEY, 0x23, {KEY_FORWARD} },
 585        { KE_KEY, 0x24, {KEY_PLAYPAUSE} },
 586        { KE_KEY, 0x25, {KEY_STOPCD} },
 587        { KE_KEY, 0x31, {KEY_MAIL} },
 588        { KE_KEY, 0x36, {KEY_WWW} },
 589        { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
 590        { KE_KEY, 0x40, {KEY_WLAN} },
 591        { KE_KEY, 0x49, {KEY_CONFIG} },
 592        { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
 593        { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
 594        { KE_KEY, 0x6a, {KEY_CONFIG} },
 595        { KE_KEY, 0x6d, {KEY_POWER} },
 596        { KE_KEY, 0x71, {KEY_STOPCD} },
 597        { KE_KEY, 0x72, {KEY_PLAYPAUSE} },
 598        { KE_KEY, 0x74, {KEY_REWIND} },
 599        { KE_KEY, 0x78, {KEY_FORWARD} },
 600        { KE_WIFI, 0x30 },
 601        { KE_BLUETOOTH, 0x44 },
 602        { KE_END, 0 }
 603};
 604
 605static struct key_entry keymap_aopen_1557[] __initdata = {
 606        { KE_KEY,  0x01, {KEY_HELP} },
 607        { KE_KEY,  0x11, {KEY_PROG1} },
 608        { KE_KEY,  0x12, {KEY_PROG2} },
 609        { KE_WIFI, 0x30 },
 610        { KE_KEY,  0x22, {KEY_REWIND} },
 611        { KE_KEY,  0x23, {KEY_FORWARD} },
 612        { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
 613        { KE_KEY,  0x25, {KEY_STOPCD} },
 614        { KE_KEY,  0x31, {KEY_MAIL} },
 615        { KE_KEY,  0x36, {KEY_WWW} },
 616        { KE_END,  0 }
 617};
 618
 619static struct key_entry keymap_prestigio[] __initdata = {
 620        { KE_KEY,  0x11, {KEY_PROG1} },
 621        { KE_KEY,  0x12, {KEY_PROG2} },
 622        { KE_WIFI, 0x30 },
 623        { KE_KEY,  0x22, {KEY_REWIND} },
 624        { KE_KEY,  0x23, {KEY_FORWARD} },
 625        { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
 626        { KE_KEY,  0x25, {KEY_STOPCD} },
 627        { KE_KEY,  0x31, {KEY_MAIL} },
 628        { KE_KEY,  0x36, {KEY_WWW} },
 629        { KE_END,  0 }
 630};
 631
 632
 633/*
 634 * If your machine is not here (which is currently rather likely), please send
 635 * a list of buttons and their key codes (reported when loading this module
 636 * with force=1) and the output of dmidecode to $MODULE_AUTHOR.
 637 */
 638static const struct dmi_system_id __initconst dmi_ids[] = {
 639        {
 640                /* Fujitsu-Siemens Amilo Pro V2000 */
 641                .callback = dmi_matched,
 642                .matches = {
 643                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 644                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"),
 645                },
 646                .driver_data = keymap_fs_amilo_pro_v2000
 647        },
 648        {
 649                /* Fujitsu-Siemens Amilo Pro Edition V3505 */
 650                .callback = dmi_matched,
 651                .matches = {
 652                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 653                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
 654                },
 655                .driver_data = keymap_fs_amilo_pro_v3505
 656        },
 657        {
 658                /* Fujitsu-Siemens Amilo M7400 */
 659                .callback = dmi_matched,
 660                .matches = {
 661                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 662                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M        "),
 663                },
 664                .driver_data = keymap_fs_amilo_pro_v2000
 665        },
 666        {
 667                /* Maxdata Pro 7000 DX */
 668                .callback = dmi_matched,
 669                .matches = {
 670                        DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
 671                        DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
 672                },
 673                .driver_data = keymap_fs_amilo_pro_v2000
 674        },
 675        {
 676                /* Fujitsu N3510 */
 677                .callback = dmi_matched,
 678                .matches = {
 679                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 680                        DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
 681                },
 682                .driver_data = keymap_fujitsu_n3510
 683        },
 684        {
 685                /* Acer Aspire 1500 */
 686                .callback = dmi_matched,
 687                .matches = {
 688                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 689                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
 690                },
 691                .driver_data = keymap_acer_aspire_1500
 692        },
 693        {
 694                /* Acer Aspire 1600 */
 695                .callback = dmi_matched,
 696                .matches = {
 697                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 698                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
 699                },
 700                .driver_data = keymap_acer_aspire_1600
 701        },
 702        {
 703                /* Acer Aspire 3020 */
 704                .callback = dmi_matched,
 705                .matches = {
 706                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 707                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
 708                },
 709                .driver_data = keymap_acer_aspire_5020
 710        },
 711        {
 712                /* Acer Aspire 5020 */
 713                .callback = dmi_matched,
 714                .matches = {
 715                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 716                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
 717                },
 718                .driver_data = keymap_acer_aspire_5020
 719        },
 720        {
 721                /* Acer TravelMate 2100 */
 722                .callback = dmi_matched,
 723                .matches = {
 724                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 725                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
 726                },
 727                .driver_data = keymap_acer_aspire_5020
 728        },
 729        {
 730                /* Acer TravelMate 2410 */
 731                .callback = dmi_matched,
 732                .matches = {
 733                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 734                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
 735                },
 736                .driver_data = keymap_acer_travelmate_2410
 737        },
 738        {
 739                /* Acer TravelMate C300 */
 740                .callback = dmi_matched,
 741                .matches = {
 742                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 743                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
 744                },
 745                .driver_data = keymap_acer_travelmate_300
 746        },
 747        {
 748                /* Acer TravelMate C100 */
 749                .callback = dmi_matched,
 750                .matches = {
 751                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 752                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
 753                },
 754                .driver_data = keymap_acer_travelmate_300
 755        },
 756        {
 757                /* Acer TravelMate C110 */
 758                .callback = dmi_matched,
 759                .matches = {
 760                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 761                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
 762                },
 763                .driver_data = keymap_acer_travelmate_110
 764        },
 765        {
 766                /* Acer TravelMate 380 */
 767                .callback = dmi_matched,
 768                .matches = {
 769                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 770                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
 771                },
 772                .driver_data = keymap_acer_travelmate_380
 773        },
 774        {
 775                /* Acer TravelMate 370 */
 776                .callback = dmi_matched,
 777                .matches = {
 778                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 779                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
 780                },
 781                .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
 782        },
 783        {
 784                /* Acer TravelMate 220 */
 785                .callback = dmi_matched,
 786                .matches = {
 787                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 788                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
 789                },
 790                .driver_data = keymap_acer_travelmate_220
 791        },
 792        {
 793                /* Acer TravelMate 260 */
 794                .callback = dmi_matched,
 795                .matches = {
 796                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 797                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
 798                },
 799                .driver_data = keymap_acer_travelmate_220
 800        },
 801        {
 802                /* Acer TravelMate 230 */
 803                .callback = dmi_matched,
 804                .matches = {
 805                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 806                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
 807                        /* acerhk looks for "TravelMate F4..." ?! */
 808                },
 809                .driver_data = keymap_acer_travelmate_230
 810        },
 811        {
 812                /* Acer TravelMate 280 */
 813                .callback = dmi_matched,
 814                .matches = {
 815                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 816                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
 817                },
 818                .driver_data = keymap_acer_travelmate_230
 819        },
 820        {
 821                /* Acer TravelMate 240 */
 822                .callback = dmi_matched,
 823                .matches = {
 824                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 825                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
 826                },
 827                .driver_data = keymap_acer_travelmate_240
 828        },
 829        {
 830                /* Acer TravelMate 250 */
 831                .callback = dmi_matched,
 832                .matches = {
 833                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 834                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
 835                },
 836                .driver_data = keymap_acer_travelmate_240
 837        },
 838        {
 839                /* Acer TravelMate 2424NWXCi */
 840                .callback = dmi_matched,
 841                .matches = {
 842                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 843                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"),
 844                },
 845                .driver_data = keymap_acer_travelmate_240
 846        },
 847        {
 848                /* Acer TravelMate 350 */
 849                .callback = dmi_matched,
 850                .matches = {
 851                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 852                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
 853                },
 854                .driver_data = keymap_acer_travelmate_350
 855        },
 856        {
 857                /* Acer TravelMate 360 */
 858                .callback = dmi_matched,
 859                .matches = {
 860                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 861                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 862                },
 863                .driver_data = keymap_acer_travelmate_360
 864        },
 865        {
 866                /* Acer TravelMate 610 */
 867                .callback = dmi_matched,
 868                .matches = {
 869                        DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
 870                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
 871                },
 872                .driver_data = keymap_acer_travelmate_610
 873        },
 874        {
 875                /* Acer TravelMate 620 */
 876                .callback = dmi_matched,
 877                .matches = {
 878                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 879                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
 880                },
 881                .driver_data = keymap_acer_travelmate_630
 882        },
 883        {
 884                /* Acer TravelMate 630 */
 885                .callback = dmi_matched,
 886                .matches = {
 887                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 888                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
 889                },
 890                .driver_data = keymap_acer_travelmate_630
 891        },
 892        {
 893                /* AOpen 1559AS */
 894                .callback = dmi_matched,
 895                .matches = {
 896                        DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
 897                        DMI_MATCH(DMI_BOARD_NAME, "E2U"),
 898                },
 899                .driver_data = keymap_aopen_1559as
 900        },
 901        {
 902                /* Medion MD 9783 */
 903                .callback = dmi_matched,
 904                .matches = {
 905                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 906                        DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
 907                },
 908                .driver_data = keymap_wistron_ms2111
 909        },
 910        {
 911                /* Medion MD 40100 */
 912                .callback = dmi_matched,
 913                .matches = {
 914                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 915                        DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
 916                },
 917                .driver_data = keymap_wistron_md40100
 918        },
 919        {
 920                /* Medion MD 2900 */
 921                .callback = dmi_matched,
 922                .matches = {
 923                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 924                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
 925                },
 926                .driver_data = keymap_wistron_md2900
 927        },
 928        {
 929                /* Medion MD 42200 */
 930                .callback = dmi_matched,
 931                .matches = {
 932                        DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
 933                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"),
 934                },
 935                .driver_data = keymap_fs_amilo_pro_v2000
 936        },
 937        {
 938                /* Medion MD 96500 */
 939                .callback = dmi_matched,
 940                .matches = {
 941                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 942                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
 943                },
 944                .driver_data = keymap_wistron_md96500
 945        },
 946        {
 947                /* Medion MD 95400 */
 948                .callback = dmi_matched,
 949                .matches = {
 950                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 951                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
 952                },
 953                .driver_data = keymap_wistron_md96500
 954        },
 955        {
 956                /* Fujitsu Siemens Amilo D7820 */
 957                .callback = dmi_matched,
 958                .matches = {
 959                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
 960                        DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
 961                },
 962                .driver_data = keymap_fs_amilo_d88x0
 963        },
 964        {
 965                /* Fujitsu Siemens Amilo D88x0 */
 966                .callback = dmi_matched,
 967                .matches = {
 968                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 969                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
 970                },
 971                .driver_data = keymap_fs_amilo_d88x0
 972        },
 973        { NULL, }
 974};
 975
 976/* Copy the good keymap, as the original ones are free'd */
 977static int __init copy_keymap(void)
 978{
 979        const struct key_entry *key;
 980        struct key_entry *new_keymap;
 981        unsigned int length = 1;
 982
 983        for (key = keymap; key->type != KE_END; key++)
 984                length++;
 985
 986        new_keymap = kmemdup(keymap, length * sizeof(struct key_entry),
 987                             GFP_KERNEL);
 988        if (!new_keymap)
 989                return -ENOMEM;
 990
 991        keymap = new_keymap;
 992
 993        return 0;
 994}
 995
 996static int __init select_keymap(void)
 997{
 998        dmi_check_system(dmi_ids);
 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;
1008                else {
1009                        printk(KERN_ERR "wistron_btns: Keymap unknown\n");
1010                        return -EINVAL;
1011                }
1012        }
1013        if (keymap == NULL) {
1014                if (!force) {
1015                        printk(KERN_ERR "wistron_btns: System unknown\n");
1016                        return -ENODEV;
1017                }
1018                keymap = keymap_empty;
1019        }
1020
1021        return copy_keymap();
1022}
1023
1024 /* Input layer interface */
1025
1026static struct input_polled_dev *wistron_idev;
1027static unsigned long jiffies_last_press;
1028static bool wifi_enabled;
1029static bool bluetooth_enabled;
1030
1031 /* led management */
1032static void wistron_mail_led_set(struct led_classdev *led_cdev,
1033                                enum led_brightness value)
1034{
1035        bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
1036}
1037
1038/* same as setting up wifi card, but for laptops on which the led is managed */
1039static void wistron_wifi_led_set(struct led_classdev *led_cdev,
1040                                enum led_brightness value)
1041{
1042        bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
1043}
1044
1045static struct led_classdev wistron_mail_led = {
1046        .name                   = "wistron:green:mail",
1047        .brightness_set         = wistron_mail_led_set,
1048};
1049
1050static struct led_classdev wistron_wifi_led = {
1051        .name                   = "wistron:red:wifi",
1052        .brightness_set         = wistron_wifi_led_set,
1053};
1054
1055static void wistron_led_init(struct device *parent)
1056{
1057        if (leds_present & FE_WIFI_LED) {
1058                u16 wifi = bios_get_default_setting(WIFI);
1059                if (wifi & 1) {
1060                        wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
1061                        if (led_classdev_register(parent, &wistron_wifi_led))
1062                                leds_present &= ~FE_WIFI_LED;
1063                        else
1064                                bios_set_state(WIFI, wistron_wifi_led.brightness);
1065
1066                } else
1067                        leds_present &= ~FE_WIFI_LED;
1068        }
1069
1070        if (leds_present & FE_MAIL_LED) {
1071                /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
1072                wistron_mail_led.brightness = LED_OFF;
1073                if (led_classdev_register(parent, &wistron_mail_led))
1074                        leds_present &= ~FE_MAIL_LED;
1075                else
1076                        bios_set_state(MAIL_LED, wistron_mail_led.brightness);
1077        }
1078}
1079
1080static void wistron_led_remove(void)
1081{
1082        if (leds_present & FE_MAIL_LED)
1083                led_classdev_unregister(&wistron_mail_led);
1084
1085        if (leds_present & FE_WIFI_LED)
1086                led_classdev_unregister(&wistron_wifi_led);
1087}
1088
1089static inline void wistron_led_suspend(void)
1090{
1091        if (leds_present & FE_MAIL_LED)
1092                led_classdev_suspend(&wistron_mail_led);
1093
1094        if (leds_present & FE_WIFI_LED)
1095                led_classdev_suspend(&wistron_wifi_led);
1096}
1097
1098static inline void wistron_led_resume(void)
1099{
1100        if (leds_present & FE_MAIL_LED)
1101                led_classdev_resume(&wistron_mail_led);
1102
1103        if (leds_present & FE_WIFI_LED)
1104                led_classdev_resume(&wistron_wifi_led);
1105}
1106
1107static void handle_key(u8 code)
1108{
1109        const struct key_entry *key =
1110                sparse_keymap_entry_from_scancode(wistron_idev->input, code);
1111
1112        if (key) {
1113                switch (key->type) {
1114                case KE_WIFI:
1115                        if (have_wifi) {
1116                                wifi_enabled = !wifi_enabled;
1117                                bios_set_state(WIFI, wifi_enabled);
1118                        }
1119                        break;
1120
1121                case KE_BLUETOOTH:
1122                        if (have_bluetooth) {
1123                                bluetooth_enabled = !bluetooth_enabled;
1124                                bios_set_state(BLUETOOTH, bluetooth_enabled);
1125                        }
1126                        break;
1127
1128                default:
1129                        sparse_keymap_report_entry(wistron_idev->input,
1130                                                   key, 1, true);
1131                        break;
1132                }
1133                jiffies_last_press = jiffies;
1134        } else
1135                printk(KERN_NOTICE
1136                        "wistron_btns: Unknown key code %02X\n", code);
1137}
1138
1139static void poll_bios(bool discard)
1140{
1141        u8 qlen;
1142        u16 val;
1143
1144        for (;;) {
1145                qlen = CMOS_READ(cmos_address);
1146                if (qlen == 0)
1147                        break;
1148                val = bios_pop_queue();
1149                if (val != 0 && !discard)
1150                        handle_key((u8)val);
1151        }
1152}
1153
1154static void wistron_flush(struct input_polled_dev *dev)
1155{
1156        /* Flush stale event queue */
1157        poll_bios(true);
1158}
1159
1160static void wistron_poll(struct input_polled_dev *dev)
1161{
1162        poll_bios(false);
1163
1164        /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
1165        if (time_before(jiffies, jiffies_last_press + 2 * HZ))
1166                dev->poll_interval = POLL_INTERVAL_BURST;
1167        else
1168                dev->poll_interval = POLL_INTERVAL_DEFAULT;
1169}
1170
1171static int wistron_setup_keymap(struct input_dev *dev,
1172                                          struct key_entry *entry)
1173{
1174        switch (entry->type) {
1175
1176        /* if wifi or bluetooth are not available, create normal keys */
1177        case KE_WIFI:
1178                if (!have_wifi) {
1179                        entry->type = KE_KEY;
1180                        entry->keycode = KEY_WLAN;
1181                }
1182                break;
1183
1184        case KE_BLUETOOTH:
1185                if (!have_bluetooth) {
1186                        entry->type = KE_KEY;
1187                        entry->keycode = KEY_BLUETOOTH;
1188                }
1189                break;
1190
1191        case KE_END:
1192                if (entry->code & FE_UNTESTED)
1193                        printk(KERN_WARNING "Untested laptop multimedia keys, "
1194                                "please report success or failure to "
1195                                "eric.piel@tremplin-utc.net\n");
1196                break;
1197        }
1198
1199        return 0;
1200}
1201
1202static int setup_input_dev(void)
1203{
1204        struct input_dev *input_dev;
1205        int error;
1206
1207        wistron_idev = input_allocate_polled_device();
1208        if (!wistron_idev)
1209                return -ENOMEM;
1210
1211        wistron_idev->open = wistron_flush;
1212        wistron_idev->poll = wistron_poll;
1213        wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
1214
1215        input_dev = wistron_idev->input;
1216        input_dev->name = "Wistron laptop buttons";
1217        input_dev->phys = "wistron/input0";
1218        input_dev->id.bustype = BUS_HOST;
1219        input_dev->dev.parent = &wistron_device->dev;
1220
1221        error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
1222        if (error)
1223                goto err_free_dev;
1224
1225        error = input_register_polled_device(wistron_idev);
1226        if (error)
1227                goto err_free_keymap;
1228
1229        return 0;
1230
1231 err_free_keymap:
1232        sparse_keymap_free(input_dev);
1233 err_free_dev:
1234        input_free_polled_device(wistron_idev);
1235        return error;
1236}
1237
1238/* Driver core */
1239
1240static int wistron_probe(struct platform_device *dev)
1241{
1242        int err;
1243
1244        bios_attach();
1245        cmos_address = bios_get_cmos_address();
1246
1247        if (have_wifi) {
1248                u16 wifi = bios_get_default_setting(WIFI);
1249                if (wifi & 1)
1250                        wifi_enabled = wifi & 2;
1251                else
1252                        have_wifi = 0;
1253
1254                if (have_wifi)
1255                        bios_set_state(WIFI, wifi_enabled);
1256        }
1257
1258        if (have_bluetooth) {
1259                u16 bt = bios_get_default_setting(BLUETOOTH);
1260                if (bt & 1)
1261                        bluetooth_enabled = bt & 2;
1262                else
1263                        have_bluetooth = false;
1264
1265                if (have_bluetooth)
1266                        bios_set_state(BLUETOOTH, bluetooth_enabled);
1267        }
1268
1269        wistron_led_init(&dev->dev);
1270
1271        err = setup_input_dev();
1272        if (err) {
1273                bios_detach();
1274                return err;
1275        }
1276
1277        return 0;
1278}
1279
1280static int wistron_remove(struct platform_device *dev)
1281{
1282        wistron_led_remove();
1283        input_unregister_polled_device(wistron_idev);
1284        sparse_keymap_free(wistron_idev->input);
1285        input_free_polled_device(wistron_idev);
1286        bios_detach();
1287
1288        return 0;
1289}
1290
1291#ifdef CONFIG_PM
1292static int wistron_suspend(struct device *dev)
1293{
1294        if (have_wifi)
1295                bios_set_state(WIFI, 0);
1296
1297        if (have_bluetooth)
1298                bios_set_state(BLUETOOTH, 0);
1299
1300        wistron_led_suspend();
1301
1302        return 0;
1303}
1304
1305static int wistron_resume(struct device *dev)
1306{
1307        if (have_wifi)
1308                bios_set_state(WIFI, wifi_enabled);
1309
1310        if (have_bluetooth)
1311                bios_set_state(BLUETOOTH, bluetooth_enabled);
1312
1313        wistron_led_resume();
1314
1315        poll_bios(true);
1316
1317        return 0;
1318}
1319
1320static const struct dev_pm_ops wistron_pm_ops = {
1321        .suspend        = wistron_suspend,
1322        .resume         = wistron_resume,
1323        .poweroff       = wistron_suspend,
1324        .restore        = wistron_resume,
1325};
1326#endif
1327
1328static struct platform_driver wistron_driver = {
1329        .driver         = {
1330                .name   = "wistron-bios",
1331                .owner  = THIS_MODULE,
1332#ifdef CONFIG_PM
1333                .pm     = &wistron_pm_ops,
1334#endif
1335        },
1336        .probe          = wistron_probe,
1337        .remove         = wistron_remove,
1338};
1339
1340static int __init wb_module_init(void)
1341{
1342        int err;
1343
1344        err = select_keymap();
1345        if (err)
1346                return err;
1347
1348        err = map_bios();
1349        if (err)
1350                goto err_free_keymap;
1351
1352        err = platform_driver_register(&wistron_driver);
1353        if (err)
1354                goto err_unmap_bios;
1355
1356        wistron_device = platform_device_alloc("wistron-bios", -1);
1357        if (!wistron_device) {
1358                err = -ENOMEM;
1359                goto err_unregister_driver;
1360        }
1361
1362        err = platform_device_add(wistron_device);
1363        if (err)
1364                goto err_free_device;
1365
1366        return 0;
1367
1368 err_free_device:
1369        platform_device_put(wistron_device);
1370 err_unregister_driver:
1371        platform_driver_unregister(&wistron_driver);
1372 err_unmap_bios:
1373        unmap_bios();
1374 err_free_keymap:
1375        kfree(keymap);
1376
1377        return err;
1378}
1379
1380static void __exit wb_module_exit(void)
1381{
1382        platform_device_unregister(wistron_device);
1383        platform_driver_unregister(&wistron_driver);
1384        unmap_bios();
1385        kfree(keymap);
1386}
1387
1388module_init(wb_module_init);
1389module_exit(wb_module_exit);
1390