aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/matrix-keymap.c
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 /drivers/input/matrix-keymap.c
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>
Diffstat (limited to 'drivers/input/matrix-keymap.c')
-rw-r--r--drivers/input/matrix-keymap.c175
1 files changed, 98 insertions, 77 deletions
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