OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [keyboard/] [spitzkbd.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
3
 *
4
 *  Copyright (c) 2005 Richard Purdie
5
 *
6
 *  Based on corgikbd.c
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License version 2 as
10
 *  published by the Free Software Foundation.
11
 *
12
 */
13
 
14
#include <linux/delay.h>
15
#include <linux/platform_device.h>
16
#include <linux/init.h>
17
#include <linux/input.h>
18
#include <linux/interrupt.h>
19
#include <linux/jiffies.h>
20
#include <linux/module.h>
21
#include <linux/slab.h>
22
 
23
#include <asm/arch/spitz.h>
24
#include <asm/arch/hardware.h>
25
#include <asm/arch/pxa-regs.h>
26
 
27
#define KB_ROWS                 7
28
#define KB_COLS                 11
29
#define KB_ROWMASK(r)           (1 << (r))
30
#define SCANCODE(r,c)           (((r)<<4) + (c) + 1)
31
#define NR_SCANCODES            ((KB_ROWS<<4) + 1)
32
 
33
#define SCAN_INTERVAL           (50) /* ms */
34
#define HINGE_SCAN_INTERVAL     (150) /* ms */
35
 
36
#define SPITZ_KEY_CALENDER      KEY_F1
37
#define SPITZ_KEY_ADDRESS       KEY_F2
38
#define SPITZ_KEY_FN            KEY_F3
39
#define SPITZ_KEY_CANCEL        KEY_F4
40
#define SPITZ_KEY_EXOK          KEY_F5
41
#define SPITZ_KEY_EXCANCEL      KEY_F6
42
#define SPITZ_KEY_EXJOGDOWN     KEY_F7
43
#define SPITZ_KEY_EXJOGUP       KEY_F8
44
#define SPITZ_KEY_JAP1          KEY_LEFTALT
45
#define SPITZ_KEY_JAP2          KEY_RIGHTCTRL
46
#define SPITZ_KEY_SYNC          KEY_F9
47
#define SPITZ_KEY_MAIL          KEY_F10
48
#define SPITZ_KEY_OK            KEY_F11
49
#define SPITZ_KEY_MENU          KEY_F12
50
 
51
static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
52
        0,                                                                                                                /* 0 */
53
        KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0,  /* 1-16 */
54
        0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
55
        KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0,                                 /* 33-48 */
56
        SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,         /* 49-64 */
57
        SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0,   /* 65-80 */
58
        SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0,      /* 81-96 */
59
        KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0  /* 97-112 */
60
};
61
 
62
static int spitz_strobes[] = {
63
        SPITZ_GPIO_KEY_STROBE0,
64
        SPITZ_GPIO_KEY_STROBE1,
65
        SPITZ_GPIO_KEY_STROBE2,
66
        SPITZ_GPIO_KEY_STROBE3,
67
        SPITZ_GPIO_KEY_STROBE4,
68
        SPITZ_GPIO_KEY_STROBE5,
69
        SPITZ_GPIO_KEY_STROBE6,
70
        SPITZ_GPIO_KEY_STROBE7,
71
        SPITZ_GPIO_KEY_STROBE8,
72
        SPITZ_GPIO_KEY_STROBE9,
73
        SPITZ_GPIO_KEY_STROBE10,
74
};
75
 
76
static int spitz_senses[] = {
77
        SPITZ_GPIO_KEY_SENSE0,
78
        SPITZ_GPIO_KEY_SENSE1,
79
        SPITZ_GPIO_KEY_SENSE2,
80
        SPITZ_GPIO_KEY_SENSE3,
81
        SPITZ_GPIO_KEY_SENSE4,
82
        SPITZ_GPIO_KEY_SENSE5,
83
        SPITZ_GPIO_KEY_SENSE6,
84
};
85
 
86
struct spitzkbd {
87
        unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
88
        struct input_dev *input;
89
        char phys[32];
90
 
91
        spinlock_t lock;
92
        struct timer_list timer;
93
        struct timer_list htimer;
94
 
95
        unsigned int suspended;
96
        unsigned long suspend_jiffies;
97
};
98
 
99
#define KB_DISCHARGE_DELAY      10
100
#define KB_ACTIVATE_DELAY       10
101
 
102
/* Helper functions for reading the keyboard matrix
103
 * Note: We should really be using pxa_gpio_mode to alter GPDR but it
104
 *       requires a function call per GPIO bit which is excessive
105
 *       when we need to access 11 bits at once, multiple times.
106
 * These functions must be called within local_irq_save()/local_irq_restore()
107
 * or similar.
108
 */
109
static inline void spitzkbd_discharge_all(void)
110
{
111
        /* STROBE All HiZ */
112
        GPCR0  =  SPITZ_GPIO_G0_STROBE_BIT;
113
        GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
114
        GPCR1  =  SPITZ_GPIO_G1_STROBE_BIT;
115
        GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
116
        GPCR2  =  SPITZ_GPIO_G2_STROBE_BIT;
117
        GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
118
        GPCR3  =  SPITZ_GPIO_G3_STROBE_BIT;
119
        GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
120
}
121
 
122
static inline void spitzkbd_activate_all(void)
123
{
124
        /* STROBE ALL -> High */
125
        GPSR0  =  SPITZ_GPIO_G0_STROBE_BIT;
126
        GPDR0 |=  SPITZ_GPIO_G0_STROBE_BIT;
127
        GPSR1  =  SPITZ_GPIO_G1_STROBE_BIT;
128
        GPDR1 |=  SPITZ_GPIO_G1_STROBE_BIT;
129
        GPSR2  =  SPITZ_GPIO_G2_STROBE_BIT;
130
        GPDR2 |=  SPITZ_GPIO_G2_STROBE_BIT;
131
        GPSR3  =  SPITZ_GPIO_G3_STROBE_BIT;
132
        GPDR3 |=  SPITZ_GPIO_G3_STROBE_BIT;
133
 
134
        udelay(KB_DISCHARGE_DELAY);
135
 
136
        /* Clear any interrupts we may have triggered when altering the GPIO lines */
137
        GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
138
        GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
139
        GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
140
        GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
141
}
142
 
143
static inline void spitzkbd_activate_col(int col)
144
{
145
        int gpio = spitz_strobes[col];
146
        GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
147
        GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
148
        GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
149
        GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
150
        GPSR(gpio) = GPIO_bit(gpio);
151
        GPDR(gpio) |= GPIO_bit(gpio);
152
}
153
 
154
static inline void spitzkbd_reset_col(int col)
155
{
156
        int gpio = spitz_strobes[col];
157
        GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
158
        GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
159
        GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
160
        GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
161
        GPCR(gpio) = GPIO_bit(gpio);
162
        GPDR(gpio) |= GPIO_bit(gpio);
163
}
164
 
165
static inline int spitzkbd_get_row_status(int col)
166
{
167
        return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
168
                | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
169
                | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
170
}
171
 
172
/*
173
 * The spitz keyboard only generates interrupts when a key is pressed.
174
 * When a key is pressed, we enable a timer which then scans the
175
 * keyboard to detect when the key is released.
176
 */
177
 
178
/* Scan the hardware keyboard and push any changes up through the input layer */
179
static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data)
180
{
181
        unsigned int row, col, rowd;
182
        unsigned long flags;
183
        unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
184
 
185
        if (spitzkbd_data->suspended)
186
                return;
187
 
188
        spin_lock_irqsave(&spitzkbd_data->lock, flags);
189
 
190
        num_pressed = 0;
191
        for (col = 0; col < KB_COLS; col++) {
192
                /*
193
                 * Discharge the output driver capacitatance
194
                 * in the keyboard matrix. (Yes it is significant..)
195
                 */
196
 
197
                spitzkbd_discharge_all();
198
                udelay(KB_DISCHARGE_DELAY);
199
 
200
                spitzkbd_activate_col(col);
201
                udelay(KB_ACTIVATE_DELAY);
202
 
203
                rowd = spitzkbd_get_row_status(col);
204
                for (row = 0; row < KB_ROWS; row++) {
205
                        unsigned int scancode, pressed;
206
 
207
                        scancode = SCANCODE(row, col);
208
                        pressed = rowd & KB_ROWMASK(row);
209
 
210
                        input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
211
 
212
                        if (pressed)
213
                                num_pressed++;
214
                }
215
                spitzkbd_reset_col(col);
216
        }
217
 
218
        spitzkbd_activate_all();
219
 
220
        input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
221
        input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey);
222
 
223
        if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
224
                input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
225
                spitzkbd_data->suspend_jiffies = jiffies;
226
        }
227
 
228
        input_sync(spitzkbd_data->input);
229
 
230
        /* if any keys are pressed, enable the timer */
231
        if (num_pressed)
232
                mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
233
 
234
        spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
235
}
236
 
237
/*
238
 * spitz keyboard interrupt handler.
239
 */
240
static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id)
241
{
242
        struct spitzkbd *spitzkbd_data = dev_id;
243
 
244
        if (!timer_pending(&spitzkbd_data->timer)) {
245
                /** wait chattering delay **/
246
                udelay(20);
247
                spitzkbd_scankeyboard(spitzkbd_data);
248
        }
249
 
250
        return IRQ_HANDLED;
251
}
252
 
253
/*
254
 * spitz timer checking for released keys
255
 */
256
static void spitzkbd_timer_callback(unsigned long data)
257
{
258
        struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
259
 
260
        spitzkbd_scankeyboard(spitzkbd_data);
261
}
262
 
263
/*
264
 * The hinge switches generate an interrupt.
265
 * We debounce the switches and pass them to the input system.
266
 */
267
 
268
static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id)
269
{
270
        struct spitzkbd *spitzkbd_data = dev_id;
271
 
272
        if (!timer_pending(&spitzkbd_data->htimer))
273
                mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
274
 
275
        return IRQ_HANDLED;
276
}
277
 
278
#define HINGE_STABLE_COUNT 2
279
static int sharpsl_hinge_state;
280
static int hinge_count;
281
 
282
static void spitzkbd_hinge_timer(unsigned long data)
283
{
284
        struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
285
        unsigned long state;
286
        unsigned long flags;
287
 
288
        state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
289
        state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
290
        if (state != sharpsl_hinge_state) {
291
                hinge_count = 0;
292
                sharpsl_hinge_state = state;
293
        } else if (hinge_count < HINGE_STABLE_COUNT) {
294
                hinge_count++;
295
        }
296
 
297
        if (hinge_count >= HINGE_STABLE_COUNT) {
298
                spin_lock_irqsave(&spitzkbd_data->lock, flags);
299
 
300
                input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
301
                input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
302
                input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
303
                input_sync(spitzkbd_data->input);
304
 
305
                spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
306
        } else {
307
                mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
308
        }
309
}
310
 
311
#ifdef CONFIG_PM
312
static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state)
313
{
314
        int i;
315
        struct spitzkbd *spitzkbd = platform_get_drvdata(dev);
316
        spitzkbd->suspended = 1;
317
 
318
        /* Set Strobe lines as inputs - *except* strobe line 0 leave this
319
           enabled so we can detect a power button press for resume */
320
        for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
321
                pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
322
 
323
        return 0;
324
}
325
 
326
static int spitzkbd_resume(struct platform_device *dev)
327
{
328
        int i;
329
        struct spitzkbd *spitzkbd = platform_get_drvdata(dev);
330
 
331
        for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
332
                pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
333
 
334
        /* Upon resume, ignore the suspend key for a short while */
335
        spitzkbd->suspend_jiffies = jiffies;
336
        spitzkbd->suspended = 0;
337
 
338
        return 0;
339
}
340
#else
341
#define spitzkbd_suspend        NULL
342
#define spitzkbd_resume         NULL
343
#endif
344
 
345
static int __init spitzkbd_probe(struct platform_device *dev)
346
{
347
        struct spitzkbd *spitzkbd;
348
        struct input_dev *input_dev;
349
        int i, err = -ENOMEM;
350
 
351
        spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
352
        input_dev = input_allocate_device();
353
        if (!spitzkbd || !input_dev)
354
                goto fail;
355
 
356
        platform_set_drvdata(dev, spitzkbd);
357
        strcpy(spitzkbd->phys, "spitzkbd/input0");
358
 
359
        spin_lock_init(&spitzkbd->lock);
360
 
361
        /* Init Keyboard rescan timer */
362
        init_timer(&spitzkbd->timer);
363
        spitzkbd->timer.function = spitzkbd_timer_callback;
364
        spitzkbd->timer.data = (unsigned long) spitzkbd;
365
 
366
        /* Init Hinge Timer */
367
        init_timer(&spitzkbd->htimer);
368
        spitzkbd->htimer.function = spitzkbd_hinge_timer;
369
        spitzkbd->htimer.data = (unsigned long) spitzkbd;
370
 
371
        spitzkbd->suspend_jiffies = jiffies;
372
 
373
        spitzkbd->input = input_dev;
374
 
375
        input_dev->name = "Spitz Keyboard";
376
        input_dev->phys = spitzkbd->phys;
377
        input_dev->dev.parent = &dev->dev;
378
 
379
        input_dev->id.bustype = BUS_HOST;
380
        input_dev->id.vendor = 0x0001;
381
        input_dev->id.product = 0x0001;
382
        input_dev->id.version = 0x0100;
383
 
384
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
385
                BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
386
        input_dev->keycode = spitzkbd->keycode;
387
        input_dev->keycodesize = sizeof(unsigned char);
388
        input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
389
 
390
        memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
391
        for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
392
                set_bit(spitzkbd->keycode[i], input_dev->keybit);
393
        clear_bit(0, input_dev->keybit);
394
        set_bit(KEY_SUSPEND, input_dev->keybit);
395
        set_bit(SW_LID, input_dev->swbit);
396
        set_bit(SW_TABLET_MODE, input_dev->swbit);
397
        set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
398
 
399
        err = input_register_device(input_dev);
400
        if (err)
401
                goto fail;
402
 
403
        mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
404
 
405
        /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
406
        for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
407
                pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
408
                if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
409
                                IRQF_DISABLED|IRQF_TRIGGER_RISING,
410
                                "Spitzkbd Sense", spitzkbd))
411
                        printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
412
        }
413
 
414
        /* Set Strobe lines as outputs - set high */
415
        for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
416
                pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
417
 
418
        pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
419
        pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
420
        pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
421
        pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
422
 
423
        request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt,
424
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
425
                    "Spitzkbd Sync", spitzkbd);
426
        request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt,
427
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
428
                    "Spitzkbd PwrOn", spitzkbd);
429
        request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr,
430
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
431
                    "Spitzkbd SWA", spitzkbd);
432
        request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
433
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
434
                    "Spitzkbd SWB", spitzkbd);
435
        request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
436
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
437
                    "Spitzkbd HP", spitzkbd);
438
 
439
        return 0;
440
 
441
 fail:  input_free_device(input_dev);
442
        kfree(spitzkbd);
443
        return err;
444
}
445
 
446
static int spitzkbd_remove(struct platform_device *dev)
447
{
448
        int i;
449
        struct spitzkbd *spitzkbd = platform_get_drvdata(dev);
450
 
451
        for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
452
                free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
453
 
454
        free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
455
        free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
456
        free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
457
        free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
458
        free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
459
 
460
        del_timer_sync(&spitzkbd->htimer);
461
        del_timer_sync(&spitzkbd->timer);
462
 
463
        input_unregister_device(spitzkbd->input);
464
 
465
        kfree(spitzkbd);
466
 
467
        return 0;
468
}
469
 
470
static struct platform_driver spitzkbd_driver = {
471
        .probe          = spitzkbd_probe,
472
        .remove         = spitzkbd_remove,
473
        .suspend        = spitzkbd_suspend,
474
        .resume         = spitzkbd_resume,
475
        .driver         = {
476
                .name   = "spitz-keyboard",
477
                .owner  = THIS_MODULE,
478
        },
479
};
480
 
481
static int __devinit spitzkbd_init(void)
482
{
483
        return platform_driver_register(&spitzkbd_driver);
484
}
485
 
486
static void __exit spitzkbd_exit(void)
487
{
488
        platform_driver_unregister(&spitzkbd_driver);
489
}
490
 
491
module_init(spitzkbd_init);
492
module_exit(spitzkbd_exit);
493
 
494
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
495
MODULE_DESCRIPTION("Spitz Keyboard Driver");
496
MODULE_LICENSE("GPLv2");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.