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");
  49
  50static bool force; /* = 0; */
  51module_param(force, bool, 0);
  52MODULE_PARM_DESC(force, "Load even if computer is not in database");
  53
  54static char *keymap_name; /* = NULL; */
  55module_param_named(keymap, keymap_name, charp, 0);
  56MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
  57
  58static struct platform_device *wistron_device;
  59
  60 /* BIOS interface implementation */
  61
  62static void __iomem *bios_entry_point; /* BIOS routine entry point */
  63static void __iomem *bios_code_map_base;
  64static void __iomem *bios_data_map_base;
  65
  66static u8 cmos_address;
  67
  68struct regs {
  69        u32 eax, ebx, ecx;
  70};
  71
  72static void call_bios(struct regs *regs)
  73{
  74        unsigned long flags;
  75
  76        preempt_disable();
  77        local_irq_save(flags);
  78        asm volatile ("pushl %%ebp;"
  79                      "movl %7, %%ebp;"
  80                      "call *%6;"
  81                      "popl %%ebp"
  82                      : "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx)
  83                      : "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx),
  84                        "m" (bios_entry_point), "m" (bios_data_map_base)
  85                      : "edx", "edi", "esi", "memory");
  86        local_irq_restore(flags);
  87        preempt_enable();
  88}
  89
  90static ssize_t __init locate_wistron_bios(void __iomem *base)
  91{
  92        static unsigned char __initdata signature[] =
  93                { 0x42, 0x21, 0x55, 0x30 };
  94        ssize_t offset;
  95
  96        for (offset = 0; offset < 0x10000; offset += 0x10) {
  97                if (check_signature(base + offset, signature,
  98                                    sizeof(signature)) != 0)
  99                        return offset;
 100        }
 101        return -1;
 102}
 103
 104static int __init map_bios(void)
 105{
 106        void __iomem *base;
 107        ssize_t offset;
 108        u32 entry_point;
 109
 110        base = ioremap(0xF0000, 0x10000); /* Can't fail */
 111        offset = locate_wistron_bios(base);
 112        if (offset < 0) {
 113                printk(KERN_ERR "wistron_btns: BIOS entry point not found\n");
 114                iounmap(base);
 115                return -ENODEV;
 116        }
 117
 118        entry_point = readl(base + offset + 5);
 119        printk(KERN_DEBUG
 120                "wistron_btns: BIOS signature found at %p, entry point %08X\n",
 121                base + offset, entry_point);
 122
 123        if (entry_point >= 0xF0000) {
 124                bios_code_map_base = base;
 125                bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
 126        } else {
 127                iounmap(base);
 128                bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000);
 129                if (bios_code_map_base == NULL) {
 130                        printk(KERN_ERR
 131                                "wistron_btns: Can't map BIOS code at %08X\n",
 132                                entry_point & ~0x3FFF);
 133                        goto err;
 134                }
 135                bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
 136        }
 137        /* The Windows driver maps 0x10000 bytes, we keep only one page... */
 138        bios_data_map_base = ioremap(0x400, 0xc00);
 139        if (bios_data_map_base == NULL) {
 140                printk(KERN_ERR "wistron_btns: Can't map BIOS data\n");
 141                goto err_code;
 142        }
 143        return 0;
 144
 145err_code:
 146        iounmap(bios_code_map_base);
 147err:
 148        return -ENOMEM;
 149}
 150
 151static inline void unmap_bios(void)
 152{
 153        iounmap(bios_code_map_base);
 154        iounmap(bios_data_map_base);
 155}
 156
 157 /* BIOS calls */
 158
 159static u16 bios_pop_queue(void)
 160{
 161        struct regs regs;
 162
 163        memset(&regs, 0, sizeof (regs));
 164        regs.eax = 0x9610;
 165        regs.ebx = 0x061C;
 166        regs.ecx = 0x0000;
 167        call_bios(&regs);
 168
 169        return regs.eax;
 170}
 171
 172static void bios_attach(void)
 173{
 174        struct regs regs;
 175
 176        memset(&regs, 0, sizeof (regs));
 177        regs.eax = 0x9610;
 178        regs.ebx = 0x012E;
 179        call_bios(&regs);
 180}
 181
 182static void bios_detach(void)
 183{
 184        struct regs regs;
 185
 186        memset(&regs, 0, sizeof (regs));
 187        regs.eax = 0x9610;
 188        regs.ebx = 0x002E;
 189        call_bios(&regs);
 190}
 191
 192static u8 bios_get_cmos_address(void)
 193{
 194        struct regs regs;
 195
 196        memset(&regs, 0, sizeof (regs));
 197        regs.eax = 0x9610;
 198        regs.ebx = 0x051C;
 199        call_bios(&regs);
 200
 201        return regs.ecx;
 202}
 203
 204static u16 bios_get_default_setting(u8 subsys)
 205{
 206        struct regs regs;
 207
 208        memset(&regs, 0, sizeof (regs));
 209        regs.eax = 0x9610;
 210        regs.ebx = 0x0200 | subsys;
 211        call_bios(&regs);
 212
 213        return regs.eax;
 214}
 215
 216static void bios_set_state(u8 subsys, int enable)
 217{
 218        struct regs regs;
 219
 220        memset(&regs, 0, sizeof (regs));
 221        regs.eax = 0x9610;
 222        regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
 223        call_bios(&regs);
 224}
 225
 226/* Hardware database */
 227
 228#define KE_WIFI         (KE_LAST + 1)
 229#define KE_BLUETOOTH    (KE_LAST + 2)
 230
 231#define FE_MAIL_LED 0x01
 232#define FE_WIFI_LED 0x02
 233#define FE_UNTESTED 0x80
 234
 235static struct key_entry *keymap; /* = NULL; Current key map */
 236static bool have_wifi;
 237static bool have_bluetooth;
 238static int leds_present;        /* bitmask of leds present */
 239
 240static int __init dmi_matched(const struct dmi_system_id *dmi)
 241{
 242        const struct key_entry *key;
 243
 244        keymap = dmi->driver_data;
 245        for (key = keymap; key->type != KE_END; key++) {
 246                if (key->type == KE_WIFI)
 247                        have_wifi = true;
 248                else if (key->type == KE_BLUETOOTH)
 249                        have_bluetooth = true;
 250        }
 251        leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED);
 252
 253        return 1;
 254}
 255
 256static struct key_entry keymap_empty[] __initdata = {
 257        { KE_END, 0 }
 258};
 259
 260static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
 261        { KE_KEY,  0x01, {KEY_HELP} },
 262        { KE_KEY,  0x11, {KEY_PROG1} },
 263        { KE_KEY,  0x12, {KEY_PROG2} },
 264        { KE_WIFI, 0x30 },
 265        { KE_KEY,  0x31, {KEY_MAIL} },
 266        { KE_KEY,  0x36, {KEY_WWW} },
 267        { KE_END,  0 }
 268};
 269
 270static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
 271        { KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */
 272        { KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
 273        { KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
 274        { KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
 275        { KE_KEY,       0x36, {KEY_WWW} },           /* www button */
 276        { KE_WIFI,      0x78 },                      /* satellite dish button */
 277        { KE_END,       0 }
 278};
 279
 280static struct key_entry keymap_fs_amilo_pro_v8210[] __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,       FE_WIFI_LED }
 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, 0 }
 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 const struct dmi_system_id dmi_ids[] __initconst = {
 648        {
 649                /* Fujitsu-Siemens Amilo Pro V2000 */
 650                .callback = dmi_matched,
 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                /* Fujitsu-Siemens Amilo Pro Edition V3505 */
 659                .callback = dmi_matched,
 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                /* Fujitsu-Siemens Amilo Pro Edition V8210 */
 668                .callback = dmi_matched,
 669                .matches = {
 670                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 671                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"),
 672                },
 673                .driver_data = keymap_fs_amilo_pro_v8210
 674        },
 675        {
 676                /* Fujitsu-Siemens Amilo M7400 */
 677                .callback = dmi_matched,
 678                .matches = {
 679                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 680                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M        "),
 681                },
 682                .driver_data = keymap_fs_amilo_pro_v2000
 683        },
 684        {
 685                /* Maxdata Pro 7000 DX */
 686                .callback = dmi_matched,
 687                .matches = {
 688                        DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
 689                        DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
 690                },
 691                .driver_data = keymap_fs_amilo_pro_v2000
 692        },
 693        {
 694                /* Fujitsu N3510 */
 695                .callback = dmi_matched,
 696                .matches = {
 697                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 698                        DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
 699                },
 700                .driver_data = keymap_fujitsu_n3510
 701        },
 702        {
 703                /* Acer Aspire 1500 */
 704                .callback = dmi_matched,
 705                .matches = {
 706                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 707                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
 708                },
 709                .driver_data = keymap_acer_aspire_1500
 710        },
 711        {
 712                /* Acer Aspire 1600 */
 713                .callback = dmi_matched,
 714                .matches = {
 715                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 716                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
 717                },
 718                .driver_data = keymap_acer_aspire_1600
 719        },
 720        {
 721                /* Acer Aspire 3020 */
 722                .callback = dmi_matched,
 723                .matches = {
 724                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 725                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
 726                },
 727                .driver_data = keymap_acer_aspire_5020
 728        },
 729        {
 730                /* Acer Aspire 5020 */
 731                .callback = dmi_matched,
 732                .matches = {
 733                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 734                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
 735                },
 736                .driver_data = keymap_acer_aspire_5020
 737        },
 738        {
 739                /* Acer TravelMate 2100 */
 740                .callback = dmi_matched,
 741                .matches = {
 742                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 743                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
 744                },
 745                .driver_data = keymap_acer_aspire_5020
 746        },
 747        {
 748                /* Acer TravelMate 2410 */
 749                .callback = dmi_matched,
 750                .matches = {
 751                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 752                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
 753                },
 754                .driver_data = keymap_acer_travelmate_2410
 755        },
 756        {
 757                /* Acer TravelMate C300 */
 758                .callback = dmi_matched,
 759                .matches = {
 760                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 761                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
 762                },
 763                .driver_data = keymap_acer_travelmate_300
 764        },
 765        {
 766                /* Acer TravelMate C100 */
 767                .callback = dmi_matched,
 768                .matches = {
 769                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 770                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
 771                },
 772                .driver_data = keymap_acer_travelmate_300
 773        },
 774        {
 775                /* Acer TravelMate C110 */
 776                .callback = dmi_matched,
 777                .matches = {
 778                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 779                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
 780                },
 781                .driver_data = keymap_acer_travelmate_110
 782        },
 783        {
 784                /* Acer TravelMate 380 */
 785                .callback = dmi_matched,
 786                .matches = {
 787                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 788                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
 789                },
 790                .driver_data = keymap_acer_travelmate_380
 791        },
 792        {
 793                /* Acer TravelMate 370 */
 794                .callback = dmi_matched,
 795                .matches = {
 796                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 797                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
 798                },
 799                .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
 800        },
 801        {
 802                /* Acer TravelMate 220 */
 803                .callback = dmi_matched,
 804                .matches = {
 805                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 806                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
 807                },
 808                .driver_data = keymap_acer_travelmate_220
 809        },
 810        {
 811                /* Acer TravelMate 260 */
 812                .callback = dmi_matched,
 813                .matches = {
 814                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 815                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
 816                },
 817                .driver_data = keymap_acer_travelmate_220
 818        },
 819        {
 820                /* Acer TravelMate 230 */
 821                .callback = dmi_matched,
 822                .matches = {
 823                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 824                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
 825                        /* acerhk looks for "TravelMate F4..." ?! */
 826                },
 827                .driver_data = keymap_acer_travelmate_230
 828        },
 829        {
 830                /* Acer TravelMate 280 */
 831                .callback = dmi_matched,
 832                .matches = {
 833                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 834                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
 835                },
 836                .driver_data = keymap_acer_travelmate_230
 837        },
 838        {
 839                /* Acer TravelMate 240 */
 840                .callback = dmi_matched,
 841                .matches = {
 842                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 843                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
 844                },
 845                .driver_data = keymap_acer_travelmate_240
 846        },
 847        {
 848                /* Acer TravelMate 250 */
 849                .callback = dmi_matched,
 850                .matches = {
 851                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 852                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
 853                },
 854                .driver_data = keymap_acer_travelmate_240
 855        },
 856        {
 857                /* Acer TravelMate 2424NWXCi */
 858                .callback = dmi_matched,
 859                .matches = {
 860                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 861                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"),
 862                },
 863                .driver_data = keymap_acer_travelmate_240
 864        },
 865        {
 866                /* Acer TravelMate 350 */
 867                .callback = dmi_matched,
 868                .matches = {
 869                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 870                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
 871                },
 872                .driver_data = keymap_acer_travelmate_350
 873        },
 874        {
 875                /* Acer TravelMate 360 */
 876                .callback = dmi_matched,
 877                .matches = {
 878                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 879                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 880                },
 881                .driver_data = keymap_acer_travelmate_360
 882        },
 883        {
 884                /* Acer TravelMate 610 */
 885                .callback = dmi_matched,
 886                .matches = {
 887                        DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
 888                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
 889                },
 890                .driver_data = keymap_acer_travelmate_610
 891        },
 892        {
 893                /* Acer TravelMate 620 */
 894                .callback = dmi_matched,
 895                .matches = {
 896                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 897                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
 898                },
 899                .driver_data = keymap_acer_travelmate_630
 900        },
 901        {
 902                /* Acer TravelMate 630 */
 903                .callback = dmi_matched,
 904                .matches = {
 905                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 906                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
 907                },
 908                .driver_data = keymap_acer_travelmate_630
 909        },
 910        {
 911                /* AOpen 1559AS */
 912                .callback = dmi_matched,
 913                .matches = {
 914                        DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
 915                        DMI_MATCH(DMI_BOARD_NAME, "E2U"),
 916                },
 917                .driver_data = keymap_aopen_1559as
 918        },
 919        {
 920                /* Medion MD 9783 */
 921                .callback = dmi_matched,
 922                .matches = {
 923                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 924                        DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
 925                },
 926                .driver_data = keymap_wistron_ms2111
 927        },
 928        {
 929                /* Medion MD 40100 */
 930                .callback = dmi_matched,
 931                .matches = {
 932                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 933                        DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
 934                },
 935                .driver_data = keymap_wistron_md40100
 936        },
 937        {
 938                /* Medion MD 2900 */
 939                .callback = dmi_matched,
 940                .matches = {
 941                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 942                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
 943                },
 944                .driver_data = keymap_wistron_md2900
 945        },
 946        {
 947                /* Medion MD 42200 */
 948                .callback = dmi_matched,
 949                .matches = {
 950                        DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
 951                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"),
 952                },
 953                .driver_data = keymap_fs_amilo_pro_v2000
 954        },
 955        {
 956                /* Medion MD 96500 */
 957                .callback = dmi_matched,
 958                .matches = {
 959                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 960                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
 961                },
 962                .driver_data = keymap_wistron_md96500
 963        },
 964        {
 965                /* Medion MD 95400 */
 966                .callback = dmi_matched,
 967                .matches = {
 968                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 969                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
 970                },
 971                .driver_data = keymap_wistron_md96500
 972        },
 973        {
 974                /* Fujitsu Siemens Amilo D7820 */
 975                .callback = dmi_matched,
 976                .matches = {
 977                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
 978                        DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
 979                },
 980                .driver_data = keymap_fs_amilo_d88x0
 981        },
 982        {
 983                /* Fujitsu Siemens Amilo D88x0 */
 984                .callback = dmi_matched,
 985                .matches = {
 986                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 987                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
 988                },
 989                .driver_data = keymap_fs_amilo_d88x0
 990        },
 991        { NULL, }
 992};
 993MODULE_DEVICE_TABLE(dmi, dmi_ids);
 994
 995/* Copy the good keymap, as the original ones are free'd */
 996static int __init copy_keymap(void)
 997{
 998        const struct key_entry *key;
 999        struct key_entry *new_keymap;
1000        unsigned int length = 1;
1001
1002        for (key = keymap; key->type != KE_END; key++)
1003                length++;
1004
1005        new_keymap = kmemdup(keymap, length * sizeof(struct key_entry),
1006                             GFP_KERNEL);
1007        if (!new_keymap)
1008                return -ENOMEM;
1009
1010        keymap = new_keymap;
1011
1012        return 0;
1013}
1014
1015static int __init select_keymap(void)
1016{
1017        dmi_check_system(dmi_ids);
1018        if (keymap_name != NULL) {
1019                if (strcmp (keymap_name, "1557/MS2141") == 0)
1020                        keymap = keymap_wistron_ms2141;
1021                else if (strcmp (keymap_name, "aopen1557") == 0)
1022                        keymap = keymap_aopen_1557;
1023                else if (strcmp (keymap_name, "prestigio") == 0)
1024                        keymap = keymap_prestigio;
1025                else if (strcmp (keymap_name, "generic") == 0)
1026                        keymap = keymap_wistron_generic;
1027                else {
1028                        printk(KERN_ERR "wistron_btns: Keymap unknown\n");
1029                        return -EINVAL;
1030                }
1031        }
1032        if (keymap == NULL) {
1033                if (!force) {
1034                        printk(KERN_ERR "wistron_btns: System unknown\n");
1035                        return -ENODEV;
1036                }
1037                keymap = keymap_empty;
1038        }
1039
1040        return copy_keymap();
1041}
1042
1043 /* Input layer interface */
1044
1045static struct input_polled_dev *wistron_idev;
1046static unsigned long jiffies_last_press;
1047static bool wifi_enabled;
1048static bool bluetooth_enabled;
1049
1050 /* led management */
1051static void wistron_mail_led_set(struct led_classdev *led_cdev,
1052                                enum led_brightness value)
1053{
1054        bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
1055}
1056
1057/* same as setting up wifi card, but for laptops on which the led is managed */
1058static void wistron_wifi_led_set(struct led_classdev *led_cdev,
1059                                enum led_brightness value)
1060{
1061        bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
1062}
1063
1064static struct led_classdev wistron_mail_led = {
1065        .name                   = "wistron:green:mail",
1066        .brightness_set         = wistron_mail_led_set,
1067};
1068
1069static struct led_classdev wistron_wifi_led = {
1070        .name                   = "wistron:red:wifi",
1071        .brightness_set         = wistron_wifi_led_set,
1072};
1073
1074static void wistron_led_init(struct device *parent)
1075{
1076        if (leds_present & FE_WIFI_LED) {
1077                u16 wifi = bios_get_default_setting(WIFI);
1078                if (wifi & 1) {
1079                        wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
1080                        if (led_classdev_register(parent, &wistron_wifi_led))
1081                                leds_present &= ~FE_WIFI_LED;
1082                        else
1083                                bios_set_state(WIFI, wistron_wifi_led.brightness);
1084
1085                } else
1086                        leds_present &= ~FE_WIFI_LED;
1087        }
1088
1089        if (leds_present & FE_MAIL_LED) {
1090                /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
1091                wistron_mail_led.brightness = LED_OFF;
1092                if (led_classdev_register(parent, &wistron_mail_led))
1093                        leds_present &= ~FE_MAIL_LED;
1094                else
1095                        bios_set_state(MAIL_LED, wistron_mail_led.brightness);
1096        }
1097}
1098
1099static void wistron_led_remove(void)
1100{
1101        if (leds_present & FE_MAIL_LED)
1102                led_classdev_unregister(&wistron_mail_led);
1103
1104        if (leds_present & FE_WIFI_LED)
1105                led_classdev_unregister(&wistron_wifi_led);
1106}
1107
1108static inline void wistron_led_suspend(void)
1109{
1110        if (leds_present & FE_MAIL_LED)
1111                led_classdev_suspend(&wistron_mail_led);
1112
1113        if (leds_present & FE_WIFI_LED)
1114                led_classdev_suspend(&wistron_wifi_led);
1115}
1116
1117static inline void wistron_led_resume(void)
1118{
1119        if (leds_present & FE_MAIL_LED)
1120                led_classdev_resume(&wistron_mail_led);
1121
1122        if (leds_present & FE_WIFI_LED)
1123                led_classdev_resume(&wistron_wifi_led);
1124}
1125
1126static void handle_key(u8 code)
1127{
1128        const struct key_entry *key =
1129                sparse_keymap_entry_from_scancode(wistron_idev->input, code);
1130
1131        if (key) {
1132                switch (key->type) {
1133                case KE_WIFI:
1134                        if (have_wifi) {
1135                                wifi_enabled = !wifi_enabled;
1136                                bios_set_state(WIFI, wifi_enabled);
1137                        }
1138                        break;
1139
1140                case KE_BLUETOOTH:
1141                        if (have_bluetooth) {
1142                                bluetooth_enabled = !bluetooth_enabled;
1143                                bios_set_state(BLUETOOTH, bluetooth_enabled);
1144                        }
1145                        break;
1146
1147                default:
1148                        sparse_keymap_report_entry(wistron_idev->input,
1149                                                   key, 1, true);
1150                        break;
1151                }
1152                jiffies_last_press = jiffies;
1153        } else
1154                printk(KERN_NOTICE
1155                        "wistron_btns: Unknown key code %02X\n", code);
1156}
1157
1158static void poll_bios(bool discard)
1159{
1160        u8 qlen;
1161        u16 val;
1162
1163        for (;;) {
1164                qlen = CMOS_READ(cmos_address);
1165                if (qlen == 0)
1166                        break;
1167                val = bios_pop_queue();
1168                if (val != 0 && !discard)
1169                        handle_key((u8)val);
1170        }
1171}
1172
1173static void wistron_flush(struct input_polled_dev *dev)
1174{
1175        /* Flush stale event queue */
1176        poll_bios(true);
1177}
1178
1179static void wistron_poll(struct input_polled_dev *dev)
1180{
1181        poll_bios(false);
1182
1183        /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
1184        if (time_before(jiffies, jiffies_last_press + 2 * HZ))
1185                dev->poll_interval = POLL_INTERVAL_BURST;
1186        else
1187                dev->poll_interval = POLL_INTERVAL_DEFAULT;
1188}
1189
1190static int wistron_setup_keymap(struct input_dev *dev,
1191                                          struct key_entry *entry)
1192{
1193        switch (entry->type) {
1194
1195        /* if wifi or bluetooth are not available, create normal keys */
1196        case KE_WIFI:
1197                if (!have_wifi) {
1198                        entry->type = KE_KEY;
1199                        entry->keycode = KEY_WLAN;
1200                }
1201                break;
1202
1203        case KE_BLUETOOTH:
1204                if (!have_bluetooth) {
1205                        entry->type = KE_KEY;
1206                        entry->keycode = KEY_BLUETOOTH;
1207                }
1208                break;
1209
1210        case KE_END:
1211                if (entry->code & FE_UNTESTED)
1212                        printk(KERN_WARNING "Untested laptop multimedia keys, "
1213                                "please report success or failure to "
1214                                "eric.piel@tremplin-utc.net\n");
1215                break;
1216        }
1217
1218        return 0;
1219}
1220
1221static int setup_input_dev(void)
1222{
1223        struct input_dev *input_dev;
1224        int error;
1225
1226        wistron_idev = input_allocate_polled_device();
1227        if (!wistron_idev)
1228                return -ENOMEM;
1229
1230        wistron_idev->open = wistron_flush;
1231        wistron_idev->poll = wistron_poll;
1232        wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
1233
1234        input_dev = wistron_idev->input;
1235        input_dev->name = "Wistron laptop buttons";
1236        input_dev->phys = "wistron/input0";
1237        input_dev->id.bustype = BUS_HOST;
1238        input_dev->dev.parent = &wistron_device->dev;
1239
1240        error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
1241        if (error)
1242                goto err_free_dev;
1243
1244        error = input_register_polled_device(wistron_idev);
1245        if (error)
1246                goto err_free_dev;
1247
1248        return 0;
1249
1250 err_free_dev:
1251        input_free_polled_device(wistron_idev);
1252        return error;
1253}
1254
1255/* Driver core */
1256
1257static int wistron_probe(struct platform_device *dev)
1258{
1259        int err;
1260
1261        bios_attach();
1262        cmos_address = bios_get_cmos_address();
1263
1264        if (have_wifi) {
1265                u16 wifi = bios_get_default_setting(WIFI);
1266                if (wifi & 1)
1267                        wifi_enabled = wifi & 2;
1268                else
1269                        have_wifi = 0;
1270
1271                if (have_wifi)
1272                        bios_set_state(WIFI, wifi_enabled);
1273        }
1274
1275        if (have_bluetooth) {
1276                u16 bt = bios_get_default_setting(BLUETOOTH);
1277                if (bt & 1)
1278                        bluetooth_enabled = bt & 2;
1279                else
1280                        have_bluetooth = false;
1281
1282                if (have_bluetooth)
1283                        bios_set_state(BLUETOOTH, bluetooth_enabled);
1284        }
1285
1286        wistron_led_init(&dev->dev);
1287
1288        err = setup_input_dev();
1289        if (err) {
1290                bios_detach();
1291                return err;
1292        }
1293
1294        return 0;
1295}
1296
1297static int wistron_remove(struct platform_device *dev)
1298{
1299        wistron_led_remove();
1300        input_unregister_polled_device(wistron_idev);
1301        input_free_polled_device(wistron_idev);
1302        bios_detach();
1303
1304        return 0;
1305}
1306
1307#ifdef CONFIG_PM
1308static int wistron_suspend(struct device *dev)
1309{
1310        if (have_wifi)
1311                bios_set_state(WIFI, 0);
1312
1313        if (have_bluetooth)
1314                bios_set_state(BLUETOOTH, 0);
1315
1316        wistron_led_suspend();
1317
1318        return 0;
1319}
1320
1321static int wistron_resume(struct device *dev)
1322{
1323        if (have_wifi)
1324                bios_set_state(WIFI, wifi_enabled);
1325
1326        if (have_bluetooth)
1327                bios_set_state(BLUETOOTH, bluetooth_enabled);
1328
1329        wistron_led_resume();
1330
1331        poll_bios(true);
1332
1333        return 0;
1334}
1335
1336static const struct dev_pm_ops wistron_pm_ops = {
1337        .suspend        = wistron_suspend,
1338        .resume         = wistron_resume,
1339        .poweroff       = wistron_suspend,
1340        .restore        = wistron_resume,
1341};
1342#endif
1343
1344static struct platform_driver wistron_driver = {
1345        .driver         = {
1346                .name   = "wistron-bios",
1347#ifdef CONFIG_PM
1348                .pm     = &wistron_pm_ops,
1349#endif
1350        },
1351        .probe          = wistron_probe,
1352        .remove         = wistron_remove,
1353};
1354
1355static int __init wb_module_init(void)
1356{
1357        int err;
1358
1359        err = select_keymap();
1360        if (err)
1361                return err;
1362
1363        err = map_bios();
1364        if (err)
1365                goto err_free_keymap;
1366
1367        err = platform_driver_register(&wistron_driver);
1368        if (err)
1369                goto err_unmap_bios;
1370
1371        wistron_device = platform_device_alloc("wistron-bios", -1);
1372        if (!wistron_device) {
1373                err = -ENOMEM;
1374                goto err_unregister_driver;
1375        }
1376
1377        err = platform_device_add(wistron_device);
1378        if (err)
1379                goto err_free_device;
1380
1381        return 0;
1382
1383 err_free_device:
1384        platform_device_put(wistron_device);
1385 err_unregister_driver:
1386        platform_driver_unregister(&wistron_driver);
1387 err_unmap_bios:
1388        unmap_bios();
1389 err_free_keymap:
1390        kfree(keymap);
1391
1392        return err;
1393}
1394
1395static void __exit wb_module_exit(void)
1396{
1397        platform_device_unregister(wistron_device);
1398        platform_driver_unregister(&wistron_driver);
1399        unmap_bios();
1400        kfree(keymap);
1401}
1402
1403module_init(wb_module_init);
1404module_exit(wb_module_exit);
1405