aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorChao Xie <chao.xie@marvell.com>2013-05-05 23:25:10 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-06-19 01:56:51 -0400
commite4156979c7d34e5197b16fa31c1c7549eae675e5 (patch)
treef0c5da640eb564f512960af66da4fc34f0b24730 /drivers/input
parent0a085a9482fa51efb58c9d351ea98e83c5df93fc (diff)
Input: pxa27x-keypad - add device tree support
Signed-off-by: Chao Xie <chao.xie@marvell.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c246
1 files changed, 242 insertions, 4 deletions
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 5b2d8764dd37..533fd6c7c3c8 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -118,6 +118,229 @@ struct pxa27x_keypad {
118 unsigned int direct_key_mask; 118 unsigned int direct_key_mask;
119}; 119};
120 120
121#ifdef CONFIG_OF
122static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad)
123{
124 struct input_dev *input_dev = keypad->input_dev;
125 struct device *dev = input_dev->dev.parent;
126 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
127 u32 rows, cols;
128 int error;
129
130 error = matrix_keypad_parse_of_params(dev, &rows, &cols);
131 if (error)
132 return error;
133
134 if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) {
135 dev_err(dev, "rows or cols exceeds maximum value\n");
136 return -EINVAL;
137 }
138
139 pdata->matrix_key_rows = rows;
140 pdata->matrix_key_cols = cols;
141
142 error = matrix_keypad_build_keymap(NULL, NULL,
143 pdata->matrix_key_rows,
144 pdata->matrix_key_cols,
145 keypad->keycodes, input_dev);
146 if (error)
147 return error;
148
149 return 0;
150}
151
152static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad)
153{
154 struct input_dev *input_dev = keypad->input_dev;
155 struct device *dev = input_dev->dev.parent;
156 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
157 struct device_node *np = dev->of_node;
158 const __be16 *prop;
159 unsigned short code;
160 unsigned int proplen, size;
161 int i;
162 int error;
163
164 error = of_property_read_u32(np, "marvell,direct-key-count",
165 &pdata->direct_key_num);
166 if (error) {
167 /*
168 * If do not have marvel,direct-key-count defined,
169 * it means direct key is not supported.
170 */
171 return error == -EINVAL ? 0 : error;
172 }
173
174 error = of_property_read_u32(np, "marvell,direct-key-mask",
175 &pdata->direct_key_mask);
176 if (error) {
177 if (error != -EINVAL)
178 return error;
179
180 /*
181 * If marvell,direct-key-mask is not defined, driver will use
182 * default value. Default value is set when configure the keypad.
183 */
184 pdata->direct_key_mask = 0;
185 }
186
187 pdata->direct_key_low_active = of_property_read_bool(np,
188 "marvell,direct-key-low-active");
189
190 prop = of_get_property(np, "marvell,direct-key-map", &proplen);
191 if (!prop)
192 return -EINVAL;
193
194 if (proplen % sizeof(u16))
195 return -EINVAL;
196
197 size = proplen / sizeof(u16);
198
199 /* Only MAX_DIRECT_KEY_NUM is accepted.*/
200 if (size > MAX_DIRECT_KEY_NUM)
201 return -EINVAL;
202
203 for (i = 0; i < size; i++) {
204 code = be16_to_cpup(prop + i);
205 keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code;
206 __set_bit(code, input_dev->keybit);
207 }
208
209 return 0;
210}
211
212static int pxa27x_keypad_rotary_parse_dt(struct pxa27x_keypad *keypad)
213{
214 const __be32 *prop;
215 int i, relkey_ret;
216 unsigned int code, proplen;
217 const char *rotaryname[2] = {
218 "marvell,rotary0", "marvell,rotary1"};
219 const char relkeyname[] = {"marvell,rotary-rel-key"};
220 struct input_dev *input_dev = keypad->input_dev;
221 struct device *dev = input_dev->dev.parent;
222 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
223 struct device_node *np = dev->of_node;
224
225 relkey_ret = of_property_read_u32(np, relkeyname, &code);
226 /* if can read correct rotary key-code, we do not need this. */
227 if (relkey_ret == 0) {
228 unsigned short relcode;
229
230 /* rotary0 taks lower half, rotary1 taks upper half. */
231 relcode = code & 0xffff;
232 pdata->rotary0_rel_code = (code & 0xffff);
233 __set_bit(relcode, input_dev->relbit);
234
235 relcode = code >> 16;
236 pdata->rotary1_rel_code = relcode;
237 __set_bit(relcode, input_dev->relbit);
238 }
239
240 for (i = 0; i < 2; i++) {
241 prop = of_get_property(np, rotaryname[i], &proplen);
242 /*
243 * If the prop is not set, it means keypad does not need
244 * initialize the rotaryX.
245 */
246 if (!prop)
247 continue;
248
249 code = be32_to_cpup(prop);
250 /*
251 * Not all up/down key code are valid.
252 * Now we depends on direct-rel-code.
253 */
254 if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) {
255 return relkey_ret;
256 } else {
257 unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1);
258 unsigned short keycode;
259
260 keycode = code & 0xffff;
261 keypad->keycodes[n] = keycode;
262 __set_bit(keycode, input_dev->keybit);
263
264 keycode = code >> 16;
265 keypad->keycodes[n + 1] = keycode;
266 __set_bit(keycode, input_dev->keybit);
267
268 if (i == 0)
269 pdata->rotary0_rel_code = -1;
270 else
271 pdata->rotary1_rel_code = -1;
272 }
273 if (i == 0)
274 pdata->enable_rotary0 = 1;
275 else
276 pdata->enable_rotary1 = 1;
277 }
278
279 keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
280 keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
281
282 return 0;
283}
284
285static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
286{
287 struct input_dev *input_dev = keypad->input_dev;
288 struct device *dev = input_dev->dev.parent;
289 struct device_node *np = dev->of_node;
290 int error;
291
292 keypad->pdata = devm_kzalloc(dev, sizeof(*keypad->pdata),
293 GFP_KERNEL);
294 if (!keypad->pdata) {
295 dev_err(dev, "failed to allocate memory for pdata\n");
296 return -ENOMEM;
297 }
298
299 error = pxa27x_keypad_matrix_key_parse_dt(keypad);
300 if (error) {
301 dev_err(dev, "failed to parse matrix key\n");
302 return error;
303 }
304
305 error = pxa27x_keypad_direct_key_parse_dt(keypad);
306 if (error) {
307 dev_err(dev, "failed to parse direct key\n");
308 return error;
309 }
310
311 error = pxa27x_keypad_rotary_parse_dt(keypad);
312 if (error) {
313 dev_err(dev, "failed to parse rotary key\n");
314 return error;
315 }
316
317 error = of_property_read_u32(np, "marvell,debounce-interval",
318 &keypad->pdata->debounce_interval);
319 if (error) {
320 dev_err(dev, "failed to parse debpunce-interval\n");
321 return error;
322 }
323
324 /*
325 * The keycodes may not only includes matrix key but also the direct
326 * key or rotary key.
327 */
328 input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
329
330 return 0;
331}
332
333#else
334
335static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
336{
337 dev_info(keypad->input_dev->dev.parent, "missing platform data\n");
338
339 return -EINVAL;
340}
341
342#endif
343
121static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) 344static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
122{ 345{
123 struct pxa27x_keypad_platform_data *pdata = keypad->pdata; 346 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
@@ -492,15 +715,15 @@ static const struct dev_pm_ops pxa27x_keypad_pm_ops = {
492static int pxa27x_keypad_probe(struct platform_device *pdev) 715static int pxa27x_keypad_probe(struct platform_device *pdev)
493{ 716{
494 struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; 717 struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data;
718 struct device_node *np = pdev->dev.of_node;
495 struct pxa27x_keypad *keypad; 719 struct pxa27x_keypad *keypad;
496 struct input_dev *input_dev; 720 struct input_dev *input_dev;
497 struct resource *res; 721 struct resource *res;
498 int irq, error; 722 int irq, error;
499 723
500 if (pdata == NULL) { 724 /* Driver need build keycode from device tree or pdata */
501 dev_err(&pdev->dev, "no platform data defined\n"); 725 if (!np && !pdata)
502 return -EINVAL; 726 return -EINVAL;
503 }
504 727
505 irq = platform_get_irq(pdev, 0); 728 irq = platform_get_irq(pdev, 0);
506 if (irq < 0) { 729 if (irq < 0) {
@@ -562,12 +785,18 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
562 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 785 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
563 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 786 input_set_capability(input_dev, EV_MSC, MSC_SCAN);
564 787
565 error = pxa27x_keypad_build_keycode(keypad); 788 if (pdata)
789 error = pxa27x_keypad_build_keycode(keypad);
790 else
791 error = pxa27x_keypad_build_keycode_from_dt(keypad);
566 if (error) { 792 if (error) {
567 dev_err(&pdev->dev, "failed to build keycode\n"); 793 dev_err(&pdev->dev, "failed to build keycode\n");
568 goto failed_put_clk; 794 goto failed_put_clk;
569 } 795 }
570 796
797 /* If device tree is supported, pdata will be allocated. */
798 pdata = keypad->pdata;
799
571 if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || 800 if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
572 (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { 801 (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
573 input_dev->evbit[0] |= BIT_MASK(EV_REL); 802 input_dev->evbit[0] |= BIT_MASK(EV_REL);
@@ -628,11 +857,20 @@ static int pxa27x_keypad_remove(struct platform_device *pdev)
628/* work with hotplug and coldplug */ 857/* work with hotplug and coldplug */
629MODULE_ALIAS("platform:pxa27x-keypad"); 858MODULE_ALIAS("platform:pxa27x-keypad");
630 859
860#ifdef CONFIG_OF
861static const struct of_device_id pxa27x_keypad_dt_match[] = {
862 { .compatible = "marvell,pxa27x-keypad" },
863 {},
864};
865MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match);
866#endif
867
631static struct platform_driver pxa27x_keypad_driver = { 868static struct platform_driver pxa27x_keypad_driver = {
632 .probe = pxa27x_keypad_probe, 869 .probe = pxa27x_keypad_probe,
633 .remove = pxa27x_keypad_remove, 870 .remove = pxa27x_keypad_remove,
634 .driver = { 871 .driver = {
635 .name = "pxa27x-keypad", 872 .name = "pxa27x-keypad",
873 .of_match_table = of_match_ptr(pxa27x_keypad_dt_match),
636 .owner = THIS_MODULE, 874 .owner = THIS_MODULE,
637#ifdef CONFIG_PM 875#ifdef CONFIG_PM
638 .pm = &pxa27x_keypad_pm_ops, 876 .pm = &pxa27x_keypad_pm_ops,