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