diff options
author | AnilKumar Ch <anilkumar@ti.com> | 2012-11-21 01:49:31 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-11-21 01:55:10 -0500 |
commit | 4a83eecff65bd327bf5cb3b400b96fa975c73308 (patch) | |
tree | 78e4fabcc1cc60875a6a557a215bc93c110e4536 /drivers/input | |
parent | 5383116b86d8e877684770d05acd1dda62be102d (diff) |
Input: matrix-keypad - add device tree support
Also the driver was modifued to take advantage of recent improvements in
matrix_keypad_build_keymap() implementation, which automatically allocates
memory for keymap.
The driver was tested on AM335x EVM.
Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 119 |
1 files changed, 97 insertions, 22 deletions
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 18b72372028a..05d3a969ff4e 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
24 | #include <linux/input/matrix_keypad.h> | 24 | #include <linux/input/matrix_keypad.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/of.h> | ||
27 | #include <linux/of_gpio.h> | ||
28 | #include <linux/of_platform.h> | ||
26 | 29 | ||
27 | struct matrix_keypad { | 30 | struct matrix_keypad { |
28 | const struct matrix_keypad_platform_data *pdata; | 31 | const struct matrix_keypad_platform_data *pdata; |
@@ -37,8 +40,6 @@ struct matrix_keypad { | |||
37 | bool scan_pending; | 40 | bool scan_pending; |
38 | bool stopped; | 41 | bool stopped; |
39 | bool gpio_all_disabled; | 42 | bool gpio_all_disabled; |
40 | |||
41 | unsigned short keycodes[]; | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | /* | 45 | /* |
@@ -118,6 +119,7 @@ static void matrix_keypad_scan(struct work_struct *work) | |||
118 | struct matrix_keypad *keypad = | 119 | struct matrix_keypad *keypad = |
119 | container_of(work, struct matrix_keypad, work.work); | 120 | container_of(work, struct matrix_keypad, work.work); |
120 | struct input_dev *input_dev = keypad->input_dev; | 121 | struct input_dev *input_dev = keypad->input_dev; |
122 | const unsigned short *keycodes = input_dev->keycode; | ||
121 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 123 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
122 | uint32_t new_state[MATRIX_MAX_COLS]; | 124 | uint32_t new_state[MATRIX_MAX_COLS]; |
123 | int row, col, code; | 125 | int row, col, code; |
@@ -153,7 +155,7 @@ static void matrix_keypad_scan(struct work_struct *work) | |||
153 | code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); | 155 | code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); |
154 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | 156 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
155 | input_report_key(input_dev, | 157 | input_report_key(input_dev, |
156 | keypad->keycodes[code], | 158 | keycodes[code], |
157 | new_state[col] & (1 << row)); | 159 | new_state[col] & (1 << row)); |
158 | } | 160 | } |
159 | } | 161 | } |
@@ -394,33 +396,95 @@ static void matrix_keypad_free_gpio(struct matrix_keypad *keypad) | |||
394 | gpio_free(pdata->col_gpios[i]); | 396 | gpio_free(pdata->col_gpios[i]); |
395 | } | 397 | } |
396 | 398 | ||
399 | #ifdef CONFIG_OF | ||
400 | static struct matrix_keypad_platform_data * __devinit | ||
401 | matrix_keypad_parse_dt(struct device *dev) | ||
402 | { | ||
403 | struct matrix_keypad_platform_data *pdata; | ||
404 | struct device_node *np = dev->of_node; | ||
405 | unsigned int *gpios; | ||
406 | int i; | ||
407 | |||
408 | if (!np) { | ||
409 | dev_err(dev, "device lacks DT data\n"); | ||
410 | return ERR_PTR(-ENODEV); | ||
411 | } | ||
412 | |||
413 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
414 | if (!pdata) { | ||
415 | dev_err(dev, "could not allocate memory for platform data\n"); | ||
416 | return ERR_PTR(-ENOMEM); | ||
417 | } | ||
418 | |||
419 | pdata->num_row_gpios = of_gpio_named_count(np, "row-gpios"); | ||
420 | pdata->num_col_gpios = of_gpio_named_count(np, "col-gpios"); | ||
421 | if (!pdata->num_row_gpios || !pdata->num_col_gpios) { | ||
422 | dev_err(dev, "number of keypad rows/columns not specified\n"); | ||
423 | return ERR_PTR(-EINVAL); | ||
424 | } | ||
425 | |||
426 | if (of_get_property(np, "linux,no-autorepeat", NULL)) | ||
427 | pdata->no_autorepeat = true; | ||
428 | if (of_get_property(np, "linux,wakeup", NULL)) | ||
429 | pdata->wakeup = true; | ||
430 | if (of_get_property(np, "gpio-activelow", NULL)) | ||
431 | pdata->active_low = true; | ||
432 | |||
433 | of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms); | ||
434 | of_property_read_u32(np, "col-scan-delay-us", | ||
435 | &pdata->col_scan_delay_us); | ||
436 | |||
437 | gpios = devm_kzalloc(dev, | ||
438 | sizeof(unsigned int) * | ||
439 | (pdata->num_row_gpios + pdata->num_col_gpios), | ||
440 | GFP_KERNEL); | ||
441 | if (!gpios) { | ||
442 | dev_err(dev, "could not allocate memory for gpios\n"); | ||
443 | return ERR_PTR(-ENOMEM); | ||
444 | } | ||
445 | |||
446 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
447 | gpios[i] = of_get_named_gpio(np, "row-gpios", i); | ||
448 | |||
449 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
450 | gpios[pdata->num_row_gpios + i] = | ||
451 | of_get_named_gpio(np, "col-gpios", i); | ||
452 | |||
453 | pdata->row_gpios = gpios; | ||
454 | pdata->col_gpios = &gpios[pdata->num_row_gpios]; | ||
455 | |||
456 | return pdata; | ||
457 | } | ||
458 | #else | ||
459 | static inline struct matrix_keypad_platform_data * | ||
460 | matrix_keypad_parse_dt(struct device *dev) | ||
461 | { | ||
462 | dev_err(dev, "no platform data defined\n"); | ||
463 | |||
464 | return ERR_PTR(-EINVAL); | ||
465 | } | ||
466 | #endif | ||
467 | |||
397 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) | 468 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) |
398 | { | 469 | { |
399 | const struct matrix_keypad_platform_data *pdata; | 470 | const struct matrix_keypad_platform_data *pdata; |
400 | const struct matrix_keymap_data *keymap_data; | ||
401 | struct matrix_keypad *keypad; | 471 | struct matrix_keypad *keypad; |
402 | struct input_dev *input_dev; | 472 | struct input_dev *input_dev; |
403 | unsigned int row_shift; | ||
404 | size_t keymap_size; | ||
405 | int err; | 473 | int err; |
406 | 474 | ||
407 | pdata = pdev->dev.platform_data; | 475 | pdata = dev_get_platdata(&pdev->dev); |
408 | if (!pdata) { | 476 | if (!pdata) { |
409 | dev_err(&pdev->dev, "no platform data defined\n"); | 477 | pdata = matrix_keypad_parse_dt(&pdev->dev); |
410 | return -EINVAL; | 478 | if (IS_ERR(pdata)) { |
411 | } | 479 | dev_err(&pdev->dev, "no platform data defined\n"); |
412 | 480 | return PTR_ERR(pdata); | |
413 | keymap_data = pdata->keymap_data; | 481 | } |
414 | if (!keymap_data) { | 482 | } else if (!pdata->keymap_data) { |
415 | dev_err(&pdev->dev, "no keymap data defined\n"); | 483 | dev_err(&pdev->dev, "no keymap data defined\n"); |
416 | return -EINVAL; | 484 | return -EINVAL; |
417 | } | 485 | } |
418 | 486 | ||
419 | row_shift = get_count_order(pdata->num_col_gpios); | 487 | keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); |
420 | keymap_size = (pdata->num_row_gpios << row_shift) * | ||
421 | sizeof(keypad->keycodes[0]); | ||
422 | keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size, | ||
423 | GFP_KERNEL); | ||
424 | input_dev = input_allocate_device(); | 488 | input_dev = input_allocate_device(); |
425 | if (!keypad || !input_dev) { | 489 | if (!keypad || !input_dev) { |
426 | err = -ENOMEM; | 490 | err = -ENOMEM; |
@@ -429,7 +493,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
429 | 493 | ||
430 | keypad->input_dev = input_dev; | 494 | keypad->input_dev = input_dev; |
431 | keypad->pdata = pdata; | 495 | keypad->pdata = pdata; |
432 | keypad->row_shift = row_shift; | 496 | keypad->row_shift = get_count_order(pdata->num_col_gpios); |
433 | keypad->stopped = true; | 497 | keypad->stopped = true; |
434 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); | 498 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); |
435 | spin_lock_init(&keypad->lock); | 499 | spin_lock_init(&keypad->lock); |
@@ -440,12 +504,14 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
440 | input_dev->open = matrix_keypad_start; | 504 | input_dev->open = matrix_keypad_start; |
441 | input_dev->close = matrix_keypad_stop; | 505 | input_dev->close = matrix_keypad_stop; |
442 | 506 | ||
443 | err = matrix_keypad_build_keymap(keymap_data, NULL, | 507 | err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, |
444 | pdata->num_row_gpios, | 508 | pdata->num_row_gpios, |
445 | pdata->num_col_gpios, | 509 | pdata->num_col_gpios, |
446 | keypad->keycodes, input_dev); | 510 | NULL, input_dev); |
447 | if (err) | 511 | if (err) { |
512 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
448 | goto err_free_mem; | 513 | goto err_free_mem; |
514 | } | ||
449 | 515 | ||
450 | if (!pdata->no_autorepeat) | 516 | if (!pdata->no_autorepeat) |
451 | __set_bit(EV_REP, input_dev->evbit); | 517 | __set_bit(EV_REP, input_dev->evbit); |
@@ -488,6 +554,14 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) | |||
488 | return 0; | 554 | return 0; |
489 | } | 555 | } |
490 | 556 | ||
557 | #ifdef CONFIG_OF | ||
558 | static const struct of_device_id matrix_keypad_dt_match[] = { | ||
559 | { .compatible = "gpio-matrix-keypad" }, | ||
560 | { } | ||
561 | }; | ||
562 | MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match); | ||
563 | #endif | ||
564 | |||
491 | static struct platform_driver matrix_keypad_driver = { | 565 | static struct platform_driver matrix_keypad_driver = { |
492 | .probe = matrix_keypad_probe, | 566 | .probe = matrix_keypad_probe, |
493 | .remove = __devexit_p(matrix_keypad_remove), | 567 | .remove = __devexit_p(matrix_keypad_remove), |
@@ -495,6 +569,7 @@ static struct platform_driver matrix_keypad_driver = { | |||
495 | .name = "matrix-keypad", | 569 | .name = "matrix-keypad", |
496 | .owner = THIS_MODULE, | 570 | .owner = THIS_MODULE, |
497 | .pm = &matrix_keypad_pm_ops, | 571 | .pm = &matrix_keypad_pm_ops, |
572 | .of_match_table = of_match_ptr(matrix_keypad_dt_match), | ||
498 | }, | 573 | }, |
499 | }; | 574 | }; |
500 | module_platform_driver(matrix_keypad_driver); | 575 | module_platform_driver(matrix_keypad_driver); |