diff options
| -rw-r--r-- | Documentation/devicetree/bindings/input/tca8418_keypad.txt | 8 | ||||
| -rw-r--r-- | drivers/input/keyboard/tca8418_keypad.c | 68 |
2 files changed, 49 insertions, 27 deletions
diff --git a/Documentation/devicetree/bindings/input/tca8418_keypad.txt b/Documentation/devicetree/bindings/input/tca8418_keypad.txt new file mode 100644 index 000000000000..2a1538f0053f --- /dev/null +++ b/Documentation/devicetree/bindings/input/tca8418_keypad.txt | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | |||
| 2 | Required properties: | ||
| 3 | - compatible: "ti,tca8418" | ||
| 4 | - reg: the I2C address | ||
| 5 | - interrupts: IRQ line number, should trigger on falling edge | ||
| 6 | - keypad,num-rows: The number of rows | ||
| 7 | - keypad,num-columns: The number of columns | ||
| 8 | - linux,keymap: Keys definitions, see keypad-matrix. | ||
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, |
