blob: f7b555852bbf7c8e5c39956000985c0510b43c62 [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>
Duy Truong790f06d2013-02-13 16:38:12 -08005 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Eric Miaobab76142009-06-29 00:20:52 -07006 *
7 * Based on corgikbd.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/types.h>
16#include <linux/delay.h>
17#include <linux/platform_device.h>
18#include <linux/init.h>
19#include <linux/input.h>
20#include <linux/irq.h>
21#include <linux/interrupt.h>
22#include <linux/jiffies.h>
23#include <linux/module.h>
24#include <linux/gpio.h>
25#include <linux/input/matrix_keypad.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Eric Miaobab76142009-06-29 00:20:52 -070027
28struct matrix_keypad {
29 const struct matrix_keypad_platform_data *pdata;
30 struct input_dev *input_dev;
31 unsigned short *keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -070032 unsigned int row_shift;
Eric Miaobab76142009-06-29 00:20:52 -070033
Dmitry Torokhovdd219232009-12-24 22:50:23 -080034 DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
35
Eric Miaobab76142009-06-29 00:20:52 -070036 uint32_t last_key_state[MATRIX_MAX_COLS];
37 struct delayed_work work;
Anirudh Ghayal473bb182012-04-19 16:36:11 +053038 struct mutex lock;
Eric Miaobab76142009-06-29 00:20:52 -070039 bool scan_pending;
40 bool stopped;
Luotao Fufb76dd12010-06-10 12:05:23 -070041 bool gpio_all_disabled;
Eric Miaobab76142009-06-29 00:20:52 -070042};
43
44/*
45 * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
46 * minmal side effect when scanning other columns, here it is configured to
47 * be input, and it should work on most platforms.
48 */
49static void __activate_col(const struct matrix_keypad_platform_data *pdata,
50 int col, bool on)
51{
52 bool level_on = !pdata->active_low;
53
54 if (on) {
55 gpio_direction_output(pdata->col_gpios[col], level_on);
56 } else {
57 gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
58 gpio_direction_input(pdata->col_gpios[col]);
59 }
60}
61
62static void activate_col(const struct matrix_keypad_platform_data *pdata,
63 int col, bool on)
64{
65 __activate_col(pdata, col, on);
66
67 if (on && pdata->col_scan_delay_us)
68 udelay(pdata->col_scan_delay_us);
69}
70
71static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
72 bool on)
73{
74 int col;
75
76 for (col = 0; col < pdata->num_col_gpios; col++)
77 __activate_col(pdata, col, on);
78}
79
80static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
81 int row)
82{
83 return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
84 !pdata->active_low : pdata->active_low;
85}
86
87static void enable_row_irqs(struct matrix_keypad *keypad)
88{
89 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
90 int i;
91
Luotao Fufb76dd12010-06-10 12:05:23 -070092 if (pdata->clustered_irq > 0)
93 enable_irq(pdata->clustered_irq);
94 else {
95 for (i = 0; i < pdata->num_row_gpios; i++)
96 enable_irq(gpio_to_irq(pdata->row_gpios[i]));
97 }
Eric Miaobab76142009-06-29 00:20:52 -070098}
99
100static void disable_row_irqs(struct matrix_keypad *keypad)
101{
102 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
103 int i;
104
Luotao Fufb76dd12010-06-10 12:05:23 -0700105 if (pdata->clustered_irq > 0)
106 disable_irq_nosync(pdata->clustered_irq);
107 else {
108 for (i = 0; i < pdata->num_row_gpios; i++)
109 disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
110 }
Eric Miaobab76142009-06-29 00:20:52 -0700111}
112
113/*
114 * This gets the keys from keyboard and reports it to input subsystem
115 */
116static void matrix_keypad_scan(struct work_struct *work)
117{
118 struct matrix_keypad *keypad =
119 container_of(work, struct matrix_keypad, work.work);
120 struct input_dev *input_dev = keypad->input_dev;
121 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
122 uint32_t new_state[MATRIX_MAX_COLS];
123 int row, col, code;
124
125 /* de-activate all columns for scanning */
126 activate_all_cols(pdata, false);
127
128 memset(new_state, 0, sizeof(new_state));
129
130 /* assert each column and read the row status out */
131 for (col = 0; col < pdata->num_col_gpios; col++) {
132
133 activate_col(pdata, col, true);
134
135 for (row = 0; row < pdata->num_row_gpios; row++)
136 new_state[col] |=
137 row_asserted(pdata, row) ? (1 << row) : 0;
138
139 activate_col(pdata, col, false);
140 }
141
142 for (col = 0; col < pdata->num_col_gpios; col++) {
143 uint32_t bits_changed;
144
145 bits_changed = keypad->last_key_state[col] ^ new_state[col];
146 if (bits_changed == 0)
147 continue;
148
149 for (row = 0; row < pdata->num_row_gpios; row++) {
150 if ((bits_changed & (1 << row)) == 0)
151 continue;
152
Eric Miaod82f1c32009-08-05 01:24:41 -0700153 code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
Eric Miaobab76142009-06-29 00:20:52 -0700154 input_event(input_dev, EV_MSC, MSC_SCAN, code);
155 input_report_key(input_dev,
156 keypad->keycodes[code],
157 new_state[col] & (1 << row));
158 }
159 }
160 input_sync(input_dev);
161
162 memcpy(keypad->last_key_state, new_state, sizeof(new_state));
163
164 activate_all_cols(pdata, true);
165
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530166 mutex_lock(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700167 keypad->scan_pending = false;
168 enable_row_irqs(keypad);
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530169 mutex_unlock(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700170}
171
172static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
173{
174 struct matrix_keypad *keypad = id;
Eric Miaobab76142009-06-29 00:20:52 -0700175
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530176 mutex_lock(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700177
178 /*
179 * See if another IRQ beaten us to it and scheduled the
180 * scan already. In that case we should not try to
181 * disable IRQs again.
182 */
183 if (unlikely(keypad->scan_pending || keypad->stopped))
184 goto out;
185
186 disable_row_irqs(keypad);
187 keypad->scan_pending = true;
188 schedule_delayed_work(&keypad->work,
189 msecs_to_jiffies(keypad->pdata->debounce_ms));
190
191out:
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530192 mutex_unlock(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700193 return IRQ_HANDLED;
194}
195
196static int matrix_keypad_start(struct input_dev *dev)
197{
198 struct matrix_keypad *keypad = input_get_drvdata(dev);
199
200 keypad->stopped = false;
201 mb();
202
203 /*
204 * Schedule an immediate key scan to capture current key state;
205 * columns will be activated and IRQs be enabled after the scan.
206 */
207 schedule_delayed_work(&keypad->work, 0);
208
209 return 0;
210}
211
212static void matrix_keypad_stop(struct input_dev *dev)
213{
214 struct matrix_keypad *keypad = input_get_drvdata(dev);
215
216 keypad->stopped = true;
217 mb();
218 flush_work(&keypad->work.work);
219 /*
220 * matrix_keypad_scan() will leave IRQs enabled;
221 * we should disable them now.
222 */
223 disable_row_irqs(keypad);
224}
225
226#ifdef CONFIG_PM
Luotao Fufb76dd12010-06-10 12:05:23 -0700227static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
Eric Miaobab76142009-06-29 00:20:52 -0700228{
Eric Miaobab76142009-06-29 00:20:52 -0700229 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
Luotao Fufb76dd12010-06-10 12:05:23 -0700230 unsigned int gpio;
Eric Miaobab76142009-06-29 00:20:52 -0700231 int i;
232
Luotao Fufb76dd12010-06-10 12:05:23 -0700233 if (pdata->clustered_irq > 0) {
234 if (enable_irq_wake(pdata->clustered_irq) == 0)
235 keypad->gpio_all_disabled = true;
236 } else {
Eric Miaobab76142009-06-29 00:20:52 -0700237
Dmitry Torokhovdd219232009-12-24 22:50:23 -0800238 for (i = 0; i < pdata->num_row_gpios; i++) {
239 if (!test_bit(i, keypad->disabled_gpios)) {
Luotao Fufb76dd12010-06-10 12:05:23 -0700240 gpio = pdata->row_gpios[i];
Dmitry Torokhovdd219232009-12-24 22:50:23 -0800241
242 if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
243 __set_bit(i, keypad->disabled_gpios);
244 }
245 }
246 }
Luotao Fufb76dd12010-06-10 12:05:23 -0700247}
248
249static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
250{
251 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
252 unsigned int gpio;
253 int i;
254
255 if (pdata->clustered_irq > 0) {
256 if (keypad->gpio_all_disabled) {
257 disable_irq_wake(pdata->clustered_irq);
258 keypad->gpio_all_disabled = false;
259 }
260 } else {
261 for (i = 0; i < pdata->num_row_gpios; i++) {
262 if (test_and_clear_bit(i, keypad->disabled_gpios)) {
263 gpio = pdata->row_gpios[i];
264 disable_irq_wake(gpio_to_irq(gpio));
265 }
266 }
267 }
268}
269
270static int matrix_keypad_suspend(struct device *dev)
271{
272 struct platform_device *pdev = to_platform_device(dev);
273 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
274
275 matrix_keypad_stop(keypad->input_dev);
276
277 if (device_may_wakeup(&pdev->dev))
278 matrix_keypad_enable_wakeup(keypad);
Eric Miaobab76142009-06-29 00:20:52 -0700279
280 return 0;
281}
282
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800283static int matrix_keypad_resume(struct device *dev)
Eric Miaobab76142009-06-29 00:20:52 -0700284{
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800285 struct platform_device *pdev = to_platform_device(dev);
Eric Miaobab76142009-06-29 00:20:52 -0700286 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
Eric Miaobab76142009-06-29 00:20:52 -0700287
Luotao Fufb76dd12010-06-10 12:05:23 -0700288 if (device_may_wakeup(&pdev->dev))
289 matrix_keypad_disable_wakeup(keypad);
Eric Miaobab76142009-06-29 00:20:52 -0700290
291 matrix_keypad_start(keypad->input_dev);
292
293 return 0;
294}
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800295
296static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
297 matrix_keypad_suspend, matrix_keypad_resume);
Eric Miaobab76142009-06-29 00:20:52 -0700298#endif
299
300static int __devinit init_matrix_gpio(struct platform_device *pdev,
301 struct matrix_keypad *keypad)
302{
303 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
304 int i, err = -EINVAL;
305
306 /* initialized strobe lines as outputs, activated */
307 for (i = 0; i < pdata->num_col_gpios; i++) {
308 err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
309 if (err) {
310 dev_err(&pdev->dev,
311 "failed to request GPIO%d for COL%d\n",
312 pdata->col_gpios[i], i);
313 goto err_free_cols;
314 }
315
316 gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
317 }
318
319 for (i = 0; i < pdata->num_row_gpios; i++) {
320 err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
321 if (err) {
322 dev_err(&pdev->dev,
323 "failed to request GPIO%d for ROW%d\n",
324 pdata->row_gpios[i], i);
325 goto err_free_rows;
326 }
327
328 gpio_direction_input(pdata->row_gpios[i]);
329 }
330
Luotao Fufb76dd12010-06-10 12:05:23 -0700331 if (pdata->clustered_irq > 0) {
332 err = request_irq(pdata->clustered_irq,
Eric Miaobab76142009-06-29 00:20:52 -0700333 matrix_keypad_interrupt,
Luotao Fufb76dd12010-06-10 12:05:23 -0700334 pdata->clustered_irq_flags,
Eric Miaobab76142009-06-29 00:20:52 -0700335 "matrix-keypad", keypad);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 if (err < 0) {
Eric Miaobab76142009-06-29 00:20:52 -0700337 dev_err(&pdev->dev,
Luotao Fufb76dd12010-06-10 12:05:23 -0700338 "Unable to acquire clustered interrupt\n");
339 goto err_free_rows;
340 }
341 } else {
342 for (i = 0; i < pdata->num_row_gpios; i++) {
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530343 err = request_threaded_irq(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700344 gpio_to_irq(pdata->row_gpios[i]),
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530345 NULL,
Luotao Fufb76dd12010-06-10 12:05:23 -0700346 matrix_keypad_interrupt,
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530347 IRQF_DISABLED | IRQF_ONESHOT |
Luotao Fufb76dd12010-06-10 12:05:23 -0700348 IRQF_TRIGGER_RISING |
349 IRQF_TRIGGER_FALLING,
350 "matrix-keypad", keypad);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 if (err < 0) {
Luotao Fufb76dd12010-06-10 12:05:23 -0700352 dev_err(&pdev->dev,
353 "Unable to acquire interrupt "
354 "for GPIO line %i\n",
355 pdata->row_gpios[i]);
356 goto err_free_irqs;
357 }
Eric Miaobab76142009-06-29 00:20:52 -0700358 }
359 }
360
361 /* initialized as disabled - enabled by input->open */
362 disable_row_irqs(keypad);
363 return 0;
364
365err_free_irqs:
366 while (--i >= 0)
367 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
368 i = pdata->num_row_gpios;
369err_free_rows:
370 while (--i >= 0)
371 gpio_free(pdata->row_gpios[i]);
372 i = pdata->num_col_gpios;
373err_free_cols:
374 while (--i >= 0)
375 gpio_free(pdata->col_gpios[i]);
376
377 return err;
378}
379
380static int __devinit matrix_keypad_probe(struct platform_device *pdev)
381{
382 const struct matrix_keypad_platform_data *pdata;
383 const struct matrix_keymap_data *keymap_data;
384 struct matrix_keypad *keypad;
385 struct input_dev *input_dev;
386 unsigned short *keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -0700387 unsigned int row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700388 int err;
389
390 pdata = pdev->dev.platform_data;
391 if (!pdata) {
392 dev_err(&pdev->dev, "no platform data defined\n");
393 return -EINVAL;
394 }
395
396 keymap_data = pdata->keymap_data;
397 if (!keymap_data) {
398 dev_err(&pdev->dev, "no keymap data defined\n");
399 return -EINVAL;
400 }
401
Eric Miaod82f1c32009-08-05 01:24:41 -0700402 row_shift = get_count_order(pdata->num_col_gpios);
Eric Miaobab76142009-06-29 00:20:52 -0700403
404 keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
Eric Miaod82f1c32009-08-05 01:24:41 -0700405 keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
406 sizeof(*keycodes),
Eric Miaobab76142009-06-29 00:20:52 -0700407 GFP_KERNEL);
408 input_dev = input_allocate_device();
409 if (!keypad || !keycodes || !input_dev) {
410 err = -ENOMEM;
411 goto err_free_mem;
412 }
413
414 keypad->input_dev = input_dev;
415 keypad->pdata = pdata;
416 keypad->keycodes = keycodes;
Eric Miaod82f1c32009-08-05 01:24:41 -0700417 keypad->row_shift = row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700418 keypad->stopped = true;
419 INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530420 mutex_init(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700421
422 input_dev->name = pdev->name;
423 input_dev->id.bustype = BUS_HOST;
424 input_dev->dev.parent = &pdev->dev;
H Hartley Sweeten9d32c302010-04-05 22:29:09 -0700425 input_dev->evbit[0] = BIT_MASK(EV_KEY);
426 if (!pdata->no_autorepeat)
427 input_dev->evbit[0] |= BIT_MASK(EV_REP);
Eric Miaobab76142009-06-29 00:20:52 -0700428 input_dev->open = matrix_keypad_start;
429 input_dev->close = matrix_keypad_stop;
430
431 input_dev->keycode = keycodes;
432 input_dev->keycodesize = sizeof(*keycodes);
Dmitry Torokhov77a53fd2009-08-25 19:24:13 -0700433 input_dev->keycodemax = pdata->num_row_gpios << row_shift;
Eric Miaobab76142009-06-29 00:20:52 -0700434
Dmitry Torokhov77a53fd2009-08-25 19:24:13 -0700435 matrix_keypad_build_keymap(keymap_data, row_shift,
436 input_dev->keycode, input_dev->keybit);
Eric Miaobab76142009-06-29 00:20:52 -0700437
438 input_set_capability(input_dev, EV_MSC, MSC_SCAN);
439 input_set_drvdata(input_dev, keypad);
440
441 err = init_matrix_gpio(pdev, keypad);
442 if (err)
443 goto err_free_mem;
444
445 err = input_register_device(keypad->input_dev);
446 if (err)
447 goto err_free_mem;
448
449 device_init_wakeup(&pdev->dev, pdata->wakeup);
450 platform_set_drvdata(pdev, keypad);
451
452 return 0;
453
454err_free_mem:
455 input_free_device(input_dev);
456 kfree(keycodes);
457 kfree(keypad);
458 return err;
459}
460
461static int __devexit matrix_keypad_remove(struct platform_device *pdev)
462{
463 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
464 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
465 int i;
466
467 device_init_wakeup(&pdev->dev, 0);
468
Luotao Fufb76dd12010-06-10 12:05:23 -0700469 if (pdata->clustered_irq > 0) {
470 free_irq(pdata->clustered_irq, keypad);
471 } else {
472 for (i = 0; i < pdata->num_row_gpios; i++)
473 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
Eric Miaobab76142009-06-29 00:20:52 -0700474 }
475
Luotao Fufb76dd12010-06-10 12:05:23 -0700476 for (i = 0; i < pdata->num_row_gpios; i++)
477 gpio_free(pdata->row_gpios[i]);
478
Eric Miaobab76142009-06-29 00:20:52 -0700479 for (i = 0; i < pdata->num_col_gpios; i++)
480 gpio_free(pdata->col_gpios[i]);
481
Anirudh Ghayal473bb182012-04-19 16:36:11 +0530482 mutex_destroy(&keypad->lock);
Eric Miaobab76142009-06-29 00:20:52 -0700483 input_unregister_device(keypad->input_dev);
484 platform_set_drvdata(pdev, NULL);
485 kfree(keypad->keycodes);
486 kfree(keypad);
487
488 return 0;
489}
490
491static struct platform_driver matrix_keypad_driver = {
492 .probe = matrix_keypad_probe,
493 .remove = __devexit_p(matrix_keypad_remove),
Eric Miaobab76142009-06-29 00:20:52 -0700494 .driver = {
495 .name = "matrix-keypad",
496 .owner = THIS_MODULE,
Dmitry Torokhovf72a28a2009-12-03 22:24:15 -0800497#ifdef CONFIG_PM
498 .pm = &matrix_keypad_pm_ops,
499#endif
Eric Miaobab76142009-06-29 00:20:52 -0700500 },
501};
JJ Ding5146c842011-11-29 11:08:39 -0800502module_platform_driver(matrix_keypad_driver);
Eric Miaobab76142009-06-29 00:20:52 -0700503
504MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
505MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
506MODULE_LICENSE("GPL v2");
507MODULE_ALIAS("platform:matrix-keypad");