diff options
author | Alban Bedel <alban.bedel@avionic-design.de> | 2012-11-05 13:55:25 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-11-29 12:28:50 -0500 |
commit | e89e29b8585379c844b03fb3aa2cca73e2bc5b26 (patch) | |
tree | 904bb25bb9c50818617ccf5e83ae501cb534f386 /drivers/input/keyboard | |
parent | 852d20aed8a029ea8496e85052493b275f19d22b (diff) |
Input: tca8418_keypad - add support for device tree bindings
Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/tca8418_keypad.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index f1e966bdcff5..1a2894dd03ca 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/i2c.h> | 35 | #include <linux/i2c.h> |
36 | #include <linux/input.h> | 36 | #include <linux/input.h> |
37 | #include <linux/input/tca8418_keypad.h> | 37 | #include <linux/input/tca8418_keypad.h> |
38 | #include <linux/of.h> | ||
38 | 39 | ||
39 | /* TCA8418 hardware limits */ | 40 | /* TCA8418 hardware limits */ |
40 | #define TCA8418_MAX_ROWS 8 | 41 | #define TCA8418_MAX_ROWS 8 |
@@ -116,10 +117,15 @@ static const struct i2c_device_id tca8418_id[] = { | |||
116 | }; | 117 | }; |
117 | MODULE_DEVICE_TABLE(i2c, tca8418_id); | 118 | MODULE_DEVICE_TABLE(i2c, tca8418_id); |
118 | 119 | ||
120 | #ifdef CONFIG_OF | ||
121 | static const struct of_device_id tca8418_dt_ids[] __devinitconst = { | ||
122 | { .compatible = "ti,tca8418", }, | ||
123 | { } | ||
124 | }; | ||
125 | MODULE_DEVICE_TABLE(of, tca8418_dt_ids); | ||
126 | #endif | ||
127 | |||
119 | struct tca8418_keypad { | 128 | struct tca8418_keypad { |
120 | unsigned int rows; | ||
121 | unsigned int cols; | ||
122 | unsigned int keypad_mask; /* Mask for keypad col/rol regs */ | ||
123 | unsigned int irq; | 129 | unsigned int irq; |
124 | unsigned int row_shift; | 130 | unsigned int row_shift; |
125 | 131 | ||
@@ -241,7 +247,8 @@ exit: | |||
241 | /* | 247 | /* |
242 | * Configure the TCA8418 for keypad operation | 248 | * Configure the TCA8418 for keypad operation |
243 | */ | 249 | */ |
244 | static int tca8418_configure(struct tca8418_keypad *keypad_data) | 250 | static int tca8418_configure(struct tca8418_keypad *keypad_data, |
251 | u32 rows, u32 cols) | ||
245 | { | 252 | { |
246 | int reg, error; | 253 | int reg, error; |
247 | 254 | ||
@@ -253,9 +260,8 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data) | |||
253 | 260 | ||
254 | 261 | ||
255 | /* Assemble a mask for row and column registers */ | 262 | /* Assemble a mask for row and column registers */ |
256 | reg = ~(~0 << keypad_data->rows); | 263 | reg = ~(~0 << rows); |
257 | reg += (~(~0 << keypad_data->cols)) << 8; | 264 | reg += (~(~0 << cols)) << 8; |
258 | keypad_data->keypad_mask = reg; | ||
259 | 265 | ||
260 | /* Set registers to keypad mode */ | 266 | /* Set registers to keypad mode */ |
261 | error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg); | 267 | error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg); |
@@ -277,25 +283,36 @@ static int tca8418_keypad_probe(struct i2c_client *client, | |||
277 | client->dev.platform_data; | 283 | client->dev.platform_data; |
278 | struct tca8418_keypad *keypad_data; | 284 | struct tca8418_keypad *keypad_data; |
279 | struct input_dev *input; | 285 | struct input_dev *input; |
286 | const struct matrix_keymap_data *keymap_data = NULL; | ||
287 | u32 rows = 0, cols = 0; | ||
288 | bool rep = false; | ||
289 | bool irq_is_gpio = false; | ||
280 | int error, row_shift, max_keys; | 290 | int error, row_shift, max_keys; |
281 | 291 | ||
282 | /* Copy the platform data */ | 292 | /* Copy the platform data */ |
283 | if (!pdata) { | 293 | if (pdata) { |
284 | dev_dbg(&client->dev, "no platform data\n"); | 294 | if (!pdata->keymap_data) { |
285 | return -EINVAL; | 295 | dev_err(&client->dev, "no keymap data defined\n"); |
296 | return -EINVAL; | ||
297 | } | ||
298 | keymap_data = pdata->keymap_data; | ||
299 | rows = pdata->rows; | ||
300 | cols = pdata->cols; | ||
301 | rep = pdata->rep; | ||
302 | irq_is_gpio = pdata->irq_is_gpio; | ||
303 | } else { | ||
304 | struct device_node *np = client->dev.of_node; | ||
305 | of_property_read_u32(np, "keypad,num-rows", &rows); | ||
306 | of_property_read_u32(np, "keypad,num-columns", &cols); | ||
307 | rep = of_property_read_bool(np, "keypad,autorepeat"); | ||
286 | } | 308 | } |
287 | 309 | ||
288 | if (!pdata->keymap_data) { | 310 | if (!rows || rows > TCA8418_MAX_ROWS) { |
289 | dev_err(&client->dev, "no keymap data defined\n"); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
293 | if (!pdata->rows || pdata->rows > TCA8418_MAX_ROWS) { | ||
294 | dev_err(&client->dev, "invalid rows\n"); | 311 | dev_err(&client->dev, "invalid rows\n"); |
295 | return -EINVAL; | 312 | return -EINVAL; |
296 | } | 313 | } |
297 | 314 | ||
298 | if (!pdata->cols || pdata->cols > TCA8418_MAX_COLS) { | 315 | if (!cols || cols > TCA8418_MAX_COLS) { |
299 | dev_err(&client->dev, "invalid columns\n"); | 316 | dev_err(&client->dev, "invalid columns\n"); |
300 | return -EINVAL; | 317 | return -EINVAL; |
301 | } | 318 | } |
@@ -307,8 +324,8 @@ static int tca8418_keypad_probe(struct i2c_client *client, | |||
307 | return -ENODEV; | 324 | return -ENODEV; |
308 | } | 325 | } |
309 | 326 | ||
310 | row_shift = get_count_order(pdata->cols); | 327 | row_shift = get_count_order(cols); |
311 | max_keys = pdata->rows << row_shift; | 328 | max_keys = rows << row_shift; |
312 | 329 | ||
313 | /* Allocate memory for keypad_data, keymap and input device */ | 330 | /* Allocate memory for keypad_data, keymap and input device */ |
314 | keypad_data = kzalloc(sizeof(*keypad_data) + | 331 | keypad_data = kzalloc(sizeof(*keypad_data) + |
@@ -316,13 +333,11 @@ static int tca8418_keypad_probe(struct i2c_client *client, | |||
316 | if (!keypad_data) | 333 | if (!keypad_data) |
317 | return -ENOMEM; | 334 | return -ENOMEM; |
318 | 335 | ||
319 | keypad_data->rows = pdata->rows; | ||
320 | keypad_data->cols = pdata->cols; | ||
321 | keypad_data->client = client; | 336 | keypad_data->client = client; |
322 | keypad_data->row_shift = row_shift; | 337 | keypad_data->row_shift = row_shift; |
323 | 338 | ||
324 | /* Initialize the chip or fail if chip isn't present */ | 339 | /* Initialize the chip or fail if chip isn't present */ |
325 | error = tca8418_configure(keypad_data); | 340 | error = tca8418_configure(keypad_data, rows, cols); |
326 | if (error < 0) | 341 | if (error < 0) |
327 | goto fail1; | 342 | goto fail1; |
328 | 343 | ||
@@ -342,21 +357,20 @@ static int tca8418_keypad_probe(struct i2c_client *client, | |||
342 | input->id.product = 0x001; | 357 | input->id.product = 0x001; |
343 | input->id.version = 0x0001; | 358 | input->id.version = 0x0001; |
344 | 359 | ||
345 | error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, | 360 | error = matrix_keypad_build_keymap(keymap_data, NULL, rows, cols, |
346 | pdata->rows, pdata->cols, | ||
347 | keypad_data->keymap, input); | 361 | keypad_data->keymap, input); |
348 | if (error) { | 362 | if (error) { |
349 | dev_dbg(&client->dev, "Failed to build keymap\n"); | 363 | dev_dbg(&client->dev, "Failed to build keymap\n"); |
350 | goto fail2; | 364 | goto fail2; |
351 | } | 365 | } |
352 | 366 | ||
353 | if (pdata->rep) | 367 | if (rep) |
354 | __set_bit(EV_REP, input->evbit); | 368 | __set_bit(EV_REP, input->evbit); |
355 | input_set_capability(input, EV_MSC, MSC_SCAN); | 369 | input_set_capability(input, EV_MSC, MSC_SCAN); |
356 | 370 | ||
357 | input_set_drvdata(input, keypad_data); | 371 | input_set_drvdata(input, keypad_data); |
358 | 372 | ||
359 | if (pdata->irq_is_gpio) | 373 | if (irq_is_gpio) |
360 | client->irq = gpio_to_irq(client->irq); | 374 | client->irq = gpio_to_irq(client->irq); |
361 | 375 | ||
362 | error = request_threaded_irq(client->irq, NULL, tca8418_irq_handler, | 376 | error = request_threaded_irq(client->irq, NULL, tca8418_irq_handler, |
@@ -401,11 +415,11 @@ static int tca8418_keypad_remove(struct i2c_client *client) | |||
401 | return 0; | 415 | return 0; |
402 | } | 416 | } |
403 | 417 | ||
404 | |||
405 | static struct i2c_driver tca8418_keypad_driver = { | 418 | static struct i2c_driver tca8418_keypad_driver = { |
406 | .driver = { | 419 | .driver = { |
407 | .name = TCA8418_NAME, | 420 | .name = TCA8418_NAME, |
408 | .owner = THIS_MODULE, | 421 | .owner = THIS_MODULE, |
422 | .of_match_table = of_match_ptr(tca8418_dt_ids), | ||
409 | }, | 423 | }, |
410 | .probe = tca8418_keypad_probe, | 424 | .probe = tca8418_keypad_probe, |
411 | .remove = tca8418_keypad_remove, | 425 | .remove = tca8418_keypad_remove, |