diff options
Diffstat (limited to 'drivers/input/keyboard/matrix_keypad.c')
-rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 99 |
1 files changed, 50 insertions, 49 deletions
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 9b223d73de32..18b72372028a 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -27,7 +27,6 @@ struct matrix_keypad { const struct matrix_keypad_platform_data *pdata; struct input_dev *input_dev; - unsigned short *keycodes; unsigned int row_shift; DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); @@ -38,6 +37,8 @@ struct matrix_keypad { bool scan_pending; bool stopped; bool gpio_all_disabled; + + unsigned short keycodes[]; }; /* @@ -224,7 +225,7 @@ static void matrix_keypad_stop(struct input_dev *dev) disable_row_irqs(keypad); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) { const struct matrix_keypad_platform_data *pdata = keypad->pdata; @@ -293,16 +294,16 @@ static int matrix_keypad_resume(struct device *dev) return 0; } - -static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, - matrix_keypad_suspend, matrix_keypad_resume); #endif -static int __devinit init_matrix_gpio(struct platform_device *pdev, - struct matrix_keypad *keypad) +static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, + matrix_keypad_suspend, matrix_keypad_resume); + +static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev, + struct matrix_keypad *keypad) { const struct matrix_keypad_platform_data *pdata = keypad->pdata; - int i, err = -EINVAL; + int i, err; /* initialized strobe lines as outputs, activated */ for (i = 0; i < pdata->num_col_gpios; i++) { @@ -348,8 +349,7 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, "matrix-keypad", keypad); if (err) { dev_err(&pdev->dev, - "Unable to acquire interrupt " - "for GPIO line %i\n", + "Unable to acquire interrupt for GPIO line %i\n", pdata->row_gpios[i]); goto err_free_irqs; } @@ -375,14 +375,33 @@ err_free_cols: return err; } +static void matrix_keypad_free_gpio(struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + if (pdata->clustered_irq > 0) { + free_irq(pdata->clustered_irq, keypad); + } else { + for (i = 0; i < pdata->num_row_gpios; i++) + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); + } + + for (i = 0; i < pdata->num_row_gpios; i++) + gpio_free(pdata->row_gpios[i]); + + for (i = 0; i < pdata->num_col_gpios; i++) + gpio_free(pdata->col_gpios[i]); +} + static int __devinit matrix_keypad_probe(struct platform_device *pdev) { const struct matrix_keypad_platform_data *pdata; const struct matrix_keymap_data *keymap_data; struct matrix_keypad *keypad; struct input_dev *input_dev; - unsigned short *keycodes; unsigned int row_shift; + size_t keymap_size; int err; pdata = pdev->dev.platform_data; @@ -398,20 +417,18 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) } row_shift = get_count_order(pdata->num_col_gpios); - - keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); - keycodes = kzalloc((pdata->num_row_gpios << row_shift) * - sizeof(*keycodes), - GFP_KERNEL); + keymap_size = (pdata->num_row_gpios << row_shift) * + sizeof(keypad->keycodes[0]); + keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size, + GFP_KERNEL); input_dev = input_allocate_device(); - if (!keypad || !keycodes || !input_dev) { + if (!keypad || !input_dev) { err = -ENOMEM; goto err_free_mem; } keypad->input_dev = input_dev; keypad->pdata = pdata; - keypad->keycodes = keycodes; keypad->row_shift = row_shift; keypad->stopped = true; INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); @@ -420,38 +437,38 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY); - if (!pdata->no_autorepeat) - input_dev->evbit[0] |= BIT_MASK(EV_REP); input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; - input_dev->keycode = keycodes; - input_dev->keycodesize = sizeof(*keycodes); - input_dev->keycodemax = pdata->num_row_gpios << row_shift; - - matrix_keypad_build_keymap(keymap_data, row_shift, - input_dev->keycode, input_dev->keybit); + err = matrix_keypad_build_keymap(keymap_data, NULL, + pdata->num_row_gpios, + pdata->num_col_gpios, + keypad->keycodes, input_dev); + if (err) + goto err_free_mem; + if (!pdata->no_autorepeat) + __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); - err = init_matrix_gpio(pdev, keypad); + err = matrix_keypad_init_gpio(pdev, keypad); if (err) goto err_free_mem; err = input_register_device(keypad->input_dev); if (err) - goto err_free_mem; + goto err_free_gpio; device_init_wakeup(&pdev->dev, pdata->wakeup); platform_set_drvdata(pdev, keypad); return 0; +err_free_gpio: + matrix_keypad_free_gpio(keypad); err_free_mem: input_free_device(input_dev); - kfree(keycodes); kfree(keypad); return err; } @@ -459,29 +476,15 @@ err_free_mem: static int __devexit matrix_keypad_remove(struct platform_device *pdev) { struct matrix_keypad *keypad = platform_get_drvdata(pdev); - const struct matrix_keypad_platform_data *pdata = keypad->pdata; - int i; device_init_wakeup(&pdev->dev, 0); - if (pdata->clustered_irq > 0) { - free_irq(pdata->clustered_irq, keypad); - } else { - for (i = 0; i < pdata->num_row_gpios; i++) - free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); - } - - for (i = 0; i < pdata->num_row_gpios; i++) - gpio_free(pdata->row_gpios[i]); - - for (i = 0; i < pdata->num_col_gpios; i++) - gpio_free(pdata->col_gpios[i]); - + matrix_keypad_free_gpio(keypad); input_unregister_device(keypad->input_dev); - platform_set_drvdata(pdev, NULL); - kfree(keypad->keycodes); kfree(keypad); + platform_set_drvdata(pdev, NULL); + return 0; } @@ -491,9 +494,7 @@ static struct platform_driver matrix_keypad_driver = { .driver = { .name = "matrix-keypad", .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &matrix_keypad_pm_ops, -#endif }, }; module_platform_driver(matrix_keypad_driver); |