diff options
author | Chao Xie <chao.xie@marvell.com> | 2013-05-05 23:25:10 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-06-19 01:56:51 -0400 |
commit | e4156979c7d34e5197b16fa31c1c7549eae675e5 (patch) | |
tree | f0c5da640eb564f512960af66da4fc34f0b24730 /drivers/input | |
parent | 0a085a9482fa51efb58c9d351ea98e83c5df93fc (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.c | 246 |
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 | ||
122 | static 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 | |||
152 | static 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 | |||
212 | static 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 | |||
285 | static 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 | |||
335 | static 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 | |||
121 | static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 344 | static 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 = { | |||
492 | static int pxa27x_keypad_probe(struct platform_device *pdev) | 715 | static 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 */ |
629 | MODULE_ALIAS("platform:pxa27x-keypad"); | 858 | MODULE_ALIAS("platform:pxa27x-keypad"); |
630 | 859 | ||
860 | #ifdef CONFIG_OF | ||
861 | static const struct of_device_id pxa27x_keypad_dt_match[] = { | ||
862 | { .compatible = "marvell,pxa27x-keypad" }, | ||
863 | {}, | ||
864 | }; | ||
865 | MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match); | ||
866 | #endif | ||
867 | |||
631 | static struct platform_driver pxa27x_keypad_driver = { | 868 | static 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, |