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