aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-05-11 01:37:15 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-05-11 01:39:43 -0400
commitb45c8f35a7fec17bdd159a7815203b6137c00ab9 (patch)
treec6fc8efe76ff2b382e8290d6df59129200032a5d
parent1932811f426fee71b7ece67e70aeba7e1b0ebb6d (diff)
Input: matrix-keymap - wire up device tree support
When platform keymap is not supplied to matrix_keypad_build_keymap() and device tree support is enabled, try locating specified property and load keymap from it. If property name is not defined, try using "linux,keymap". Based on earlier patch by Viresh Kumar <viresh.kumar@st.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/keyboard/tegra-kbc.c56
-rw-r--r--drivers/input/matrix-keymap.c175
-rw-r--r--include/linux/input/matrix_keypad.h18
3 files changed, 130 insertions, 119 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 6722d376e898..4ffe64d53107 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -619,8 +619,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
619} 619}
620 620
621#ifdef CONFIG_OF 621#ifdef CONFIG_OF
622static struct tegra_kbc_platform_data * __devinit 622static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata(
623tegra_kbc_dt_parse_pdata(struct platform_device *pdev) 623 struct platform_device *pdev)
624{ 624{
625 struct tegra_kbc_platform_data *pdata; 625 struct tegra_kbc_platform_data *pdata;
626 struct device_node *np = pdev->dev.of_node; 626 struct device_node *np = pdev->dev.of_node;
@@ -660,10 +660,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
660 pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; 660 pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL;
661 } 661 }
662 662
663 pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap");
664
665 /* FIXME: Add handling of linux,fn-keymap here */
666
667 return pdata; 663 return pdata;
668} 664}
669#else 665#else
@@ -674,10 +670,36 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
674} 670}
675#endif 671#endif
676 672
673static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
674{
675 const struct tegra_kbc_platform_data *pdata = kbc->pdata;
676 const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
677 unsigned int keymap_rows = KBC_MAX_KEY;
678 int retval;
679
680 if (keymap_data && pdata->use_fn_map)
681 keymap_rows *= 2;
682
683 retval = matrix_keypad_build_keymap(keymap_data, NULL,
684 keymap_rows, KBC_MAX_COL,
685 kbc->keycode, kbc->idev);
686 if (retval == -ENOSYS || retval == -ENOENT) {
687 /*
688 * If there is no OF support in kernel or keymap
689 * property is missing, use default keymap.
690 */
691 retval = matrix_keypad_build_keymap(
692 &tegra_kbc_default_keymap_data, NULL,
693 keymap_rows, KBC_MAX_COL,
694 kbc->keycode, kbc->idev);
695 }
696
697 return retval;
698}
699
677static int __devinit tegra_kbc_probe(struct platform_device *pdev) 700static int __devinit tegra_kbc_probe(struct platform_device *pdev)
678{ 701{
679 const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; 702 const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
680 const struct matrix_keymap_data *keymap_data;
681 struct tegra_kbc *kbc; 703 struct tegra_kbc *kbc;
682 struct input_dev *input_dev; 704 struct input_dev *input_dev;
683 struct resource *res; 705 struct resource *res;
@@ -686,7 +708,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
686 int num_rows = 0; 708 int num_rows = 0;
687 unsigned int debounce_cnt; 709 unsigned int debounce_cnt;
688 unsigned int scan_time_rows; 710 unsigned int scan_time_rows;
689 unsigned int keymap_rows;
690 711
691 if (!pdata) 712 if (!pdata)
692 pdata = tegra_kbc_dt_parse_pdata(pdev); 713 pdata = tegra_kbc_dt_parse_pdata(pdev);
@@ -768,17 +789,9 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
768 input_dev->open = tegra_kbc_open; 789 input_dev->open = tegra_kbc_open;
769 input_dev->close = tegra_kbc_close; 790 input_dev->close = tegra_kbc_close;
770 791
771 keymap_rows = KBC_MAX_KEY; 792 err = tegra_kbd_setup_keymap(kbc);
772 if (pdata->use_fn_map)
773 keymap_rows *= 2;
774
775 keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data;
776
777 err = matrix_keypad_build_keymap(keymap_data, NULL,
778 keymap_rows, KBC_MAX_COL,
779 kbc->keycode, input_dev);
780 if (err) { 793 if (err) {
781 dev_err(&pdev->dev, "failed to build keymap\n"); 794 dev_err(&pdev->dev, "failed to setup keymap\n");
782 goto err_put_clk; 795 goto err_put_clk;
783 } 796 }
784 797
@@ -805,9 +818,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
805 platform_set_drvdata(pdev, kbc); 818 platform_set_drvdata(pdev, kbc);
806 device_init_wakeup(&pdev->dev, pdata->wakeup); 819 device_init_wakeup(&pdev->dev, pdata->wakeup);
807 820
808 if (!pdev->dev.platform_data)
809 matrix_keyboard_of_free_keymap(pdata->keymap_data);
810
811 return 0; 821 return 0;
812 822
813err_free_irq: 823err_free_irq:
@@ -822,10 +832,8 @@ err_free_mem:
822 input_free_device(input_dev); 832 input_free_device(input_dev);
823 kfree(kbc); 833 kfree(kbc);
824err_free_pdata: 834err_free_pdata:
825 if (!pdev->dev.platform_data) { 835 if (!pdev->dev.platform_data)
826 matrix_keyboard_of_free_keymap(pdata->keymap_data);
827 kfree(pdata); 836 kfree(pdata);
828 }
829 837
830 return err; 838 return err;
831} 839}
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index de7992d55da2..db92c1ebfc59 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -17,15 +17,91 @@
17 * 17 *
18 */ 18 */
19 19
20#include <linux/device.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/input.h> 23#include <linux/input.h>
23#include <linux/of.h> 24#include <linux/of.h>
24#include <linux/export.h> 25#include <linux/export.h>
25#include <linux/gfp.h>
26#include <linux/slab.h>
27#include <linux/input/matrix_keypad.h> 26#include <linux/input/matrix_keypad.h>
28 27
28static bool matrix_keypad_map_key(struct input_dev *input_dev,
29 unsigned int rows, unsigned int cols,
30 unsigned int row_shift, unsigned int key)
31{
32 unsigned char *keymap = input_dev->keycode;
33 unsigned int row = KEY_ROW(key);
34 unsigned int col = KEY_COL(key);
35 unsigned short code = KEY_VAL(key);
36
37 if (row >= rows || col >= cols) {
38 dev_err(input_dev->dev.parent,
39 "%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
40 __func__, key, row, col, rows, cols);
41 return false;
42 }
43
44 keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
45 __set_bit(code, input_dev->keybit);
46
47 return true;
48}
49
50#ifdef CONFIG_OF
51static int matrix_keypad_parse_of_keymap(const char *propname,
52 unsigned int rows, unsigned int cols,
53 struct input_dev *input_dev)
54{
55 struct device *dev = input_dev->dev.parent;
56 struct device_node *np = dev->of_node;
57 unsigned int row_shift = get_count_order(cols);
58 unsigned int max_keys = rows << row_shift;
59 unsigned int proplen, i, size;
60 const __be32 *prop;
61
62 if (!np)
63 return -ENOENT;
64
65 if (!propname)
66 propname = "linux,keymap";
67
68 prop = of_get_property(np, propname, &proplen);
69 if (!prop) {
70 dev_err(dev, "OF: %s property not defined in %s\n",
71 propname, np->full_name);
72 return -ENOENT;
73 }
74
75 if (proplen % sizeof(u32)) {
76 dev_err(dev, "OF: Malformed keycode property %s in %s\n",
77 propname, np->full_name);
78 return -EINVAL;
79 }
80
81 size = proplen / sizeof(u32);
82 if (size > max_keys) {
83 dev_err(dev, "OF: %s size overflow\n", propname);
84 return -EINVAL;
85 }
86
87 for (i = 0; i < size; i++) {
88 unsigned int key = be32_to_cpup(prop + i);
89
90 if (!matrix_keypad_map_key(input_dev, rows, cols,
91 row_shift, key))
92 return -EINVAL;
93 }
94
95 return 0;
96}
97#else
98static int matrix_keypad_parse_of_keymap(const char *propname,
99 unsigned int rows, unsigned int cols,
100 struct input_dev *input_dev)
101{
102 return -ENOSYS;
103}
104#endif
29 105
30/** 106/**
31 * matrix_keypad_build_keymap - convert platform keymap into matrix keymap 107 * matrix_keypad_build_keymap - convert platform keymap into matrix keymap
@@ -41,6 +117,13 @@
41 * This function converts platform keymap (encoded with KEY() macro) into 117 * This function converts platform keymap (encoded with KEY() macro) into
42 * an array of keycodes that is suitable for using in a standard matrix 118 * an array of keycodes that is suitable for using in a standard matrix
43 * keyboard driver that uses row and col as indices. 119 * keyboard driver that uses row and col as indices.
120 *
121 * If @keymap_data is not supplied and device tree support is enabled
122 * it will attempt load the keymap from property specified by @keymap_name
123 * argument (or "linux,keymap" if @keymap_name is %NULL).
124 *
125 * Callers are expected to set up input_dev->dev.parent before calling this
126 * function.
44 */ 127 */
45int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, 128int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
46 const char *keymap_name, 129 const char *keymap_name,
@@ -50,6 +133,7 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
50{ 133{
51 unsigned int row_shift = get_count_order(cols); 134 unsigned int row_shift = get_count_order(cols);
52 int i; 135 int i;
136 int error;
53 137
54 input_dev->keycode = keymap; 138 input_dev->keycode = keymap;
55 input_dev->keycodesize = sizeof(*keymap); 139 input_dev->keycodesize = sizeof(*keymap);
@@ -57,86 +141,23 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
57 141
58 __set_bit(EV_KEY, input_dev->evbit); 142 __set_bit(EV_KEY, input_dev->evbit);
59 143
60 for (i = 0; i < keymap_data->keymap_size; i++) { 144 if (keymap_data) {
61 unsigned int key = keymap_data->keymap[i]; 145 for (i = 0; i < keymap_data->keymap_size; i++) {
62 unsigned int row = KEY_ROW(key); 146 unsigned int key = keymap_data->keymap[i];
63 unsigned int col = KEY_COL(key);
64 unsigned short code = KEY_VAL(key);
65 147
66 if (row >= rows || col >= cols) { 148 if (!matrix_keypad_map_key(input_dev, rows, cols,
67 dev_err(input_dev->dev.parent, 149 row_shift, key))
68 "%s: invalid keymap entry %d (row: %d, col: %d, rows: %d, cols: %d)\n", 150 return -EINVAL;
69 __func__, i, row, col, rows, cols);
70 return -EINVAL;
71 } 151 }
72 152 } else {
73 keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; 153 error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols,
74 __set_bit(code, input_dev->keybit); 154 input_dev);
155 if (error)
156 return error;
75 } 157 }
158
76 __clear_bit(KEY_RESERVED, input_dev->keybit); 159 __clear_bit(KEY_RESERVED, input_dev->keybit);
77 160
78 return 0; 161 return 0;
79} 162}
80EXPORT_SYMBOL(matrix_keypad_build_keymap); 163EXPORT_SYMBOL(matrix_keypad_build_keymap);
81
82#ifdef CONFIG_OF
83struct matrix_keymap_data *
84matrix_keyboard_of_fill_keymap(struct device_node *np,
85 const char *propname)
86{
87 struct matrix_keymap_data *kd;
88 u32 *keymap;
89 int proplen, i;
90 const __be32 *prop;
91
92 if (!np)
93 return NULL;
94
95 if (!propname)
96 propname = "linux,keymap";
97
98 prop = of_get_property(np, propname, &proplen);
99 if (!prop)
100 return NULL;
101
102 if (proplen % sizeof(u32)) {
103 pr_warn("Malformed keymap property %s in %s\n",
104 propname, np->full_name);
105 return NULL;
106 }
107
108 kd = kzalloc(sizeof(*kd), GFP_KERNEL);
109 if (!kd)
110 return NULL;
111
112 kd->keymap = keymap = kzalloc(proplen, GFP_KERNEL);
113 if (!kd->keymap) {
114 kfree(kd);
115 return NULL;
116 }
117
118 kd->keymap_size = proplen / sizeof(u32);
119
120 for (i = 0; i < kd->keymap_size; i++) {
121 u32 tmp = be32_to_cpup(prop + i);
122 int key_code, row, col;
123
124 row = (tmp >> 24) & 0xff;
125 col = (tmp >> 16) & 0xff;
126 key_code = tmp & 0xffff;
127 keymap[i] = KEY(row, col, key_code);
128 }
129
130 return kd;
131}
132EXPORT_SYMBOL_GPL(matrix_keyboard_of_fill_keymap);
133
134void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd)
135{
136 if (kd) {
137 kfree(kd->keymap);
138 kfree(kd);
139 }
140}
141EXPORT_SYMBOL_GPL(matrix_keyboard_of_free_keymap);
142#endif
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
index e8fe08ebc245..5f3aa6b11bfa 100644
--- a/include/linux/input/matrix_keypad.h
+++ b/include/linux/input/matrix_keypad.h
@@ -81,22 +81,4 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
81 unsigned short *keymap, 81 unsigned short *keymap,
82 struct input_dev *input_dev); 82 struct input_dev *input_dev);
83 83
84#ifdef CONFIG_OF
85struct matrix_keymap_data *
86matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname);
87
88void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd);
89#else
90static inline struct matrix_keymap_data *
91matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname)
92{
93 return NULL;
94}
95
96static inline void
97matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd)
98{
99}
100#endif
101
102#endif /* _MATRIX_KEYPAD_H */ 84#endif /* _MATRIX_KEYPAD_H */