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(®s, 0, sizeof (regs)); 164 regs.eax = 0x9610; 165 regs.ebx = 0x061C; 166 regs.ecx = 0x0000; 167 call_bios(®s); 168 169 return regs.eax; 170} 171 172static void bios_attach(void) 173{ 174 struct regs regs; 175 176 memset(®s, 0, sizeof (regs)); 177 regs.eax = 0x9610; 178 regs.ebx = 0x012E; 179 call_bios(®s); 180} 181 182static void bios_detach(void) 183{ 184 struct regs regs; 185 186 memset(®s, 0, sizeof (regs)); 187 regs.eax = 0x9610; 188 regs.ebx = 0x002E; 189 call_bios(®s); 190} 191 192static u8 bios_get_cmos_address(void) 193{ 194 struct regs regs; 195 196 memset(®s, 0, sizeof (regs)); 197 regs.eax = 0x9610; 198 regs.ebx = 0x051C; 199 call_bios(®s); 200 201 return regs.ecx; 202} 203 204static u16 bios_get_default_setting(u8 subsys) 205{ 206 struct regs regs; 207 208 memset(®s, 0, sizeof (regs)); 209 regs.eax = 0x9610; 210 regs.ebx = 0x0200 | subsys; 211 call_bios(®s); 212 213 return regs.eax; 214} 215 216static void bios_set_state(u8 subsys, int enable) 217{ 218 struct regs regs; 219 220 memset(®s, 0, sizeof (regs)); 221 regs.eax = 0x9610; 222 regs.ebx = (enable ? 0x0100 : 0x0000) | subsys; 223 call_bios(®s); 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_keymap; 1247 1248 return 0; 1249 1250 err_free_keymap: 1251 sparse_keymap_free(input_dev); 1252 err_free_dev: 1253 input_free_polled_device(wistron_idev); 1254 return error; 1255} 1256 1257/* Driver core */ 1258 1259static int wistron_probe(struct platform_device *dev) 1260{ 1261 int err; 1262 1263 bios_attach(); 1264 cmos_address = bios_get_cmos_address(); 1265 1266 if (have_wifi) { 1267 u16 wifi = bios_get_default_setting(WIFI); 1268 if (wifi & 1) 1269 wifi_enabled = wifi & 2; 1270 else 1271 have_wifi = 0; 1272 1273 if (have_wifi) 1274 bios_set_state(WIFI, wifi_enabled); 1275 } 1276 1277 if (have_bluetooth) { 1278 u16 bt = bios_get_default_setting(BLUETOOTH); 1279 if (bt & 1) 1280 bluetooth_enabled = bt & 2; 1281 else 1282 have_bluetooth = false; 1283 1284 if (have_bluetooth) 1285 bios_set_state(BLUETOOTH, bluetooth_enabled); 1286 } 1287 1288 wistron_led_init(&dev->dev); 1289 1290 err = setup_input_dev(); 1291 if (err) { 1292 bios_detach(); 1293 return err; 1294 } 1295 1296 return 0; 1297} 1298 1299static int wistron_remove(struct platform_device *dev) 1300{ 1301 wistron_led_remove(); 1302 input_unregister_polled_device(wistron_idev); 1303 sparse_keymap_free(wistron_idev->input); 1304 input_free_polled_device(wistron_idev); 1305 bios_detach(); 1306 1307 return 0; 1308} 1309 1310#ifdef CONFIG_PM 1311static int wistron_suspend(struct device *dev) 1312{ 1313 if (have_wifi) 1314 bios_set_state(WIFI, 0); 1315 1316 if (have_bluetooth) 1317 bios_set_state(BLUETOOTH, 0); 1318 1319 wistron_led_suspend(); 1320 1321 return 0; 1322} 1323 1324static int wistron_resume(struct device *dev) 1325{ 1326 if (have_wifi) 1327 bios_set_state(WIFI, wifi_enabled); 1328 1329 if (have_bluetooth) 1330 bios_set_state(BLUETOOTH, bluetooth_enabled); 1331 1332 wistron_led_resume(); 1333 1334 poll_bios(true); 1335 1336 return 0; 1337} 1338 1339static const struct dev_pm_ops wistron_pm_ops = { 1340 .suspend = wistron_suspend, 1341 .resume = wistron_resume, 1342 .poweroff = wistron_suspend, 1343 .restore = wistron_resume, 1344}; 1345#endif 1346 1347static struct platform_driver wistron_driver = { 1348 .driver = { 1349 .name = "wistron-bios", 1350#ifdef CONFIG_PM 1351 .pm = &wistron_pm_ops, 1352#endif 1353 }, 1354 .probe = wistron_probe, 1355 .remove = wistron_remove, 1356}; 1357 1358static int __init wb_module_init(void) 1359{ 1360 int err; 1361 1362 err = select_keymap(); 1363 if (err) 1364 return err; 1365 1366 err = map_bios(); 1367 if (err) 1368 goto err_free_keymap; 1369 1370 err = platform_driver_register(&wistron_driver); 1371 if (err) 1372 goto err_unmap_bios; 1373 1374 wistron_device = platform_device_alloc("wistron-bios", -1); 1375 if (!wistron_device) { 1376 err = -ENOMEM; 1377 goto err_unregister_driver; 1378 } 1379 1380 err = platform_device_add(wistron_device); 1381 if (err) 1382 goto err_free_device; 1383 1384 return 0; 1385 1386 err_free_device: 1387 platform_device_put(wistron_device); 1388 err_unregister_driver: 1389 platform_driver_unregister(&wistron_driver); 1390 err_unmap_bios: 1391 unmap_bios(); 1392 err_free_keymap: 1393 kfree(keymap); 1394 1395 return err; 1396} 1397 1398static void __exit wb_module_exit(void) 1399{ 1400 platform_device_unregister(wistron_device); 1401 platform_driver_unregister(&wistron_driver); 1402 unmap_bios(); 1403 kfree(keymap); 1404} 1405 1406module_init(wb_module_init); 1407module_exit(wb_module_exit); 1408