1 From a38e5cd354ef968dc6dc0decf579243c8d473698 Mon Sep 17 00:00:00 2001
2 From: Eric Miao <eric.y.miao@gmail.com>
3 Date: Tue, 3 Nov 2009 15:43:49 +0200
4 Subject: [PATCH 2/7] Input: add support for generic GPIO-based matrix keypad
6 Original patch by Marek Vasut, modified by Eric in:
8 1. use delayed work to simplify the debouncing
9 2. combine col_polarity/row_polarity into a single active_low field
10 3. use a generic bit array based XOR algorithm to detect key
11 press/release, which should make the column assertion time
12 shorter and code a bit cleaner
13 4. remove the ALT_FN handling, which is no way generic, the ALT_FN
14 key should be treated as no different from other keys, and
15 translation will be done by user space by commands like 'loadkeys'.
16 5. explicitly disable row IRQs and flush potential pending work,
17 and schedule an immediate scan after resuming as suggested
19 6. incorporate review comments from many others
21 Patch tested on Littleton/PXA310 (though PXA310 has a dedicate keypad
22 controller, I have to configure those pins as generic GPIO to use this
23 driver, works quite well, though), and Sharp Zaurus model SL-C7x0
26 [dtor@mail.ru: fix error unwinding path, support changing keymap
28 Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
29 Reviewed-by: Trilok Soni <soni.trilok@gmail.com>
30 Reviewed-by: Uli Luckas <u.luckas@road.de>
31 Reviewed-by: Russell King <linux@arm.linux.org.uk>
32 Reviewed-by: Robert Jarzmik <robert.jarzmik@free.fr>
33 Signed-off-by: Eric Miao <eric.miao@marvell.com>
34 Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
38 drivers/input/keyboard/Kconfig
39 drivers/input/keyboard/Makefile
41 drivers/input/keyboard/Kconfig | 9 +
42 drivers/input/keyboard/Makefile | 1 +
43 drivers/input/keyboard/matrix_keypad.c | 453 ++++++++++++++++++++++++++++++++
44 include/linux/input/matrix_keypad.h | 65 +++++
45 4 files changed, 528 insertions(+), 0 deletions(-)
46 create mode 100644 drivers/input/keyboard/matrix_keypad.c
47 create mode 100644 include/linux/input/matrix_keypad.h
49 diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
50 index 59ad05a..b0a3c78 100644
51 --- a/drivers/input/keyboard/Kconfig
52 +++ b/drivers/input/keyboard/Kconfig
53 @@ -199,6 +199,15 @@ config KEYBOARD_ATARI
54 To compile this driver as a module, choose M here: the
55 module will be called atakbd.
57 +config KEYBOARD_MATRIX
58 + tristate "GPIO driven matrix keypad support"
59 + depends on GENERIC_GPIO
61 + Enable support for GPIO driven matrix keypad.
63 + To compile this driver as a module, choose M here: the
64 + module will be called matrix_keypad.
66 config KEYBOARD_HIL_OLD
67 tristate "HP HIL keyboard support (simple driver)"
68 depends on GSC || HP300
69 diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
70 index 81e59f7..7b8bc44 100644
71 --- a/drivers/input/keyboard/Makefile
72 +++ b/drivers/input/keyboard/Makefile
73 @@ -28,5 +28,6 @@ obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
74 obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
75 obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
76 obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
77 +obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
78 obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
79 obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
80 diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
82 index 0000000..e9b2e7c
84 +++ b/drivers/input/keyboard/matrix_keypad.c
87 + * GPIO driven matrix keyboard driver
89 + * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
91 + * Based on corgikbd.c
93 + * This program is free software; you can redistribute it and/or modify
94 + * it under the terms of the GNU General Public License version 2 as
95 + * published by the Free Software Foundation.
99 +#include <linux/types.h>
100 +#include <linux/delay.h>
101 +#include <linux/platform_device.h>
102 +#include <linux/init.h>
103 +#include <linux/input.h>
104 +#include <linux/irq.h>
105 +#include <linux/interrupt.h>
106 +#include <linux/jiffies.h>
107 +#include <linux/module.h>
108 +#include <linux/gpio.h>
109 +#include <linux/input/matrix_keypad.h>
111 +struct matrix_keypad {
112 + const struct matrix_keypad_platform_data *pdata;
113 + struct input_dev *input_dev;
114 + unsigned short *keycodes;
116 + uint32_t last_key_state[MATRIX_MAX_COLS];
117 + struct delayed_work work;
124 + * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
125 + * minmal side effect when scanning other columns, here it is configured to
126 + * be input, and it should work on most platforms.
128 +static void __activate_col(const struct matrix_keypad_platform_data *pdata,
131 + bool level_on = !pdata->active_low;
134 + gpio_direction_output(pdata->col_gpios[col], level_on);
136 + gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
137 + gpio_direction_input(pdata->col_gpios[col]);
141 +static void activate_col(const struct matrix_keypad_platform_data *pdata,
144 + __activate_col(pdata, col, on);
146 + if (on && pdata->col_scan_delay_us)
147 + udelay(pdata->col_scan_delay_us);
150 +static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
155 + for (col = 0; col < pdata->num_col_gpios; col++)
156 + __activate_col(pdata, col, on);
159 +static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
162 + return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
163 + !pdata->active_low : pdata->active_low;
166 +static void enable_row_irqs(struct matrix_keypad *keypad)
168 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
171 + for (i = 0; i < pdata->num_row_gpios; i++)
172 + enable_irq(gpio_to_irq(pdata->row_gpios[i]));
175 +static void disable_row_irqs(struct matrix_keypad *keypad)
177 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
180 + for (i = 0; i < pdata->num_row_gpios; i++)
181 + disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
185 + * This gets the keys from keyboard and reports it to input subsystem
187 +static void matrix_keypad_scan(struct work_struct *work)
189 + struct matrix_keypad *keypad =
190 + container_of(work, struct matrix_keypad, work.work);
191 + struct input_dev *input_dev = keypad->input_dev;
192 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
193 + uint32_t new_state[MATRIX_MAX_COLS];
194 + int row, col, code;
196 + /* de-activate all columns for scanning */
197 + activate_all_cols(pdata, false);
199 + memset(new_state, 0, sizeof(new_state));
201 + /* assert each column and read the row status out */
202 + for (col = 0; col < pdata->num_col_gpios; col++) {
204 + activate_col(pdata, col, true);
206 + for (row = 0; row < pdata->num_row_gpios; row++)
208 + row_asserted(pdata, row) ? (1 << row) : 0;
210 + activate_col(pdata, col, false);
213 + for (col = 0; col < pdata->num_col_gpios; col++) {
214 + uint32_t bits_changed;
216 + bits_changed = keypad->last_key_state[col] ^ new_state[col];
217 + if (bits_changed == 0)
220 + for (row = 0; row < pdata->num_row_gpios; row++) {
221 + if ((bits_changed & (1 << row)) == 0)
224 + code = (row << 4) + col;
225 + input_event(input_dev, EV_MSC, MSC_SCAN, code);
226 + input_report_key(input_dev,
227 + keypad->keycodes[code],
228 + new_state[col] & (1 << row));
231 + input_sync(input_dev);
233 + memcpy(keypad->last_key_state, new_state, sizeof(new_state));
235 + activate_all_cols(pdata, true);
237 + /* Enable IRQs again */
238 + spin_lock_irq(&keypad->lock);
239 + keypad->scan_pending = false;
240 + enable_row_irqs(keypad);
241 + spin_unlock_irq(&keypad->lock);
244 +static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
246 + struct matrix_keypad *keypad = id;
247 + unsigned long flags;
249 + spin_lock_irqsave(&keypad->lock, flags);
252 + * See if another IRQ beaten us to it and scheduled the
253 + * scan already. In that case we should not try to
254 + * disable IRQs again.
256 + if (unlikely(keypad->scan_pending || keypad->stopped))
259 + disable_row_irqs(keypad);
260 + keypad->scan_pending = true;
261 + schedule_delayed_work(&keypad->work,
262 + msecs_to_jiffies(keypad->pdata->debounce_ms));
265 + spin_unlock_irqrestore(&keypad->lock, flags);
266 + return IRQ_HANDLED;
269 +static int matrix_keypad_start(struct input_dev *dev)
271 + struct matrix_keypad *keypad = input_get_drvdata(dev);
273 + keypad->stopped = false;
277 + * Schedule an immediate key scan to capture current key state;
278 + * columns will be activated and IRQs be enabled after the scan.
280 + schedule_delayed_work(&keypad->work, 0);
285 +static void matrix_keypad_stop(struct input_dev *dev)
287 + struct matrix_keypad *keypad = input_get_drvdata(dev);
289 + keypad->stopped = true;
291 + flush_work(&keypad->work.work);
293 + * matrix_keypad_scan() will leave IRQs enabled;
294 + * we should disable them now.
296 + disable_row_irqs(keypad);
300 +static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
302 + struct matrix_keypad *keypad = platform_get_drvdata(pdev);
303 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
306 + matrix_keypad_stop(keypad->input_dev);
308 + if (device_may_wakeup(&pdev->dev))
309 + for (i = 0; i < pdata->num_row_gpios; i++)
310 + enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
315 +static int matrix_keypad_resume(struct platform_device *pdev)
317 + struct matrix_keypad *keypad = platform_get_drvdata(pdev);
318 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
321 + if (device_may_wakeup(&pdev->dev))
322 + for (i = 0; i < pdata->num_row_gpios; i++)
323 + disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
325 + matrix_keypad_start(keypad->input_dev);
330 +#define matrix_keypad_suspend NULL
331 +#define matrix_keypad_resume NULL
334 +static int __devinit init_matrix_gpio(struct platform_device *pdev,
335 + struct matrix_keypad *keypad)
337 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
338 + int i, err = -EINVAL;
340 + /* initialized strobe lines as outputs, activated */
341 + for (i = 0; i < pdata->num_col_gpios; i++) {
342 + err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
344 + dev_err(&pdev->dev,
345 + "failed to request GPIO%d for COL%d\n",
346 + pdata->col_gpios[i], i);
347 + goto err_free_cols;
350 + gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
353 + for (i = 0; i < pdata->num_row_gpios; i++) {
354 + err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
356 + dev_err(&pdev->dev,
357 + "failed to request GPIO%d for ROW%d\n",
358 + pdata->row_gpios[i], i);
359 + goto err_free_rows;
362 + gpio_direction_input(pdata->row_gpios[i]);
365 + for (i = 0; i < pdata->num_row_gpios; i++) {
366 + err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
367 + matrix_keypad_interrupt,
369 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
370 + "matrix-keypad", keypad);
372 + dev_err(&pdev->dev,
373 + "Unable to acquire interrupt for GPIO line %i\n",
374 + pdata->row_gpios[i]);
375 + goto err_free_irqs;
379 + /* initialized as disabled - enabled by input->open */
380 + disable_row_irqs(keypad);
385 + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
386 + i = pdata->num_row_gpios;
389 + gpio_free(pdata->row_gpios[i]);
390 + i = pdata->num_col_gpios;
393 + gpio_free(pdata->col_gpios[i]);
398 +static int __devinit matrix_keypad_probe(struct platform_device *pdev)
400 + const struct matrix_keypad_platform_data *pdata;
401 + const struct matrix_keymap_data *keymap_data;
402 + struct matrix_keypad *keypad;
403 + struct input_dev *input_dev;
404 + unsigned short *keycodes;
408 + pdata = pdev->dev.platform_data;
410 + dev_err(&pdev->dev, "no platform data defined\n");
414 + keymap_data = pdata->keymap_data;
415 + if (!keymap_data) {
416 + dev_err(&pdev->dev, "no keymap data defined\n");
420 + if (!keymap_data->max_keymap_size) {
421 + dev_err(&pdev->dev, "invalid keymap data supplied\n");
425 + keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
426 + keycodes = kzalloc(keymap_data->max_keymap_size *
427 + sizeof(keypad->keycodes),
429 + input_dev = input_allocate_device();
430 + if (!keypad || !keycodes || !input_dev) {
435 + keypad->input_dev = input_dev;
436 + keypad->pdata = pdata;
437 + keypad->keycodes = keycodes;
438 + keypad->stopped = true;
439 + INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
440 + spin_lock_init(&keypad->lock);
442 + input_dev->name = pdev->name;
443 + input_dev->id.bustype = BUS_HOST;
444 + input_dev->dev.parent = &pdev->dev;
445 + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
446 + input_dev->open = matrix_keypad_start;
447 + input_dev->close = matrix_keypad_stop;
449 + input_dev->keycode = keycodes;
450 + input_dev->keycodesize = sizeof(*keycodes);
451 + input_dev->keycodemax = keymap_data->max_keymap_size;
453 + for (i = 0; i < keymap_data->keymap_size; i++) {
454 + unsigned int key = keymap_data->keymap[i];
455 + unsigned int row = KEY_ROW(key);
456 + unsigned int col = KEY_COL(key);
457 + unsigned short code = KEY_VAL(key);
459 + keycodes[(row << 4) + col] = code;
460 + __set_bit(code, input_dev->keybit);
462 + __clear_bit(KEY_RESERVED, input_dev->keybit);
464 + input_set_capability(input_dev, EV_MSC, MSC_SCAN);
465 + input_set_drvdata(input_dev, keypad);
467 + err = init_matrix_gpio(pdev, keypad);
471 + err = input_register_device(keypad->input_dev);
475 + device_init_wakeup(&pdev->dev, pdata->wakeup);
476 + platform_set_drvdata(pdev, keypad);
481 + input_free_device(input_dev);
487 +static int __devexit matrix_keypad_remove(struct platform_device *pdev)
489 + struct matrix_keypad *keypad = platform_get_drvdata(pdev);
490 + const struct matrix_keypad_platform_data *pdata = keypad->pdata;
493 + device_init_wakeup(&pdev->dev, 0);
495 + for (i = 0; i < pdata->num_row_gpios; i++) {
496 + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
497 + gpio_free(pdata->row_gpios[i]);
500 + for (i = 0; i < pdata->num_col_gpios; i++)
501 + gpio_free(pdata->col_gpios[i]);
503 + input_unregister_device(keypad->input_dev);
504 + platform_set_drvdata(pdev, NULL);
505 + kfree(keypad->keycodes);
511 +static struct platform_driver matrix_keypad_driver = {
512 + .probe = matrix_keypad_probe,
513 + .remove = __devexit_p(matrix_keypad_remove),
514 + .suspend = matrix_keypad_suspend,
515 + .resume = matrix_keypad_resume,
517 + .name = "matrix-keypad",
518 + .owner = THIS_MODULE,
522 +static int __init matrix_keypad_init(void)
524 + return platform_driver_register(&matrix_keypad_driver);
527 +static void __exit matrix_keypad_exit(void)
529 + platform_driver_unregister(&matrix_keypad_driver);
532 +module_init(matrix_keypad_init);
533 +module_exit(matrix_keypad_exit);
535 +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
536 +MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
537 +MODULE_LICENSE("GPL v2");
538 +MODULE_ALIAS("platform:matrix-keypad");
539 diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
541 index 0000000..7964516
543 +++ b/include/linux/input/matrix_keypad.h
545 +#ifndef _MATRIX_KEYPAD_H
546 +#define _MATRIX_KEYPAD_H
548 +#include <linux/types.h>
549 +#include <linux/input.h>
551 +#define MATRIX_MAX_ROWS 16
552 +#define MATRIX_MAX_COLS 16
554 +#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
555 + (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
558 +#define KEY_ROW(k) (((k) >> 24) & 0xff)
559 +#define KEY_COL(k) (((k) >> 16) & 0xff)
560 +#define KEY_VAL(k) ((k) & 0xffff)
563 + * struct matrix_keymap_data - keymap for matrix keyboards
564 + * @keymap: pointer to array of uint32 values encoded with KEY() macro
565 + * representing keymap
566 + * @keymap_size: number of entries (initialized) in this keymap
567 + * @max_keymap_size: maximum size of keymap supported by the device
569 + * This structure is supposed to be used by platform code to supply
570 + * keymaps to drivers that implement matrix-like keypads/keyboards.
572 +struct matrix_keymap_data {
573 + const uint32_t *keymap;
574 + unsigned int keymap_size;
575 + unsigned int max_keymap_size;
579 + * struct matrix_keypad_platform_data - platform-dependent keypad data
580 + * @keymap_data: pointer to &matrix_keymap_data
581 + * @row_gpios: array of gpio numbers reporesenting rows
582 + * @col_gpios: array of gpio numbers reporesenting colums
583 + * @num_row_gpios: actual number of row gpios used by device
584 + * @num_col_gpios: actual number of col gpios used by device
585 + * @col_scan_delay_us: delay, measured in microseconds, that is
586 + * needed before we can keypad after activating column gpio
587 + * @debounce_ms: debounce interval in milliseconds
589 + * This structure represents platform-specific data that use used by
590 + * matrix_keypad driver to perform proper initialization.
592 +struct matrix_keypad_platform_data {
593 + const struct matrix_keymap_data *keymap_data;
595 + unsigned int row_gpios[MATRIX_MAX_ROWS];
596 + unsigned int col_gpios[MATRIX_MAX_COLS];
597 + unsigned int num_row_gpios;
598 + unsigned int num_col_gpios;
600 + unsigned int col_scan_delay_us;
602 + /* key debounce interval in milli-second */
603 + unsigned int debounce_ms;
609 +#endif /* _MATRIX_KEYPAD_H */