include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / input / misc / wistron_btns.c
index 26e17a9..04d5a4a 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/input-polldev.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
@@ -28,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/preempt.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
@@ -224,28 +226,17 @@ static void bios_set_state(u8 subsys, int enable)
 
 /* Hardware database */
 
-struct key_entry {
-       char type;              /* See KE_* below */
-       u8 code;
-       union {
-               u16 keycode;            /* For KE_KEY */
-               struct {                /* For KE_SW */
-                       u8 code;
-                       u8 value;
-               } sw;
-       };
-};
-
-enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
+#define KE_WIFI                (KE_LAST + 1)
+#define KE_BLUETOOTH   (KE_LAST + 2)
 
 #define FE_MAIL_LED 0x01
 #define FE_WIFI_LED 0x02
 #define FE_UNTESTED 0x80
 
 static struct key_entry *keymap; /* = NULL; Current key map */
-static int have_wifi;
-static int have_bluetooth;
-static int have_leds;
+static bool have_wifi;
+static bool have_bluetooth;
+static int leds_present;       /* bitmask of leds present */
 
 static int __init dmi_matched(const struct dmi_system_id *dmi)
 {
@@ -254,11 +245,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi)
        keymap = dmi->driver_data;
        for (key = keymap; key->type != KE_END; key++) {
                if (key->type == KE_WIFI)
-                       have_wifi = 1;
+                       have_wifi = true;
                else if (key->type == KE_BLUETOOTH)
-                       have_bluetooth = 1;
+                       have_bluetooth = true;
        }
-       have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+       leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED);
 
        return 1;
 }
@@ -611,15 +602,43 @@ static struct key_entry keymap_wistron_generic[] __initdata = {
        { KE_END, 0 }
 };
 
+static struct key_entry keymap_aopen_1557[] __initdata = {
+       { KE_KEY,  0x01, {KEY_HELP} },
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY,  0x22, {KEY_REWIND} },
+       { KE_KEY,  0x23, {KEY_FORWARD} },
+       { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY,  0x25, {KEY_STOPCD} },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
+       { KE_END,  0 }
+};
+
+static struct key_entry keymap_prestigio[] __initdata = {
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY,  0x22, {KEY_REWIND} },
+       { KE_KEY,  0x23, {KEY_FORWARD} },
+       { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY,  0x25, {KEY_STOPCD} },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
+       { KE_END,  0 }
+};
+
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
  * with force=1) and the output of dmidecode to $MODULE_AUTHOR.
  */
-static struct dmi_system_id dmi_ids[] __initdata = {
+static const struct dmi_system_id __initconst dmi_ids[] = {
        {
+               /* Fujitsu-Siemens Amilo Pro V2000 */
                .callback = dmi_matched,
-               .ident = "Fujitsu-Siemens Amilo Pro V2000",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"),
@@ -627,8 +646,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fs_amilo_pro_v2000
        },
        {
+               /* Fujitsu-Siemens Amilo Pro Edition V3505 */
                .callback = dmi_matched,
-               .ident = "Fujitsu-Siemens Amilo Pro Edition V3505",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
@@ -636,8 +655,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fs_amilo_pro_v3505
        },
        {
+               /* Fujitsu-Siemens Amilo M7400 */
                .callback = dmi_matched,
-               .ident = "Fujitsu-Siemens Amilo M7400",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M        "),
@@ -645,8 +664,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fs_amilo_pro_v2000
        },
        {
+               /* Maxdata Pro 7000 DX */
                .callback = dmi_matched,
-               .ident = "Maxdata Pro 7000 DX",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
@@ -654,8 +673,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fs_amilo_pro_v2000
        },
        {
+               /* Fujitsu N3510 */
                .callback = dmi_matched,
-               .ident = "Fujitsu N3510",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
@@ -663,8 +682,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fujitsu_n3510
        },
        {
+               /* Acer Aspire 1500 */
                .callback = dmi_matched,
-               .ident = "Acer Aspire 1500",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
@@ -672,8 +691,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_aspire_1500
        },
        {
+               /* Acer Aspire 1600 */
                .callback = dmi_matched,
-               .ident = "Acer Aspire 1600",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
@@ -681,8 +700,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_aspire_1600
        },
        {
+               /* Acer Aspire 3020 */
                .callback = dmi_matched,
-               .ident = "Acer Aspire 3020",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
@@ -690,8 +709,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_aspire_5020
        },
        {
+               /* Acer Aspire 5020 */
                .callback = dmi_matched,
-               .ident = "Acer Aspire 5020",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
@@ -699,8 +718,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_aspire_5020
        },
        {
+               /* Acer TravelMate 2100 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 2100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
@@ -708,8 +727,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_aspire_5020
        },
        {
+               /* Acer TravelMate 2410 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 2410",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
@@ -717,8 +736,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_2410
        },
        {
+               /* Acer TravelMate C300 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate C300",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
@@ -726,8 +745,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_300
        },
        {
+               /* Acer TravelMate C100 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate C100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
@@ -735,8 +754,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_300
        },
        {
+               /* Acer TravelMate C110 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate C110",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
@@ -744,8 +763,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_110
        },
        {
+               /* Acer TravelMate 380 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 380",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
@@ -753,8 +772,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_380
        },
        {
+               /* Acer TravelMate 370 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 370",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
@@ -762,8 +781,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
        },
        {
+               /* Acer TravelMate 220 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 220",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
@@ -771,8 +790,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_220
        },
        {
+               /* Acer TravelMate 260 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 260",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
@@ -780,8 +799,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_220
        },
        {
+               /* Acer TravelMate 230 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 230",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
@@ -790,8 +809,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_230
        },
        {
+               /* Acer TravelMate 280 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 280",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
@@ -799,8 +818,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_230
        },
        {
+               /* Acer TravelMate 240 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 240",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
@@ -808,8 +827,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_240
        },
        {
+               /* Acer TravelMate 250 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 250",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
@@ -817,8 +836,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_240
        },
        {
+               /* Acer TravelMate 2424NWXCi */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 2424NWXCi",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"),
@@ -826,8 +845,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_240
        },
        {
+               /* Acer TravelMate 350 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 350",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
@@ -835,8 +854,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_350
        },
        {
+               /* Acer TravelMate 360 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 360",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
@@ -844,8 +863,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_360
        },
        {
+               /* Acer TravelMate 610 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 610",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
@@ -853,8 +872,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_610
        },
        {
+               /* Acer TravelMate 620 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 620",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
@@ -862,8 +881,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_630
        },
        {
+               /* Acer TravelMate 630 */
                .callback = dmi_matched,
-               .ident = "Acer TravelMate 630",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
@@ -871,8 +890,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_acer_travelmate_630
        },
        {
+               /* AOpen 1559AS */
                .callback = dmi_matched,
-               .ident = "AOpen 1559AS",
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
                        DMI_MATCH(DMI_BOARD_NAME, "E2U"),
@@ -880,8 +899,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_aopen_1559as
        },
        {
+               /* Medion MD 9783 */
                .callback = dmi_matched,
-               .ident = "Medion MD 9783",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
@@ -889,8 +908,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_wistron_ms2111
        },
        {
+               /* Medion MD 40100 */
                .callback = dmi_matched,
-               .ident = "Medion MD 40100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
@@ -898,8 +917,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_wistron_md40100
        },
        {
+               /* Medion MD 2900 */
                .callback = dmi_matched,
-               .ident = "Medion MD 2900",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
@@ -907,8 +926,17 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_wistron_md2900
        },
        {
+               /* Medion MD 42200 */
+               .callback = dmi_matched,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v2000
+       },
+       {
+               /* Medion MD 96500 */
                .callback = dmi_matched,
-               .ident = "Medion MD 96500",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
@@ -916,8 +944,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_wistron_md96500
        },
        {
+               /* Medion MD 95400 */
                .callback = dmi_matched,
-               .ident = "Medion MD 95400",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
@@ -925,8 +953,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_wistron_md96500
        },
        {
+               /* Fujitsu Siemens Amilo D7820 */
                .callback = dmi_matched,
-               .ident = "Fujitsu Siemens Amilo D7820",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
                        DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
@@ -934,8 +962,8 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                .driver_data = keymap_fs_amilo_d88x0
        },
        {
+               /* Fujitsu Siemens Amilo D88x0 */
                .callback = dmi_matched,
-               .ident = "Fujitsu Siemens Amilo D88x0",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
@@ -971,6 +999,10 @@ static int __init select_keymap(void)
        if (keymap_name != NULL) {
                if (strcmp (keymap_name, "1557/MS2141") == 0)
                        keymap = keymap_wistron_ms2141;
+               else if (strcmp (keymap_name, "aopen1557") == 0)
+                       keymap = keymap_aopen_1557;
+               else if (strcmp (keymap_name, "prestigio") == 0)
+                       keymap = keymap_prestigio;
                else if (strcmp (keymap_name, "generic") == 0)
                        keymap = keymap_wistron_generic;
                else {
@@ -993,23 +1025,8 @@ static int __init select_keymap(void)
 
 static struct input_polled_dev *wistron_idev;
 static unsigned long jiffies_last_press;
-static int wifi_enabled;
-static int bluetooth_enabled;
-
-static void report_key(struct input_dev *dev, unsigned int keycode)
-{
-       input_report_key(dev, keycode, 1);
-       input_sync(dev);
-       input_report_key(dev, keycode, 0);
-       input_sync(dev);
-}
-
-static void report_switch(struct input_dev *dev, unsigned int code, int value)
-{
-       input_report_switch(dev, code, value);
-       input_sync(dev);
-}
-
+static bool wifi_enabled;
+static bool bluetooth_enabled;
 
  /* led management */
 static void wistron_mail_led_set(struct led_classdev *led_cdev,
@@ -1037,24 +1054,24 @@ static struct led_classdev wistron_wifi_led = {
 
 static void __devinit wistron_led_init(struct device *parent)
 {
-       if (have_leds & FE_WIFI_LED) {
+       if (leds_present & FE_WIFI_LED) {
                u16 wifi = bios_get_default_setting(WIFI);
                if (wifi & 1) {
                        wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
                        if (led_classdev_register(parent, &wistron_wifi_led))
-                               have_leds &= ~FE_WIFI_LED;
+                               leds_present &= ~FE_WIFI_LED;
                        else
                                bios_set_state(WIFI, wistron_wifi_led.brightness);
 
                } else
-                       have_leds &= ~FE_WIFI_LED;
+                       leds_present &= ~FE_WIFI_LED;
        }
 
-       if (have_leds & FE_MAIL_LED) {
+       if (leds_present & FE_MAIL_LED) {
                /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
                wistron_mail_led.brightness = LED_OFF;
                if (led_classdev_register(parent, &wistron_mail_led))
-                       have_leds &= ~FE_MAIL_LED;
+                       leds_present &= ~FE_MAIL_LED;
                else
                        bios_set_state(MAIL_LED, wistron_mail_led.brightness);
        }
@@ -1062,68 +1079,38 @@ static void __devinit wistron_led_init(struct device *parent)
 
 static void __devexit wistron_led_remove(void)
 {
-       if (have_leds & FE_MAIL_LED)
+       if (leds_present & FE_MAIL_LED)
                led_classdev_unregister(&wistron_mail_led);
 
-       if (have_leds & FE_WIFI_LED)
+       if (leds_present & FE_WIFI_LED)
                led_classdev_unregister(&wistron_wifi_led);
 }
 
 static inline void wistron_led_suspend(void)
 {
-       if (have_leds & FE_MAIL_LED)
+       if (leds_present & FE_MAIL_LED)
                led_classdev_suspend(&wistron_mail_led);
 
-       if (have_leds & FE_WIFI_LED)
+       if (leds_present & FE_WIFI_LED)
                led_classdev_suspend(&wistron_wifi_led);
 }
 
 static inline void wistron_led_resume(void)
 {
-       if (have_leds & FE_MAIL_LED)
+       if (leds_present & FE_MAIL_LED)
                led_classdev_resume(&wistron_mail_led);
 
-       if (have_leds & FE_WIFI_LED)
+       if (leds_present & FE_WIFI_LED)
                led_classdev_resume(&wistron_wifi_led);
 }
 
-static struct key_entry *wistron_get_entry_by_scancode(int code)
-{
-       struct key_entry *key;
-
-       for (key = keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *wistron_get_entry_by_keycode(int keycode)
-{
-       struct key_entry *key;
-
-       for (key = keymap; key->type != KE_END; key++)
-               if (key->type == KE_KEY && keycode == key->keycode)
-                       return key;
-
-       return NULL;
-}
-
 static void handle_key(u8 code)
 {
-       const struct key_entry *key = wistron_get_entry_by_scancode(code);
+       const struct key_entry *key =
+               sparse_keymap_entry_from_scancode(wistron_idev->input, code);
 
        if (key) {
                switch (key->type) {
-               case KE_KEY:
-                       report_key(wistron_idev->input, key->keycode);
-                       break;
-
-               case KE_SW:
-                       report_switch(wistron_idev->input,
-                                     key->sw.code, key->sw.value);
-                       break;
-
                case KE_WIFI:
                        if (have_wifi) {
                                wifi_enabled = !wifi_enabled;
@@ -1139,7 +1126,9 @@ static void handle_key(u8 code)
                        break;
 
                default:
-                       BUG();
+                       sparse_keymap_report_entry(wistron_idev->input,
+                                                  key, 1, true);
+                       break;
                }
                jiffies_last_press = jiffies;
        } else
@@ -1179,42 +1168,39 @@ static void wistron_poll(struct input_polled_dev *dev)
                dev->poll_interval = POLL_INTERVAL_DEFAULT;
 }
 
-static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+static int __devinit wistron_setup_keymap(struct input_dev *dev,
+                                         struct key_entry *entry)
 {
-       const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
+       switch (entry->type) {
 
-       return -EINVAL;
-}
+       /* if wifi or bluetooth are not available, create normal keys */
+       case KE_WIFI:
+               if (!have_wifi) {
+                       entry->type = KE_KEY;
+                       entry->keycode = KEY_WLAN;
+               }
+               break;
 
-static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-       struct key_entry *key;
-       int old_keycode;
-
-       if (keycode < 0 || keycode > KEY_MAX)
-               return -EINVAL;
-
-       key = wistron_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!wistron_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
+       case KE_BLUETOOTH:
+               if (!have_bluetooth) {
+                       entry->type = KE_KEY;
+                       entry->keycode = KEY_BLUETOOTH;
+               }
+               break;
+
+       case KE_END:
+               if (entry->code & FE_UNTESTED)
+                       printk(KERN_WARNING "Untested laptop multimedia keys, "
+                               "please report success or failure to "
+                               "eric.piel@tremplin-utc.net\n");
+               break;
        }
 
-       return -EINVAL;
+       return 0;
 }
 
 static int __devinit setup_input_dev(void)
 {
-       struct key_entry *key;
        struct input_dev *input_dev;
        int error;
 
@@ -1222,7 +1208,7 @@ static int __devinit setup_input_dev(void)
        if (!wistron_idev)
                return -ENOMEM;
 
-       wistron_idev->flush = wistron_flush;
+       wistron_idev->open = wistron_flush;
        wistron_idev->poll = wistron_poll;
        wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
 
@@ -1232,56 +1218,21 @@ static int __devinit setup_input_dev(void)
        input_dev->id.bustype = BUS_HOST;
        input_dev->dev.parent = &wistron_device->dev;
 
-       input_dev->getkeycode = wistron_getkeycode;
-       input_dev->setkeycode = wistron_setkeycode;
-
-       for (key = keymap; key->type != KE_END; key++) {
-               switch (key->type) {
-                       case KE_KEY:
-                               set_bit(EV_KEY, input_dev->evbit);
-                               set_bit(key->keycode, input_dev->keybit);
-                               break;
-
-                       case KE_SW:
-                               set_bit(EV_SW, input_dev->evbit);
-                               set_bit(key->sw.code, input_dev->swbit);
-                               break;
-
-                       /* if wifi or bluetooth are not available, create normal keys */
-                       case KE_WIFI:
-                               if (!have_wifi) {
-                                       key->type = KE_KEY;
-                                       key->keycode = KEY_WLAN;
-                                       key--;
-                               }
-                               break;
-
-                       case KE_BLUETOOTH:
-                               if (!have_bluetooth) {
-                                       key->type = KE_KEY;
-                                       key->keycode = KEY_BLUETOOTH;
-                                       key--;
-                               }
-                               break;
-
-                       default:
-                               break;
-               }
-       }
-
-       /* reads information flags on KE_END */
-       if (key->code & FE_UNTESTED)
-               printk(KERN_WARNING "Untested laptop multimedia keys, "
-                       "please report success or failure to eric.piel"
-                       "@tremplin-utc.net\n");
+       error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
+       if (error)
+               goto err_free_dev;
 
        error = input_register_polled_device(wistron_idev);
-       if (error) {
-               input_free_polled_device(wistron_idev);
-               return error;
-       }
+       if (error)
+               goto err_free_keymap;
 
        return 0;
+
+ err_free_keymap:
+       sparse_keymap_free(input_dev);
+ err_free_dev:
+       input_free_polled_device(wistron_idev);
+       return error;
 }
 
 /* Driver core */
@@ -1296,7 +1247,7 @@ static int __devinit wistron_probe(struct platform_device *dev)
        if (have_wifi) {
                u16 wifi = bios_get_default_setting(WIFI);
                if (wifi & 1)
-                       wifi_enabled = (wifi & 2) ? 1 : 0;
+                       wifi_enabled = wifi & 2;
                else
                        have_wifi = 0;
 
@@ -1307,15 +1258,16 @@ static int __devinit wistron_probe(struct platform_device *dev)
        if (have_bluetooth) {
                u16 bt = bios_get_default_setting(BLUETOOTH);
                if (bt & 1)
-                       bluetooth_enabled = (bt & 2) ? 1 : 0;
+                       bluetooth_enabled = bt & 2;
                else
-                       have_bluetooth = 0;
+                       have_bluetooth = false;
 
                if (have_bluetooth)
                        bios_set_state(BLUETOOTH, bluetooth_enabled);
        }
 
        wistron_led_init(&dev->dev);
+
        err = setup_input_dev();
        if (err) {
                bios_detach();
@@ -1329,6 +1281,7 @@ static int __devexit wistron_remove(struct platform_device *dev)
 {
        wistron_led_remove();
        input_unregister_polled_device(wistron_idev);
+       sparse_keymap_free(wistron_idev->input);
        input_free_polled_device(wistron_idev);
        bios_detach();
 
@@ -1336,7 +1289,7 @@ static int __devexit wistron_remove(struct platform_device *dev)
 }
 
 #ifdef CONFIG_PM
-static int wistron_suspend(struct platform_device *dev, pm_message_t state)
+static int wistron_suspend(struct device *dev)
 {
        if (have_wifi)
                bios_set_state(WIFI, 0);
@@ -1345,10 +1298,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state)
                bios_set_state(BLUETOOTH, 0);
 
        wistron_led_suspend();
+
        return 0;
 }
 
-static int wistron_resume(struct platform_device *dev)
+static int wistron_resume(struct device *dev)
 {
        if (have_wifi)
                bios_set_state(WIFI, wifi_enabled);
@@ -1357,24 +1311,30 @@ static int wistron_resume(struct platform_device *dev)
                bios_set_state(BLUETOOTH, bluetooth_enabled);
 
        wistron_led_resume();
+
        poll_bios(true);
 
        return 0;
 }
-#else
-#define wistron_suspend                NULL
-#define wistron_resume         NULL
+
+static const struct dev_pm_ops wistron_pm_ops = {
+       .suspend        = wistron_suspend,
+       .resume         = wistron_resume,
+       .poweroff       = wistron_suspend,
+       .restore        = wistron_resume,
+};
 #endif
 
 static struct platform_driver wistron_driver = {
        .driver         = {
                .name   = "wistron-bios",
                .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &wistron_pm_ops,
+#endif
        },
        .probe          = wistron_probe,
        .remove         = __devexit_p(wistron_remove),
-       .suspend        = wistron_suspend,
-       .resume         = wistron_resume,
 };
 
 static int __init wb_module_init(void)