Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/misc/wistron_btns.c
15109 views
1
/*
2
* Wistron laptop button driver
3
* Copyright (C) 2005 Miloslav Trmac <[email protected]>
4
* Copyright (C) 2005 Bernhard Rosenkraenzer <[email protected]>
5
* Copyright (C) 2005 Dmitry Torokhov <[email protected]>
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
46
MODULE_AUTHOR("Miloslav Trmac <[email protected]>");
47
MODULE_DESCRIPTION("Wistron laptop button driver");
48
MODULE_LICENSE("GPL v2");
49
MODULE_VERSION("0.3");
50
51
static int force; /* = 0; */
52
module_param(force, bool, 0);
53
MODULE_PARM_DESC(force, "Load even if computer is not in database");
54
55
static char *keymap_name; /* = NULL; */
56
module_param_named(keymap, keymap_name, charp, 0);
57
MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
58
59
static struct platform_device *wistron_device;
60
61
/* BIOS interface implementation */
62
63
static void __iomem *bios_entry_point; /* BIOS routine entry point */
64
static void __iomem *bios_code_map_base;
65
static void __iomem *bios_data_map_base;
66
67
static u8 cmos_address;
68
69
struct regs {
70
u32 eax, ebx, ecx;
71
};
72
73
static void call_bios(struct regs *regs)
74
{
75
unsigned long flags;
76
77
preempt_disable();
78
local_irq_save(flags);
79
asm volatile ("pushl %%ebp;"
80
"movl %7, %%ebp;"
81
"call *%6;"
82
"popl %%ebp"
83
: "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx)
84
: "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx),
85
"m" (bios_entry_point), "m" (bios_data_map_base)
86
: "edx", "edi", "esi", "memory");
87
local_irq_restore(flags);
88
preempt_enable();
89
}
90
91
static ssize_t __init locate_wistron_bios(void __iomem *base)
92
{
93
static unsigned char __initdata signature[] =
94
{ 0x42, 0x21, 0x55, 0x30 };
95
ssize_t offset;
96
97
for (offset = 0; offset < 0x10000; offset += 0x10) {
98
if (check_signature(base + offset, signature,
99
sizeof(signature)) != 0)
100
return offset;
101
}
102
return -1;
103
}
104
105
static int __init map_bios(void)
106
{
107
void __iomem *base;
108
ssize_t offset;
109
u32 entry_point;
110
111
base = ioremap(0xF0000, 0x10000); /* Can't fail */
112
offset = locate_wistron_bios(base);
113
if (offset < 0) {
114
printk(KERN_ERR "wistron_btns: BIOS entry point not found\n");
115
iounmap(base);
116
return -ENODEV;
117
}
118
119
entry_point = readl(base + offset + 5);
120
printk(KERN_DEBUG
121
"wistron_btns: BIOS signature found at %p, entry point %08X\n",
122
base + offset, entry_point);
123
124
if (entry_point >= 0xF0000) {
125
bios_code_map_base = base;
126
bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
127
} else {
128
iounmap(base);
129
bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000);
130
if (bios_code_map_base == NULL) {
131
printk(KERN_ERR
132
"wistron_btns: Can't map BIOS code at %08X\n",
133
entry_point & ~0x3FFF);
134
goto err;
135
}
136
bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
137
}
138
/* The Windows driver maps 0x10000 bytes, we keep only one page... */
139
bios_data_map_base = ioremap(0x400, 0xc00);
140
if (bios_data_map_base == NULL) {
141
printk(KERN_ERR "wistron_btns: Can't map BIOS data\n");
142
goto err_code;
143
}
144
return 0;
145
146
err_code:
147
iounmap(bios_code_map_base);
148
err:
149
return -ENOMEM;
150
}
151
152
static inline void unmap_bios(void)
153
{
154
iounmap(bios_code_map_base);
155
iounmap(bios_data_map_base);
156
}
157
158
/* BIOS calls */
159
160
static u16 bios_pop_queue(void)
161
{
162
struct regs regs;
163
164
memset(&regs, 0, sizeof (regs));
165
regs.eax = 0x9610;
166
regs.ebx = 0x061C;
167
regs.ecx = 0x0000;
168
call_bios(&regs);
169
170
return regs.eax;
171
}
172
173
static void __devinit bios_attach(void)
174
{
175
struct regs regs;
176
177
memset(&regs, 0, sizeof (regs));
178
regs.eax = 0x9610;
179
regs.ebx = 0x012E;
180
call_bios(&regs);
181
}
182
183
static void bios_detach(void)
184
{
185
struct regs regs;
186
187
memset(&regs, 0, sizeof (regs));
188
regs.eax = 0x9610;
189
regs.ebx = 0x002E;
190
call_bios(&regs);
191
}
192
193
static u8 __devinit bios_get_cmos_address(void)
194
{
195
struct regs regs;
196
197
memset(&regs, 0, sizeof (regs));
198
regs.eax = 0x9610;
199
regs.ebx = 0x051C;
200
call_bios(&regs);
201
202
return regs.ecx;
203
}
204
205
static u16 __devinit bios_get_default_setting(u8 subsys)
206
{
207
struct regs regs;
208
209
memset(&regs, 0, sizeof (regs));
210
regs.eax = 0x9610;
211
regs.ebx = 0x0200 | subsys;
212
call_bios(&regs);
213
214
return regs.eax;
215
}
216
217
static void bios_set_state(u8 subsys, int enable)
218
{
219
struct regs regs;
220
221
memset(&regs, 0, sizeof (regs));
222
regs.eax = 0x9610;
223
regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
224
call_bios(&regs);
225
}
226
227
/* Hardware database */
228
229
#define KE_WIFI (KE_LAST + 1)
230
#define KE_BLUETOOTH (KE_LAST + 2)
231
232
#define FE_MAIL_LED 0x01
233
#define FE_WIFI_LED 0x02
234
#define FE_UNTESTED 0x80
235
236
static struct key_entry *keymap; /* = NULL; Current key map */
237
static bool have_wifi;
238
static bool have_bluetooth;
239
static int leds_present; /* bitmask of leds present */
240
241
static int __init dmi_matched(const struct dmi_system_id *dmi)
242
{
243
const struct key_entry *key;
244
245
keymap = dmi->driver_data;
246
for (key = keymap; key->type != KE_END; key++) {
247
if (key->type == KE_WIFI)
248
have_wifi = true;
249
else if (key->type == KE_BLUETOOTH)
250
have_bluetooth = true;
251
}
252
leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED);
253
254
return 1;
255
}
256
257
static struct key_entry keymap_empty[] __initdata = {
258
{ KE_END, 0 }
259
};
260
261
static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
262
{ KE_KEY, 0x01, {KEY_HELP} },
263
{ KE_KEY, 0x11, {KEY_PROG1} },
264
{ KE_KEY, 0x12, {KEY_PROG2} },
265
{ KE_WIFI, 0x30 },
266
{ KE_KEY, 0x31, {KEY_MAIL} },
267
{ KE_KEY, 0x36, {KEY_WWW} },
268
{ KE_END, 0 }
269
};
270
271
static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
272
{ KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */
273
{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
274
{ KE_BLUETOOTH, 0x30 }, /* Fn+F10 */
275
{ KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */
276
{ KE_KEY, 0x36, {KEY_WWW} }, /* www button */
277
{ KE_WIFI, 0x78 }, /* satellite dish button */
278
{ KE_END, 0 }
279
};
280
281
static struct key_entry keymap_fujitsu_n3510[] __initdata = {
282
{ KE_KEY, 0x11, {KEY_PROG1} },
283
{ KE_KEY, 0x12, {KEY_PROG2} },
284
{ KE_KEY, 0x36, {KEY_WWW} },
285
{ KE_KEY, 0x31, {KEY_MAIL} },
286
{ KE_KEY, 0x71, {KEY_STOPCD} },
287
{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
288
{ KE_KEY, 0x74, {KEY_REWIND} },
289
{ KE_KEY, 0x78, {KEY_FORWARD} },
290
{ KE_END, 0 }
291
};
292
293
static struct key_entry keymap_wistron_ms2111[] __initdata = {
294
{ KE_KEY, 0x11, {KEY_PROG1} },
295
{ KE_KEY, 0x12, {KEY_PROG2} },
296
{ KE_KEY, 0x13, {KEY_PROG3} },
297
{ KE_KEY, 0x31, {KEY_MAIL} },
298
{ KE_KEY, 0x36, {KEY_WWW} },
299
{ KE_END, FE_MAIL_LED }
300
};
301
302
static struct key_entry keymap_wistron_md40100[] __initdata = {
303
{ KE_KEY, 0x01, {KEY_HELP} },
304
{ KE_KEY, 0x02, {KEY_CONFIG} },
305
{ KE_KEY, 0x31, {KEY_MAIL} },
306
{ KE_KEY, 0x36, {KEY_WWW} },
307
{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
308
{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
309
};
310
311
static struct key_entry keymap_wistron_ms2141[] __initdata = {
312
{ KE_KEY, 0x11, {KEY_PROG1} },
313
{ KE_KEY, 0x12, {KEY_PROG2} },
314
{ KE_WIFI, 0x30 },
315
{ KE_KEY, 0x22, {KEY_REWIND} },
316
{ KE_KEY, 0x23, {KEY_FORWARD} },
317
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
318
{ KE_KEY, 0x25, {KEY_STOPCD} },
319
{ KE_KEY, 0x31, {KEY_MAIL} },
320
{ KE_KEY, 0x36, {KEY_WWW} },
321
{ KE_END, 0 }
322
};
323
324
static struct key_entry keymap_acer_aspire_1500[] __initdata = {
325
{ KE_KEY, 0x01, {KEY_HELP} },
326
{ KE_KEY, 0x03, {KEY_POWER} },
327
{ KE_KEY, 0x11, {KEY_PROG1} },
328
{ KE_KEY, 0x12, {KEY_PROG2} },
329
{ KE_WIFI, 0x30 },
330
{ KE_KEY, 0x31, {KEY_MAIL} },
331
{ KE_KEY, 0x36, {KEY_WWW} },
332
{ KE_KEY, 0x49, {KEY_CONFIG} },
333
{ KE_BLUETOOTH, 0x44 },
334
{ KE_END, FE_UNTESTED }
335
};
336
337
static struct key_entry keymap_acer_aspire_1600[] __initdata = {
338
{ KE_KEY, 0x01, {KEY_HELP} },
339
{ KE_KEY, 0x03, {KEY_POWER} },
340
{ KE_KEY, 0x08, {KEY_MUTE} },
341
{ KE_KEY, 0x11, {KEY_PROG1} },
342
{ KE_KEY, 0x12, {KEY_PROG2} },
343
{ KE_KEY, 0x13, {KEY_PROG3} },
344
{ KE_KEY, 0x31, {KEY_MAIL} },
345
{ KE_KEY, 0x36, {KEY_WWW} },
346
{ KE_KEY, 0x49, {KEY_CONFIG} },
347
{ KE_WIFI, 0x30 },
348
{ KE_BLUETOOTH, 0x44 },
349
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
350
};
351
352
/* 3020 has been tested */
353
static struct key_entry keymap_acer_aspire_5020[] __initdata = {
354
{ KE_KEY, 0x01, {KEY_HELP} },
355
{ KE_KEY, 0x03, {KEY_POWER} },
356
{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
357
{ KE_KEY, 0x11, {KEY_PROG1} },
358
{ KE_KEY, 0x12, {KEY_PROG2} },
359
{ KE_KEY, 0x31, {KEY_MAIL} },
360
{ KE_KEY, 0x36, {KEY_WWW} },
361
{ KE_KEY, 0x6a, {KEY_CONFIG} },
362
{ KE_WIFI, 0x30 },
363
{ KE_BLUETOOTH, 0x44 },
364
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
365
};
366
367
static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
368
{ KE_KEY, 0x01, {KEY_HELP} },
369
{ KE_KEY, 0x6d, {KEY_POWER} },
370
{ KE_KEY, 0x11, {KEY_PROG1} },
371
{ KE_KEY, 0x12, {KEY_PROG2} },
372
{ KE_KEY, 0x31, {KEY_MAIL} },
373
{ KE_KEY, 0x36, {KEY_WWW} },
374
{ KE_KEY, 0x6a, {KEY_CONFIG} },
375
{ KE_WIFI, 0x30 },
376
{ KE_BLUETOOTH, 0x44 },
377
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
378
};
379
380
static struct key_entry keymap_acer_travelmate_110[] __initdata = {
381
{ KE_KEY, 0x01, {KEY_HELP} },
382
{ KE_KEY, 0x02, {KEY_CONFIG} },
383
{ KE_KEY, 0x03, {KEY_POWER} },
384
{ KE_KEY, 0x08, {KEY_MUTE} },
385
{ KE_KEY, 0x11, {KEY_PROG1} },
386
{ KE_KEY, 0x12, {KEY_PROG2} },
387
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
388
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
389
{ KE_KEY, 0x31, {KEY_MAIL} },
390
{ KE_KEY, 0x36, {KEY_WWW} },
391
{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
392
{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
393
{ KE_WIFI, 0x30 },
394
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
395
};
396
397
static struct key_entry keymap_acer_travelmate_300[] __initdata = {
398
{ KE_KEY, 0x01, {KEY_HELP} },
399
{ KE_KEY, 0x02, {KEY_CONFIG} },
400
{ KE_KEY, 0x03, {KEY_POWER} },
401
{ KE_KEY, 0x08, {KEY_MUTE} },
402
{ KE_KEY, 0x11, {KEY_PROG1} },
403
{ KE_KEY, 0x12, {KEY_PROG2} },
404
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
405
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
406
{ KE_KEY, 0x31, {KEY_MAIL} },
407
{ KE_KEY, 0x36, {KEY_WWW} },
408
{ KE_WIFI, 0x30 },
409
{ KE_BLUETOOTH, 0x44 },
410
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
411
};
412
413
static struct key_entry keymap_acer_travelmate_380[] __initdata = {
414
{ KE_KEY, 0x01, {KEY_HELP} },
415
{ KE_KEY, 0x02, {KEY_CONFIG} },
416
{ KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
417
{ KE_KEY, 0x11, {KEY_PROG1} },
418
{ KE_KEY, 0x12, {KEY_PROG2} },
419
{ KE_KEY, 0x13, {KEY_PROG3} },
420
{ KE_KEY, 0x31, {KEY_MAIL} },
421
{ KE_KEY, 0x36, {KEY_WWW} },
422
{ KE_WIFI, 0x30 },
423
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
424
};
425
426
/* unusual map */
427
static struct key_entry keymap_acer_travelmate_220[] __initdata = {
428
{ KE_KEY, 0x01, {KEY_HELP} },
429
{ KE_KEY, 0x02, {KEY_CONFIG} },
430
{ KE_KEY, 0x11, {KEY_MAIL} },
431
{ KE_KEY, 0x12, {KEY_WWW} },
432
{ KE_KEY, 0x13, {KEY_PROG2} },
433
{ KE_KEY, 0x31, {KEY_PROG1} },
434
{ KE_END, FE_WIFI_LED | FE_UNTESTED }
435
};
436
437
static struct key_entry keymap_acer_travelmate_230[] __initdata = {
438
{ KE_KEY, 0x01, {KEY_HELP} },
439
{ KE_KEY, 0x02, {KEY_CONFIG} },
440
{ KE_KEY, 0x11, {KEY_PROG1} },
441
{ KE_KEY, 0x12, {KEY_PROG2} },
442
{ KE_KEY, 0x31, {KEY_MAIL} },
443
{ KE_KEY, 0x36, {KEY_WWW} },
444
{ KE_END, FE_WIFI_LED | FE_UNTESTED }
445
};
446
447
static struct key_entry keymap_acer_travelmate_240[] __initdata = {
448
{ KE_KEY, 0x01, {KEY_HELP} },
449
{ KE_KEY, 0x02, {KEY_CONFIG} },
450
{ KE_KEY, 0x03, {KEY_POWER} },
451
{ KE_KEY, 0x08, {KEY_MUTE} },
452
{ KE_KEY, 0x31, {KEY_MAIL} },
453
{ KE_KEY, 0x36, {KEY_WWW} },
454
{ KE_KEY, 0x11, {KEY_PROG1} },
455
{ KE_KEY, 0x12, {KEY_PROG2} },
456
{ KE_BLUETOOTH, 0x44 },
457
{ KE_WIFI, 0x30 },
458
{ KE_END, FE_UNTESTED }
459
};
460
461
static struct key_entry keymap_acer_travelmate_350[] __initdata = {
462
{ KE_KEY, 0x01, {KEY_HELP} },
463
{ KE_KEY, 0x02, {KEY_CONFIG} },
464
{ KE_KEY, 0x11, {KEY_PROG1} },
465
{ KE_KEY, 0x12, {KEY_PROG2} },
466
{ KE_KEY, 0x13, {KEY_MAIL} },
467
{ KE_KEY, 0x14, {KEY_PROG3} },
468
{ KE_KEY, 0x15, {KEY_WWW} },
469
{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
470
};
471
472
static struct key_entry keymap_acer_travelmate_360[] __initdata = {
473
{ KE_KEY, 0x01, {KEY_HELP} },
474
{ KE_KEY, 0x02, {KEY_CONFIG} },
475
{ KE_KEY, 0x11, {KEY_PROG1} },
476
{ KE_KEY, 0x12, {KEY_PROG2} },
477
{ KE_KEY, 0x13, {KEY_MAIL} },
478
{ KE_KEY, 0x14, {KEY_PROG3} },
479
{ KE_KEY, 0x15, {KEY_WWW} },
480
{ KE_KEY, 0x40, {KEY_WLAN} },
481
{ KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
482
};
483
484
/* Wifi subsystem only activates the led. Therefore we need to pass
485
* wifi event as a normal key, then userspace can really change the wifi state.
486
* TODO we need to export led state to userspace (wifi and mail) */
487
static struct key_entry keymap_acer_travelmate_610[] __initdata = {
488
{ KE_KEY, 0x01, {KEY_HELP} },
489
{ KE_KEY, 0x02, {KEY_CONFIG} },
490
{ KE_KEY, 0x11, {KEY_PROG1} },
491
{ KE_KEY, 0x12, {KEY_PROG2} },
492
{ KE_KEY, 0x13, {KEY_PROG3} },
493
{ KE_KEY, 0x14, {KEY_MAIL} },
494
{ KE_KEY, 0x15, {KEY_WWW} },
495
{ KE_KEY, 0x40, {KEY_WLAN} },
496
{ KE_END, FE_MAIL_LED | FE_WIFI_LED }
497
};
498
499
static struct key_entry keymap_acer_travelmate_630[] __initdata = {
500
{ KE_KEY, 0x01, {KEY_HELP} },
501
{ KE_KEY, 0x02, {KEY_CONFIG} },
502
{ KE_KEY, 0x03, {KEY_POWER} },
503
{ KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
504
{ KE_KEY, 0x11, {KEY_PROG1} },
505
{ KE_KEY, 0x12, {KEY_PROG2} },
506
{ KE_KEY, 0x13, {KEY_PROG3} },
507
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
508
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
509
{ KE_KEY, 0x31, {KEY_MAIL} },
510
{ KE_KEY, 0x36, {KEY_WWW} },
511
{ KE_WIFI, 0x30 },
512
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
513
};
514
515
static struct key_entry keymap_aopen_1559as[] __initdata = {
516
{ KE_KEY, 0x01, {KEY_HELP} },
517
{ KE_KEY, 0x06, {KEY_PROG3} },
518
{ KE_KEY, 0x11, {KEY_PROG1} },
519
{ KE_KEY, 0x12, {KEY_PROG2} },
520
{ KE_WIFI, 0x30 },
521
{ KE_KEY, 0x31, {KEY_MAIL} },
522
{ KE_KEY, 0x36, {KEY_WWW} },
523
{ KE_END, 0 },
524
};
525
526
static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
527
{ KE_KEY, 0x01, {KEY_HELP} },
528
{ KE_KEY, 0x08, {KEY_MUTE} },
529
{ KE_KEY, 0x31, {KEY_MAIL} },
530
{ KE_KEY, 0x36, {KEY_WWW} },
531
{ KE_KEY, 0x11, {KEY_PROG1} },
532
{ KE_KEY, 0x12, {KEY_PROG2} },
533
{ KE_KEY, 0x13, {KEY_PROG3} },
534
{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
535
};
536
537
static struct key_entry keymap_wistron_md2900[] __initdata = {
538
{ KE_KEY, 0x01, {KEY_HELP} },
539
{ KE_KEY, 0x02, {KEY_CONFIG} },
540
{ KE_KEY, 0x11, {KEY_PROG1} },
541
{ KE_KEY, 0x12, {KEY_PROG2} },
542
{ KE_KEY, 0x31, {KEY_MAIL} },
543
{ KE_KEY, 0x36, {KEY_WWW} },
544
{ KE_WIFI, 0x30 },
545
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
546
};
547
548
static struct key_entry keymap_wistron_md96500[] __initdata = {
549
{ KE_KEY, 0x01, {KEY_HELP} },
550
{ KE_KEY, 0x02, {KEY_CONFIG} },
551
{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
552
{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
553
{ KE_KEY, 0x08, {KEY_MUTE} },
554
{ KE_KEY, 0x11, {KEY_PROG1} },
555
{ KE_KEY, 0x12, {KEY_PROG2} },
556
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
557
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
558
{ KE_KEY, 0x22, {KEY_REWIND} },
559
{ KE_KEY, 0x23, {KEY_FORWARD} },
560
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
561
{ KE_KEY, 0x25, {KEY_STOPCD} },
562
{ KE_KEY, 0x31, {KEY_MAIL} },
563
{ KE_KEY, 0x36, {KEY_WWW} },
564
{ KE_WIFI, 0x30 },
565
{ KE_BLUETOOTH, 0x44 },
566
{ KE_END, FE_UNTESTED }
567
};
568
569
static struct key_entry keymap_wistron_generic[] __initdata = {
570
{ KE_KEY, 0x01, {KEY_HELP} },
571
{ KE_KEY, 0x02, {KEY_CONFIG} },
572
{ KE_KEY, 0x03, {KEY_POWER} },
573
{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
574
{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
575
{ KE_KEY, 0x08, {KEY_MUTE} },
576
{ KE_KEY, 0x11, {KEY_PROG1} },
577
{ KE_KEY, 0x12, {KEY_PROG2} },
578
{ KE_KEY, 0x13, {KEY_PROG3} },
579
{ KE_KEY, 0x14, {KEY_MAIL} },
580
{ KE_KEY, 0x15, {KEY_WWW} },
581
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
582
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
583
{ KE_KEY, 0x22, {KEY_REWIND} },
584
{ KE_KEY, 0x23, {KEY_FORWARD} },
585
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
586
{ KE_KEY, 0x25, {KEY_STOPCD} },
587
{ KE_KEY, 0x31, {KEY_MAIL} },
588
{ KE_KEY, 0x36, {KEY_WWW} },
589
{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
590
{ KE_KEY, 0x40, {KEY_WLAN} },
591
{ KE_KEY, 0x49, {KEY_CONFIG} },
592
{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
593
{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
594
{ KE_KEY, 0x6a, {KEY_CONFIG} },
595
{ KE_KEY, 0x6d, {KEY_POWER} },
596
{ KE_KEY, 0x71, {KEY_STOPCD} },
597
{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
598
{ KE_KEY, 0x74, {KEY_REWIND} },
599
{ KE_KEY, 0x78, {KEY_FORWARD} },
600
{ KE_WIFI, 0x30 },
601
{ KE_BLUETOOTH, 0x44 },
602
{ KE_END, 0 }
603
};
604
605
static struct key_entry keymap_aopen_1557[] __initdata = {
606
{ KE_KEY, 0x01, {KEY_HELP} },
607
{ KE_KEY, 0x11, {KEY_PROG1} },
608
{ KE_KEY, 0x12, {KEY_PROG2} },
609
{ KE_WIFI, 0x30 },
610
{ KE_KEY, 0x22, {KEY_REWIND} },
611
{ KE_KEY, 0x23, {KEY_FORWARD} },
612
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
613
{ KE_KEY, 0x25, {KEY_STOPCD} },
614
{ KE_KEY, 0x31, {KEY_MAIL} },
615
{ KE_KEY, 0x36, {KEY_WWW} },
616
{ KE_END, 0 }
617
};
618
619
static struct key_entry keymap_prestigio[] __initdata = {
620
{ KE_KEY, 0x11, {KEY_PROG1} },
621
{ KE_KEY, 0x12, {KEY_PROG2} },
622
{ KE_WIFI, 0x30 },
623
{ KE_KEY, 0x22, {KEY_REWIND} },
624
{ KE_KEY, 0x23, {KEY_FORWARD} },
625
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
626
{ KE_KEY, 0x25, {KEY_STOPCD} },
627
{ KE_KEY, 0x31, {KEY_MAIL} },
628
{ KE_KEY, 0x36, {KEY_WWW} },
629
{ KE_END, 0 }
630
};
631
632
633
/*
634
* If your machine is not here (which is currently rather likely), please send
635
* a list of buttons and their key codes (reported when loading this module
636
* with force=1) and the output of dmidecode to $MODULE_AUTHOR.
637
*/
638
static const struct dmi_system_id __initconst dmi_ids[] = {
639
{
640
/* Fujitsu-Siemens Amilo Pro V2000 */
641
.callback = dmi_matched,
642
.matches = {
643
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
644
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"),
645
},
646
.driver_data = keymap_fs_amilo_pro_v2000
647
},
648
{
649
/* Fujitsu-Siemens Amilo Pro Edition V3505 */
650
.callback = dmi_matched,
651
.matches = {
652
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
653
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
654
},
655
.driver_data = keymap_fs_amilo_pro_v3505
656
},
657
{
658
/* Fujitsu-Siemens Amilo M7400 */
659
.callback = dmi_matched,
660
.matches = {
661
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
662
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "),
663
},
664
.driver_data = keymap_fs_amilo_pro_v2000
665
},
666
{
667
/* Maxdata Pro 7000 DX */
668
.callback = dmi_matched,
669
.matches = {
670
DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
671
DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
672
},
673
.driver_data = keymap_fs_amilo_pro_v2000
674
},
675
{
676
/* Fujitsu N3510 */
677
.callback = dmi_matched,
678
.matches = {
679
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
680
DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
681
},
682
.driver_data = keymap_fujitsu_n3510
683
},
684
{
685
/* Acer Aspire 1500 */
686
.callback = dmi_matched,
687
.matches = {
688
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
689
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
690
},
691
.driver_data = keymap_acer_aspire_1500
692
},
693
{
694
/* Acer Aspire 1600 */
695
.callback = dmi_matched,
696
.matches = {
697
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
698
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
699
},
700
.driver_data = keymap_acer_aspire_1600
701
},
702
{
703
/* Acer Aspire 3020 */
704
.callback = dmi_matched,
705
.matches = {
706
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
707
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
708
},
709
.driver_data = keymap_acer_aspire_5020
710
},
711
{
712
/* Acer Aspire 5020 */
713
.callback = dmi_matched,
714
.matches = {
715
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
716
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
717
},
718
.driver_data = keymap_acer_aspire_5020
719
},
720
{
721
/* Acer TravelMate 2100 */
722
.callback = dmi_matched,
723
.matches = {
724
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
725
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
726
},
727
.driver_data = keymap_acer_aspire_5020
728
},
729
{
730
/* Acer TravelMate 2410 */
731
.callback = dmi_matched,
732
.matches = {
733
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
734
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
735
},
736
.driver_data = keymap_acer_travelmate_2410
737
},
738
{
739
/* Acer TravelMate C300 */
740
.callback = dmi_matched,
741
.matches = {
742
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
743
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
744
},
745
.driver_data = keymap_acer_travelmate_300
746
},
747
{
748
/* Acer TravelMate C100 */
749
.callback = dmi_matched,
750
.matches = {
751
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
752
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
753
},
754
.driver_data = keymap_acer_travelmate_300
755
},
756
{
757
/* Acer TravelMate C110 */
758
.callback = dmi_matched,
759
.matches = {
760
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
761
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
762
},
763
.driver_data = keymap_acer_travelmate_110
764
},
765
{
766
/* Acer TravelMate 380 */
767
.callback = dmi_matched,
768
.matches = {
769
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
770
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
771
},
772
.driver_data = keymap_acer_travelmate_380
773
},
774
{
775
/* Acer TravelMate 370 */
776
.callback = dmi_matched,
777
.matches = {
778
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
779
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
780
},
781
.driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
782
},
783
{
784
/* Acer TravelMate 220 */
785
.callback = dmi_matched,
786
.matches = {
787
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
788
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
789
},
790
.driver_data = keymap_acer_travelmate_220
791
},
792
{
793
/* Acer TravelMate 260 */
794
.callback = dmi_matched,
795
.matches = {
796
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
797
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
798
},
799
.driver_data = keymap_acer_travelmate_220
800
},
801
{
802
/* Acer TravelMate 230 */
803
.callback = dmi_matched,
804
.matches = {
805
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
806
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
807
/* acerhk looks for "TravelMate F4..." ?! */
808
},
809
.driver_data = keymap_acer_travelmate_230
810
},
811
{
812
/* Acer TravelMate 280 */
813
.callback = dmi_matched,
814
.matches = {
815
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
816
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
817
},
818
.driver_data = keymap_acer_travelmate_230
819
},
820
{
821
/* Acer TravelMate 240 */
822
.callback = dmi_matched,
823
.matches = {
824
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
825
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
826
},
827
.driver_data = keymap_acer_travelmate_240
828
},
829
{
830
/* Acer TravelMate 250 */
831
.callback = dmi_matched,
832
.matches = {
833
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
834
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
835
},
836
.driver_data = keymap_acer_travelmate_240
837
},
838
{
839
/* Acer TravelMate 2424NWXCi */
840
.callback = dmi_matched,
841
.matches = {
842
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
843
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"),
844
},
845
.driver_data = keymap_acer_travelmate_240
846
},
847
{
848
/* Acer TravelMate 350 */
849
.callback = dmi_matched,
850
.matches = {
851
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
852
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
853
},
854
.driver_data = keymap_acer_travelmate_350
855
},
856
{
857
/* Acer TravelMate 360 */
858
.callback = dmi_matched,
859
.matches = {
860
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
861
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
862
},
863
.driver_data = keymap_acer_travelmate_360
864
},
865
{
866
/* Acer TravelMate 610 */
867
.callback = dmi_matched,
868
.matches = {
869
DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
870
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
871
},
872
.driver_data = keymap_acer_travelmate_610
873
},
874
{
875
/* Acer TravelMate 620 */
876
.callback = dmi_matched,
877
.matches = {
878
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
879
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
880
},
881
.driver_data = keymap_acer_travelmate_630
882
},
883
{
884
/* Acer TravelMate 630 */
885
.callback = dmi_matched,
886
.matches = {
887
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
888
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
889
},
890
.driver_data = keymap_acer_travelmate_630
891
},
892
{
893
/* AOpen 1559AS */
894
.callback = dmi_matched,
895
.matches = {
896
DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
897
DMI_MATCH(DMI_BOARD_NAME, "E2U"),
898
},
899
.driver_data = keymap_aopen_1559as
900
},
901
{
902
/* Medion MD 9783 */
903
.callback = dmi_matched,
904
.matches = {
905
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
906
DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
907
},
908
.driver_data = keymap_wistron_ms2111
909
},
910
{
911
/* Medion MD 40100 */
912
.callback = dmi_matched,
913
.matches = {
914
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
915
DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
916
},
917
.driver_data = keymap_wistron_md40100
918
},
919
{
920
/* Medion MD 2900 */
921
.callback = dmi_matched,
922
.matches = {
923
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
924
DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
925
},
926
.driver_data = keymap_wistron_md2900
927
},
928
{
929
/* Medion MD 42200 */
930
.callback = dmi_matched,
931
.matches = {
932
DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
933
DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"),
934
},
935
.driver_data = keymap_fs_amilo_pro_v2000
936
},
937
{
938
/* Medion MD 96500 */
939
.callback = dmi_matched,
940
.matches = {
941
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
942
DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
943
},
944
.driver_data = keymap_wistron_md96500
945
},
946
{
947
/* Medion MD 95400 */
948
.callback = dmi_matched,
949
.matches = {
950
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
951
DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
952
},
953
.driver_data = keymap_wistron_md96500
954
},
955
{
956
/* Fujitsu Siemens Amilo D7820 */
957
.callback = dmi_matched,
958
.matches = {
959
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
960
DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
961
},
962
.driver_data = keymap_fs_amilo_d88x0
963
},
964
{
965
/* Fujitsu Siemens Amilo D88x0 */
966
.callback = dmi_matched,
967
.matches = {
968
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
969
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
970
},
971
.driver_data = keymap_fs_amilo_d88x0
972
},
973
{ NULL, }
974
};
975
976
/* Copy the good keymap, as the original ones are free'd */
977
static int __init copy_keymap(void)
978
{
979
const struct key_entry *key;
980
struct key_entry *new_keymap;
981
unsigned int length = 1;
982
983
for (key = keymap; key->type != KE_END; key++)
984
length++;
985
986
new_keymap = kmemdup(keymap, length * sizeof(struct key_entry),
987
GFP_KERNEL);
988
if (!new_keymap)
989
return -ENOMEM;
990
991
keymap = new_keymap;
992
993
return 0;
994
}
995
996
static int __init select_keymap(void)
997
{
998
dmi_check_system(dmi_ids);
999
if (keymap_name != NULL) {
1000
if (strcmp (keymap_name, "1557/MS2141") == 0)
1001
keymap = keymap_wistron_ms2141;
1002
else if (strcmp (keymap_name, "aopen1557") == 0)
1003
keymap = keymap_aopen_1557;
1004
else if (strcmp (keymap_name, "prestigio") == 0)
1005
keymap = keymap_prestigio;
1006
else if (strcmp (keymap_name, "generic") == 0)
1007
keymap = keymap_wistron_generic;
1008
else {
1009
printk(KERN_ERR "wistron_btns: Keymap unknown\n");
1010
return -EINVAL;
1011
}
1012
}
1013
if (keymap == NULL) {
1014
if (!force) {
1015
printk(KERN_ERR "wistron_btns: System unknown\n");
1016
return -ENODEV;
1017
}
1018
keymap = keymap_empty;
1019
}
1020
1021
return copy_keymap();
1022
}
1023
1024
/* Input layer interface */
1025
1026
static struct input_polled_dev *wistron_idev;
1027
static unsigned long jiffies_last_press;
1028
static bool wifi_enabled;
1029
static bool bluetooth_enabled;
1030
1031
/* led management */
1032
static void wistron_mail_led_set(struct led_classdev *led_cdev,
1033
enum led_brightness value)
1034
{
1035
bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
1036
}
1037
1038
/* same as setting up wifi card, but for laptops on which the led is managed */
1039
static void wistron_wifi_led_set(struct led_classdev *led_cdev,
1040
enum led_brightness value)
1041
{
1042
bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
1043
}
1044
1045
static struct led_classdev wistron_mail_led = {
1046
.name = "wistron:green:mail",
1047
.brightness_set = wistron_mail_led_set,
1048
};
1049
1050
static struct led_classdev wistron_wifi_led = {
1051
.name = "wistron:red:wifi",
1052
.brightness_set = wistron_wifi_led_set,
1053
};
1054
1055
static void __devinit wistron_led_init(struct device *parent)
1056
{
1057
if (leds_present & FE_WIFI_LED) {
1058
u16 wifi = bios_get_default_setting(WIFI);
1059
if (wifi & 1) {
1060
wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
1061
if (led_classdev_register(parent, &wistron_wifi_led))
1062
leds_present &= ~FE_WIFI_LED;
1063
else
1064
bios_set_state(WIFI, wistron_wifi_led.brightness);
1065
1066
} else
1067
leds_present &= ~FE_WIFI_LED;
1068
}
1069
1070
if (leds_present & FE_MAIL_LED) {
1071
/* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
1072
wistron_mail_led.brightness = LED_OFF;
1073
if (led_classdev_register(parent, &wistron_mail_led))
1074
leds_present &= ~FE_MAIL_LED;
1075
else
1076
bios_set_state(MAIL_LED, wistron_mail_led.brightness);
1077
}
1078
}
1079
1080
static void __devexit wistron_led_remove(void)
1081
{
1082
if (leds_present & FE_MAIL_LED)
1083
led_classdev_unregister(&wistron_mail_led);
1084
1085
if (leds_present & FE_WIFI_LED)
1086
led_classdev_unregister(&wistron_wifi_led);
1087
}
1088
1089
static inline void wistron_led_suspend(void)
1090
{
1091
if (leds_present & FE_MAIL_LED)
1092
led_classdev_suspend(&wistron_mail_led);
1093
1094
if (leds_present & FE_WIFI_LED)
1095
led_classdev_suspend(&wistron_wifi_led);
1096
}
1097
1098
static inline void wistron_led_resume(void)
1099
{
1100
if (leds_present & FE_MAIL_LED)
1101
led_classdev_resume(&wistron_mail_led);
1102
1103
if (leds_present & FE_WIFI_LED)
1104
led_classdev_resume(&wistron_wifi_led);
1105
}
1106
1107
static void handle_key(u8 code)
1108
{
1109
const struct key_entry *key =
1110
sparse_keymap_entry_from_scancode(wistron_idev->input, code);
1111
1112
if (key) {
1113
switch (key->type) {
1114
case KE_WIFI:
1115
if (have_wifi) {
1116
wifi_enabled = !wifi_enabled;
1117
bios_set_state(WIFI, wifi_enabled);
1118
}
1119
break;
1120
1121
case KE_BLUETOOTH:
1122
if (have_bluetooth) {
1123
bluetooth_enabled = !bluetooth_enabled;
1124
bios_set_state(BLUETOOTH, bluetooth_enabled);
1125
}
1126
break;
1127
1128
default:
1129
sparse_keymap_report_entry(wistron_idev->input,
1130
key, 1, true);
1131
break;
1132
}
1133
jiffies_last_press = jiffies;
1134
} else
1135
printk(KERN_NOTICE
1136
"wistron_btns: Unknown key code %02X\n", code);
1137
}
1138
1139
static void poll_bios(bool discard)
1140
{
1141
u8 qlen;
1142
u16 val;
1143
1144
for (;;) {
1145
qlen = CMOS_READ(cmos_address);
1146
if (qlen == 0)
1147
break;
1148
val = bios_pop_queue();
1149
if (val != 0 && !discard)
1150
handle_key((u8)val);
1151
}
1152
}
1153
1154
static void wistron_flush(struct input_polled_dev *dev)
1155
{
1156
/* Flush stale event queue */
1157
poll_bios(true);
1158
}
1159
1160
static void wistron_poll(struct input_polled_dev *dev)
1161
{
1162
poll_bios(false);
1163
1164
/* Increase poll frequency if user is currently pressing keys (< 2s ago) */
1165
if (time_before(jiffies, jiffies_last_press + 2 * HZ))
1166
dev->poll_interval = POLL_INTERVAL_BURST;
1167
else
1168
dev->poll_interval = POLL_INTERVAL_DEFAULT;
1169
}
1170
1171
static int __devinit wistron_setup_keymap(struct input_dev *dev,
1172
struct key_entry *entry)
1173
{
1174
switch (entry->type) {
1175
1176
/* if wifi or bluetooth are not available, create normal keys */
1177
case KE_WIFI:
1178
if (!have_wifi) {
1179
entry->type = KE_KEY;
1180
entry->keycode = KEY_WLAN;
1181
}
1182
break;
1183
1184
case KE_BLUETOOTH:
1185
if (!have_bluetooth) {
1186
entry->type = KE_KEY;
1187
entry->keycode = KEY_BLUETOOTH;
1188
}
1189
break;
1190
1191
case KE_END:
1192
if (entry->code & FE_UNTESTED)
1193
printk(KERN_WARNING "Untested laptop multimedia keys, "
1194
"please report success or failure to "
1195
"[email protected]\n");
1196
break;
1197
}
1198
1199
return 0;
1200
}
1201
1202
static int __devinit setup_input_dev(void)
1203
{
1204
struct input_dev *input_dev;
1205
int error;
1206
1207
wistron_idev = input_allocate_polled_device();
1208
if (!wistron_idev)
1209
return -ENOMEM;
1210
1211
wistron_idev->open = wistron_flush;
1212
wistron_idev->poll = wistron_poll;
1213
wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
1214
1215
input_dev = wistron_idev->input;
1216
input_dev->name = "Wistron laptop buttons";
1217
input_dev->phys = "wistron/input0";
1218
input_dev->id.bustype = BUS_HOST;
1219
input_dev->dev.parent = &wistron_device->dev;
1220
1221
error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
1222
if (error)
1223
goto err_free_dev;
1224
1225
error = input_register_polled_device(wistron_idev);
1226
if (error)
1227
goto err_free_keymap;
1228
1229
return 0;
1230
1231
err_free_keymap:
1232
sparse_keymap_free(input_dev);
1233
err_free_dev:
1234
input_free_polled_device(wistron_idev);
1235
return error;
1236
}
1237
1238
/* Driver core */
1239
1240
static int __devinit wistron_probe(struct platform_device *dev)
1241
{
1242
int err;
1243
1244
bios_attach();
1245
cmos_address = bios_get_cmos_address();
1246
1247
if (have_wifi) {
1248
u16 wifi = bios_get_default_setting(WIFI);
1249
if (wifi & 1)
1250
wifi_enabled = wifi & 2;
1251
else
1252
have_wifi = 0;
1253
1254
if (have_wifi)
1255
bios_set_state(WIFI, wifi_enabled);
1256
}
1257
1258
if (have_bluetooth) {
1259
u16 bt = bios_get_default_setting(BLUETOOTH);
1260
if (bt & 1)
1261
bluetooth_enabled = bt & 2;
1262
else
1263
have_bluetooth = false;
1264
1265
if (have_bluetooth)
1266
bios_set_state(BLUETOOTH, bluetooth_enabled);
1267
}
1268
1269
wistron_led_init(&dev->dev);
1270
1271
err = setup_input_dev();
1272
if (err) {
1273
bios_detach();
1274
return err;
1275
}
1276
1277
return 0;
1278
}
1279
1280
static int __devexit wistron_remove(struct platform_device *dev)
1281
{
1282
wistron_led_remove();
1283
input_unregister_polled_device(wistron_idev);
1284
sparse_keymap_free(wistron_idev->input);
1285
input_free_polled_device(wistron_idev);
1286
bios_detach();
1287
1288
return 0;
1289
}
1290
1291
#ifdef CONFIG_PM
1292
static int wistron_suspend(struct device *dev)
1293
{
1294
if (have_wifi)
1295
bios_set_state(WIFI, 0);
1296
1297
if (have_bluetooth)
1298
bios_set_state(BLUETOOTH, 0);
1299
1300
wistron_led_suspend();
1301
1302
return 0;
1303
}
1304
1305
static int wistron_resume(struct device *dev)
1306
{
1307
if (have_wifi)
1308
bios_set_state(WIFI, wifi_enabled);
1309
1310
if (have_bluetooth)
1311
bios_set_state(BLUETOOTH, bluetooth_enabled);
1312
1313
wistron_led_resume();
1314
1315
poll_bios(true);
1316
1317
return 0;
1318
}
1319
1320
static const struct dev_pm_ops wistron_pm_ops = {
1321
.suspend = wistron_suspend,
1322
.resume = wistron_resume,
1323
.poweroff = wistron_suspend,
1324
.restore = wistron_resume,
1325
};
1326
#endif
1327
1328
static struct platform_driver wistron_driver = {
1329
.driver = {
1330
.name = "wistron-bios",
1331
.owner = THIS_MODULE,
1332
#ifdef CONFIG_PM
1333
.pm = &wistron_pm_ops,
1334
#endif
1335
},
1336
.probe = wistron_probe,
1337
.remove = __devexit_p(wistron_remove),
1338
};
1339
1340
static int __init wb_module_init(void)
1341
{
1342
int err;
1343
1344
err = select_keymap();
1345
if (err)
1346
return err;
1347
1348
err = map_bios();
1349
if (err)
1350
goto err_free_keymap;
1351
1352
err = platform_driver_register(&wistron_driver);
1353
if (err)
1354
goto err_unmap_bios;
1355
1356
wistron_device = platform_device_alloc("wistron-bios", -1);
1357
if (!wistron_device) {
1358
err = -ENOMEM;
1359
goto err_unregister_driver;
1360
}
1361
1362
err = platform_device_add(wistron_device);
1363
if (err)
1364
goto err_free_device;
1365
1366
return 0;
1367
1368
err_free_device:
1369
platform_device_put(wistron_device);
1370
err_unregister_driver:
1371
platform_driver_unregister(&wistron_driver);
1372
err_unmap_bios:
1373
unmap_bios();
1374
err_free_keymap:
1375
kfree(keymap);
1376
1377
return err;
1378
}
1379
1380
static void __exit wb_module_exit(void)
1381
{
1382
platform_device_unregister(wistron_device);
1383
platform_driver_unregister(&wistron_driver);
1384
unmap_bios();
1385
kfree(keymap);
1386
}
1387
1388
module_init(wb_module_init);
1389
module_exit(wb_module_exit);
1390
1391