omap3-pandora-kernel: Add AUFS2 shim and keypad 'WIP' code.
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / keypad / 0002-Input-add-support-for-generic-GPIO-based-matrix-keyp.patch
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
5
6 Original patch by Marek Vasut, modified by Eric in:
7
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
18    by Uli Luckas
19 6. incorporate review comments from many others
20
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
24 and SL-C1000.
25
26 [dtor@mail.ru: fix error unwinding path, support changing keymap
27  from userspace]
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>
35
36 Conflicts:
37
38         drivers/input/keyboard/Kconfig
39         drivers/input/keyboard/Makefile
40 ---
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
48
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.
56  
57 +config KEYBOARD_MATRIX
58 +       tristate "GPIO driven matrix keypad support"
59 +       depends on GENERIC_GPIO
60 +       help
61 +         Enable support for GPIO driven matrix keypad.
62 +
63 +         To compile this driver as a module, choose M here: the
64 +         module will be called matrix_keypad.
65 +
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
81 new file mode 100644
82 index 0000000..e9b2e7c
83 --- /dev/null
84 +++ b/drivers/input/keyboard/matrix_keypad.c
85 @@ -0,0 +1,453 @@
86 +/*
87 + *  GPIO driven matrix keyboard driver
88 + *
89 + *  Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
90 + *
91 + *  Based on corgikbd.c
92 + *
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.
96 + *
97 + */
98 +
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>
110 +
111 +struct matrix_keypad {
112 +       const struct matrix_keypad_platform_data *pdata;
113 +       struct input_dev *input_dev;
114 +       unsigned short *keycodes;
115 +
116 +       uint32_t last_key_state[MATRIX_MAX_COLS];
117 +       struct delayed_work work;
118 +       bool scan_pending;
119 +       bool stopped;
120 +       spinlock_t lock;
121 +};
122 +
123 +/*
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.
127 + */
128 +static void __activate_col(const struct matrix_keypad_platform_data *pdata,
129 +                          int col, bool on)
130 +{
131 +       bool level_on = !pdata->active_low;
132 +
133 +       if (on) {
134 +               gpio_direction_output(pdata->col_gpios[col], level_on);
135 +       } else {
136 +               gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
137 +               gpio_direction_input(pdata->col_gpios[col]);
138 +       }
139 +}
140 +
141 +static void activate_col(const struct matrix_keypad_platform_data *pdata,
142 +                        int col, bool on)
143 +{
144 +       __activate_col(pdata, col, on);
145 +
146 +       if (on && pdata->col_scan_delay_us)
147 +               udelay(pdata->col_scan_delay_us);
148 +}
149 +
150 +static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
151 +                             bool on)
152 +{
153 +       int col;
154 +
155 +       for (col = 0; col < pdata->num_col_gpios; col++)
156 +               __activate_col(pdata, col, on);
157 +}
158 +
159 +static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
160 +                        int row)
161 +{
162 +       return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
163 +                       !pdata->active_low : pdata->active_low;
164 +}
165 +
166 +static void enable_row_irqs(struct matrix_keypad *keypad)
167 +{
168 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
169 +       int i;
170 +
171 +       for (i = 0; i < pdata->num_row_gpios; i++)
172 +               enable_irq(gpio_to_irq(pdata->row_gpios[i]));
173 +}
174 +
175 +static void disable_row_irqs(struct matrix_keypad *keypad)
176 +{
177 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
178 +       int i;
179 +
180 +       for (i = 0; i < pdata->num_row_gpios; i++)
181 +               disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
182 +}
183 +
184 +/*
185 + * This gets the keys from keyboard and reports it to input subsystem
186 + */
187 +static void matrix_keypad_scan(struct work_struct *work)
188 +{
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;
195 +
196 +       /* de-activate all columns for scanning */
197 +       activate_all_cols(pdata, false);
198 +
199 +       memset(new_state, 0, sizeof(new_state));
200 +
201 +       /* assert each column and read the row status out */
202 +       for (col = 0; col < pdata->num_col_gpios; col++) {
203 +
204 +               activate_col(pdata, col, true);
205 +
206 +               for (row = 0; row < pdata->num_row_gpios; row++)
207 +                       new_state[col] |=
208 +                               row_asserted(pdata, row) ? (1 << row) : 0;
209 +
210 +               activate_col(pdata, col, false);
211 +       }
212 +
213 +       for (col = 0; col < pdata->num_col_gpios; col++) {
214 +               uint32_t bits_changed;
215 +
216 +               bits_changed = keypad->last_key_state[col] ^ new_state[col];
217 +               if (bits_changed == 0)
218 +                       continue;
219 +
220 +               for (row = 0; row < pdata->num_row_gpios; row++) {
221 +                       if ((bits_changed & (1 << row)) == 0)
222 +                               continue;
223 +
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));
229 +               }
230 +       }
231 +       input_sync(input_dev);
232 +
233 +       memcpy(keypad->last_key_state, new_state, sizeof(new_state));
234 +
235 +       activate_all_cols(pdata, true);
236 +
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);
242 +}
243 +
244 +static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
245 +{
246 +       struct matrix_keypad *keypad = id;
247 +       unsigned long flags;
248 +
249 +       spin_lock_irqsave(&keypad->lock, flags);
250 +
251 +       /*
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.
255 +        */
256 +       if (unlikely(keypad->scan_pending || keypad->stopped))
257 +               goto out;
258 +
259 +       disable_row_irqs(keypad);
260 +       keypad->scan_pending = true;
261 +       schedule_delayed_work(&keypad->work,
262 +               msecs_to_jiffies(keypad->pdata->debounce_ms));
263 +
264 +out:
265 +       spin_unlock_irqrestore(&keypad->lock, flags);
266 +       return IRQ_HANDLED;
267 +}
268 +
269 +static int matrix_keypad_start(struct input_dev *dev)
270 +{
271 +       struct matrix_keypad *keypad = input_get_drvdata(dev);
272 +
273 +       keypad->stopped = false;
274 +       mb();
275 +
276 +       /*
277 +        * Schedule an immediate key scan to capture current key state;
278 +        * columns will be activated and IRQs be enabled after the scan.
279 +        */
280 +       schedule_delayed_work(&keypad->work, 0);
281 +
282 +       return 0;
283 +}
284 +
285 +static void matrix_keypad_stop(struct input_dev *dev)
286 +{
287 +       struct matrix_keypad *keypad = input_get_drvdata(dev);
288 +
289 +       keypad->stopped = true;
290 +       mb();
291 +       flush_work(&keypad->work.work);
292 +       /*
293 +        * matrix_keypad_scan() will leave IRQs enabled;
294 +        * we should disable them now.
295 +        */
296 +       disable_row_irqs(keypad);
297 +}
298 +
299 +#ifdef CONFIG_PM
300 +static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
301 +{
302 +       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
303 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
304 +       int i;
305 +
306 +       matrix_keypad_stop(keypad->input_dev);
307 +
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]));
311 +
312 +       return 0;
313 +}
314 +
315 +static int matrix_keypad_resume(struct platform_device *pdev)
316 +{
317 +       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
318 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
319 +       int i;
320 +
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]));
324 +
325 +       matrix_keypad_start(keypad->input_dev);
326 +
327 +       return 0;
328 +}
329 +#else
330 +#define matrix_keypad_suspend  NULL
331 +#define matrix_keypad_resume   NULL
332 +#endif
333 +
334 +static int __devinit init_matrix_gpio(struct platform_device *pdev,
335 +                                       struct matrix_keypad *keypad)
336 +{
337 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
338 +       int i, err = -EINVAL;
339 +
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");
343 +               if (err) {
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;
348 +               }
349 +
350 +               gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
351 +       }
352 +
353 +       for (i = 0; i < pdata->num_row_gpios; i++) {
354 +               err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
355 +               if (err) {
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;
360 +               }
361 +
362 +               gpio_direction_input(pdata->row_gpios[i]);
363 +       }
364 +
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,
368 +                               IRQF_DISABLED |
369 +                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
370 +                               "matrix-keypad", keypad);
371 +               if (err) {
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;
376 +               }
377 +       }
378 +
379 +       /* initialized as disabled - enabled by input->open */
380 +       disable_row_irqs(keypad);
381 +       return 0;
382 +
383 +err_free_irqs:
384 +       while (--i >= 0)
385 +               free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
386 +       i = pdata->num_row_gpios;
387 +err_free_rows:
388 +       while (--i >= 0)
389 +               gpio_free(pdata->row_gpios[i]);
390 +       i = pdata->num_col_gpios;
391 +err_free_cols:
392 +       while (--i >= 0)
393 +               gpio_free(pdata->col_gpios[i]);
394 +
395 +       return err;
396 +}
397 +
398 +static int __devinit matrix_keypad_probe(struct platform_device *pdev)
399 +{
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;
405 +       int i;
406 +       int err;
407 +
408 +       pdata = pdev->dev.platform_data;
409 +       if (!pdata) {
410 +               dev_err(&pdev->dev, "no platform data defined\n");
411 +               return -EINVAL;
412 +       }
413 +
414 +       keymap_data = pdata->keymap_data;
415 +       if (!keymap_data) {
416 +               dev_err(&pdev->dev, "no keymap data defined\n");
417 +               return -EINVAL;
418 +       }
419 +
420 +       if (!keymap_data->max_keymap_size) {
421 +               dev_err(&pdev->dev, "invalid keymap data supplied\n");
422 +               return -EINVAL;
423 +       }
424 +
425 +       keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
426 +       keycodes = kzalloc(keymap_data->max_keymap_size *
427 +                               sizeof(keypad->keycodes),
428 +                          GFP_KERNEL);
429 +       input_dev = input_allocate_device();
430 +       if (!keypad || !keycodes || !input_dev) {
431 +               err = -ENOMEM;
432 +               goto err_free_mem;
433 +       }
434 +
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);
441 +
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;
448 +
449 +       input_dev->keycode      = keycodes;
450 +       input_dev->keycodesize  = sizeof(*keycodes);
451 +       input_dev->keycodemax   = keymap_data->max_keymap_size;
452 +
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);
458 +
459 +               keycodes[(row << 4) + col] = code;
460 +               __set_bit(code, input_dev->keybit);
461 +       }
462 +       __clear_bit(KEY_RESERVED, input_dev->keybit);
463 +
464 +       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
465 +       input_set_drvdata(input_dev, keypad);
466 +
467 +       err = init_matrix_gpio(pdev, keypad);
468 +       if (err)
469 +               goto err_free_mem;
470 +
471 +       err = input_register_device(keypad->input_dev);
472 +       if (err)
473 +               goto err_free_mem;
474 +
475 +       device_init_wakeup(&pdev->dev, pdata->wakeup);
476 +       platform_set_drvdata(pdev, keypad);
477 +
478 +       return 0;
479 +
480 +err_free_mem:
481 +       input_free_device(input_dev);
482 +       kfree(keycodes);
483 +       kfree(keypad);
484 +       return err;
485 +}
486 +
487 +static int __devexit matrix_keypad_remove(struct platform_device *pdev)
488 +{
489 +       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
490 +       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
491 +       int i;
492 +
493 +       device_init_wakeup(&pdev->dev, 0);
494 +
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]);
498 +       }
499 +
500 +       for (i = 0; i < pdata->num_col_gpios; i++)
501 +               gpio_free(pdata->col_gpios[i]);
502 +
503 +       input_unregister_device(keypad->input_dev);
504 +       platform_set_drvdata(pdev, NULL);
505 +       kfree(keypad->keycodes);
506 +       kfree(keypad);
507 +
508 +       return 0;
509 +}
510 +
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,
516 +       .driver         = {
517 +               .name   = "matrix-keypad",
518 +               .owner  = THIS_MODULE,
519 +       },
520 +};
521 +
522 +static int __init matrix_keypad_init(void)
523 +{
524 +       return platform_driver_register(&matrix_keypad_driver);
525 +}
526 +
527 +static void __exit matrix_keypad_exit(void)
528 +{
529 +       platform_driver_unregister(&matrix_keypad_driver);
530 +}
531 +
532 +module_init(matrix_keypad_init);
533 +module_exit(matrix_keypad_exit);
534 +
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
540 new file mode 100644
541 index 0000000..7964516
542 --- /dev/null
543 +++ b/include/linux/input/matrix_keypad.h
544 @@ -0,0 +1,65 @@
545 +#ifndef _MATRIX_KEYPAD_H
546 +#define _MATRIX_KEYPAD_H
547 +
548 +#include <linux/types.h>
549 +#include <linux/input.h>
550 +
551 +#define MATRIX_MAX_ROWS                16
552 +#define MATRIX_MAX_COLS                16
553 +
554 +#define KEY(row, col, val)     ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
555 +                                (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
556 +                                (val & 0xffff))
557 +
558 +#define KEY_ROW(k)             (((k) >> 24) & 0xff)
559 +#define KEY_COL(k)             (((k) >> 16) & 0xff)
560 +#define KEY_VAL(k)             ((k) & 0xffff)
561 +
562 +/**
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
568 + *
569 + * This structure is supposed to be used by platform code to supply
570 + * keymaps to drivers that implement matrix-like keypads/keyboards.
571 + */
572 +struct matrix_keymap_data {
573 +       const uint32_t *keymap;
574 +       unsigned int    keymap_size;
575 +       unsigned int    max_keymap_size;
576 +};
577 +
578 +/**
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
588 + *
589 + * This structure represents platform-specific data that use used by
590 + * matrix_keypad driver to perform proper initialization.
591 + */
592 +struct matrix_keypad_platform_data {
593 +       const struct matrix_keymap_data *keymap_data;
594 +
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;
599 +
600 +       unsigned int    col_scan_delay_us;
601 +
602 +       /* key debounce interval in milli-second */
603 +       unsigned int    debounce_ms;
604 +
605 +       bool            active_low;
606 +       bool            wakeup;
607 +};
608 +
609 +#endif /* _MATRIX_KEYPAD_H */
610 -- 
611 1.6.3.1
612