xref: /openbmc/linux/drivers/input/misc/wistron_btns.c (revision cdc780f044a803aff8845b949f800f0f3d095d5f)
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  
34  MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
35  MODULE_DESCRIPTION("Wistron laptop button driver");
36  MODULE_LICENSE("GPL v2");
37  
38  static bool force; /* = 0; */
39  module_param(force, bool, 0);
40  MODULE_PARM_DESC(force, "Load even if computer is not in database");
41  
42  static char *keymap_name; /* = NULL; */
43  module_param_named(keymap, keymap_name, charp, 0);
44  MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
45  
46  static struct platform_device *wistron_device;
47  
48   /* BIOS interface implementation */
49  
50  static void __iomem *bios_entry_point; /* BIOS routine entry point */
51  static void __iomem *bios_code_map_base;
52  static void __iomem *bios_data_map_base;
53  
54  static u8 cmos_address;
55  
56  struct regs {
57  	u32 eax, ebx, ecx;
58  };
59  
call_bios(struct regs * regs)60  static 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  
locate_wistron_bios(void __iomem * base)78  static 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  
map_bios(void)92  static 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  
133  err_code:
134  	iounmap(bios_code_map_base);
135  err:
136  	return -ENOMEM;
137  }
138  
unmap_bios(void)139  static inline void unmap_bios(void)
140  {
141  	iounmap(bios_code_map_base);
142  	iounmap(bios_data_map_base);
143  }
144  
145   /* BIOS calls */
146  
bios_pop_queue(void)147  static 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  
bios_attach(void)160  static 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  
bios_detach(void)170  static 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  
bios_get_cmos_address(void)180  static 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  
bios_get_default_setting(u8 subsys)192  static 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  
bios_set_state(u8 subsys,int enable)204  static 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  
223  static struct key_entry *keymap; /* = NULL; Current key map */
224  static bool have_wifi;
225  static bool have_bluetooth;
226  static int leds_present;	/* bitmask of leds present */
227  
dmi_matched(const struct dmi_system_id * dmi)228  static 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  
244  static struct key_entry keymap_empty[] __initdata = {
245  	{ KE_END, 0 }
246  };
247  
248  static 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  
258  static 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  
268  static 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  
278  static 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  
290  static 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  
299  static 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  
308  static 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  
321  static 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  
334  static 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 */
350  static 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  
364  static 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  
377  static 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  
394  static 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  
410  static 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 */
424  static 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  
434  static 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  
444  static 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  
458  static 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  
469  static 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) */
484  static 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  
496  static 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  
512  static 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  
523  static 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  
534  static 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  
545  static 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  
566  static 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  
602  static 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  
616  static 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   */
635  static 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  };
981  MODULE_DEVICE_TABLE(dmi, dmi_ids);
982  
983  /* Copy the good keymap, as the original ones are free'd */
copy_keymap(void)984  static 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  
select_keymap(void)1003  static 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  
1033  static struct input_dev *wistron_idev;
1034  static unsigned long jiffies_last_press;
1035  static bool wifi_enabled;
1036  static bool bluetooth_enabled;
1037  
1038   /* led management */
wistron_mail_led_set(struct led_classdev * led_cdev,enum led_brightness value)1039  static 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 */
wistron_wifi_led_set(struct led_classdev * led_cdev,enum led_brightness value)1046  static 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  
1052  static struct led_classdev wistron_mail_led = {
1053  	.name			= "wistron:green:mail",
1054  	.brightness_set		= wistron_mail_led_set,
1055  };
1056  
1057  static struct led_classdev wistron_wifi_led = {
1058  	.name			= "wistron:red:wifi",
1059  	.brightness_set		= wistron_wifi_led_set,
1060  };
1061  
wistron_led_init(struct device * parent)1062  static 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  
wistron_led_remove(void)1087  static 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  
wistron_led_suspend(void)1096  static 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  
wistron_led_resume(void)1105  static 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  
handle_key(u8 code)1114  static 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  
poll_bios(bool discard)1146  static 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  
wistron_flush(struct input_dev * dev)1161  static int wistron_flush(struct input_dev *dev)
1162  {
1163  	/* Flush stale event queue */
1164  	poll_bios(true);
1165  
1166  	return 0;
1167  }
1168  
wistron_poll(struct input_dev * dev)1169  static 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  
wistron_setup_keymap(struct input_dev * dev,struct key_entry * entry)1180  static 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  
setup_input_dev(void)1211  static 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  
wistron_probe(struct platform_device * dev)1249  static 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  
wistron_remove(struct platform_device * dev)1289  static int wistron_remove(struct platform_device *dev)
1290  {
1291  	wistron_led_remove();
1292  	input_unregister_device(wistron_idev);
1293  	bios_detach();
1294  
1295  	return 0;
1296  }
1297  
wistron_suspend(struct device * dev)1298  static int wistron_suspend(struct device *dev)
1299  {
1300  	if (have_wifi)
1301  		bios_set_state(WIFI, 0);
1302  
1303  	if (have_bluetooth)
1304  		bios_set_state(BLUETOOTH, 0);
1305  
1306  	wistron_led_suspend();
1307  
1308  	return 0;
1309  }
1310  
wistron_resume(struct device * dev)1311  static int wistron_resume(struct device *dev)
1312  {
1313  	if (have_wifi)
1314  		bios_set_state(WIFI, wifi_enabled);
1315  
1316  	if (have_bluetooth)
1317  		bios_set_state(BLUETOOTH, bluetooth_enabled);
1318  
1319  	wistron_led_resume();
1320  
1321  	poll_bios(true);
1322  
1323  	return 0;
1324  }
1325  
1326  static const struct dev_pm_ops wistron_pm_ops = {
1327  	.suspend	= wistron_suspend,
1328  	.resume		= wistron_resume,
1329  	.poweroff	= wistron_suspend,
1330  	.restore	= wistron_resume,
1331  };
1332  
1333  static struct platform_driver wistron_driver = {
1334  	.driver		= {
1335  		.name	= "wistron-bios",
1336  		.pm	= pm_sleep_ptr(&wistron_pm_ops),
1337  	},
1338  	.probe		= wistron_probe,
1339  	.remove		= wistron_remove,
1340  };
1341  
wb_module_init(void)1342  static int __init wb_module_init(void)
1343  {
1344  	int err;
1345  
1346  	err = select_keymap();
1347  	if (err)
1348  		return err;
1349  
1350  	err = map_bios();
1351  	if (err)
1352  		goto err_free_keymap;
1353  
1354  	err = platform_driver_register(&wistron_driver);
1355  	if (err)
1356  		goto err_unmap_bios;
1357  
1358  	wistron_device = platform_device_alloc("wistron-bios", -1);
1359  	if (!wistron_device) {
1360  		err = -ENOMEM;
1361  		goto err_unregister_driver;
1362  	}
1363  
1364  	err = platform_device_add(wistron_device);
1365  	if (err)
1366  		goto err_free_device;
1367  
1368  	return 0;
1369  
1370   err_free_device:
1371  	platform_device_put(wistron_device);
1372   err_unregister_driver:
1373  	platform_driver_unregister(&wistron_driver);
1374   err_unmap_bios:
1375  	unmap_bios();
1376   err_free_keymap:
1377  	kfree(keymap);
1378  
1379  	return err;
1380  }
1381  
wb_module_exit(void)1382  static void __exit wb_module_exit(void)
1383  {
1384  	platform_device_unregister(wistron_device);
1385  	platform_driver_unregister(&wistron_driver);
1386  	unmap_bios();
1387  	kfree(keymap);
1388  }
1389  
1390  module_init(wb_module_init);
1391  module_exit(wb_module_exit);
1392