blob: f9d86cfb0db07e695b75d9e9aea66316af9f6b07 [file] [log] [blame]
Eric Miaobab76142009-06-29 00:20:52 -07001/*
2 * GPIO driven matrix keyboard driver
3 *
4 * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
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/types.h>
15#include <linux/delay.h>
16#include <linux/platform_device.h>
17#include <linux/init.h>
18#include <linux/input.h>
19#include <linux/irq.h>
20#include <linux/interrupt.h>
21#include <linux/jiffies.h>
22#include <linux/module.h>
23#include <linux/gpio.h>
24#include <linux/input/matrix_keypad.h>
25
26struct matrix_keypad {
27 const struct matrix_keypad_platform_data *pdata;
28 struct input_dev *input_dev;
29 unsigned short *keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -070030 unsigned int row_shift;
Eric Miaobab76142009-06-29 00:20:52 -070031
Dmitry Torokhovdd219232009-12-24 22:50:23 -080032 DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
33
Eric Miaobab76142009-06-29 00:20:52 -070034 uint32_t last_key_state[MATRIX_MAX_COLS];
35 struct delayed_work work;
Dmitry Torokhovdd219232009-12-24 22:50:23 -080036 spinlock_t lock;
Eric Miaobab76142009-06-29 00:20:52 -070037 bool scan_pending;
38 bool stopped;
Eric Miaobab76142009-06-29 00:20:52 -070039};
40
41/*
42 * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
43 * minmal side effect when scanning other columns, here it is configured to
44 * be input, and it should work on most platforms.
45 */
46static void __activate_col(const struct matrix_keypad_platform_data *pdata,
47 int col, bool on)
48{
49 bool level_on = !pdata->active_low;
50
51 if (on) {
52 gpio_direction_output(pdata->col_gpios[col], level_on);
53 } else {
54 gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
55 gpio_direction_input(pdata->col_gpios[col]);
56 }
57}
58
59static void activate_col(const struct matrix_keypad_platform_data *pdata,
60 int col, bool on)
61{
62 __activate_col(pdata, col, on);
63
64 if (on && pdata->col_scan_delay_us)
65 udelay(pdata->col_scan_delay_us);
66}
67
68static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
69 bool on)
70{
71 int col;
72
73 for (col = 0; col < pdata->num_col_gpios; col++)
74 __activate_col(pdata, col, on);
75}
76
77static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
78 int row)
79{
80 return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
81 !pdata->active_low : pdata->active_low;
82}
83
84static void enable_row_irqs(struct matrix_keypad *keypad)
85{
86 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
87 int i;
88
89 for (i = 0; i < pdata->num_row_gpios; i++)
90 enable_irq(gpio_to_irq(pdata->row_gpios[i]));
91}
92
93static void disable_row_irqs(struct matrix_keypad *keypad)
94{
95 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
96 int i;
97
98 for (i = 0; i < pdata->num_row_gpios; i++)
99 disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
100}
101
102/*
103 * This gets the keys from keyboard and reports it to input subsystem
104 */
105static void matrix_keypad_scan(struct work_struct *work)
106{
107 struct matrix_keypad *keypad =
108 container_of(work, struct matrix_keypad, work.work);
109 struct input_dev *input_dev = keypad->input_dev;
110 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
111 uint32_t new_state[MATRIX_MAX_COLS];
112 int row, col, code;
113
114 /* de-activate all columns for scanning */
115 activate_all_cols(pdata, false);
116
117 memset(new_state, 0, sizeof(new_state));
118
119 /* assert each column and read the row status out */
120 for (col = 0; col < pdata->num_col_gpios; col++) {
121
122 activate_col(pdata, col, true);
123
124 for (row = 0; row < pdata->num_row_gpios; row++)
125 new_state[col] |=
126 row_asserted(pdata, row) ? (1 << row) : 0;
127
128 activate_col(pdata, col, false);
129 }
130
131 for (col = 0; col < pdata->num_col_gpios; col++) {
132 uint32_t bits_changed;
133
134 bits_changed = keypad->last_key_state[col] ^ new_state[col];
135 if (bits_changed == 0)
136 continue;
137
138 for (row = 0; row < pdata->num_row_gpios; row++) {
139 if ((bits_changed & (1 << row)) == 0)
140 continue;
141
Eric Miaod82f1c32009-08-05 01:24:41 -0700142 code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
Eric Miaobab76142009-06-29 00:20:52 -0700143 input_event(input_dev, EV_MSC, MSC_SCAN, code);
144 input_report_key(input_dev,
145 keypad->keycodes[code],
146 new_state[col] & (1 << row));
147 }
148 }
149 input_sync(input_dev);
150
151 memcpy(keypad->last_key_state, new_state, sizeof(new_state));
152
153 activate_all_cols(pdata, true);
154
155 /* Enable IRQs again */
156 spin_lock_irq(&keypad->lock);
157 keypad->scan_pending = false;
158 enable_row_irqs(keypad);
159 spin_unlock_irq(&keypad->lock);
160}
161
162static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
163{
164 struct matrix_keypad *keypad = id;
165 unsigned long flags;
166
167 spin_lock_irqsave(&keypad->lock, flags);
168
169 /*
170 * See if another IRQ beaten us to it and scheduled the
171 * scan already. In that case we should not try to
172 * disable IRQs again.
173 */
174 if (unlikely(keypad->scan_pending || keypad->stopped))
175 goto out;
176
177 disable_row_irqs(keypad);
178 keypad->scan_pending = true;
179 schedule_delayed_work(&keypad->work,
180 msecs_to_jiffies(keypad->pdata->debounce_ms));
181
182out:
183 spin_unlock_irqrestore(&keypad->lock, flags);
184 return IRQ_HANDLED;
185}
186
187static int matrix_keypad_start(struct input_dev *dev)
188{
189 struct matrix_keypad *keypad = input_get_drvdata(dev);
190
191 keypad->stopped = false;
192 mb();
193
194 /*
195 * Schedule an immediate key scan to capture current key state;
196 * columns will be activated and IRQs be enabled after the scan.
197 */
198 schedule_delayed_work(&keypad->work, 0);
199
200 return 0;
201}
202
203static void matrix_keypad_stop(struct input_dev *dev)
204{
205 struct matrix_keypad *keypad = input_get_drvdata(dev);
206
207 keypad->stopped = true;
208 mb();
209 flush_work(&keypad->work.work);
210 /*
211 * matrix_keypad_scan() will leave IRQs enabled;
212 * we should disable them now.
213 */
214 disable_row_irqs(keypad);
215}
216
217#ifdef CONFIG_PM
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800218static int matrix_keypad_suspend(struct device *dev)
Eric Miaobab76142009-06-29 00:20:52 -0700219{
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800220 struct platform_device *pdev = to_platform_device(dev);
Eric Miaobab76142009-06-29 00:20:52 -0700221 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
222 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
223 int i;
224
225 matrix_keypad_stop(keypad->input_dev);
226
Dmitry Torokhovdd219232009-12-24 22:50:23 -0800227 if (device_may_wakeup(&pdev->dev)) {
228 for (i = 0; i < pdata->num_row_gpios; i++) {
229 if (!test_bit(i, keypad->disabled_gpios)) {
230 unsigned int gpio = pdata->row_gpios[i];
231
232 if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
233 __set_bit(i, keypad->disabled_gpios);
234 }
235 }
236 }
Eric Miaobab76142009-06-29 00:20:52 -0700237
238 return 0;
239}
240
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800241static int matrix_keypad_resume(struct device *dev)
Eric Miaobab76142009-06-29 00:20:52 -0700242{
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800243 struct platform_device *pdev = to_platform_device(dev);
Eric Miaobab76142009-06-29 00:20:52 -0700244 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
245 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
246 int i;
247
Dmitry Torokhovdd219232009-12-24 22:50:23 -0800248 if (device_may_wakeup(&pdev->dev)) {
249 for (i = 0; i < pdata->num_row_gpios; i++) {
250 if (test_and_clear_bit(i, keypad->disabled_gpios)) {
251 unsigned int gpio = pdata->row_gpios[i];
252
253 disable_irq_wake(gpio_to_irq(gpio));
254 }
255 }
256 }
Eric Miaobab76142009-06-29 00:20:52 -0700257
258 matrix_keypad_start(keypad->input_dev);
259
260 return 0;
261}
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800262
263static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
264 matrix_keypad_suspend, matrix_keypad_resume);
Eric Miaobab76142009-06-29 00:20:52 -0700265#endif
266
267static int __devinit init_matrix_gpio(struct platform_device *pdev,
268 struct matrix_keypad *keypad)
269{
270 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
271 int i, err = -EINVAL;
272
273 /* initialized strobe lines as outputs, activated */
274 for (i = 0; i < pdata->num_col_gpios; i++) {
275 err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
276 if (err) {
277 dev_err(&pdev->dev,
278 "failed to request GPIO%d for COL%d\n",
279 pdata->col_gpios[i], i);
280 goto err_free_cols;
281 }
282
283 gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
284 }
285
286 for (i = 0; i < pdata->num_row_gpios; i++) {
287 err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
288 if (err) {
289 dev_err(&pdev->dev,
290 "failed to request GPIO%d for ROW%d\n",
291 pdata->row_gpios[i], i);
292 goto err_free_rows;
293 }
294
295 gpio_direction_input(pdata->row_gpios[i]);
296 }
297
298 for (i = 0; i < pdata->num_row_gpios; i++) {
299 err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
300 matrix_keypad_interrupt,
301 IRQF_DISABLED |
302 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
303 "matrix-keypad", keypad);
304 if (err) {
305 dev_err(&pdev->dev,
306 "Unable to acquire interrupt for GPIO line %i\n",
307 pdata->row_gpios[i]);
308 goto err_free_irqs;
309 }
310 }
311
312 /* initialized as disabled - enabled by input->open */
313 disable_row_irqs(keypad);
314 return 0;
315
316err_free_irqs:
317 while (--i >= 0)
318 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
319 i = pdata->num_row_gpios;
320err_free_rows:
321 while (--i >= 0)
322 gpio_free(pdata->row_gpios[i]);
323 i = pdata->num_col_gpios;
324err_free_cols:
325 while (--i >= 0)
326 gpio_free(pdata->col_gpios[i]);
327
328 return err;
329}
330
331static int __devinit matrix_keypad_probe(struct platform_device *pdev)
332{
333 const struct matrix_keypad_platform_data *pdata;
334 const struct matrix_keymap_data *keymap_data;
335 struct matrix_keypad *keypad;
336 struct input_dev *input_dev;
337 unsigned short *keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -0700338 unsigned int row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700339 int err;
340
341 pdata = pdev->dev.platform_data;
342 if (!pdata) {
343 dev_err(&pdev->dev, "no platform data defined\n");
344 return -EINVAL;
345 }
346
347 keymap_data = pdata->keymap_data;
348 if (!keymap_data) {
349 dev_err(&pdev->dev, "no keymap data defined\n");
350 return -EINVAL;
351 }
352
Eric Miaod82f1c32009-08-05 01:24:41 -0700353 row_shift = get_count_order(pdata->num_col_gpios);
Eric Miaobab76142009-06-29 00:20:52 -0700354
355 keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
Eric Miaod82f1c32009-08-05 01:24:41 -0700356 keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
357 sizeof(*keycodes),
Eric Miaobab76142009-06-29 00:20:52 -0700358 GFP_KERNEL);
359 input_dev = input_allocate_device();
360 if (!keypad || !keycodes || !input_dev) {
361 err = -ENOMEM;
362 goto err_free_mem;
363 }
364
365 keypad->input_dev = input_dev;
366 keypad->pdata = pdata;
367 keypad->keycodes = keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -0700368 keypad->row_shift = row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700369 keypad->stopped = true;
370 INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
371 spin_lock_init(&keypad->lock);
372
373 input_dev->name = pdev->name;
374 input_dev->id.bustype = BUS_HOST;
375 input_dev->dev.parent = &pdev->dev;
H Hartley Sweeten9d32c302010-04-05 22:29:09 -0700376 input_dev->evbit[0] = BIT_MASK(EV_KEY);
377 if (!pdata->no_autorepeat)
378 input_dev->evbit[0] |= BIT_MASK(EV_REP);
Eric Miaobab76142009-06-29 00:20:52 -0700379 input_dev->open = matrix_keypad_start;
380 input_dev->close = matrix_keypad_stop;
381
382 input_dev->keycode = keycodes;
383 input_dev->keycodesize = sizeof(*keycodes);
Dmitry Torokhov77a53fd2009-08-25 19:24:13 -0700384 input_dev->keycodemax = pdata->num_row_gpios << row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700385
Dmitry Torokhov77a53fd2009-08-25 19:24:13 -0700386 matrix_keypad_build_keymap(keymap_data, row_shift,
387 input_dev->keycode, input_dev->keybit);
Eric Miaobab76142009-06-29 00:20:52 -0700388
389 input_set_capability(input_dev, EV_MSC, MSC_SCAN);
390 input_set_drvdata(input_dev, keypad);
391
392 err = init_matrix_gpio(pdev, keypad);
393 if (err)
394 goto err_free_mem;
395
396 err = input_register_device(keypad->input_dev);
397 if (err)
398 goto err_free_mem;
399
400 device_init_wakeup(&pdev->dev, pdata->wakeup);
401 platform_set_drvdata(pdev, keypad);
402
403 return 0;
404
405err_free_mem:
406 input_free_device(input_dev);
407 kfree(keycodes);
408 kfree(keypad);
409 return err;
410}
411
412static int __devexit matrix_keypad_remove(struct platform_device *pdev)
413{
414 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
415 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
416 int i;
417
418 device_init_wakeup(&pdev->dev, 0);
419
420 for (i = 0; i < pdata->num_row_gpios; i++) {
421 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
422 gpio_free(pdata->row_gpios[i]);
423 }
424
425 for (i = 0; i < pdata->num_col_gpios; i++)
426 gpio_free(pdata->col_gpios[i]);
427
428 input_unregister_device(keypad->input_dev);
429 platform_set_drvdata(pdev, NULL);
430 kfree(keypad->keycodes);
431 kfree(keypad);
432
433 return 0;
434}
435
436static struct platform_driver matrix_keypad_driver = {
437 .probe = matrix_keypad_probe,
438 .remove = __devexit_p(matrix_keypad_remove),
Eric Miaobab76142009-06-29 00:20:52 -0700439 .driver = {
440 .name = "matrix-keypad",
441 .owner = THIS_MODULE,
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800442#ifdef CONFIG_PM
443 .pm = &matrix_keypad_pm_ops,
444#endif
Eric Miaobab76142009-06-29 00:20:52 -0700445 },
446};
447
448static int __init matrix_keypad_init(void)
449{
450 return platform_driver_register(&matrix_keypad_driver);
451}
452
453static void __exit matrix_keypad_exit(void)
454{
455 platform_driver_unregister(&matrix_keypad_driver);
456}
457
458module_init(matrix_keypad_init);
459module_exit(matrix_keypad_exit);
460
461MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
462MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
463MODULE_LICENSE("GPL v2");
464MODULE_ALIAS("platform:matrix-keypad");