diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-04-21 01:33:09 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-04-21 02:06:52 -0400 |
| commit | b83643ebf2242388585e95c9a8d2353745d77cfd (patch) | |
| tree | 453d51b7f20c37d90d3b8d168379ee50978669dc | |
| parent | 01111fcd42b050bdb7113a7c2c0aed2eaef67b53 (diff) | |
Input: matrix-keypad - undo GPIO setup if input_register_device fails
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
| -rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index a4ff08caa44b..98ae281bedb0 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -299,11 +299,11 @@ static int matrix_keypad_resume(struct device *dev) | |||
| 299 | static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, | 299 | static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, |
| 300 | matrix_keypad_suspend, matrix_keypad_resume); | 300 | matrix_keypad_suspend, matrix_keypad_resume); |
| 301 | 301 | ||
| 302 | static int __devinit init_matrix_gpio(struct platform_device *pdev, | 302 | static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev, |
| 303 | struct matrix_keypad *keypad) | 303 | struct matrix_keypad *keypad) |
| 304 | { | 304 | { |
| 305 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 305 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
| 306 | int i, err = -EINVAL; | 306 | int i, err; |
| 307 | 307 | ||
| 308 | /* initialized strobe lines as outputs, activated */ | 308 | /* initialized strobe lines as outputs, activated */ |
| 309 | for (i = 0; i < pdata->num_col_gpios; i++) { | 309 | for (i = 0; i < pdata->num_col_gpios; i++) { |
| @@ -349,8 +349,7 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, | |||
| 349 | "matrix-keypad", keypad); | 349 | "matrix-keypad", keypad); |
| 350 | if (err) { | 350 | if (err) { |
| 351 | dev_err(&pdev->dev, | 351 | dev_err(&pdev->dev, |
| 352 | "Unable to acquire interrupt " | 352 | "Unable to acquire interrupt for GPIO line %i\n", |
| 353 | "for GPIO line %i\n", | ||
| 354 | pdata->row_gpios[i]); | 353 | pdata->row_gpios[i]); |
| 355 | goto err_free_irqs; | 354 | goto err_free_irqs; |
| 356 | } | 355 | } |
| @@ -376,6 +375,25 @@ err_free_cols: | |||
| 376 | return err; | 375 | return err; |
| 377 | } | 376 | } |
| 378 | 377 | ||
| 378 | static void matrix_keypad_free_gpio(struct matrix_keypad *keypad) | ||
| 379 | { | ||
| 380 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 381 | int i; | ||
| 382 | |||
| 383 | if (pdata->clustered_irq > 0) { | ||
| 384 | free_irq(pdata->clustered_irq, keypad); | ||
| 385 | } else { | ||
| 386 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 387 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 388 | } | ||
| 389 | |||
| 390 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 391 | gpio_free(pdata->row_gpios[i]); | ||
| 392 | |||
| 393 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
| 394 | gpio_free(pdata->col_gpios[i]); | ||
| 395 | } | ||
| 396 | |||
| 379 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) | 397 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) |
| 380 | { | 398 | { |
| 381 | const struct matrix_keypad_platform_data *pdata; | 399 | const struct matrix_keypad_platform_data *pdata; |
| @@ -435,19 +453,21 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 435 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 453 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 436 | input_set_drvdata(input_dev, keypad); | 454 | input_set_drvdata(input_dev, keypad); |
| 437 | 455 | ||
| 438 | err = init_matrix_gpio(pdev, keypad); | 456 | err = matrix_keypad_init_gpio(pdev, keypad); |
| 439 | if (err) | 457 | if (err) |
| 440 | goto err_free_mem; | 458 | goto err_free_mem; |
| 441 | 459 | ||
| 442 | err = input_register_device(keypad->input_dev); | 460 | err = input_register_device(keypad->input_dev); |
| 443 | if (err) | 461 | if (err) |
| 444 | goto err_free_mem; | 462 | goto err_free_gpio; |
| 445 | 463 | ||
| 446 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 464 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
| 447 | platform_set_drvdata(pdev, keypad); | 465 | platform_set_drvdata(pdev, keypad); |
| 448 | 466 | ||
| 449 | return 0; | 467 | return 0; |
| 450 | 468 | ||
| 469 | err_free_gpio: | ||
| 470 | matrix_keypad_free_gpio(keypad); | ||
| 451 | err_free_mem: | 471 | err_free_mem: |
| 452 | input_free_device(input_dev); | 472 | input_free_device(input_dev); |
| 453 | kfree(keypad); | 473 | kfree(keypad); |
| @@ -457,28 +477,15 @@ err_free_mem: | |||
| 457 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) | 477 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) |
| 458 | { | 478 | { |
| 459 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | 479 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); |
| 460 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 461 | int i; | ||
| 462 | 480 | ||
| 463 | device_init_wakeup(&pdev->dev, 0); | 481 | device_init_wakeup(&pdev->dev, 0); |
| 464 | 482 | ||
| 465 | if (pdata->clustered_irq > 0) { | 483 | matrix_keypad_free_gpio(keypad); |
| 466 | free_irq(pdata->clustered_irq, keypad); | ||
| 467 | } else { | ||
| 468 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 469 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 470 | } | ||
| 471 | |||
| 472 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 473 | gpio_free(pdata->row_gpios[i]); | ||
| 474 | |||
| 475 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
| 476 | gpio_free(pdata->col_gpios[i]); | ||
| 477 | |||
| 478 | input_unregister_device(keypad->input_dev); | 484 | input_unregister_device(keypad->input_dev); |
| 479 | platform_set_drvdata(pdev, NULL); | ||
| 480 | kfree(keypad); | 485 | kfree(keypad); |
| 481 | 486 | ||
| 487 | platform_set_drvdata(pdev, NULL); | ||
| 488 | |||
| 482 | return 0; | 489 | return 0; |
| 483 | } | 490 | } |
| 484 | 491 | ||
