conf/distro/jlime-donkey.conf : Added parted & Dialog to distro_rdepends
[vuplus_openembedded] / packages / linux / linux-openzaurus-2.6.18+git / tosa-keyboard-r18.patch
1  drivers/input/keyboard/Kconfig   |   12 -
2  drivers/input/keyboard/Makefile  |    1 
3  drivers/input/keyboard/tosakbd.c |  467 +++++++++++++++++++++++++++++++++++++++
4  3 files changed, 479 insertions(+), 1 deletion(-)
5
6 Index: git/drivers/input/keyboard/Kconfig
7 ===================================================================
8 --- git.orig/drivers/input/keyboard/Kconfig     2006-10-31 16:08:57.000000000 +0000
9 +++ git/drivers/input/keyboard/Kconfig  2006-11-07 22:13:10.000000000 +0000
10 @@ -148,12 +148,22 @@ config KEYBOARD_SPITZ
11         depends on PXA_SHARPSL
12         default y
13         help
14 -         Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
15 +         Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
16           SL-C3000 and Sl-C3100 series of PDAs.
17  
18           To compile this driver as a module, choose M here: the
19           module will be called spitzkbd.
20  
21 +config KEYBOARD_TOSA
22 +       tristate "Tosa keyboard"
23 +       depends on PXA_SHARPSL
24 +       default y
25 +       help
26 +         Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
27 +
28 +         To compile this driver as a module, choose M here: the
29 +         module will be called tosakbd.
30 +
31  config KEYBOARD_AMIGA
32         tristate "Amiga keyboard"
33         depends on AMIGA
34 Index: git/drivers/input/keyboard/Makefile
35 ===================================================================
36 --- git.orig/drivers/input/keyboard/Makefile    2006-10-31 16:08:57.000000000 +0000
37 +++ git/drivers/input/keyboard/Makefile 2006-11-07 22:13:10.000000000 +0000
38 @@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_SPITZ)          += spitzkb
39  obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
40  obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
41  obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
42 +obj-$(CONFIG_KEYBOARD_TOSA)            += tosakbd.o
43  
44 Index: git/drivers/input/keyboard/tosakbd.c
45 ===================================================================
46 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
47 +++ git/drivers/input/keyboard/tosakbd.c        2006-11-07 23:27:19.000000000 +0000
48 @@ -0,0 +1,467 @@
49 +/*
50 + *  Keyboard driver for Sharp Tosa models (SL-6000x)
51 + *
52 + *  Copyright (c) 2005 Dirk Opfer
53 + *
54 + *  Based on xtkbd.c/locomkbd.c/corgikbd.c
55 + *
56 + *  This program is free software; you can redistribute it and/or modify
57 + *  it under the terms of the GNU General Public License version 2 as
58 + *  published by the Free Software Foundation.
59 + *
60 + */
61 +
62 +#include <linux/delay.h>
63 +#include <linux/platform_device.h>
64 +#include <linux/init.h>
65 +#include <linux/input.h>
66 +#include <linux/interrupt.h>
67 +#include <linux/jiffies.h>
68 +#include <linux/module.h>
69 +#include <linux/slab.h>
70 +
71 +#include <asm/arch/tosa.h>
72 +#include <asm/arch/hardware.h>
73 +#include <asm/arch/pxa-regs.h>
74 +
75 +
76 +#define TOSA_KEY_STROBE_NUM    (11)
77 +#define TOSA_KEY_SENSE_NUM     (7)
78 +
79 +#define KEYMASK_ON             (0x1<<0)
80 +#define KEYMASK_REC            (0x1<<1)
81 +#define KEYMASK_SYNC           (0x1<<2)
82 +
83 +#define KB_ROWS                        7
84 +#define KB_COLS                        11
85 +#define KB_ROWMASK(r)          (1 << (r))
86 +#define SCANCODE(r,c)          ( ((r)<<4) + (c) + 1 )
87 +#define        NR_SCANCODES            (SCANCODE(KB_ROWS-1,KB_COLS)+1+1) 
88 +
89 +#define SCAN_INTERVAL          (HZ/10)
90 +#define HP_SCAN_INTERVAL       (150) /* ms */
91 +#define HP_STABLE_COUNT                2
92 +
93 +#define TOSA_KEY_CALENDER       KEY_F1
94 +#define TOSA_KEY_ADDRESS        KEY_F2
95 +#define TOSA_KEY_FN             KEY_F3
96 +#define TOSA_KEY_CANCEL                KEY_F4
97 +#define TOSA_KEY_OFF            KEY_SUSPEND
98 +#define TOSA_KEY_CENTER         KEY_F5
99 +#define TOSA_KEY_REC            KEY_F6
100 +#define TOSA_KEY_LIGHT          KEY_F7
101 +#define TOSA_KEY_RECORD         KEY_F8
102 +#define TOSA_KEY_HOME           KEY_F9
103 +#define TOSA_KEY_MAIL           KEY_F10
104 +#define TOSA_KEY_OK             KEY_F11
105 +#define TOSA_KEY_MENU           KEY_F12
106 +#define TOSA_KEY_SYNC           KEY_F13
107 +
108 +#define GET_ROWS_STATUS(c)     ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT)
109 +#define KB_DISCHARGE_DELAY     10
110 +#define KB_ACTIVATE_DELAY      10
111 +
112 +
113 +static unsigned char tosakbd_keycode[NR_SCANCODES] = {
114 +       0,                                                                                                                      /* 0 */
115 +       0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, 0, 0, 0, TOSA_KEY_OFF, 0, 0, 0, 0,                                      /*1 - 16*/
116 +       KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, 0, 0, 0, TOSA_KEY_RECORD, 0, 0, 0, 0,                           /*17 - 32*/
117 +       KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, 0, 0, 0, TOSA_KEY_SYNC, 0, 0, 0, 0,                           /*33 - 48*/
118 +       KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESS, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, KEY_LEFTSHIFT, 0 , 0,0 , 0, 0, 0, 0,       /*49 - 64*/
119 +       KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDER, TOSA_KEY_HOME, TOSA_KEY_REC, TOSA_KEY_LIGHT, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,        /*65 - 80*/
120 +       KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0,                        /*81 - 96*/
121 +       KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0,                   /*97 - 109*/
122 +};
123 +
124 +struct tosakbd {
125 +       unsigned char keycode[ARRAY_SIZE(tosakbd_keycode)];
126 +       struct input_dev *input;
127 +
128 +       spinlock_t lock;
129 +       struct timer_list timer;
130 +       struct timer_list hptimer;
131 +
132 +       int hp_state;
133 +       int hp_count;
134 +
135 +       unsigned int suspended;
136 +       unsigned long suspend_jiffies;
137 +};
138 +
139 +/* Helper functions for reading the keyboard matrix 
140 + * Note: We should really be using pxa_gpio_mode to alter GPDR but it 
141 + *       requires a function call per GPIO bit which is excessive
142 + *       when we need to access 12 bits at once, multiple times.
143 + * These functions must be called within local_irq_save()/local_irq_restore()
144 + * or similar. 
145 + */
146 +static inline void tosakbd_discharge_all(void)
147 +{
148 +       /* STROBE All HiZ */
149 +       GPCR1  = TOSA_GPIO_HIGH_STROBE_BIT;
150 +       GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT;
151 +       GPCR2  = TOSA_GPIO_LOW_STROBE_BIT;
152 +       GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT;
153 +}
154 +
155 +static inline void tosakbd_activate_all(void)
156 +{
157 +       /* STROBE ALL -> High */
158 +       GPSR1  = TOSA_GPIO_HIGH_STROBE_BIT;
159 +       GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT;
160 +       GPSR2  = TOSA_GPIO_LOW_STROBE_BIT;
161 +       GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT;
162 +
163 +       udelay(KB_DISCHARGE_DELAY);
164 +
165 +       /* STATE CLEAR */
166 +       GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; 
167 +}
168 +
169 +static inline void tosakbd_activate_col(int col)
170 +{
171 +       if (col<=5) {
172 +               /* STROBE col -> High, not col -> HiZ */
173 +               GPSR1 = TOSA_GPIO_STROBE_BIT(col);
174 +               GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
175 +       } else {
176 +               /* STROBE col -> High, not col -> HiZ */
177 +               GPSR2 = TOSA_GPIO_STROBE_BIT(col);
178 +               GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
179 +       } 
180 +}
181 +
182 +static inline void tosakbd_reset_col(int col)
183 +{
184 +       if (col<=5) {
185 +               /* STROBE col -> Low */
186 +               GPCR1 = TOSA_GPIO_STROBE_BIT(col);
187 +               /* STROBE col -> out, not col -> HiZ */
188 +               GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
189 +       } else {
190 +               /* STROBE col -> Low */
191 +               GPCR2 = TOSA_GPIO_STROBE_BIT(col);
192 +               /* STROBE col -> out, not col -> HiZ */
193 +               GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
194 +       } 
195 +}
196 +
197 +/*
198 + * Read the GPIOs for POWER, RECORD and SYNC
199 + */
200 +static int read_port_key_status_raw(void)
201 +{
202 +       int val=0;
203 +
204 +       /* Power key */
205 +       if ((GPLR0 & GPIO_bit(TOSA_GPIO_ON_KEY))==0)
206 +               val |= KEYMASK_ON;
207 +       /* Record key */
208 +       if ((GPLR0 & GPIO_bit(TOSA_GPIO_RECORD_BTN))==0)
209 +               val |= KEYMASK_REC;
210 +       /* Sync key */
211 +       if ((GPLR0 & GPIO_bit(TOSA_GPIO_SYNC))==0)
212 +               val |= KEYMASK_SYNC;
213 +       return val;
214 +}
215 +
216 +
217 +/*
218 + * The tosa keyboard only generates interrupts when a key is pressed.
219 + * So when a key is pressed, we enable a timer.  This timer scans the
220 + * keyboard, and this is how we detect when the key is released.
221 + */
222 +
223 +/* Scan the hardware keyboard and push any changes up through the input layer */
224 +static void tosakbd_scankeyboard(struct tosakbd *tosakbd_data) 
225 +{
226 +       unsigned int row, col, rowd;
227 +       unsigned long flags;
228 +       unsigned int num_pressed = 0;
229 +
230 +       if (tosakbd_data->suspended)
231 +               return;
232 +
233 +       spin_lock_irqsave(&tosakbd_data->lock, flags);
234 +
235 +       for (col = 0; col < KB_COLS; col++) {
236 +               /*
237 +                * Discharge the output driver capacitatance
238 +                * in the keyboard matrix. (Yes it is significant..)
239 +                */
240 +               tosakbd_discharge_all();
241 +               udelay(KB_DISCHARGE_DELAY);
242 +
243 +               tosakbd_activate_col( col);
244 +               udelay(KB_ACTIVATE_DELAY);
245 +               
246 +               rowd = GET_ROWS_STATUS(col);
247 +
248 +               for (row = 0; row < KB_ROWS; row++) {
249 +                       unsigned int scancode, pressed;
250 +                       scancode = SCANCODE(row, col);
251 +                       pressed = rowd & KB_ROWMASK(row);
252 +                       input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed);
253 +                       if (pressed)
254 +                               num_pressed++;
255 +               }
256 +
257 +               tosakbd_reset_col(col);
258 +       }
259 +
260 +       tosakbd_activate_all();
261 +
262 +       rowd = read_port_key_status_raw();
263 +
264 +       for (row = 0; row < 3; row++ ) {
265 +               unsigned int scancode, pressed;
266 +               scancode = SCANCODE(row, KB_COLS);
267 +               pressed = rowd & KB_ROWMASK(row);
268 +               input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed);
269 +               if (pressed)
270 +                       num_pressed++;
271 +
272 +               if (pressed && (tosakbd_data->keycode[scancode] == TOSA_KEY_OFF)
273 +                                                               && time_after(jiffies, tosakbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
274 +                       input_event(tosakbd_data->input, EV_PWR, TOSA_KEY_OFF, 1);
275 +                       tosakbd_data->suspend_jiffies = jiffies;
276 +               }
277 +       }
278 +       
279 +       input_sync(tosakbd_data->input);
280 +
281 +       /* if any keys are pressed, enable the timer */
282 +       if (num_pressed)
283 +               mod_timer(&tosakbd_data->timer, jiffies + SCAN_INTERVAL);
284 +
285 +       spin_unlock_irqrestore(&tosakbd_data->lock, flags);
286 +}
287 +
288 +/* 
289 + * tosa keyboard interrupt handler.
290 + */
291 +static irqreturn_t tosakbd_interrupt(int irq, void *dev_id)
292 +{
293 +       struct tosakbd *tosakbd_data = dev_id;
294 +
295 +       if (!timer_pending(&tosakbd_data->timer)) 
296 +       {
297 +               /** wait chattering delay **/
298 +               udelay(20);
299 +               tosakbd_scankeyboard(tosakbd_data);
300 +       }
301 +
302 +       return IRQ_HANDLED;
303 +}
304 +
305 +/*
306 + * tosa timer checking for released keys
307 + */
308 +static void tosakbd_timer_callback(unsigned long data)
309 +{
310 +       struct tosakbd *tosakbd_data = (struct tosakbd *) data;
311 +       tosakbd_scankeyboard(tosakbd_data);
312 +}
313 +
314 +/*
315 + * The headphone generates an interrupt.
316 + * We debounce the switche and pass them to the input system.
317 + */
318 +
319 +static irqreturn_t tosakbd_hp_isr(int irq, void *dev_id)
320 +{
321 +       struct tosakbd *tosakbd_data = dev_id;
322 +
323 +       if (!timer_pending(&tosakbd_data->hptimer))
324 +               mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL));
325 +
326 +       return IRQ_HANDLED;
327 +}
328 +
329 +static void tosakbd_hp_timer(unsigned long data)
330 +{
331 +       struct tosakbd *tosakbd_data = (struct tosakbd *) data;
332 +       unsigned long state;
333 +       unsigned long flags;
334 +
335 +       state = (GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN));
336 +       if (state != tosakbd_data->hp_state) {
337 +               tosakbd_data->hp_count = 0;
338 +               tosakbd_data->hp_state = state;
339 +       } else if (tosakbd_data->hp_count < HP_STABLE_COUNT) {
340 +               tosakbd_data->hp_count++;
341 +       }
342 +
343 +       if (tosakbd_data->hp_count >= HP_STABLE_COUNT) {
344 +               spin_lock_irqsave(&tosakbd_data->lock, flags);
345 +
346 +               input_report_switch(tosakbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)) == 0));
347 +               input_sync(tosakbd_data->input);
348 +
349 +               spin_unlock_irqrestore(&tosakbd_data->lock, flags);
350 +       } else {
351 +               mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL));
352 +       }
353 +}
354 +
355 +#ifdef CONFIG_PM
356 +static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
357 +{
358 +       struct tosakbd *tosakbd = platform_get_drvdata(dev);
359 +
360 +       tosakbd->suspended = 1;
361 +
362 +       return 0;
363 +}
364 +
365 +static int tosakbd_resume(struct platform_device *dev)
366 +{
367 +       struct tosakbd *tosakbd = platform_get_drvdata(dev);
368 +
369 +       /* Upon resume, ignore the suspend key for a short while */
370 +       tosakbd->suspend_jiffies = jiffies;
371 +       tosakbd->suspended = 0;
372 +
373 +       return 0;
374 +}
375 +#else
376 +#define tosakbd_suspend                NULL
377 +#define tosakbd_resume         NULL
378 +#endif
379 +
380 +static int __init tosakbd_probe(struct platform_device *pdev) {
381 +
382 +       int i;
383 +       struct tosakbd *tosakbd;
384 +       struct input_dev *input_dev;
385 +
386 +       tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL);
387 +       if (!tosakbd)
388 +               return -ENOMEM;
389 +
390 +       input_dev = input_allocate_device();
391 +       if (!input_dev) {
392 +               kfree(tosakbd);
393 +               return -ENOMEM;
394 +       }
395 +
396 +       platform_set_drvdata(pdev,tosakbd);
397 +
398 +       spin_lock_init(&tosakbd->lock);
399 +
400 +       /* Init Keyboard rescan timer */
401 +       init_timer(&tosakbd->timer);
402 +       tosakbd->timer.function = tosakbd_timer_callback;
403 +       tosakbd->timer.data = (unsigned long) tosakbd;
404 +
405 +       /* Init Headphone Timer */
406 +       init_timer(&tosakbd->hptimer);
407 +       tosakbd->hptimer.function = tosakbd_hp_timer;
408 +       tosakbd->hptimer.data = (unsigned long) tosakbd;
409 +
410 +       tosakbd->suspend_jiffies = jiffies;
411 +
412 +       tosakbd->input = input_dev;
413 +
414 +       input_dev->private = tosakbd;
415 +       input_dev->name = "Tosa Keyboard";
416 +       input_dev->phys = "tosakbd/input0";
417 +       input_dev->cdev.dev = &pdev->dev;
418 +
419 +       input_dev->id.bustype = BUS_HOST;
420 +       input_dev->id.vendor = 0x0001;
421 +       input_dev->id.product = 0x0001;
422 +       input_dev->id.version = 0x0100;
423 +
424 +       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
425 +       input_dev->keycode = tosakbd->keycode;
426 +       input_dev->keycodesize = sizeof(unsigned char);
427 +       input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode);
428 +
429 +       memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd->keycode));
430 +       for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++)
431 +               set_bit(tosakbd->keycode[i], input_dev->keybit);
432 +       clear_bit(0, input_dev->keybit);
433 +       set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
434 +
435 +       input_register_device(tosakbd->input);
436 +
437 +       /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
438 +       for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) {
439 +               pxa_gpio_mode( TOSA_GPIO_KEY_SENSE(i) | GPIO_IN);       
440 +               if (request_irq(TOSA_IRQ_GPIO_KEY_SENSE(i), tosakbd_interrupt,
441 +                                               SA_INTERRUPT | SA_TRIGGER_RISING, "tosakbd", tosakbd)) {
442 +                       printk("tosakbd: Can't get IRQ: %d !\n", i);
443 +               }
444 +       }
445 +       
446 +       /* Set Strobe lines as outputs - set high */
447 +       for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) {
448 +               pxa_gpio_mode( TOSA_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);    
449 +       }
450 +
451 +       // Power&Rec Button
452 +       pxa_gpio_mode( TOSA_GPIO_ON_KEY | GPIO_IN);     
453 +       pxa_gpio_mode( TOSA_GPIO_RECORD_BTN | GPIO_IN); 
454 +       pxa_gpio_mode( TOSA_GPIO_SYNC | GPIO_IN);
455 +       pxa_gpio_mode( TOSA_GPIO_EAR_IN | GPIO_IN);
456 +
457 +       if (request_irq(TOSA_IRQ_GPIO_ON_KEY, tosakbd_interrupt, SA_INTERRUPT | SA_TRIGGER_FALLING, "On key", tosakbd) ||
458 +           request_irq(TOSA_IRQ_GPIO_RECORD_BTN, tosakbd_interrupt, SA_INTERRUPT | SA_TRIGGER_FALLING, "Record key", tosakbd) ||
459 +           request_irq(TOSA_IRQ_GPIO_SYNC, tosakbd_interrupt, SA_INTERRUPT | SA_TRIGGER_FALLING, "Sync key", tosakbd) ||
460 +           request_irq(TOSA_IRQ_GPIO_EAR_IN, tosakbd_hp_isr, SA_INTERRUPT | SA_TRIGGER_FALLING, "HP in", tosakbd)) {
461 +               printk("Could not allocate KEYBD IRQ!\n");
462 +       }
463 +
464 +       printk(KERN_INFO "input: Tosa Keyboard Registered\n");
465 +
466 +       return 0;
467 +}
468 +
469 +static int tosakbd_remove(struct platform_device *dev) {
470 +       
471 +       int i;
472 +       struct tosakbd *tosakbd = platform_get_drvdata(dev);
473 +       
474 +       for (i = 0; i < TOSA_KEY_SENSE_NUM; i++)
475 +               free_irq(TOSA_IRQ_GPIO_KEY_SENSE(i),tosakbd); 
476 +       
477 +       free_irq(TOSA_IRQ_GPIO_ON_KEY,tosakbd); 
478 +       free_irq(TOSA_IRQ_GPIO_RECORD_BTN,tosakbd); 
479 +       free_irq(TOSA_IRQ_GPIO_SYNC,tosakbd); 
480 +
481 +       del_timer_sync(&tosakbd->timer);
482 +
483 +       input_unregister_device(tosakbd->input);
484 +       
485 +       kfree(tosakbd);
486 +       
487 +       return 0;
488 +}
489 +
490 +static struct platform_driver tosakbd_driver = {
491 +       .probe          = tosakbd_probe,
492 +       .remove         = tosakbd_remove,
493 +       .suspend        = tosakbd_suspend,
494 +       .resume         = tosakbd_resume,
495 +       .driver         = {
496 +               .name   = "tosa-keyboard",
497 +       },
498 +};
499 +
500 +static int __devinit tosakbd_init(void)
501 +{
502 +       return platform_driver_register(&tosakbd_driver);
503 +}
504 +
505 +static void __exit tosakbd_exit(void)
506 +{
507 +       platform_driver_unregister(&tosakbd_driver);
508 +}
509 +
510 +module_init(tosakbd_init);
511 +module_exit(tosakbd_exit);
512 +
513 +MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
514 +MODULE_DESCRIPTION("Tosa Keyboard Driver");
515 +MODULE_LICENSE("GPLv2");