aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-03-31 03:41:12 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-03-31 03:48:29 -0400
commite10af9e79a97ac5d305ec1be94338e8d3fd7aaa4 (patch)
tree097a883b2be59488f84d4415ba5cfd86ac221ef8
parentda5bce199fa9209c462259125f9a0144adf6885c (diff)
Input: tegra-kbc - support for defining row/columns based on SoC
NVIDIA's Tegra20 and Tegra30 supports the 16x8 keyboard matrix and T114 support the 11x8 Key matrix. Add support for defining the maximum row/columns based on SoC through proper compatibility. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/keyboard/tegra-kbc.c80
1 files changed, 62 insertions, 18 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 68b2b65024d6..b46142f78ef2 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -27,18 +27,19 @@
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/of.h> 29#include <linux/of.h>
30#include <linux/of_device.h>
30#include <linux/clk.h> 31#include <linux/clk.h>
31#include <linux/slab.h> 32#include <linux/slab.h>
32#include <linux/input/matrix_keypad.h> 33#include <linux/input/matrix_keypad.h>
33#include <linux/clk/tegra.h> 34#include <linux/clk/tegra.h>
34#include <linux/err.h> 35#include <linux/err.h>
35 36
36#define KBC_MAX_GPIO 24
37#define KBC_MAX_KPENT 8 37#define KBC_MAX_KPENT 8
38 38
39#define KBC_MAX_ROW 16 39/* Maximum row/column supported by Tegra KBC yet is 16x8 */
40#define KBC_MAX_COL 8 40#define KBC_MAX_GPIO 24
41#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) 41/* Maximum keys supported by Tegra KBC yet is 16 x 8*/
42#define KBC_MAX_KEY (16 * 8)
42 43
43#define KBC_MAX_DEBOUNCE_CNT 0x3ffu 44#define KBC_MAX_DEBOUNCE_CNT 0x3ffu
44 45
@@ -81,6 +82,12 @@ enum tegra_pin_type {
81 PIN_CFG_ROW, 82 PIN_CFG_ROW,
82}; 83};
83 84
85/* Tegra KBC hw support */
86struct tegra_kbc_hw_support {
87 int max_rows;
88 int max_columns;
89};
90
84struct tegra_kbc_pin_cfg { 91struct tegra_kbc_pin_cfg {
85 enum tegra_pin_type type; 92 enum tegra_pin_type type;
86 unsigned char num; 93 unsigned char num;
@@ -109,6 +116,9 @@ struct tegra_kbc {
109 u32 wakeup_key; 116 u32 wakeup_key;
110 struct timer_list timer; 117 struct timer_list timer;
111 struct clk *clk; 118 struct clk *clk;
119 const struct tegra_kbc_hw_support *hw_support;
120 int max_keys;
121 int num_rows_and_columns;
112}; 122};
113 123
114static void tegra_kbc_report_released_keys(struct input_dev *input, 124static void tegra_kbc_report_released_keys(struct input_dev *input,
@@ -205,11 +215,11 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
205 215
206 /* 216 /*
207 * If the platform uses Fn keymaps, translate keys on a Fn keypress. 217 * If the platform uses Fn keymaps, translate keys on a Fn keypress.
208 * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. 218 * Function keycodes are max_keys apart from the plain keycodes.
209 */ 219 */
210 if (fn_keypress) { 220 if (fn_keypress) {
211 for (i = 0; i < num_down; i++) { 221 for (i = 0; i < num_down; i++) {
212 scancodes[i] += KBC_MAX_KEY; 222 scancodes[i] += kbc->max_keys;
213 keycodes[i] = kbc->keycode[scancodes[i]]; 223 keycodes[i] = kbc->keycode[scancodes[i]];
214 } 224 }
215 } 225 }
@@ -316,7 +326,7 @@ static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter)
316 /* Either mask all keys or none. */ 326 /* Either mask all keys or none. */
317 rst_val = (filter && !kbc->wakeup) ? ~0 : 0; 327 rst_val = (filter && !kbc->wakeup) ? ~0 : 0;
318 328
319 for (i = 0; i < KBC_MAX_ROW; i++) 329 for (i = 0; i < kbc->hw_support->max_rows; i++)
320 writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); 330 writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4);
321} 331}
322 332
@@ -453,7 +463,7 @@ static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc,
453 463
454 switch (pin_cfg->type) { 464 switch (pin_cfg->type) {
455 case PIN_CFG_ROW: 465 case PIN_CFG_ROW:
456 if (pin_cfg->num >= KBC_MAX_ROW) { 466 if (pin_cfg->num >= kbc->hw_support->max_rows) {
457 dev_err(kbc->dev, 467 dev_err(kbc->dev,
458 "pin_cfg[%d]: invalid row number %d\n", 468 "pin_cfg[%d]: invalid row number %d\n",
459 i, pin_cfg->num); 469 i, pin_cfg->num);
@@ -463,7 +473,7 @@ static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc,
463 break; 473 break;
464 474
465 case PIN_CFG_COL: 475 case PIN_CFG_COL:
466 if (pin_cfg->num >= KBC_MAX_COL) { 476 if (pin_cfg->num >= kbc->hw_support->max_columns) {
467 dev_err(kbc->dev, 477 dev_err(kbc->dev,
468 "pin_cfg[%d]: invalid column number %d\n", 478 "pin_cfg[%d]: invalid column number %d\n",
469 i, pin_cfg->num); 479 i, pin_cfg->num);
@@ -521,6 +531,18 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
521 } 531 }
522 num_cols = proplen / sizeof(u32); 532 num_cols = proplen / sizeof(u32);
523 533
534 if (num_rows > kbc->hw_support->max_rows) {
535 dev_err(kbc->dev,
536 "Number of rows is more than supported by hardware\n");
537 return -EINVAL;
538 }
539
540 if (num_cols > kbc->hw_support->max_columns) {
541 dev_err(kbc->dev,
542 "Number of cols is more than supported by hardware\n");
543 return -EINVAL;
544 }
545
524 if (!of_get_property(np, "linux,keymap", &proplen)) { 546 if (!of_get_property(np, "linux,keymap", &proplen)) {
525 dev_err(kbc->dev, "property linux,keymap not found\n"); 547 dev_err(kbc->dev, "property linux,keymap not found\n");
526 return -ENOENT; 548 return -ENOENT;
@@ -533,7 +555,7 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
533 } 555 }
534 556
535 /* Set all pins as non-configured */ 557 /* Set all pins as non-configured */
536 for (i = 0; i < KBC_MAX_GPIO; i++) 558 for (i = 0; i < kbc->num_rows_and_columns; i++)
537 kbc->pin_cfg[i].type = PIN_CFG_IGNORE; 559 kbc->pin_cfg[i].type = PIN_CFG_IGNORE;
538 560
539 ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", 561 ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins",
@@ -563,6 +585,24 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
563 return 0; 585 return 0;
564} 586}
565 587
588static const struct tegra_kbc_hw_support tegra20_kbc_hw_support = {
589 .max_rows = 16,
590 .max_columns = 8,
591};
592
593static const struct tegra_kbc_hw_support tegra11_kbc_hw_support = {
594 .max_rows = 11,
595 .max_columns = 8,
596};
597
598static const struct of_device_id tegra_kbc_of_match[] = {
599 { .compatible = "nvidia,tegra114-kbc", .data = &tegra11_kbc_hw_support},
600 { .compatible = "nvidia,tegra30-kbc", .data = &tegra20_kbc_hw_support},
601 { .compatible = "nvidia,tegra20-kbc", .data = &tegra20_kbc_hw_support},
602 { },
603};
604MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
605
566static int tegra_kbc_probe(struct platform_device *pdev) 606static int tegra_kbc_probe(struct platform_device *pdev)
567{ 607{
568 struct tegra_kbc *kbc; 608 struct tegra_kbc *kbc;
@@ -571,7 +611,10 @@ static int tegra_kbc_probe(struct platform_device *pdev)
571 int num_rows = 0; 611 int num_rows = 0;
572 unsigned int debounce_cnt; 612 unsigned int debounce_cnt;
573 unsigned int scan_time_rows; 613 unsigned int scan_time_rows;
574 unsigned int keymap_rows = KBC_MAX_KEY; 614 unsigned int keymap_rows;
615 const struct of_device_id *match;
616
617 match = of_match_device(of_match_ptr(tegra_kbc_of_match), &pdev->dev);
575 618
576 kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); 619 kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL);
577 if (!kbc) { 620 if (!kbc) {
@@ -580,6 +623,12 @@ static int tegra_kbc_probe(struct platform_device *pdev)
580 } 623 }
581 624
582 kbc->dev = &pdev->dev; 625 kbc->dev = &pdev->dev;
626 kbc->hw_support = match->data;
627 kbc->max_keys = kbc->hw_support->max_rows *
628 kbc->hw_support->max_columns;
629 kbc->num_rows_and_columns = kbc->hw_support->max_rows +
630 kbc->hw_support->max_columns;
631 keymap_rows = kbc->max_keys;
583 spin_lock_init(&kbc->lock); 632 spin_lock_init(&kbc->lock);
584 633
585 err = tegra_kbc_parse_dt(kbc); 634 err = tegra_kbc_parse_dt(kbc);
@@ -640,7 +689,8 @@ static int tegra_kbc_probe(struct platform_device *pdev)
640 keymap_rows *= 2; 689 keymap_rows *= 2;
641 690
642 err = matrix_keypad_build_keymap(kbc->keymap_data, NULL, 691 err = matrix_keypad_build_keymap(kbc->keymap_data, NULL,
643 keymap_rows, KBC_MAX_COL, 692 keymap_rows,
693 kbc->hw_support->max_columns,
644 kbc->keycode, kbc->idev); 694 kbc->keycode, kbc->idev);
645 if (err) { 695 if (err) {
646 dev_err(&pdev->dev, "failed to setup keymap\n"); 696 dev_err(&pdev->dev, "failed to setup keymap\n");
@@ -766,12 +816,6 @@ static int tegra_kbc_resume(struct device *dev)
766 816
767static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume); 817static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
768 818
769static const struct of_device_id tegra_kbc_of_match[] = {
770 { .compatible = "nvidia,tegra20-kbc", },
771 { },
772};
773MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
774
775static struct platform_driver tegra_kbc_driver = { 819static struct platform_driver tegra_kbc_driver = {
776 .probe = tegra_kbc_probe, 820 .probe = tegra_kbc_probe,
777 .driver = { 821 .driver = {