diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 16:41:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 16:41:39 -0400 |
commit | f2e1d89f9b349b3cd914b7c6ec6368632f4ad048 (patch) | |
tree | 5b0042924a9f9c8b3309c0be880f51795916fc28 /drivers/input/keyboard | |
parent | 85ffdd28be04c324349dfc7c9de3d4342c885c3f (diff) | |
parent | 82ba56c273911f7eda79849cfa0fc2d2e5a3b75b (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits)
Input: use full RCU API
Input: remove tsdev interface
Input: add support for Blackfin BF54x Keypad controller
Input: appletouch - another fix for idle reset logic
HWMON: hdaps - switch to using input-polldev
Input: add support for SEGA Dreamcast keyboard
Input: omap-keyboard - don't pretend we support changing keymap
Input: lifebook - fix X and Y axis range
Input: usbtouchscreen - add support for GeneralTouch devices
Input: fix open count handling in input interfaces
Input: keyboard - add CapsShift lock
Input: adbhid - produce all CapsLock key events
Input: ALPS - add signature for ThinkPad R61
Input: jornada720_kbd - send MSC_SCAN events
Input: add support for the HP Jornada 7xx (710/720/728) touchscreen
Input: add support for HP Jornada 7xx onboard keyboard
Input: add support for HP Jornada onboard keyboard (HP6XX)
Input: ucb1400_ts - use schedule_timeout_uninterruptible
Input: xpad - fix dependancy on LEDS class
Input: auto-select INPUT for MAC_EMUMOUSEBTN option
...
Resolved conflicts manually in drivers/hwmon/applesmc.c: converting from
a class device to a device and converting to use input-polldev created a
few apparently trivial clashes..
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 40 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 5 | ||||
-rw-r--r-- | drivers/input/keyboard/bf54x-keys.c | 382 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 81 | ||||
-rw-r--r-- | drivers/input/keyboard/jornada680_kbd.c | 277 | ||||
-rw-r--r-- | drivers/input/keyboard/jornada720_kbd.c | 185 | ||||
-rw-r--r-- | drivers/input/keyboard/maple_keyb.c | 252 | ||||
-rw-r--r-- | drivers/input/keyboard/omap-keypad.c | 22 |
8 files changed, 1223 insertions, 21 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c97d5eb0075d..2316a018fae6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -208,6 +208,27 @@ config KEYBOARD_HIL | |||
208 | This driver implements support for HIL-keyboards attached | 208 | This driver implements support for HIL-keyboards attached |
209 | to your machine, so normally you should say Y here. | 209 | to your machine, so normally you should say Y here. |
210 | 210 | ||
211 | config KEYBOARD_HP6XX | ||
212 | tristate "HP Jornada 6XX Keyboard support" | ||
213 | depends on SH_HP6XX | ||
214 | select INPUT_POLLDEV | ||
215 | help | ||
216 | This adds support for the onboard keyboard found on | ||
217 | HP Jornada 620/660/680/690. | ||
218 | |||
219 | To compile this driver as a module, choose M here: the | ||
220 | module will be called jornada680_kbd. | ||
221 | |||
222 | config KEYBOARD_HP7XX | ||
223 | tristate "HP Jornada 7XX Keyboard Driver" | ||
224 | depends on SA1100_JORNADA720_SSP && SA1100_SSP | ||
225 | help | ||
226 | Say Y here to add support for the HP Jornada 7xx (710/720/728) | ||
227 | onboard keyboard. | ||
228 | |||
229 | To compile this driver as a module, choose M here: the | ||
230 | module will be called jornada720_kbd. | ||
231 | |||
211 | config KEYBOARD_OMAP | 232 | config KEYBOARD_OMAP |
212 | tristate "TI OMAP keypad support" | 233 | tristate "TI OMAP keypad support" |
213 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 234 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
@@ -253,4 +274,23 @@ config KEYBOARD_GPIO | |||
253 | To compile this driver as a module, choose M here: the | 274 | To compile this driver as a module, choose M here: the |
254 | module will be called gpio-keys. | 275 | module will be called gpio-keys. |
255 | 276 | ||
277 | config KEYBOARD_MAPLE | ||
278 | tristate "Maple bus keyboard" | ||
279 | depends on SH_DREAMCAST && MAPLE | ||
280 | help | ||
281 | Say Y here if you have a Dreamcast console running Linux and have | ||
282 | a keyboard attached to its Maple bus. | ||
283 | |||
284 | To compile this driver as a module, choose M here: the | ||
285 | module will be called maple_keyb. | ||
286 | |||
287 | config KEYBOARD_BFIN | ||
288 | tristate "Blackfin BF54x keypad support" | ||
289 | depends on BF54x | ||
290 | help | ||
291 | Say Y here if you want to use the BF54x keypad. | ||
292 | |||
293 | To compile this driver as a module, choose M here: the | ||
294 | module will be called bf54x-keys. | ||
295 | |||
256 | endif | 296 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 28d211b87b14..e97455fdcc83 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -21,4 +21,7 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | |||
21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o | 21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o |
22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
24 | 24 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | |
25 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
26 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
27 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c new file mode 100644 index 000000000000..a67b29b089ef --- /dev/null +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * File: drivers/input/keyboard/bf54x-keys.c | ||
3 | * Based on: | ||
4 | * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
5 | * | ||
6 | * Created: | ||
7 | * Description: keypad driver for Analog Devices Blackfin BF54x Processors | ||
8 | * | ||
9 | * | ||
10 | * Modified: | ||
11 | * Copyright 2007 Analog Devices Inc. | ||
12 | * | ||
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, see the file COPYING, or write | ||
27 | * to the Free Software Foundation, Inc., | ||
28 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/version.h> | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/fs.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/irq.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/pm.h> | ||
40 | #include <linux/sysctl.h> | ||
41 | #include <linux/proc_fs.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/platform_device.h> | ||
44 | #include <linux/input.h> | ||
45 | #include <linux/irq.h> | ||
46 | |||
47 | #include <asm/portmux.h> | ||
48 | #include <asm/mach/bf54x_keys.h> | ||
49 | |||
50 | #define DRV_NAME "bf54x-keys" | ||
51 | #define TIME_SCALE 100 /* 100 ns */ | ||
52 | #define MAX_MULT (0xFF * TIME_SCALE) | ||
53 | #define MAX_RC 8 /* Max Row/Col */ | ||
54 | |||
55 | static const u16 per_rows[] = { | ||
56 | P_KEY_ROW7, | ||
57 | P_KEY_ROW6, | ||
58 | P_KEY_ROW5, | ||
59 | P_KEY_ROW4, | ||
60 | P_KEY_ROW3, | ||
61 | P_KEY_ROW2, | ||
62 | P_KEY_ROW1, | ||
63 | P_KEY_ROW0, | ||
64 | 0 | ||
65 | }; | ||
66 | |||
67 | static const u16 per_cols[] = { | ||
68 | P_KEY_COL7, | ||
69 | P_KEY_COL6, | ||
70 | P_KEY_COL5, | ||
71 | P_KEY_COL4, | ||
72 | P_KEY_COL3, | ||
73 | P_KEY_COL2, | ||
74 | P_KEY_COL1, | ||
75 | P_KEY_COL0, | ||
76 | 0 | ||
77 | }; | ||
78 | |||
79 | struct bf54x_kpad { | ||
80 | struct input_dev *input; | ||
81 | int irq; | ||
82 | unsigned short lastkey; | ||
83 | unsigned short *keycode; | ||
84 | struct timer_list timer; | ||
85 | unsigned int keyup_test_jiffies; | ||
86 | }; | ||
87 | |||
88 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | ||
89 | struct input_dev *input, u16 keyident) | ||
90 | { | ||
91 | u16 i; | ||
92 | |||
93 | for (i = 0; i < input->keycodemax; i++) | ||
94 | if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) | ||
95 | return bf54x_kpad->keycode[i]; | ||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | static inline void bfin_keycodecpy(unsigned short *keycode, | ||
100 | const unsigned int *pdata_kc, | ||
101 | unsigned short keymapsize) | ||
102 | { | ||
103 | unsigned int i; | ||
104 | |||
105 | for (i = 0; i < keymapsize; i++) { | ||
106 | keycode[i] = pdata_kc[i] & 0xffff; | ||
107 | keycode[i + keymapsize] = pdata_kc[i] >> 16; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static inline u16 bfin_kpad_get_prescale(u32 timescale) | ||
112 | { | ||
113 | u32 sclk = get_sclk(); | ||
114 | |||
115 | return ((((sclk / 1000) * timescale) / 1024) - 1); | ||
116 | } | ||
117 | |||
118 | static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) | ||
119 | { | ||
120 | return (bfin_read_KPAD_STAT() & KPAD_PRESSED); | ||
121 | } | ||
122 | |||
123 | static inline void bfin_kpad_clear_irq(void) | ||
124 | { | ||
125 | bfin_write_KPAD_STAT(0xFFFF); | ||
126 | bfin_write_KPAD_ROWCOL(0xFFFF); | ||
127 | } | ||
128 | |||
129 | static void bfin_kpad_timer(unsigned long data) | ||
130 | { | ||
131 | struct platform_device *pdev = (struct platform_device *) data; | ||
132 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
133 | |||
134 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
135 | /* Try again later */ | ||
136 | mod_timer(&bf54x_kpad->timer, | ||
137 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); | ||
142 | input_sync(bf54x_kpad->input); | ||
143 | |||
144 | /* Clear IRQ Status */ | ||
145 | |||
146 | bfin_kpad_clear_irq(); | ||
147 | enable_irq(bf54x_kpad->irq); | ||
148 | } | ||
149 | |||
150 | static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) | ||
151 | { | ||
152 | struct platform_device *pdev = dev_id; | ||
153 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
154 | struct input_dev *input = bf54x_kpad->input; | ||
155 | int key; | ||
156 | u16 rowcol = bfin_read_KPAD_ROWCOL(); | ||
157 | |||
158 | key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); | ||
159 | |||
160 | input_report_key(input, key, 1); | ||
161 | input_sync(input); | ||
162 | |||
163 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
164 | disable_irq(bf54x_kpad->irq); | ||
165 | bf54x_kpad->lastkey = key; | ||
166 | mod_timer(&bf54x_kpad->timer, | ||
167 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
168 | } else { | ||
169 | input_report_key(input, key, 0); | ||
170 | input_sync(input); | ||
171 | |||
172 | bfin_kpad_clear_irq(); | ||
173 | } | ||
174 | |||
175 | return IRQ_HANDLED; | ||
176 | } | ||
177 | |||
178 | static int __devinit bfin_kpad_probe(struct platform_device *pdev) | ||
179 | { | ||
180 | struct bf54x_kpad *bf54x_kpad; | ||
181 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
182 | struct input_dev *input; | ||
183 | int i, error; | ||
184 | |||
185 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
186 | printk(KERN_ERR DRV_NAME | ||
187 | ": No rows, cols or keymap from pdata\n"); | ||
188 | return -EINVAL; | ||
189 | } | ||
190 | |||
191 | if (!pdata->keymapsize || | ||
192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | ||
193 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); | ||
198 | if (!bf54x_kpad) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | platform_set_drvdata(pdev, bf54x_kpad); | ||
202 | |||
203 | /* Allocate memory for keymap followed by private LUT */ | ||
204 | bf54x_kpad->keycode = kmalloc(pdata->keymapsize * | ||
205 | sizeof(unsigned short) * 2, GFP_KERNEL); | ||
206 | if (!bf54x_kpad->keycode) { | ||
207 | error = -ENOMEM; | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || | ||
212 | !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { | ||
213 | printk(KERN_ERR DRV_NAME | ||
214 | ": Invalid Debounce/Columdrive Time from pdata\n"); | ||
215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | ||
216 | } else { | ||
217 | bfin_write_KPAD_MSEL( | ||
218 | ((pdata->debounce_time / TIME_SCALE) | ||
219 | & DBON_SCALE) | | ||
220 | (((pdata->coldrive_time / TIME_SCALE) << 8) | ||
221 | & COLDRV_SCALE)); | ||
222 | |||
223 | } | ||
224 | |||
225 | if (!pdata->keyup_test_interval) | ||
226 | bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); | ||
227 | else | ||
228 | bf54x_kpad->keyup_test_jiffies = | ||
229 | msecs_to_jiffies(pdata->keyup_test_interval); | ||
230 | |||
231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | ||
232 | DRV_NAME)) { | ||
233 | printk(KERN_ERR DRV_NAME | ||
234 | ": Requesting Peripherals failed\n"); | ||
235 | error = -EFAULT; | ||
236 | goto out0; | ||
237 | } | ||
238 | |||
239 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | ||
240 | DRV_NAME)) { | ||
241 | printk(KERN_ERR DRV_NAME | ||
242 | ": Requesting Peripherals failed\n"); | ||
243 | error = -EFAULT; | ||
244 | goto out1; | ||
245 | } | ||
246 | |||
247 | bf54x_kpad->irq = platform_get_irq(pdev, 0); | ||
248 | if (bf54x_kpad->irq < 0) { | ||
249 | error = -ENODEV; | ||
250 | goto out2; | ||
251 | } | ||
252 | |||
253 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | ||
254 | IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); | ||
255 | if (error) { | ||
256 | printk(KERN_ERR DRV_NAME | ||
257 | ": unable to claim irq %d; error %d\n", | ||
258 | bf54x_kpad->irq, error); | ||
259 | error = -EBUSY; | ||
260 | goto out2; | ||
261 | } | ||
262 | |||
263 | input = input_allocate_device(); | ||
264 | if (!input) { | ||
265 | error = -ENOMEM; | ||
266 | goto out3; | ||
267 | } | ||
268 | |||
269 | bf54x_kpad->input = input; | ||
270 | |||
271 | input->name = pdev->name; | ||
272 | input->phys = "bf54x-keys/input0"; | ||
273 | input->dev.parent = &pdev->dev; | ||
274 | |||
275 | input_set_drvdata(input, bf54x_kpad); | ||
276 | |||
277 | input->id.bustype = BUS_HOST; | ||
278 | input->id.vendor = 0x0001; | ||
279 | input->id.product = 0x0001; | ||
280 | input->id.version = 0x0100; | ||
281 | |||
282 | input->keycodesize = sizeof(unsigned short); | ||
283 | input->keycodemax = pdata->keymapsize; | ||
284 | input->keycode = bf54x_kpad->keycode; | ||
285 | |||
286 | bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); | ||
287 | |||
288 | /* setup input device */ | ||
289 | __set_bit(EV_KEY, input->evbit); | ||
290 | |||
291 | if (pdata->repeat) | ||
292 | __set_bit(EV_REP, input->evbit); | ||
293 | |||
294 | for (i = 0; i < input->keycodemax; i++) | ||
295 | __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit); | ||
296 | __clear_bit(KEY_RESERVED, input->keybit); | ||
297 | |||
298 | error = input_register_device(input); | ||
299 | if (error) { | ||
300 | printk(KERN_ERR DRV_NAME | ||
301 | ": Unable to register input device (%d)\n", error); | ||
302 | goto out4; | ||
303 | } | ||
304 | |||
305 | /* Init Keypad Key Up/Release test timer */ | ||
306 | |||
307 | setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); | ||
308 | |||
309 | bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); | ||
310 | |||
311 | bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | | ||
312 | (((pdata->rows - 1) << 10) & KPAD_ROWEN) | | ||
313 | (2 & KPAD_IRQMODE)); | ||
314 | |||
315 | bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); | ||
316 | |||
317 | printk(KERN_ERR DRV_NAME | ||
318 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
319 | |||
320 | return 0; | ||
321 | |||
322 | out4: | ||
323 | input_free_device(input); | ||
324 | out3: | ||
325 | free_irq(bf54x_kpad->irq, pdev); | ||
326 | out2: | ||
327 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
328 | out1: | ||
329 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
330 | out0: | ||
331 | kfree(bf54x_kpad->keycode); | ||
332 | out: | ||
333 | kfree(bf54x_kpad); | ||
334 | platform_set_drvdata(pdev, NULL); | ||
335 | |||
336 | return error; | ||
337 | } | ||
338 | |||
339 | static int __devexit bfin_kpad_remove(struct platform_device *pdev) | ||
340 | { | ||
341 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
342 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
343 | |||
344 | del_timer_sync(&bf54x_kpad->timer); | ||
345 | free_irq(bf54x_kpad->irq, pdev); | ||
346 | |||
347 | input_unregister_device(bf54x_kpad->input); | ||
348 | |||
349 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
350 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
351 | |||
352 | kfree(bf54x_kpad->keycode); | ||
353 | kfree(bf54x_kpad); | ||
354 | platform_set_drvdata(pdev, NULL); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | struct platform_driver bfin_kpad_device_driver = { | ||
360 | .probe = bfin_kpad_probe, | ||
361 | .remove = __devexit_p(bfin_kpad_remove), | ||
362 | .driver = { | ||
363 | .name = DRV_NAME, | ||
364 | } | ||
365 | }; | ||
366 | |||
367 | static int __init bfin_kpad_init(void) | ||
368 | { | ||
369 | return platform_driver_register(&bfin_kpad_device_driver); | ||
370 | } | ||
371 | |||
372 | static void __exit bfin_kpad_exit(void) | ||
373 | { | ||
374 | platform_driver_unregister(&bfin_kpad_device_driver); | ||
375 | } | ||
376 | |||
377 | module_init(bfin_kpad_init); | ||
378 | module_exit(bfin_kpad_exit); | ||
379 | |||
380 | MODULE_LICENSE("GPL"); | ||
381 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
382 | MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index f0b22b8b2769..e2a3293bc67e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -54,6 +54,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
55 | struct input_dev *input; | 55 | struct input_dev *input; |
56 | int i, error; | 56 | int i, error; |
57 | int wakeup = 0; | ||
57 | 58 | ||
58 | input = input_allocate_device(); | 59 | input = input_allocate_device(); |
59 | if (!input) | 60 | if (!input) |
@@ -77,31 +78,51 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
77 | int irq = gpio_to_irq(button->gpio); | 78 | int irq = gpio_to_irq(button->gpio); |
78 | unsigned int type = button->type ?: EV_KEY; | 79 | unsigned int type = button->type ?: EV_KEY; |
79 | 80 | ||
80 | set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); | 81 | if (irq < 0) { |
81 | error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM, | 82 | error = irq; |
82 | button->desc ? button->desc : "gpio_keys", | 83 | printk(KERN_ERR |
83 | pdev); | 84 | "gpio-keys: " |
85 | "Unable to get irq number for GPIO %d," | ||
86 | "error %d\n", | ||
87 | button->gpio, error); | ||
88 | goto fail; | ||
89 | } | ||
90 | |||
91 | error = request_irq(irq, gpio_keys_isr, | ||
92 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | ||
93 | IRQF_TRIGGER_FALLING, | ||
94 | button->desc ? button->desc : "gpio_keys", | ||
95 | pdev); | ||
84 | if (error) { | 96 | if (error) { |
85 | printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", | 97 | printk(KERN_ERR |
98 | "gpio-keys: Unable to claim irq %d; error %d\n", | ||
86 | irq, error); | 99 | irq, error); |
87 | goto fail; | 100 | goto fail; |
88 | } | 101 | } |
89 | 102 | ||
103 | if (button->wakeup) | ||
104 | wakeup = 1; | ||
105 | |||
90 | input_set_capability(input, type, button->code); | 106 | input_set_capability(input, type, button->code); |
91 | } | 107 | } |
92 | 108 | ||
93 | error = input_register_device(input); | 109 | error = input_register_device(input); |
94 | if (error) { | 110 | if (error) { |
95 | printk(KERN_ERR "Unable to register gpio-keys input device\n"); | 111 | printk(KERN_ERR |
112 | "gpio-keys: Unable to register input device, " | ||
113 | "error: %d\n", error); | ||
96 | goto fail; | 114 | goto fail; |
97 | } | 115 | } |
98 | 116 | ||
117 | device_init_wakeup(&pdev->dev, wakeup); | ||
118 | |||
99 | return 0; | 119 | return 0; |
100 | 120 | ||
101 | fail: | 121 | fail: |
102 | for (i = i - 1; i >= 0; i--) | 122 | while (--i >= 0) |
103 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); | 123 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); |
104 | 124 | ||
125 | platform_set_drvdata(pdev, NULL); | ||
105 | input_free_device(input); | 126 | input_free_device(input); |
106 | 127 | ||
107 | return error; | 128 | return error; |
@@ -113,6 +134,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
113 | struct input_dev *input = platform_get_drvdata(pdev); | 134 | struct input_dev *input = platform_get_drvdata(pdev); |
114 | int i; | 135 | int i; |
115 | 136 | ||
137 | device_init_wakeup(&pdev->dev, 0); | ||
138 | |||
116 | for (i = 0; i < pdata->nbuttons; i++) { | 139 | for (i = 0; i < pdata->nbuttons; i++) { |
117 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 140 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
118 | free_irq(irq, pdev); | 141 | free_irq(irq, pdev); |
@@ -123,9 +146,53 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
123 | return 0; | 146 | return 0; |
124 | } | 147 | } |
125 | 148 | ||
149 | |||
150 | #ifdef CONFIG_PM | ||
151 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | ||
152 | { | ||
153 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
154 | int i; | ||
155 | |||
156 | if (device_may_wakeup(&pdev->dev)) { | ||
157 | for (i = 0; i < pdata->nbuttons; i++) { | ||
158 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
159 | if (button->wakeup) { | ||
160 | int irq = gpio_to_irq(button->gpio); | ||
161 | enable_irq_wake(irq); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int gpio_keys_resume(struct platform_device *pdev) | ||
170 | { | ||
171 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
172 | int i; | ||
173 | |||
174 | if (device_may_wakeup(&pdev->dev)) { | ||
175 | for (i = 0; i < pdata->nbuttons; i++) { | ||
176 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
177 | if (button->wakeup) { | ||
178 | int irq = gpio_to_irq(button->gpio); | ||
179 | disable_irq_wake(irq); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | #else | ||
187 | #define gpio_keys_suspend NULL | ||
188 | #define gpio_keys_resume NULL | ||
189 | #endif | ||
190 | |||
126 | struct platform_driver gpio_keys_device_driver = { | 191 | struct platform_driver gpio_keys_device_driver = { |
127 | .probe = gpio_keys_probe, | 192 | .probe = gpio_keys_probe, |
128 | .remove = __devexit_p(gpio_keys_remove), | 193 | .remove = __devexit_p(gpio_keys_remove), |
194 | .suspend = gpio_keys_suspend, | ||
195 | .resume = gpio_keys_resume, | ||
129 | .driver = { | 196 | .driver = { |
130 | .name = "gpio-keys", | 197 | .name = "gpio-keys", |
131 | } | 198 | } |
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c new file mode 100644 index 000000000000..bec1cf483723 --- /dev/null +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * drivers/input/keyboard/jornada680_kbd.c | ||
3 | * | ||
4 | * HP Jornada 620/660/680/690 scan keyboard platform driver | ||
5 | * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> | ||
6 | * | ||
7 | * Based on hp680_keyb.c | ||
8 | * Copyright (C) 2006 Paul Mundt | ||
9 | * Copyright (C) 2005 Andriy Skulysh | ||
10 | * Split from drivers/input/keyboard/hp600_keyb.c | ||
11 | * Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table) | ||
12 | * Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/input.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/input-polldev.h> | ||
24 | #include <linux/jiffies.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include <asm/delay.h> | ||
29 | #include <asm/io.h> | ||
30 | |||
31 | #define PCCR 0xa4000104 | ||
32 | #define PDCR 0xa4000106 | ||
33 | #define PECR 0xa4000108 | ||
34 | #define PFCR 0xa400010a | ||
35 | #define PCDR 0xa4000124 | ||
36 | #define PDDR 0xa4000126 | ||
37 | #define PEDR 0xa4000128 | ||
38 | #define PFDR 0xa400012a | ||
39 | #define PGDR 0xa400012c | ||
40 | #define PHDR 0xa400012e | ||
41 | #define PJDR 0xa4000130 | ||
42 | #define PKDR 0xa4000132 | ||
43 | #define PLDR 0xa4000134 | ||
44 | |||
45 | static const unsigned short jornada_scancodes[] = { | ||
46 | /* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */ | ||
47 | KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */ | ||
48 | /* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */ | ||
49 | KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */ | ||
50 | /* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */ | ||
51 | 0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */ | ||
52 | /* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */ | ||
53 | KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */ | ||
54 | /* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */ | ||
55 | KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */ | ||
56 | /* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */ | ||
57 | 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */ | ||
58 | /* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */ | ||
59 | KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */ | ||
60 | /* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */ | ||
61 | KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */ | ||
62 | /* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
63 | 0, 0, 0, 0, 0 | ||
64 | }; | ||
65 | |||
66 | #define JORNADA_SCAN_SIZE 18 | ||
67 | |||
68 | struct jornadakbd { | ||
69 | struct input_polled_dev *poll_dev; | ||
70 | unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; | ||
71 | unsigned char length; | ||
72 | unsigned char old_scan[JORNADA_SCAN_SIZE]; | ||
73 | unsigned char new_scan[JORNADA_SCAN_SIZE]; | ||
74 | }; | ||
75 | |||
76 | static void jornada_parse_kbd(struct jornadakbd *jornadakbd) | ||
77 | { | ||
78 | struct input_dev *input_dev = jornadakbd->poll_dev->input; | ||
79 | unsigned short *keymap = jornadakbd->keymap; | ||
80 | unsigned int sync_me = 0; | ||
81 | unsigned int i, j; | ||
82 | |||
83 | for (i = 0; i < JORNADA_SCAN_SIZE; i++) { | ||
84 | unsigned char new = jornadakbd->new_scan[i]; | ||
85 | unsigned char old = jornadakbd->old_scan[i]; | ||
86 | unsigned int xor = new ^ old; | ||
87 | |||
88 | if (xor == 0) | ||
89 | continue; | ||
90 | |||
91 | for (j = 0; j < 8; j++) { | ||
92 | unsigned int bit = 1 << j; | ||
93 | if (xor & bit) { | ||
94 | unsigned int scancode = (i << 3) + j; | ||
95 | input_event(input_dev, | ||
96 | EV_MSC, MSC_SCAN, scancode); | ||
97 | input_report_key(input_dev, | ||
98 | keymap[scancode], | ||
99 | !(new & bit)); | ||
100 | sync_me = 1; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | if (sync_me) | ||
106 | input_sync(input_dev); | ||
107 | } | ||
108 | |||
109 | static void jornada_scan_keyb(unsigned char *s) | ||
110 | { | ||
111 | int i; | ||
112 | unsigned short ec_static, dc_static; /* = UINT16_t */ | ||
113 | unsigned char matrix_switch[] = { | ||
114 | 0xfd, 0xff, /* PTD1 PD(1) */ | ||
115 | 0xdf, 0xff, /* PTD5 PD(5) */ | ||
116 | 0x7f, 0xff, /* PTD7 PD(7) */ | ||
117 | 0xff, 0xfe, /* PTE0 PE(0) */ | ||
118 | 0xff, 0xfd, /* PTE1 PE(1) */ | ||
119 | 0xff, 0xf7, /* PTE3 PE(3) */ | ||
120 | 0xff, 0xbf, /* PTE6 PE(6) */ | ||
121 | 0xff, 0x7f, /* PTE7 PE(7) */ | ||
122 | }, *t = matrix_switch; | ||
123 | /* PD(x) : | ||
124 | 1. 0xcc0c & (1~(1 << (2*(x)+1))))) | ||
125 | 2. (0xf0cf & 0xfffff) */ | ||
126 | /* PE(x) : | ||
127 | 1. 0xcc0c & 0xffff | ||
128 | 2. 0xf0cf & (1~(1 << (2*(x)+1))))) */ | ||
129 | unsigned short matrix_PDE[] = { | ||
130 | 0xcc04, 0xf0cf, /* PD(1) */ | ||
131 | 0xc40c, 0xf0cf, /* PD(5) */ | ||
132 | 0x4c0c, 0xf0cf, /* PD(7) */ | ||
133 | 0xcc0c, 0xf0cd, /* PE(0) */ | ||
134 | 0xcc0c, 0xf0c7, /* PE(1) */ | ||
135 | 0xcc0c, 0xf04f, /* PE(3) */ | ||
136 | 0xcc0c, 0xd0cf, /* PE(6) */ | ||
137 | 0xcc0c, 0x70cf, /* PE(7) */ | ||
138 | }, *y = matrix_PDE; | ||
139 | |||
140 | /* Save these control reg bits */ | ||
141 | dc_static = (ctrl_inw(PDCR) & (~0xcc0c)); | ||
142 | ec_static = (ctrl_inw(PECR) & (~0xf0cf)); | ||
143 | |||
144 | for (i = 0; i < 8; i++) { | ||
145 | /* disable output for all but the one we want to scan */ | ||
146 | ctrl_outw((dc_static | *y++), PDCR); | ||
147 | ctrl_outw((ec_static | *y++), PECR); | ||
148 | udelay(5); | ||
149 | |||
150 | /* Get scanline row */ | ||
151 | ctrl_outb(*t++, PDDR); | ||
152 | ctrl_outb(*t++, PEDR); | ||
153 | udelay(50); | ||
154 | |||
155 | /* Read data */ | ||
156 | *s++ = ctrl_inb(PCDR); | ||
157 | *s++ = ctrl_inb(PFDR); | ||
158 | } | ||
159 | /* Scan no lines */ | ||
160 | ctrl_outb(0xff, PDDR); | ||
161 | ctrl_outb(0xff, PEDR); | ||
162 | |||
163 | /* Enable all scanlines */ | ||
164 | ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR); | ||
165 | ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR); | ||
166 | |||
167 | /* Ignore extra keys and events */ | ||
168 | *s++ = ctrl_inb(PGDR); | ||
169 | *s++ = ctrl_inb(PHDR); | ||
170 | } | ||
171 | |||
172 | static void jornadakbd680_poll(struct input_polled_dev *dev) | ||
173 | { | ||
174 | struct jornadakbd *jornadakbd = dev->private; | ||
175 | |||
176 | jornada_scan_keyb(jornadakbd->new_scan); | ||
177 | jornada_parse_kbd(jornadakbd); | ||
178 | memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE); | ||
179 | } | ||
180 | |||
181 | static int __devinit jornada680kbd_probe(struct platform_device *pdev) | ||
182 | { | ||
183 | struct jornadakbd *jornadakbd; | ||
184 | struct input_polled_dev *poll_dev; | ||
185 | struct input_dev *input_dev; | ||
186 | int i, error; | ||
187 | |||
188 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
189 | if (!jornadakbd) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | poll_dev = input_allocate_polled_device(); | ||
193 | if (!poll_dev) { | ||
194 | error = -ENOMEM; | ||
195 | goto failed; | ||
196 | } | ||
197 | |||
198 | platform_set_drvdata(pdev, jornadakbd); | ||
199 | |||
200 | jornadakbd->poll_dev = poll_dev; | ||
201 | |||
202 | memcpy(jornadakbd->keymap, jornada_scancodes, | ||
203 | sizeof(jornadakbd->keymap)); | ||
204 | |||
205 | poll_dev->private = jornadakbd; | ||
206 | poll_dev->poll = jornadakbd680_poll; | ||
207 | poll_dev->poll_interval = 50; /* msec */ | ||
208 | |||
209 | input_dev = poll_dev->input; | ||
210 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
211 | input_dev->name = "HP Jornada 680 keyboard"; | ||
212 | input_dev->phys = "jornadakbd/input0"; | ||
213 | input_dev->keycode = jornadakbd->keymap; | ||
214 | input_dev->keycodesize = sizeof(unsigned short); | ||
215 | input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); | ||
216 | input_dev->dev.parent = &pdev->dev; | ||
217 | input_dev->id.bustype = BUS_HOST; | ||
218 | |||
219 | for (i = 0; i < 128; i++) | ||
220 | if (jornadakbd->keymap[i]) | ||
221 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
222 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
223 | |||
224 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
225 | |||
226 | error = input_register_polled_device(jornadakbd->poll_dev); | ||
227 | if (error) | ||
228 | goto failed; | ||
229 | |||
230 | return 0; | ||
231 | |||
232 | failed: | ||
233 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", | ||
234 | error); | ||
235 | platform_set_drvdata(pdev, NULL); | ||
236 | input_free_polled_device(poll_dev); | ||
237 | kfree(jornadakbd); | ||
238 | return error; | ||
239 | |||
240 | } | ||
241 | |||
242 | static int __devexit jornada680kbd_remove(struct platform_device *pdev) | ||
243 | { | ||
244 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
245 | |||
246 | platform_set_drvdata(pdev, NULL); | ||
247 | input_unregister_polled_device(jornadakbd->poll_dev); | ||
248 | input_free_polled_device(jornadakbd->poll_dev); | ||
249 | kfree(jornadakbd); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static struct platform_driver jornada680kbd_driver = { | ||
255 | .driver = { | ||
256 | .name = "jornada680_kbd", | ||
257 | }, | ||
258 | .probe = jornada680kbd_probe, | ||
259 | .remove = __devexit_p(jornada680kbd_remove), | ||
260 | }; | ||
261 | |||
262 | static int __init jornada680kbd_init(void) | ||
263 | { | ||
264 | return platform_driver_register(&jornada680kbd_driver); | ||
265 | } | ||
266 | |||
267 | static void __exit jornada680kbd_exit(void) | ||
268 | { | ||
269 | platform_driver_unregister(&jornada680kbd_driver); | ||
270 | } | ||
271 | |||
272 | module_init(jornada680kbd_init); | ||
273 | module_exit(jornada680kbd_exit); | ||
274 | |||
275 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
276 | MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver"); | ||
277 | MODULE_LICENSE("GPLv2"); | ||
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c new file mode 100644 index 000000000000..e6696b3c9416 --- /dev/null +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * drivers/input/keyboard/jornada720_kbd.c | ||
3 | * | ||
4 | * HP Jornada 720 keyboard platform driver | ||
5 | * | ||
6 | * Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com> | ||
7 | * | ||
8 | * Copyright (C) 2006 jornada 720 kbd driver by | ||
9 | Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX | ||
10 | * based on (C) 2004 jornada 720 kbd driver by | ||
11 | Alex Lange <chicken@handhelds.org> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <asm/arch/jornada720.h> | ||
29 | #include <asm/hardware.h> | ||
30 | |||
31 | MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); | ||
32 | MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); | ||
33 | MODULE_LICENSE("GPLv2"); | ||
34 | |||
35 | static unsigned short jornada_std_keymap[128] = { /* ROW */ | ||
36 | 0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */ | ||
37 | KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */ | ||
38 | 0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */ | ||
39 | KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */ | ||
40 | 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */ | ||
41 | KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */ | ||
42 | 0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */ | ||
43 | KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */ | ||
44 | 0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */ | ||
45 | KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */ | ||
46 | 0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */ | ||
47 | KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */ | ||
48 | 0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */ | ||
49 | KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */ | ||
50 | 0, 0, 0, KEY_POWER, /* -> */ | ||
51 | }; | ||
52 | |||
53 | struct jornadakbd { | ||
54 | unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)]; | ||
55 | struct input_dev *input; | ||
56 | }; | ||
57 | |||
58 | static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) | ||
59 | { | ||
60 | struct platform_device *pdev = dev_id; | ||
61 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
62 | struct input_dev *input = jornadakbd->input; | ||
63 | u8 count, kbd_data, scan_code; | ||
64 | |||
65 | /* startup ssp with spinlock */ | ||
66 | jornada_ssp_start(); | ||
67 | |||
68 | if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { | ||
69 | printk(KERN_DEBUG | ||
70 | "jornada720_kbd: " | ||
71 | "GetKeycode command failed with ETIMEDOUT, " | ||
72 | "flushed bus\n"); | ||
73 | } else { | ||
74 | /* How many keycodes are waiting for us? */ | ||
75 | count = jornada_ssp_byte(TXDUMMY); | ||
76 | |||
77 | /* Lets drag them out one at a time */ | ||
78 | while (count--) { | ||
79 | /* Exchange TxDummy for location (keymap[kbddata]) */ | ||
80 | kbd_data = jornada_ssp_byte(TXDUMMY); | ||
81 | scan_code = kbd_data & 0x7f; | ||
82 | |||
83 | input_event(input, EV_MSC, MSC_SCAN, scan_code); | ||
84 | input_report_key(input, jornadakbd->keymap[scan_code], | ||
85 | !(kbd_data & 0x80)); | ||
86 | input_sync(input); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* release spinlock and turn off ssp */ | ||
91 | jornada_ssp_end(); | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | }; | ||
95 | |||
96 | static int __devinit jornada720_kbd_probe(struct platform_device *pdev) | ||
97 | { | ||
98 | struct jornadakbd *jornadakbd; | ||
99 | struct input_dev *input_dev; | ||
100 | int i, err; | ||
101 | |||
102 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
103 | input_dev = input_allocate_device(); | ||
104 | if (!jornadakbd || !input_dev) { | ||
105 | err = -ENOMEM; | ||
106 | goto fail1; | ||
107 | } | ||
108 | |||
109 | platform_set_drvdata(pdev, jornadakbd); | ||
110 | |||
111 | memcpy(jornadakbd->keymap, jornada_std_keymap, | ||
112 | sizeof(jornada_std_keymap)); | ||
113 | jornadakbd->input = input_dev; | ||
114 | |||
115 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
116 | input_dev->name = "HP Jornada 720 keyboard"; | ||
117 | input_dev->phys = "jornadakbd/input0"; | ||
118 | input_dev->keycode = jornadakbd->keymap; | ||
119 | input_dev->keycodesize = sizeof(unsigned short); | ||
120 | input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap); | ||
121 | input_dev->id.bustype = BUS_HOST; | ||
122 | input_dev->dev.parent = &pdev->dev; | ||
123 | |||
124 | for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++) | ||
125 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
126 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
127 | |||
128 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
129 | |||
130 | err = request_irq(IRQ_GPIO0, | ||
131 | jornada720_kbd_interrupt, | ||
132 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | ||
133 | "jornadakbd", pdev); | ||
134 | if (err) { | ||
135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | ||
136 | goto fail1; | ||
137 | } | ||
138 | |||
139 | err = input_register_device(jornadakbd->input); | ||
140 | if (err) | ||
141 | goto fail2; | ||
142 | |||
143 | return 0; | ||
144 | |||
145 | fail2: /* IRQ, DEVICE, MEMORY */ | ||
146 | free_irq(IRQ_GPIO0, pdev); | ||
147 | fail1: /* DEVICE, MEMORY */ | ||
148 | platform_set_drvdata(pdev, NULL); | ||
149 | input_free_device(input_dev); | ||
150 | kfree(jornadakbd); | ||
151 | return err; | ||
152 | }; | ||
153 | |||
154 | static int __devexit jornada720_kbd_remove(struct platform_device *pdev) | ||
155 | { | ||
156 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
157 | |||
158 | free_irq(IRQ_GPIO0, pdev); | ||
159 | platform_set_drvdata(pdev, NULL); | ||
160 | input_unregister_device(jornadakbd->input); | ||
161 | kfree(jornadakbd); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static struct platform_driver jornada720_kbd_driver = { | ||
167 | .driver = { | ||
168 | .name = "jornada720_kbd", | ||
169 | }, | ||
170 | .probe = jornada720_kbd_probe, | ||
171 | .remove = __devexit_p(jornada720_kbd_remove), | ||
172 | }; | ||
173 | |||
174 | static int __init jornada720_kbd_init(void) | ||
175 | { | ||
176 | return platform_driver_register(&jornada720_kbd_driver); | ||
177 | } | ||
178 | |||
179 | static void __exit jornada720_kbd_exit(void) | ||
180 | { | ||
181 | platform_driver_unregister(&jornada720_kbd_driver); | ||
182 | } | ||
183 | |||
184 | module_init(jornada720_kbd_init); | ||
185 | module_exit(jornada720_kbd_exit); | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c new file mode 100644 index 000000000000..2b404284c28a --- /dev/null +++ b/drivers/input/keyboard/maple_keyb.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * SEGA Dreamcast keyboard driver | ||
3 | * Based on drivers/usb/usbkbd.c | ||
4 | * Copyright YAEGASHI Takeshi, 2001 | ||
5 | * Porting to 2.6 Copyright Adrian McMenamin, 2007 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, see the file COPYING, or write | ||
19 | * to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/timer.h> | ||
29 | #include <linux/maple.h> | ||
30 | #include <asm/mach/maple.h> | ||
31 | |||
32 | /* Very simple mutex to ensure proper cleanup */ | ||
33 | static DEFINE_MUTEX(maple_keyb_mutex); | ||
34 | |||
35 | #define NR_SCANCODES 256 | ||
36 | |||
37 | MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); | ||
38 | MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | struct dc_kbd { | ||
42 | struct input_dev *dev; | ||
43 | unsigned short keycode[NR_SCANCODES]; | ||
44 | unsigned char new[8]; | ||
45 | unsigned char old[8]; | ||
46 | }; | ||
47 | |||
48 | static const unsigned short dc_kbd_keycode[NR_SCANCODES] = { | ||
49 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D, | ||
50 | KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, | ||
51 | KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, | ||
52 | KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, | ||
53 | KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, | ||
54 | KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, | ||
55 | KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, | ||
56 | KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, | ||
57 | KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, | ||
58 | KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, | ||
59 | KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, | ||
60 | KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, | ||
61 | KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, | ||
62 | KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, | ||
63 | KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, | ||
64 | KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, | ||
65 | KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, | ||
66 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN, | ||
67 | KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
68 | KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
69 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
70 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
71 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
72 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
73 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
74 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
75 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
76 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
77 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
78 | KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA, | ||
79 | KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, | ||
80 | KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, | ||
81 | KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED | ||
82 | }; | ||
83 | |||
84 | static void dc_scan_kbd(struct dc_kbd *kbd) | ||
85 | { | ||
86 | struct input_dev *dev = kbd->dev; | ||
87 | void *ptr; | ||
88 | int code, keycode; | ||
89 | int i; | ||
90 | |||
91 | for (i = 0; i < 8; i++) { | ||
92 | code = i + 224; | ||
93 | keycode = kbd->keycode[code]; | ||
94 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
95 | input_report_key(dev, keycode, (kbd->new[0] >> i) & 1); | ||
96 | } | ||
97 | |||
98 | for (i = 2; i < 8; i++) { | ||
99 | ptr = memchr(kbd->new + 2, kbd->old[i], 6); | ||
100 | code = kbd->old[i]; | ||
101 | if (code > 3 && ptr == NULL) { | ||
102 | keycode = kbd->keycode[code]; | ||
103 | if (keycode) { | ||
104 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
105 | input_report_key(dev, keycode, 0); | ||
106 | } else | ||
107 | printk(KERN_DEBUG "maple_keyb: " | ||
108 | "Unknown key (scancode %#x) released.", | ||
109 | code); | ||
110 | } | ||
111 | ptr = memchr(kbd->old + 2, kbd->new[i], 6); | ||
112 | code = kbd->new[i]; | ||
113 | if (code > 3 && ptr) { | ||
114 | keycode = kbd->keycode[code]; | ||
115 | if (keycode) { | ||
116 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
117 | input_report_key(dev, keycode, 1); | ||
118 | } else | ||
119 | printk(KERN_DEBUG "maple_keyb: " | ||
120 | "Unknown key (scancode %#x) pressed.", | ||
121 | code); | ||
122 | } | ||
123 | } | ||
124 | input_sync(dev); | ||
125 | memcpy(kbd->old, kbd->new, 8); | ||
126 | } | ||
127 | |||
128 | static void dc_kbd_callback(struct mapleq *mq) | ||
129 | { | ||
130 | struct maple_device *mapledev = mq->dev; | ||
131 | struct dc_kbd *kbd = mapledev->private_data; | ||
132 | unsigned long *buf = mq->recvbuf; | ||
133 | |||
134 | /* | ||
135 | * We should always be getting the lock because the only | ||
136 | * time it may be locked if driver is in cleanup phase. | ||
137 | */ | ||
138 | if (likely(mutex_trylock(&maple_keyb_mutex))) { | ||
139 | |||
140 | if (buf[1] == mapledev->function) { | ||
141 | memcpy(kbd->new, buf + 2, 8); | ||
142 | dc_scan_kbd(kbd); | ||
143 | } | ||
144 | |||
145 | mutex_unlock(&maple_keyb_mutex); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | static int dc_kbd_connect(struct maple_device *mdev) | ||
150 | { | ||
151 | int i, error; | ||
152 | struct dc_kbd *kbd; | ||
153 | struct input_dev *dev; | ||
154 | |||
155 | if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) | ||
156 | return -EINVAL; | ||
157 | |||
158 | kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); | ||
159 | dev = input_allocate_device(); | ||
160 | if (!kbd || !dev) { | ||
161 | error = -ENOMEM; | ||
162 | goto fail; | ||
163 | } | ||
164 | |||
165 | mdev->private_data = kbd; | ||
166 | |||
167 | kbd->dev = dev; | ||
168 | memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); | ||
169 | |||
170 | dev->name = mdev->product_name; | ||
171 | dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
172 | dev->keycode = kbd->keycode; | ||
173 | dev->keycodesize = sizeof (unsigned short); | ||
174 | dev->keycodemax = ARRAY_SIZE(kbd->keycode); | ||
175 | dev->id.bustype = BUS_HOST; | ||
176 | dev->dev.parent = &mdev->dev; | ||
177 | |||
178 | for (i = 0; i < NR_SCANCODES; i++) | ||
179 | __set_bit(dc_kbd_keycode[i], dev->keybit); | ||
180 | __clear_bit(KEY_RESERVED, dev->keybit); | ||
181 | |||
182 | input_set_capability(dev, EV_MSC, MSC_SCAN); | ||
183 | input_set_drvdata(dev, kbd); | ||
184 | |||
185 | error = input_register_device(dev); | ||
186 | if (error) | ||
187 | goto fail; | ||
188 | |||
189 | /* Maple polling is locked to VBLANK - which may be just 50/s */ | ||
190 | maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD); | ||
191 | return 0; | ||
192 | |||
193 | fail: | ||
194 | input_free_device(dev); | ||
195 | kfree(kbd); | ||
196 | mdev->private_data = NULL; | ||
197 | return error; | ||
198 | } | ||
199 | |||
200 | static void dc_kbd_disconnect(struct maple_device *mdev) | ||
201 | { | ||
202 | struct dc_kbd *kbd; | ||
203 | |||
204 | mutex_lock(&maple_keyb_mutex); | ||
205 | |||
206 | kbd = mdev->private_data; | ||
207 | mdev->private_data = NULL; | ||
208 | input_unregister_device(kbd->dev); | ||
209 | kfree(kbd); | ||
210 | |||
211 | mutex_unlock(&maple_keyb_mutex); | ||
212 | } | ||
213 | |||
214 | /* allow the keyboard to be used */ | ||
215 | static int probe_maple_kbd(struct device *dev) | ||
216 | { | ||
217 | struct maple_device *mdev = to_maple_dev(dev); | ||
218 | struct maple_driver *mdrv = to_maple_driver(dev->driver); | ||
219 | int error; | ||
220 | |||
221 | error = dc_kbd_connect(mdev); | ||
222 | if (error) | ||
223 | return error; | ||
224 | |||
225 | mdev->driver = mdrv; | ||
226 | mdev->registered = 1; | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct maple_driver dc_kbd_driver = { | ||
232 | .function = MAPLE_FUNC_KEYBOARD, | ||
233 | .connect = dc_kbd_connect, | ||
234 | .disconnect = dc_kbd_disconnect, | ||
235 | .drv = { | ||
236 | .name = "Dreamcast_keyboard", | ||
237 | .probe = probe_maple_kbd, | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | static int __init dc_kbd_init(void) | ||
242 | { | ||
243 | return maple_driver_register(&dc_kbd_driver.drv); | ||
244 | } | ||
245 | |||
246 | static void __exit dc_kbd_exit(void) | ||
247 | { | ||
248 | driver_unregister(&dc_kbd_driver.drv); | ||
249 | } | ||
250 | |||
251 | module_init(dc_kbd_init); | ||
252 | module_exit(dc_kbd_exit); | ||
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3a228634f101..76f1969552c5 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -233,7 +233,7 @@ static void omap_kp_tasklet(unsigned long data) | |||
233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
234 | kp_cur_group = -1; | 234 | kp_cur_group = -1; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | ||
239 | static ssize_t omap_kp_enable_show(struct device *dev, | 239 | static ssize_t omap_kp_enable_show(struct device *dev, |
@@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
318 | keymap = pdata->keymap; | 318 | keymap = pdata->keymap; |
319 | 319 | ||
320 | if (pdata->rep) | 320 | if (pdata->rep) |
321 | set_bit(EV_REP, input_dev->evbit); | 321 | __set_bit(EV_REP, input_dev->evbit); |
322 | 322 | ||
323 | if (pdata->delay) | 323 | if (pdata->delay) |
324 | omap_kp->delay = pdata->delay; | 324 | omap_kp->delay = pdata->delay; |
@@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
365 | goto err2; | 365 | goto err2; |
366 | 366 | ||
367 | /* setup input device */ | 367 | /* setup input device */ |
368 | set_bit(EV_KEY, input_dev->evbit); | 368 | __set_bit(EV_KEY, input_dev->evbit); |
369 | for (i = 0; keymap[i] != 0; i++) | 369 | for (i = 0; keymap[i] != 0; i++) |
370 | set_bit(keymap[i] & KEY_MAX, input_dev->keybit); | 370 | __set_bit(keymap[i] & KEY_MAX, input_dev->keybit); |
371 | input_dev->name = "omap-keypad"; | 371 | input_dev->name = "omap-keypad"; |
372 | input_dev->phys = "omap-keypad/input0"; | 372 | input_dev->phys = "omap-keypad/input0"; |
373 | input_dev->dev.parent = &pdev->dev; | 373 | input_dev->dev.parent = &pdev->dev; |
@@ -377,10 +377,6 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
377 | input_dev->id.product = 0x0001; | 377 | input_dev->id.product = 0x0001; |
378 | input_dev->id.version = 0x0100; | 378 | input_dev->id.version = 0x0100; |
379 | 379 | ||
380 | input_dev->keycode = keymap; | ||
381 | input_dev->keycodesize = sizeof(unsigned int); | ||
382 | input_dev->keycodemax = pdata->keymapsize; | ||
383 | |||
384 | ret = input_register_device(omap_kp->input); | 380 | ret = input_register_device(omap_kp->input); |
385 | if (ret < 0) { | 381 | if (ret < 0) { |
386 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); | 382 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); |
@@ -403,15 +399,15 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
403 | } else { | 399 | } else { |
404 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { | 400 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { |
405 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), | 401 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), |
406 | omap_kp_interrupt, | 402 | omap_kp_interrupt, |
407 | IRQF_TRIGGER_FALLING, | 403 | IRQF_TRIGGER_FALLING, |
408 | "omap-keypad", omap_kp) < 0) | 404 | "omap-keypad", omap_kp) < 0) |
409 | goto err5; | 405 | goto err5; |
410 | } | 406 | } |
411 | } | 407 | } |
412 | return 0; | 408 | return 0; |
413 | err5: | 409 | err5: |
414 | for (i = irq_idx-1; i >=0; i--) | 410 | for (i = irq_idx - 1; i >=0; i--) |
415 | free_irq(row_gpios[i], 0); | 411 | free_irq(row_gpios[i], 0); |
416 | err4: | 412 | err4: |
417 | input_unregister_device(omap_kp->input); | 413 | input_unregister_device(omap_kp->input); |
@@ -440,9 +436,9 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
440 | if (cpu_is_omap24xx()) { | 436 | if (cpu_is_omap24xx()) { |
441 | int i; | 437 | int i; |
442 | for (i = 0; i < omap_kp->cols; i++) | 438 | for (i = 0; i < omap_kp->cols; i++) |
443 | omap_free_gpio(col_gpios[i]); | 439 | omap_free_gpio(col_gpios[i]); |
444 | for (i = 0; i < omap_kp->rows; i++) { | 440 | for (i = 0; i < omap_kp->rows; i++) { |
445 | omap_free_gpio(row_gpios[i]); | 441 | omap_free_gpio(row_gpios[i]); |
446 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); | 442 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); |
447 | } | 443 | } |
448 | } else { | 444 | } else { |