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