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