Pull misc into release branch
[linux-2.6] / drivers / input / keyboard / pxa27x_keyboard.c
1 /*
2  * linux/drivers/input/keyboard/pxa27x_keyboard.c
3  *
4  * Driver for the pxa27x matrix keyboard controller.
5  *
6  * Created:     Feb 22, 2007
7  * Author:      Rodolfo Giometti <giometti@linux.it>
8  *
9  * Based on a previous implementations by Kevin O'Connor
10  * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
11  * on some suggestions by Nicolas Pitre <nico@cam.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
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/interrupt.h>
23 #include <linux/input.h>
24 #include <linux/device.h>
25 #include <linux/platform_device.h>
26
27 #include <asm/mach-types.h>
28 #include <asm/mach/arch.h>
29 #include <asm/mach/map.h>
30
31 #include <asm/arch/hardware.h>
32 #include <asm/arch/pxa-regs.h>
33 #include <asm/arch/irqs.h>
34 #include <asm/arch/pxa27x_keyboard.h>
35
36 #define DRIVER_NAME             "pxa27x-keyboard"
37
38 #define KPASMKP(col)            (col/2 == 0 ? KPASMKP0 : \
39                                  col/2 == 1 ? KPASMKP1 : \
40                                  col/2 == 2 ? KPASMKP2 : KPASMKP3)
41 #define KPASMKPx_MKC(row, col)  (1 << (row + 16 * (col % 2)))
42
43 static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
44 {
45         struct platform_device *pdev = dev_id;
46         struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
47         struct input_dev *input_dev = platform_get_drvdata(pdev);
48         unsigned long kpc = KPC;
49         int p, row, col, rel;
50
51         if (kpc & KPC_DI) {
52                 unsigned long kpdk = KPDK;
53
54                 if (!(kpdk & KPDK_DKP)) {
55                         /* better luck next time */
56                 } else if (kpc & KPC_REE0) {
57                         unsigned long kprec = KPREC;
58                         KPREC = 0x7f;
59
60                         if (kprec & KPREC_OF0)
61                                 rel = (kprec & 0xff) + 0x7f;
62                         else if (kprec & KPREC_UF0)
63                                 rel = (kprec & 0xff) - 0x7f - 0xff;
64                         else
65                                 rel = (kprec & 0xff) - 0x7f;
66
67                         if (rel) {
68                                 input_report_rel(input_dev, REL_WHEEL, rel);
69                                 input_sync(input_dev);
70                         }
71                 }
72         }
73
74         if (kpc & KPC_MI) {
75                 /* report the status of every button */
76                 for (row = 0; row < pdata->nr_rows; row++) {
77                         for (col = 0; col < pdata->nr_cols; col++) {
78                                 p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
79                                         1 : 0;
80                                 pr_debug("keycode %x - pressed %x\n",
81                                                 pdata->keycodes[row][col], p);
82                                 input_report_key(input_dev,
83                                                 pdata->keycodes[row][col], p);
84                         }
85                 }
86                 input_sync(input_dev);
87         }
88
89         return IRQ_HANDLED;
90 }
91
92 static int pxakbd_open(struct input_dev *dev)
93 {
94         /* Set keypad control register */
95         KPC |= (KPC_ASACT |
96                 KPC_MS_ALL |
97                 (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
98                 KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
99
100         KPC &= ~KPC_AS;         /* disable automatic scan */
101         KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
102
103         /* Set rotary count to mid-point value */
104         KPREC = 0x7F;
105
106         /* Enable unit clock */
107         pxa_set_cken(CKEN_KEYPAD, 1);
108
109         return 0;
110 }
111
112 static void pxakbd_close(struct input_dev *dev)
113 {
114         /* Disable clock unit */
115         pxa_set_cken(CKEN_KEYPAD, 0);
116 }
117
118 #ifdef CONFIG_PM
119 static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
120 {
121         struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
122
123         /* Save controller status */
124         pdata->reg_kpc = KPC;
125         pdata->reg_kprec = KPREC;
126
127         return 0;
128 }
129
130 static int pxakbd_resume(struct platform_device *pdev)
131 {
132         struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
133         struct input_dev *input_dev = platform_get_drvdata(pdev);
134
135         mutex_lock(&input_dev->mutex);
136
137         if (input_dev->users) {
138                 /* Restore controller status */
139                 KPC = pdata->reg_kpc;
140                 KPREC = pdata->reg_kprec;
141
142                 /* Enable unit clock */
143                 pxa_set_cken(CKEN_KEYPAD, 1);
144         }
145
146         mutex_unlock(&input_dev->mutex);
147
148         return 0;
149 }
150 #else
151 #define pxakbd_suspend  NULL
152 #define pxakbd_resume   NULL
153 #endif
154
155 static int __devinit pxakbd_probe(struct platform_device *pdev)
156 {
157         struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
158         struct input_dev *input_dev;
159         int i, row, col, error;
160
161         /* Create and register the input driver. */
162         input_dev = input_allocate_device();
163         if (!input_dev) {
164                 printk(KERN_ERR "Cannot request keypad device\n");
165                 return -ENOMEM;
166         }
167
168         input_dev->name = DRIVER_NAME;
169         input_dev->id.bustype = BUS_HOST;
170         input_dev->open = pxakbd_open;
171         input_dev->close = pxakbd_close;
172         input_dev->dev.parent = &pdev->dev;
173
174         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
175         input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
176         for (row = 0; row < pdata->nr_rows; row++) {
177                 for (col = 0; col < pdata->nr_cols; col++) {
178                         int code = pdata->keycodes[row][col];
179                         if (code > 0)
180                                 set_bit(code, input_dev->keybit);
181                 }
182         }
183
184         error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
185                             DRIVER_NAME, pdev);
186         if (error) {
187                 printk(KERN_ERR "Cannot request keypad IRQ\n");
188                 pxa_set_cken(CKEN_KEYPAD, 0);
189                 goto err_free_dev;
190         }
191
192         platform_set_drvdata(pdev, input_dev);
193
194         /* Register the input device */
195         error = input_register_device(input_dev);
196         if (error)
197                 goto err_free_irq;
198
199         /* Setup GPIOs. */
200         for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
201                 pxa_gpio_mode(pdata->gpio_modes[i]);
202
203         /*
204          * Store rows/cols info into keyboard registers.
205          */
206
207         KPC |= (pdata->nr_rows - 1) << 26;
208         KPC |= (pdata->nr_cols - 1) << 23;
209
210         for (col = 0; col < pdata->nr_cols; col++)
211                 KPC |= KPC_MS0 << col;
212
213         return 0;
214
215  err_free_irq:
216         platform_set_drvdata(pdev, NULL);
217         free_irq(IRQ_KEYPAD, pdev);
218  err_free_dev:
219         input_free_device(input_dev);
220         return error;
221 }
222
223 static int __devexit pxakbd_remove(struct platform_device *pdev)
224 {
225         struct input_dev *input_dev = platform_get_drvdata(pdev);
226
227         input_unregister_device(input_dev);
228         free_irq(IRQ_KEYPAD, pdev);
229         platform_set_drvdata(pdev, NULL);
230
231         return 0;
232 }
233
234 static struct platform_driver pxakbd_driver = {
235         .probe          = pxakbd_probe,
236         .remove         = __devexit_p(pxakbd_remove),
237         .suspend        = pxakbd_suspend,
238         .resume         = pxakbd_resume,
239         .driver         = {
240                 .name   = DRIVER_NAME,
241         },
242 };
243
244 static int __init pxakbd_init(void)
245 {
246         return platform_driver_register(&pxakbd_driver);
247 }
248
249 static void __exit pxakbd_exit(void)
250 {
251         platform_driver_unregister(&pxakbd_driver);
252 }
253
254 module_init(pxakbd_init);
255 module_exit(pxakbd_exit);
256
257 MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
258 MODULE_LICENSE("GPL");