Commit 84b256a6 authored by Bernhard Rosenkraenzer's avatar Bernhard Rosenkraenzer Committed by Dmitry Torokhov

Input: wistron - add support for Acer Aspire 1500 notebooks

Also fix a potential issue with some notebooks:

The current code assumes the response to bios_wifi_get_default_setting is
either 1 (disabled) or 3 (enabled), or wifi isn't supported.  The BIOS
response appears to be a bit field w/ 0x1 indicating hardware presence, 0x2
indicating actiation status, and the other 6 bits being unknown/reserved --
with the patch, these 6 bits are ignored.
Signed-off-by: default avatarBernhard Rosenkraenzer <bero@arklinux.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent e9fb028e
/* /*
* Wistron laptop button driver * Wistron laptop button driver
* Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
* Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
* *
* You can redistribute and/or modify this program under the terms of the * You can redistribute and/or modify this program under the terms of the
* GNU General Public License version 2 as published by the Free Software * GNU General Public License version 2 as published by the Free Software
...@@ -40,6 +41,10 @@ ...@@ -40,6 +41,10 @@
#error "POLL_FREQUENCY too high" #error "POLL_FREQUENCY too high"
#endif #endif
/* BIOS subsystem IDs */
#define WIFI 0x35
#define BLUETOOTH 0x34
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
MODULE_DESCRIPTION("Wistron laptop button driver"); MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -197,29 +202,29 @@ static u8 __init bios_get_cmos_address(void) ...@@ -197,29 +202,29 @@ static u8 __init bios_get_cmos_address(void)
return regs.ecx; return regs.ecx;
} }
static u16 __init bios_wifi_get_default_setting(void) static u16 __init bios_get_default_setting(u8 subsys)
{ {
struct regs regs; struct regs regs;
memset(&regs, 0, sizeof (regs)); memset(&regs, 0, sizeof (regs));
regs.eax = 0x9610; regs.eax = 0x9610;
regs.ebx = 0x0235; regs.ebx = 0x0200 | subsys;
call_bios(&regs); call_bios(&regs);
return regs.eax; return regs.eax;
} }
static void bios_wifi_set_state(int enable) static void bios_set_state(u8 subsys, int enable)
{ {
struct regs regs; struct regs regs;
memset(&regs, 0, sizeof (regs)); memset(&regs, 0, sizeof (regs));
regs.eax = 0x9610; regs.eax = 0x9610;
regs.ebx = enable ? 0x0135 : 0x0035; regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
call_bios(&regs); call_bios(&regs);
} }
/* Hardware database */ /* Hardware database */
struct key_entry { struct key_entry {
char type; /* See KE_* below */ char type; /* See KE_* below */
...@@ -227,10 +232,11 @@ struct key_entry { ...@@ -227,10 +232,11 @@ struct key_entry {
unsigned keycode; /* For KE_KEY */ unsigned keycode; /* For KE_KEY */
}; };
enum { KE_END, KE_KEY, KE_WIFI }; enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
static const struct key_entry *keymap; /* = NULL; Current key map */ static const struct key_entry *keymap; /* = NULL; Current key map */
static int have_wifi; static int have_wifi;
static int have_bluetooth;
static int __init dmi_matched(struct dmi_system_id *dmi) static int __init dmi_matched(struct dmi_system_id *dmi)
{ {
...@@ -241,6 +247,9 @@ static int __init dmi_matched(struct dmi_system_id *dmi) ...@@ -241,6 +247,9 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
if (key->type == KE_WIFI) { if (key->type == KE_WIFI) {
have_wifi = 1; have_wifi = 1;
break; break;
} else if (key->type == KE_BLUETOOTH) {
have_bluetooth = 1;
break;
} }
} }
return 1; return 1;
...@@ -273,6 +282,16 @@ static struct key_entry keymap_wistron_ms2141[] = { ...@@ -273,6 +282,16 @@ static struct key_entry keymap_wistron_ms2141[] = {
{ KE_END, 0 } { KE_END, 0 }
}; };
static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_WIFI, 0x30, 0 },
{ KE_KEY, 0x31, KEY_MAIL },
{ KE_KEY, 0x36, KEY_WWW },
{ KE_BLUETOOTH, 0x44, 0 },
{ KE_END, 0 }
};
/* /*
* If your machine is not here (which is currently rather likely), please send * 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 * a list of buttons and their key codes (reported when loading this module
...@@ -288,6 +307,15 @@ static struct dmi_system_id dmi_ids[] = { ...@@ -288,6 +307,15 @@ static struct dmi_system_id dmi_ids[] = {
}, },
.driver_data = keymap_fs_amilo_pro_v2000 .driver_data = keymap_fs_amilo_pro_v2000
}, },
{
.callback = dmi_matched,
.ident = "Acer Aspire 1500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
},
.driver_data = keymap_acer_aspire_1500
},
{ 0, } { 0, }
}; };
...@@ -344,6 +372,7 @@ static void report_key(unsigned keycode) ...@@ -344,6 +372,7 @@ static void report_key(unsigned keycode)
/* Driver core */ /* Driver core */
static int wifi_enabled; static int wifi_enabled;
static int bluetooth_enabled;
static void poll_bios(unsigned long); static void poll_bios(unsigned long);
...@@ -363,7 +392,14 @@ static void handle_key(u8 code) ...@@ -363,7 +392,14 @@ static void handle_key(u8 code)
case KE_WIFI: case KE_WIFI:
if (have_wifi) { if (have_wifi) {
wifi_enabled = !wifi_enabled; wifi_enabled = !wifi_enabled;
bios_wifi_set_state(wifi_enabled); bios_set_state(WIFI, wifi_enabled);
}
break;
case KE_BLUETOOTH:
if (have_bluetooth) {
bluetooth_enabled = !bluetooth_enabled;
bios_set_state(BLUETOOTH, bluetooth_enabled);
} }
break; break;
...@@ -407,21 +443,24 @@ static int __init wb_module_init(void) ...@@ -407,21 +443,24 @@ static int __init wb_module_init(void)
bios_attach(); bios_attach();
cmos_address = bios_get_cmos_address(); cmos_address = bios_get_cmos_address();
if (have_wifi) { if (have_wifi) {
switch (bios_wifi_get_default_setting()) { u16 wifi = bios_get_default_setting(WIFI);
case 0x01: if (wifi & 1)
wifi_enabled = 0; wifi_enabled = (wifi & 2) ? 1 : 0;
break; else
case 0x03:
wifi_enabled = 1;
break;
default:
have_wifi = 0; have_wifi = 0;
break;
}
if (have_wifi) if (have_wifi)
bios_wifi_set_state(wifi_enabled); bios_set_state(WIFI, wifi_enabled);
}
if (have_bluetooth) {
u16 bt = bios_get_default_setting(BLUETOOTH);
if (bt & 1)
bluetooth_enabled = (bt & 2) ? 1 : 0;
else
have_bluetooth = 0;
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
} }
setup_input_dev(); setup_input_dev();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment