Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Bernhard Rosenkraenzer <bero@arklinux.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Bernhard Rosenkraenzer and committed by
Dmitry Torokhov
84b256a6 e9fb028e

+59 -20
+59 -20
drivers/input/misc/wistron_btns.c
··· 1 1 /* 2 2 * Wistron laptop button driver 3 3 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 4 + * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> 4 5 * 5 6 * You can redistribute and/or modify this program under the terms of the 6 7 * GNU General Public License version 2 as published by the Free Software ··· 40 39 #if POLL_FREQUENCY > HZ 41 40 #error "POLL_FREQUENCY too high" 42 41 #endif 42 + 43 + /* BIOS subsystem IDs */ 44 + #define WIFI 0x35 45 + #define BLUETOOTH 0x34 43 46 44 47 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 45 48 MODULE_DESCRIPTION("Wistron laptop button driver"); ··· 202 197 return regs.ecx; 203 198 } 204 199 205 - static u16 __init bios_wifi_get_default_setting(void) 200 + static u16 __init bios_get_default_setting(u8 subsys) 206 201 { 207 202 struct regs regs; 208 203 209 204 memset(&regs, 0, sizeof (regs)); 210 205 regs.eax = 0x9610; 211 - regs.ebx = 0x0235; 206 + regs.ebx = 0x0200 | subsys; 212 207 call_bios(&regs); 213 208 214 209 return regs.eax; 215 210 } 216 211 217 - static void bios_wifi_set_state(int enable) 212 + static void bios_set_state(u8 subsys, int enable) 218 213 { 219 214 struct regs regs; 220 215 221 216 memset(&regs, 0, sizeof (regs)); 222 217 regs.eax = 0x9610; 223 - regs.ebx = enable ? 0x0135 : 0x0035; 218 + regs.ebx = (enable ? 0x0100 : 0x0000) | subsys; 224 219 call_bios(&regs); 225 220 } 226 221 227 - /* Hardware database */ 222 + /* Hardware database */ 228 223 229 224 struct key_entry { 230 225 char type; /* See KE_* below */ ··· 232 227 unsigned keycode; /* For KE_KEY */ 233 228 }; 234 229 235 - enum { KE_END, KE_KEY, KE_WIFI }; 230 + enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH }; 236 231 237 232 static const struct key_entry *keymap; /* = NULL; Current key map */ 238 233 static int have_wifi; 234 + static int have_bluetooth; 239 235 240 236 static int __init dmi_matched(struct dmi_system_id *dmi) 241 237 { ··· 246 240 for (key = keymap; key->type != KE_END; key++) { 247 241 if (key->type == KE_WIFI) { 248 242 have_wifi = 1; 243 + break; 244 + } else if (key->type == KE_BLUETOOTH) { 245 + have_bluetooth = 1; 249 246 break; 250 247 } 251 248 } ··· 282 273 { KE_END, 0 } 283 274 }; 284 275 276 + static struct key_entry keymap_acer_aspire_1500[] = { 277 + { KE_KEY, 0x11, KEY_PROG1 }, 278 + { KE_KEY, 0x12, KEY_PROG2 }, 279 + { KE_WIFI, 0x30, 0 }, 280 + { KE_KEY, 0x31, KEY_MAIL }, 281 + { KE_KEY, 0x36, KEY_WWW }, 282 + { KE_BLUETOOTH, 0x44, 0 }, 283 + { KE_END, 0 } 284 + }; 285 + 285 286 /* 286 287 * If your machine is not here (which is currently rather likely), please send 287 288 * a list of buttons and their key codes (reported when loading this module ··· 306 287 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), 307 288 }, 308 289 .driver_data = keymap_fs_amilo_pro_v2000 290 + }, 291 + { 292 + .callback = dmi_matched, 293 + .ident = "Acer Aspire 1500", 294 + .matches = { 295 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 296 + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), 297 + }, 298 + .driver_data = keymap_acer_aspire_1500 309 299 }, 310 300 { 0, } 311 301 }; ··· 372 344 /* Driver core */ 373 345 374 346 static int wifi_enabled; 347 + static int bluetooth_enabled; 375 348 376 349 static void poll_bios(unsigned long); 377 350 ··· 392 363 case KE_WIFI: 393 364 if (have_wifi) { 394 365 wifi_enabled = !wifi_enabled; 395 - bios_wifi_set_state(wifi_enabled); 366 + bios_set_state(WIFI, wifi_enabled); 367 + } 368 + break; 369 + 370 + case KE_BLUETOOTH: 371 + if (have_bluetooth) { 372 + bluetooth_enabled = !bluetooth_enabled; 373 + bios_set_state(BLUETOOTH, bluetooth_enabled); 396 374 } 397 375 break; 398 376 ··· 443 407 bios_attach(); 444 408 cmos_address = bios_get_cmos_address(); 445 409 if (have_wifi) { 446 - switch (bios_wifi_get_default_setting()) { 447 - case 0x01: 448 - wifi_enabled = 0; 449 - break; 450 - 451 - case 0x03: 452 - wifi_enabled = 1; 453 - break; 454 - 455 - default: 410 + u16 wifi = bios_get_default_setting(WIFI); 411 + if (wifi & 1) 412 + wifi_enabled = (wifi & 2) ? 1 : 0; 413 + else 456 414 have_wifi = 0; 457 - break; 458 - } 415 + 459 416 if (have_wifi) 460 - bios_wifi_set_state(wifi_enabled); 417 + bios_set_state(WIFI, wifi_enabled); 418 + } 419 + if (have_bluetooth) { 420 + u16 bt = bios_get_default_setting(BLUETOOTH); 421 + if (bt & 1) 422 + bluetooth_enabled = (bt & 2) ? 1 : 0; 423 + else 424 + have_bluetooth = 0; 425 + 426 + if (have_bluetooth) 427 + bios_set_state(BLUETOOTH, bluetooth_enabled); 461 428 } 462 429 463 430 setup_input_dev();