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 | ||