diff options
Diffstat (limited to 'drivers/input/keyboard')
28 files changed, 668 insertions, 368 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f354813a13e..c0e11ecc646 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -166,6 +166,7 @@ config KEYBOARD_LKKBD config KEYBOARD_EP93XX tristate "EP93xx Matrix Keypad support" depends on ARCH_EP93XX + select INPUT_MATRIXKMAP help Say Y here to enable the matrix keypad on the Cirrus EP93XX. @@ -224,6 +225,7 @@ config KEYBOARD_TCA6416 config KEYBOARD_TCA8418 tristate "TCA8418 Keypad Support" depends on I2C + select INPUT_MATRIXKMAP help This driver implements basic keypad functionality for keys connected through TCA8418 keypad decoder. @@ -240,6 +242,7 @@ config KEYBOARD_TCA8418 config KEYBOARD_MATRIX tristate "GPIO driven matrix keypad support" depends on GENERIC_GPIO + select INPUT_MATRIXKMAP help Enable support for GPIO driven matrix keypad. @@ -309,6 +312,17 @@ config KEYBOARD_LM8323 To compile this driver as a module, choose M here: the module will be called lm8323. +config KEYBOARD_LM8333 + tristate "LM8333 keypad chip" + depends on I2C + select INPUT_MATRIXKMAP + help + If you say yes here you get support for the National Semiconductor + LM8333 keypad controller. + + To compile this driver as a module, choose M here: the + module will be called lm8333. + config KEYBOARD_LOCOMO tristate "LoCoMo Keyboard Support" depends on SHARP_LOCOMO @@ -366,6 +380,7 @@ config KEYBOARD_MPR121 config KEYBOARD_IMX tristate "IMX keypad support" depends on ARCH_MXC + select INPUT_MATRIXKMAP help Enable support for IMX keypad port. @@ -384,6 +399,7 @@ config KEYBOARD_NEWTON config KEYBOARD_NOMADIK tristate "ST-Ericsson Nomadik SKE keyboard" depends on PLAT_NOMADIK + select INPUT_MATRIXKMAP help Say Y here if you want to use a keypad provided on the SKE controller used on the Ux500 and Nomadik platforms @@ -394,7 +410,7 @@ config KEYBOARD_NOMADIK config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" depends on ARCH_TEGRA - select INPUT_OF_MATRIX_KEYMAP if USE_OF + select INPUT_MATRIXKMAP help Say Y here if you want to use a matrix keyboard connected directly to the internal keyboard controller on Tegra SoCs. @@ -432,6 +448,7 @@ config KEYBOARD_PXA930_ROTARY config KEYBOARD_PMIC8XXX tristate "Qualcomm PMIC8XXX keypad support" depends on MFD_PM8XXX + select INPUT_MATRIXKMAP help Say Y here if you want to enable the driver for the PMIC8XXX keypad provided as a reference design from Qualcomm. This is intended @@ -443,6 +460,7 @@ config KEYBOARD_PMIC8XXX config KEYBOARD_SAMSUNG tristate "Samsung keypad support" depends on HAVE_CLK + select INPUT_MATRIXKMAP help Say Y here if you want to use the keypad on your Samsung mobile device. @@ -485,6 +503,7 @@ config KEYBOARD_SH_KEYSC config KEYBOARD_STMPE tristate "STMPE keypad support" depends on MFD_STMPE + select INPUT_MATRIXKMAP help Say Y here if you want to use the keypad controller on STMPE I/O expanders. @@ -505,6 +524,7 @@ config KEYBOARD_DAVINCI config KEYBOARD_OMAP tristate "TI OMAP keypad support" depends on (ARCH_OMAP1 || ARCH_OMAP2) + select INPUT_MATRIXKMAP help Say Y here if you want to use the OMAP keypad. @@ -512,9 +532,10 @@ config KEYBOARD_OMAP module will be called omap-keypad. config KEYBOARD_OMAP4 - tristate "TI OMAP4 keypad support" + tristate "TI OMAP4+ keypad support" + select INPUT_MATRIXKMAP help - Say Y here if you want to use the OMAP4 keypad. + Say Y here if you want to use the OMAP4+ keypad. To compile this driver as a module, choose M here: the module will be called omap4-keypad. @@ -522,6 +543,7 @@ config KEYBOARD_OMAP4 config KEYBOARD_SPEAR tristate "ST SPEAR keyboard support" depends on PLAT_SPEAR + select INPUT_MATRIXKMAP help Say Y here if you want to use the SPEAR keyboard. @@ -531,6 +553,7 @@ config KEYBOARD_SPEAR config KEYBOARD_TC3589X tristate "TC3589X Keypad support" depends on MFD_TC3589X + select INPUT_MATRIXKMAP help Say Y here if you want to use the keypad controller on TC35892/3 I/O expander. @@ -541,6 +564,7 @@ config KEYBOARD_TC3589X config KEYBOARD_TNETV107X tristate "TI TNETV107X keypad support" depends on ARCH_DAVINCI_TNETV107X + select INPUT_MATRIXKMAP help Say Y here if you want to use the TNETV107X keypad. @@ -550,6 +574,7 @@ config KEYBOARD_TNETV107X config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE + select INPUT_MATRIXKMAP help Say Y here if your board use the keypad controller on TWL4030 family chips. It's safe to say enable this @@ -573,6 +598,7 @@ config KEYBOARD_XTKBD config KEYBOARD_W90P910 tristate "W90P910 Matrix Keypad support" depends on ARCH_W90X900 + select INPUT_MATRIXKMAP help Say Y here to enable the matrix keypad on evaluation board based on W90P910. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index df7061f1291..b03b02456a8 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o +obj-$(CONFIG_KEYBOARD_LM8333) += lm8333.o obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 39ebffac207..b083bf10f13 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -197,6 +197,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad) kpad->gc.base = gpio_data->gpio_start; kpad->gc.label = kpad->client->name; kpad->gc.owner = THIS_MODULE; + kpad->gc.names = gpio_data->names; mutex_init(&kpad->gpio_lock); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index e05a2e7073c..add5ffd9fe2 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -433,7 +433,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, if (printk_ratelimit()) dev_warn(&serio->dev, "Spurious %s on %s. " - "Some program might be trying access hardware directly.\n", + "Some program might be trying to access hardware directly.\n", data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); goto out; case ATKBD_RET_ERR: diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 0ba69f3fcb5..c46fc818546 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -182,16 +182,10 @@ static void ep93xx_keypad_close(struct input_dev *pdev) } -#ifdef CONFIG_PM -/* - * NOTE: I don't know if this is correct, or will work on the ep93xx. - * - * None of the existing ep93xx drivers have power management support. - * But, this is basically what the pxa27x_keypad driver does. - */ -static int ep93xx_keypad_suspend(struct platform_device *pdev, - pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int ep93xx_keypad_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; @@ -210,8 +204,9 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, return 0; } -static int ep93xx_keypad_resume(struct platform_device *pdev) +static int ep93xx_keypad_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; @@ -232,10 +227,10 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) return 0; } -#else /* !CONFIG_PM */ -#define ep93xx_keypad_suspend NULL -#define ep93xx_keypad_resume NULL -#endif /* !CONFIG_PM */ +#endif + +static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, + ep93xx_keypad_suspend, ep93xx_keypad_resume); static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) { @@ -308,19 +303,16 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) input_dev->open = ep93xx_keypad_open; input_dev->close = ep93xx_keypad_close; input_dev->dev.parent = &pdev->dev; - input_dev->keycode = keypad->keycodes; - input_dev->keycodesize = sizeof(keypad->keycodes[0]); - input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); - input_set_drvdata(input_dev, keypad); + err = matrix_keypad_build_keymap(keymap_data, NULL, + EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS, + keypad->keycodes, input_dev); + if (err) + goto failed_free_dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY); if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) - input_dev->evbit[0] |= BIT_MASK(EV_REP); - - matrix_keypad_build_keymap(keymap_data, 3, - input_dev->keycode, input_dev->keybit); - platform_set_drvdata(pdev, keypad); + __set_bit(EV_REP, input_dev->evbit); + input_set_drvdata(input_dev, keypad); err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, 0, pdev->name, keypad); @@ -331,6 +323,7 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) if (err) goto failed_free_irq; + platform_set_drvdata(pdev, keypad); device_init_wakeup(&pdev->dev, 1); return 0; @@ -384,11 +377,10 @@ static struct platform_driver ep93xx_keypad_driver = { .driver = { .name = "ep93xx-keypad", .owner = THIS_MODULE, + .pm = &ep93xx_keypad_pm_ops, }, .probe = ep93xx_keypad_probe, .remove = __devexit_p(ep93xx_keypad_remove), - .suspend = ep93xx_keypad_suspend, - .resume = ep93xx_keypad_resume, }; module_platform_driver(ep93xx_keypad_driver); diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index fed31e0947a..589e3c258f3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -583,15 +583,4 @@ static struct serio_driver hil_serio_drv = { .interrupt = hil_dev_interrupt }; -static int __init hil_dev_init(void) -{ - return serio_register_driver(&hil_serio_drv); -} - -static void __exit hil_dev_exit(void) -{ - serio_unregister_driver(&hil_serio_drv); -} - -module_init(hil_dev_init); -module_exit(hil_dev_exit); +module_serio_driver(hil_serio_drv); diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index fb87b3bcadb..6ee7421e232 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -481,7 +481,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) } if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || - keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { + keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { dev_err(&pdev->dev, "invalid key data (too many rows or colums)\n"); error = -EINVAL; @@ -496,14 +496,17 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) input_dev->dev.parent = &pdev->dev; input_dev->open = imx_keypad_open; input_dev->close = imx_keypad_close; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - input_dev->keycode = keypad->keycodes; - input_dev->keycodesize = sizeof(keypad->keycodes[0]); - input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); - matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT, - keypad->keycodes, input_dev->keybit); + error = matrix_keypad_build_keymap(keymap_data, NULL, + MAX_MATRIX_KEY_ROWS, + MAX_MATRIX_KEY_COLS, + keypad->keycodes, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto failed_clock_put; + } + __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index eeafc30b207..9d639fa1afb 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -27,6 +27,7 @@ #include <mach/jornada720.h> #include <mach/hardware.h> +#include <mach/irqs.h> MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index fa9bb6d235e..fc0a63c2f27 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -731,19 +731,4 @@ static struct serio_driver lkkbd_drv = { .interrupt = lkkbd_interrupt, }; -/* - * The functions for insering/removing us as a module. - */ -static int __init lkkbd_init(void) -{ - return serio_register_driver(&lkkbd_drv); -} - -static void __exit lkkbd_exit(void) -{ - serio_unregister_driver(&lkkbd_drv); -} - -module_init(lkkbd_init); -module_exit(lkkbd_exit); - +module_serio_driver(lkkbd_drv); diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c new file mode 100644 index 00000000000..ca168a6679d --- /dev/null +++ b/drivers/input/keyboard/lm8333.c @@ -0,0 +1,235 @@ +/* + * LM8333 keypad driver + * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/input/matrix_keypad.h> +#include <linux/input/lm8333.h> + +#define LM8333_FIFO_READ 0x20 +#define LM8333_DEBOUNCE 0x22 +#define LM8333_READ_INT 0xD0 +#define LM8333_ACTIVE 0xE4 +#define LM8333_READ_ERROR 0xF0 + +#define LM8333_KEYPAD_IRQ (1 << 0) +#define LM8333_ERROR_IRQ (1 << 3) + +#define LM8333_ERROR_KEYOVR 0x04 +#define LM8333_ERROR_FIFOOVR 0x40 + +#define LM8333_FIFO_TRANSFER_SIZE 16 + +#define LM8333_NUM_ROWS 8 +#define LM8333_NUM_COLS 16 +#define LM8333_ROW_SHIFT 4 + +struct lm8333 { + struct i2c_client *client; + struct input_dev *input; + unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT]; +}; + +/* The accessors try twice because the first access may be needed for wakeup */ +#define LM8333_READ_RETRIES 2 + +int lm8333_read8(struct lm8333 *lm8333, u8 cmd) +{ + int retries = 0, ret; + + do { + ret = i2c_smbus_read_byte_data(lm8333->client, cmd); + } while (ret < 0 && retries++ < LM8333_READ_RETRIES); + + return ret; +} + +int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val) +{ + int retries = 0, ret; + + do { + ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val); + } while (ret < 0 && retries++ < LM8333_READ_RETRIES); + + return ret; +} + +int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf) +{ + int retries = 0, ret; + + do { + ret = i2c_smbus_read_i2c_block_data(lm8333->client, + cmd, len, buf); + } while (ret < 0 && retries++ < LM8333_READ_RETRIES); + + return ret; +} + +static void lm8333_key_handler(struct lm8333 *lm8333) +{ + struct input_dev *input = lm8333->input; + u8 keys[LM8333_FIFO_TRANSFER_SIZE]; + u8 code, pressed; + int i, ret; + + ret = lm8333_read_block(lm8333, LM8333_FIFO_READ, + LM8333_FIFO_TRANSFER_SIZE, keys); + if (ret != LM8333_FIFO_TRANSFER_SIZE) { + dev_err(&lm8333->client->dev, + "Error %d while reading FIFO\n", ret); + return; + } + + for (i = 0; keys[i] && i < LM8333_FIFO_TRANSFER_SIZE; i++) { + pressed = keys[i] & 0x80; + code = keys[i] & 0x7f; + + input_event(input, EV_MSC, MSC_SCAN, code); + input_report_key(input, lm8333->keycodes[code], pressed); + } + + input_sync(input); +} + +static irqreturn_t lm8333_irq_thread(int irq, void *data) +{ + struct lm8333 *lm8333 = data; + u8 status = lm8333_read8(lm8333, LM8333_READ_INT); + + if (!status) + return IRQ_NONE; + + if (status & LM8333_ERROR_IRQ) { + u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR); + + if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) { + u8 dummy[LM8333_FIFO_TRANSFER_SIZE]; + + lm8333_read_block(lm8333, LM8333_FIFO_READ, + LM8333_FIFO_TRANSFER_SIZE, dummy); + } + dev_err(&lm8333->client->dev, "Got error %02x\n", err); + } + + if (status & LM8333_KEYPAD_IRQ) + lm8333_key_handler(lm8333); + + return IRQ_HANDLED; +} + +static int __devinit lm8333_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct lm8333_platform_data *pdata = client->dev.platform_data; + struct lm8333 *lm8333; + struct input_dev *input; + int err, active_time; + + if (!pdata) + return -EINVAL; + + active_time = pdata->active_time ?: 500; + if (active_time / 3 <= pdata->debounce_time / 3) { + dev_err(&client->dev, "Active time not big enough!\n"); + return -EINVAL; + } + + lm8333 = kzalloc(sizeof(*lm8333), GFP_KERNEL); + input = input_allocate_device(); + if (!lm8333 || !input) { + err = -ENOMEM; + goto free_mem; + } + + lm8333->client = client; + lm8333->input = input; + + input->name = client->name; + input->dev.parent = &client->dev; + input->id.bustype = BUS_I2C; + + input_set_capability(input, EV_MSC, MSC_SCAN); + + err = matrix_keypad_build_keymap(pdata->matrix_data, NULL, + LM8333_NUM_ROWS, LM8333_NUM_COLS, + lm8333->keycodes, input); + if (err) + goto free_mem; + + if (pdata->debounce_time) { + err = lm8333_write8(lm8333, LM8333_DEBOUNCE, + pdata->debounce_time / 3); + if (err) + dev_warn(&client->dev, "Unable to set debounce time\n"); + } + + if (pdata->active_time) { + err = lm8333_write8(lm8333, LM8333_ACTIVE, + pdata->active_time / 3); + if (err) + dev_warn(&client->dev, "Unable to set active time\n"); + } + + err = request_threaded_irq(client->irq, NULL, lm8333_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lm8333", lm8333); + if (err) + goto free_mem; + + err = input_register_device(input); + if (err) + goto free_irq; + + i2c_set_clientdata(client, lm8333); + return 0; + + free_irq: + free_irq(client->irq, lm8333); + free_mem: + input_free_device(input); + kfree(lm8333); + return err; +} + +static int __devexit lm8333_remove(struct i2c_client *client) +{ + struct lm8333 *lm8333 = i2c_get_clientdata(client); + + free_irq(client->irq, lm8333); + input_unregister_device(lm8333->input); + kfree(lm8333); + + return 0; +} + +static const struct i2c_device_id lm8333_id[] = { + { "lm8333", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm8333_id); + +static struct i2c_driver lm8333_driver = { + .driver = { + .name = "lm8333", + .owner = THIS_MODULE, + }, + .probe = lm8333_probe, + .remove = __devexit_p(lm8333_remove), + .id_table = lm8333_id, +}; +module_i2c_driver(lm8333_driver); + +MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); +MODULE_DESCRIPTION("LM8333 keyboard driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 9b223d73de3..18b72372028 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); diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 48d1cab0aa1..f971898ad59 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -166,15 +166,4 @@ static struct serio_driver nkbd_drv = { .disconnect = nkbd_disconnect, }; -static int __init nkbd_init(void) -{ - return serio_register_driver(&nkbd_drv); -} - -static void __exit nkbd_exit(void) -{ - serio_unregister_driver(&nkbd_drv); -} - -module_init(nkbd_init); -module_exit(nkbd_exit); +module_serio_driver(nkbd_drv); diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 101e245944e..4ea4341a68c 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -39,7 +39,8 @@ #define SKE_KPRISA (0x1 << 2) #define SKE_KEYPAD_ROW_SHIFT 3 -#define SKE_KPD_KEYMAP_SIZE (8 * 8) +#define SKE_KPD_NUM_ROWS 8 +#define SKE_KPD_NUM_COLS 8 /* keypad auto scan registers */ #define SKE_ASR0 0x20 @@ -63,7 +64,7 @@ struct ske_keypad { void __iomem *reg_base; struct input_dev *input; const struct ske_keypad_platform_data *board; - unsigned short keymap[SKE_KPD_KEYMAP_SIZE]; + unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS]; struct clk *clk; spinlock_t ske_keypad_lock; }; @@ -261,19 +262,18 @@ static int __init ske_keypad_probe(struct platform_device *pdev) input->name = "ux500-ske-keypad"; input->dev.parent = &pdev->dev; - input->keycode = keypad->keymap; - input->keycodesize = sizeof(keypad->keymap[0]); - input->keycodemax = ARRAY_SIZE(keypad->keymap); + error = matrix_keypad_build_keymap(plat->keymap_data, NULL, + SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS, + keypad->keymap, input); + if (error) { + dev_err(&pdev->dev, "Failed to build keymap\n"); + goto err_iounmap; + } input_set_capability(input, EV_MSC, MSC_SCAN); - - __set_bit(EV_KEY, input->evbit); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT, - input->keycode, input->keybit); - clk_enable(keypad->clk); /* go through board initialization helpers */ diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 6b630d9d3df..a0222db4dc8 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -61,6 +61,7 @@ struct omap_kp { unsigned int cols; unsigned long delay; unsigned int debounce; + unsigned short keymap[]; }; static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); @@ -316,13 +317,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) if (!cpu_is_omap24xx()) omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); - input_dev->keycode = &omap_kp[1]; - input_dev->keycodesize = sizeof(unsigned short); - input_dev->keycodemax = keycodemax; - - if (pdata->rep) - __set_bit(EV_REP, input_dev->evbit); - if (pdata->delay) omap_kp->delay = pdata->delay; @@ -371,9 +365,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) goto err2; /* setup input device */ - __set_bit(EV_KEY, input_dev->evbit); - matrix_keypad_build_keymap(pdata->keymap_data, row_shift, - input_dev->keycode, input_dev->keybit); input_dev->name = "omap-keypad"; input_dev->phys = "omap-keypad/input0"; input_dev->dev.parent = &pdev->dev; @@ -383,6 +374,15 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; + if (pdata->rep) + __set_bit(EV_REP, input_dev->evbit); + + ret = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + pdata->rows, pdata->cols, + omap_kp->keymap, input_dev); + if (ret < 0) + goto err3; + ret = input_register_device(omap_kp->input); if (ret < 0) { printk(KERN_ERR "Unable to register omap-keypad input device\n"); diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index e809ac095a3..aed5f6999ce 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -68,19 +68,52 @@ #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF +enum { + KBD_REVISION_OMAP4 = 0, + KBD_REVISION_OMAP5, +}; + struct omap4_keypad { struct input_dev *input; void __iomem *base; - int irq; + unsigned int irq; unsigned int rows; unsigned int cols; + u32 reg_offset; + u32 irqreg_offset; unsigned int row_shift; unsigned char key_state[8]; unsigned short keymap[]; }; +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset) +{ + return __raw_readl(keypad_data->base + + keypad_data->reg_offset + offset); +} + +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value) +{ + __raw_writel(value, + keypad_data->base + keypad_data->reg_offset + offset); +} + +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset) +{ + return __raw_readl(keypad_data->base + + keypad_data->irqreg_offset + offset); +} + +static void kbd_write_irqreg(struct omap4_keypad *keypad_data, + u32 offset, u32 value) +{ + __raw_writel(value, + keypad_data->base + keypad_data->irqreg_offset + offset); +} + + /* Interrupt handler */ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) { @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) u32 *new_state = (u32 *) key_state; /* Disable interrupts */ - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_VAL_IRQDISABLE); - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0); - *(new_state + 1) = __raw_readl(keypad_data->base - + OMAP4_KBD_FULLCODE63_32); + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0); + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); for (row = 0; row < keypad_data->rows; row++) { changed = key_state[row] ^ keypad_data->key_state[row]; @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) sizeof(keypad_data->key_state)); /* clear pending interrupts */ - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), - keypad_data->base + OMAP4_KBD_IRQSTATUS); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); /* enable interrupts */ - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_DEF_IRQENABLE_EVENTEN | + OMAP4_DEF_IRQENABLE_LONGKEY); return IRQ_HANDLED; } @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input) disable_irq(keypad_data->irq); - __raw_writel(OMAP4_VAL_FUNCTIONALCFG, - keypad_data->base + OMAP4_KBD_CTRL); - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQSTATUS); - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, - keypad_data->base + OMAP4_KBD_IRQENABLE); - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, - keypad_data->base + OMAP4_KBD_WAKEUPENABLE); + kbd_writel(keypad_data, OMAP4_KBD_CTRL, + OMAP4_VAL_FUNCTIONALCFG); + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, + OMAP4_VAL_DEBOUNCINGTIME); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + OMAP4_VAL_IRQDISABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_DEF_IRQENABLE_EVENTEN | + OMAP4_DEF_IRQENABLE_LONGKEY); + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA); enable_irq(keypad_data->irq); @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input) disable_irq(keypad_data->irq); /* Disable interrupts */ - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_VAL_IRQDISABLE); /* clear pending interrupts */ - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), - keypad_data->base + OMAP4_KBD_IRQSTATUS); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); enable_irq(keypad_data->irq); @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) struct resource *res; resource_size_t size; unsigned int row_shift, max_keys; + int rev; int irq; int error; @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) keypad_data->rows = pdata->rows; keypad_data->cols = pdata->cols; + /* + * Enable clocks for the keypad module so that we can read + * revision register. + */ + pm_runtime_enable(&pdev->dev); + error = pm_runtime_get_sync(&pdev->dev); + if (error) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); + goto err_unmap; + } + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); + rev &= 0x03 << 30; + rev >>= 30; + switch (rev) { + case KBD_REVISION_OMAP4: + keypad_data->reg_offset = 0x00; + keypad_data->irqreg_offset = 0x00; + break; + case KBD_REVISION_OMAP5: + keypad_data->reg_offset = 0x10; + keypad_data->irqreg_offset = 0x0c; + break; + default: + dev_err(&pdev->dev, + "Keypad reports unsupported revision %d", rev); + error = -EINVAL; + goto err_pm_put_sync; + } + /* input device allocation */ keypad_data->input = input_dev = input_allocate_device(); if (!input_dev) { error = -ENOMEM; - goto err_unmap; + goto err_pm_put_sync; } input_dev->name = pdev->name; @@ -258,20 +322,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) input_dev->open = omap4_keypad_open; input_dev->close = omap4_keypad_close; - input_dev->keycode = keypad_data->keymap; - input_dev->keycodesize = sizeof(keypad_data->keymap[0]); - input_dev->keycodemax = max_keys; + error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + pdata->rows, pdata->cols, + keypad_data->keymap, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto err_free_input; + } - __set_bit(EV_KEY, input_dev->evbit); __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad_data); - matrix_keypad_build_keymap(pdata->keymap_data, row_shift, - input_dev->keycode, input_dev->keybit); - error = request_irq(keypad_data->irq, omap4_keypad_interrupt, IRQF_TRIGGER_RISING, "omap4-keypad", keypad_data); @@ -280,7 +343,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) goto err_free_input; } - pm_runtime_enable(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); error = input_register_device(keypad_data->input); if (error < 0) { @@ -296,6 +359,8 @@ err_pm_disable: free_irq(keypad_data->irq, keypad_data); err_free_input: input_free_device(input_dev); +err_pm_put_sync: + pm_runtime_put_sync(&pdev->dev); err_unmap: iounmap(keypad_data->base); err_release_mem: diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 01a1c9f8a38..52c34657d30 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -626,21 +626,21 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; - kp->input->evbit[0] = BIT_MASK(EV_KEY); - - if (pdata->rep) - __set_bit(EV_REP, kp->input->evbit); - - kp->input->keycode = kp->keycodes; - kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; - kp->input->keycodesize = sizeof(kp->keycodes); kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; - matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, - kp->input->keycode, kp->input->keybit); + rc = matrix_keypad_build_keymap(keymap_data, NULL, + PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, + kp->keycodes, kp->input); + if (rc) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto err_get_irq; + } + if (pdata->rep) + __set_bit(EV_REP, kp->input->evbit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); + input_set_drvdata(kp->input, kp); /* initialize keypad state */ diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 2391ae884fe..a061ba603a2 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -454,23 +454,23 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; - input_set_drvdata(input_dev, keypad); input_dev->open = samsung_keypad_open; input_dev->close = samsung_keypad_close; - input_dev->evbit[0] = BIT_MASK(EV_KEY); - if (!pdata->no_autorepeat) - input_dev->evbit[0] |= BIT_MASK(EV_REP); + error = matrix_keypad_build_keymap(keymap_data, NULL, + pdata->rows, pdata->cols, + keypad->keycodes, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto err_put_clk; + } input_set_capability(input_dev, EV_MSC, MSC_SCAN); + if (!pdata->no_autorepeat) + __set_bit(EV_REP, input_dev->evbit); - input_dev->keycode = keypad->keycodes; - input_dev->keycodesize = sizeof(keypad->keycodes[0]); - input_dev->keycodemax = pdata->rows << row_shift; - - matrix_keypad_build_keymap(keymap_data, row_shift, - input_dev->keycode, input_dev->keybit); + input_set_drvdata(input_dev, keypad); keypad->irq = platform_get_irq(pdev, 0); if (keypad->irq < 0) { diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 3b6b528f02f..6f287f7e153 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -19,6 +19,7 @@ #include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_wakeup.h> #include <linux/slab.h> @@ -49,7 +50,9 @@ #define KEY_VALUE 0x00FFFFFF #define ROW_MASK 0xF0 #define COLUMN_MASK 0x0F -#define ROW_SHIFT 4 +#define NUM_ROWS 16 +#define NUM_COLS 16 + #define KEY_MATRIX_SHIFT 6 struct spear_kbd { @@ -60,7 +63,8 @@ struct spear_kbd { unsigned int irq; unsigned int mode; unsigned short last_key; - unsigned short keycodes[256]; + unsigned short keycodes[NUM_ROWS * NUM_COLS]; + bool rep; }; static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) @@ -136,27 +140,49 @@ static void spear_kbd_close(struct input_dev *dev) kbd->last_key = KEY_RESERVED; } -static int __devinit spear_kbd_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static int __devinit spear_kbd_parse_dt(struct platform_device *pdev, + struct spear_kbd *kbd) { - const struct kbd_platform_data *pdata = pdev->dev.platform_data; - const struct matrix_keymap_data *keymap; - struct spear_kbd *kbd; - struct input_dev *input_dev; - struct resource *res; - int irq; + struct device_node *np = pdev->dev.of_node; int error; + u32 val; - if (!pdata) { - dev_err(&pdev->dev, "Invalid platform data\n"); + if (!np) { + dev_err(&pdev->dev, "Missing DT data\n"); return -EINVAL; } - keymap = pdata->keymap; - if (!keymap) { - dev_err(&pdev->dev, "no keymap defined\n"); - return -EINVAL; + if (of_property_read_bool(np, "autorepeat")) + kbd->rep = true; + + error = of_property_read_u32(np, "st,mode", &val); + if (error) { + dev_err(&pdev->dev, "DT: Invalid or missing mode\n"); + return error; } + kbd->mode = val; + return 0; +} +#else +static inline int spear_kbd_parse_dt(struct platform_device *pdev, + struct spear_kbd *kbd) +{ + return -ENOSYS; +} +#endif + +static int __devinit spear_kbd_probe(struct platform_device *pdev) +{ + struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev); + const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL; + struct spear_kbd *kbd; + struct input_dev *input_dev; + struct resource *res; + int irq; + int error; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no keyboard resource defined\n"); @@ -179,7 +205,15 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) kbd->input = input_dev; kbd->irq = irq; - kbd->mode = pdata->mode; + + if (!pdata) { + error = spear_kbd_parse_dt(pdev, kbd); + if (error) + goto err_free_mem; + } else { + kbd->mode = pdata->mode; + kbd->rep = pdata->rep; + } kbd->res = request_mem_region(res->start, resource_size(res), pdev->name); @@ -212,18 +246,17 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) input_dev->open = spear_kbd_open; input_dev->close = spear_kbd_close; - __set_bit(EV_KEY, input_dev->evbit); - if (pdata->rep) + error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS, + kbd->keycodes, input_dev); + if (error) { + dev_err(&pdev->dev, "Failed to build keymap\n"); + goto err_put_clk; + } + + if (kbd->rep) __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_dev->keycode = kbd->keycodes; - input_dev->keycodesize = sizeof(kbd->keycodes[0]); - input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes); - - matrix_keypad_build_keymap(keymap, ROW_SHIFT, - input_dev->keycode, input_dev->keybit); - input_set_drvdata(input_dev, kbd); error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); @@ -317,6 +350,14 @@ static int spear_kbd_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); +#ifdef CONFIG_OF +static const struct of_device_id spear_kbd_id_table[] = { + { .compatible = "st,spear300-kbd" }, + {} +}; +MODULE_DEVICE_TABLE(of, spear_kbd_id_table); +#endif + static struct platform_driver spear_kbd_driver = { .probe = spear_kbd_probe, .remove = __devexit_p(spear_kbd_remove), @@ -324,6 +365,7 @@ static struct platform_driver spear_kbd_driver = { .name = "keyboard", .owner = THIS_MODULE, .pm = &spear_kbd_pm_ops, + .of_match_table = of_match_ptr(spear_kbd_id_table), }, }; module_platform_driver(spear_kbd_driver); diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 9397cf9c625..470a8778dec 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -289,19 +289,17 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev) input->id.bustype = BUS_I2C; input->dev.parent = &pdev->dev; - input_set_capability(input, EV_MSC, MSC_SCAN); + ret = matrix_keypad_build_keymap(plat->keymap_data, NULL, + STMPE_KEYPAD_MAX_ROWS, + STMPE_KEYPAD_MAX_COLS, + keypad->keymap, input); + if (ret) + goto out_freeinput; - __set_bit(EV_KEY, input->evbit); + input_set_capability(input, EV_MSC, MSC_SCAN); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - input->keycode = keypad->keymap; - input->keycodesize = sizeof(keypad->keymap[0]); - input->keycodemax = ARRAY_SIZE(keypad->keymap); - - matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, - input->keycode, input->keybit); - for (i = 0; i < plat->keymap_data->keymap_size; i++) { unsigned int key = plat->keymap_data->keymap[i]; diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index 7437219370b..cc612c5d542 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -170,15 +170,4 @@ static struct serio_driver skbd_drv = { .disconnect = skbd_disconnect, }; -static int __init skbd_init(void) -{ - return serio_register_driver(&skbd_drv); -} - -static void __exit skbd_exit(void) -{ - serio_unregister_driver(&skbd_drv); -} - -module_init(skbd_init); -module_exit(skbd_exit); +module_serio_driver(skbd_drv); diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index a99a04b03ee..5f836b1638c 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -369,19 +369,4 @@ static struct serio_driver sunkbd_drv = { .disconnect = sunkbd_disconnect, }; -/* - * The functions for insering/removing us as a module. - */ - -static int __init sunkbd_init(void) -{ - return serio_register_driver(&sunkbd_drv); -} - -static void __exit sunkbd_exit(void) -{ - serio_unregister_driver(&sunkbd_drv); -} - -module_init(sunkbd_init); -module_exit(sunkbd_exit); +module_serio_driver(sunkbd_drv); diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 2dee3e4e7c6..7d498e69850 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -78,7 +78,7 @@ * @input: pointer to input device object * @board: keypad platform device * @krow: number of rows - * @kcol: number of coloumns + * @kcol: number of columns * @keymap: matrix scan code table for keycodes * @keypad_stopped: holds keypad status */ @@ -96,21 +96,15 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) { int ret; struct tc3589x *tc3589x = keypad->tc3589x; - u8 settle_time = keypad->board->settle_time; - u8 dbounce_period = keypad->board->debounce_period; - u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */ - u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */ - - /* validate platform configurations */ - if (keypad->board->kcol > TC3589x_MAX_KPCOL || - keypad->board->krow > TC3589x_MAX_KPROW || - keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE || - keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE) + const struct tc3589x_keypad_platform_data *board = keypad->board; + + /* validate platform configuration */ + if (board->kcol > TC3589x_MAX_KPCOL || board->krow > TC3589x_MAX_KPROW) return -EINVAL; /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, - (rows << KP_ROW_SHIFT) | column); + (board->krow << KP_ROW_SHIFT) | board->kcol); if (ret < 0) return ret; @@ -124,12 +118,14 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) return ret; /* Configure settle time */ - ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time); + ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, + board->settle_time); if (ret < 0) return ret; /* Configure debounce time */ - ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period); + ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, + board->debounce_period); if (ret < 0) return ret; @@ -337,23 +333,22 @@ static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) input->name = pdev->name; input->dev.parent = &pdev->dev; - input->keycode = keypad->keymap; - input->keycodesize = sizeof(keypad->keymap[0]); - input->keycodemax = ARRAY_SIZE(keypad->keymap); - input->open = tc3589x_keypad_open; input->close = tc3589x_keypad_close; - input_set_drvdata(input, keypad); + error = matrix_keypad_build_keymap(plat->keymap_data, NULL, + TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, + keypad->keymap, input); + if (error) { + dev_err(&pdev->dev, "Failed to build keymap\n"); + goto err_free_mem; + } input_set_capability(input, EV_MSC, MSC_SCAN); - - __set_bit(EV_KEY, input->evbit); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - matrix_keypad_build_keymap(plat->keymap_data, 0x3, - input->keycode, input->keybit); + input_set_drvdata(input, keypad); error = request_threaded_irq(irq, NULL, tc3589x_keypad_irq, plat->irqtype, diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 958ec107bfb..5f87b28b319 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -342,21 +342,20 @@ static int __devinit tca8418_keypad_probe(struct i2c_client *client, input->id.product = 0x001; input->id.version = 0x0001; - input->keycode = keypad_data->keymap; - input->keycodesize = sizeof(keypad_data->keymap[0]); - input->keycodemax = max_keys; + error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + pdata->rows, pdata->cols, + keypad_data->keymap, input); + if (error) { + dev_dbg(&client->dev, "Failed to build keymap\n"); + goto fail2; + } - __set_bit(EV_KEY, input->evbit); if (pdata->rep) __set_bit(EV_REP, input->evbit); - input_set_capability(input, EV_MSC, MSC_SCAN); input_set_drvdata(input, keypad_data); - matrix_keypad_build_keymap(pdata->keymap_data, row_shift, - input->keycode, input->keybit); - if (pdata->irq_is_gpio) client->irq = gpio_to_irq(client->irq); diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index fe4ac95ca6c..4ffe64d5310 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -619,8 +619,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, } #ifdef CONFIG_OF -static struct tegra_kbc_platform_data * __devinit -tegra_kbc_dt_parse_pdata(struct platform_device *pdev) +static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata( + struct platform_device *pdev) { struct tegra_kbc_platform_data *pdata; struct device_node *np = pdev->dev.of_node; @@ -660,10 +660,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; } - pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap"); - - /* FIXME: Add handling of linux,fn-keymap here */ - return pdata; } #else @@ -674,10 +670,36 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( } #endif +static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc) +{ + const struct tegra_kbc_platform_data *pdata = kbc->pdata; + const struct matrix_keymap_data *keymap_data = pdata->keymap_data; + unsigned int keymap_rows = KBC_MAX_KEY; + int retval; + + if (keymap_data && pdata->use_fn_map) + keymap_rows *= 2; + + retval = matrix_keypad_build_keymap(keymap_data, NULL, + keymap_rows, KBC_MAX_COL, + kbc->keycode, kbc->idev); + if (retval == -ENOSYS || retval == -ENOENT) { + /* + * If there is no OF support in kernel or keymap + * property is missing, use default keymap. + */ + retval = matrix_keypad_build_keymap( + &tegra_kbc_default_keymap_data, NULL, + keymap_rows, KBC_MAX_COL, + kbc->keycode, kbc->idev); + } + + return retval; +} + static int __devinit tegra_kbc_probe(struct platform_device *pdev) { const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; - const struct matrix_keymap_data *keymap_data; struct tegra_kbc *kbc; struct input_dev *input_dev; struct resource *res; @@ -757,29 +779,26 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS); + kbc->wakeup_key = pdata->wakeup_key; + kbc->use_fn_map = pdata->use_fn_map; + kbc->use_ghost_filter = pdata->use_ghost_filter; + input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; input_dev->open = tegra_kbc_open; input_dev->close = tegra_kbc_close; - input_set_drvdata(input_dev, kbc); + err = tegra_kbd_setup_keymap(kbc); + if (err) { + dev_err(&pdev->dev, "failed to setup keymap\n"); + goto err_put_clk; + } - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_dev->keycode = kbc->keycode; - input_dev->keycodesize = sizeof(kbc->keycode[0]); - input_dev->keycodemax = KBC_MAX_KEY; - if (pdata->use_fn_map) - input_dev->keycodemax *= 2; - - kbc->use_fn_map = pdata->use_fn_map; - kbc->use_ghost_filter = pdata->use_ghost_filter; - keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; - matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, - input_dev->keycode, input_dev->keybit); - kbc->wakeup_key = pdata->wakeup_key; + input_set_drvdata(input_dev, kbc); err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); @@ -799,9 +818,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, kbc); device_init_wakeup(&pdev->dev, pdata->wakeup); - if (!pdev->dev.platform_data) - matrix_keyboard_of_free_keymap(pdata->keymap_data); - return 0; err_free_irq: @@ -816,10 +832,8 @@ err_free_mem: input_free_device(input_dev); kfree(kbc); err_free_pdata: - if (!pdev->dev.platform_data) { - matrix_keyboard_of_free_keymap(pdata->keymap_data); + if (!pdev->dev.platform_data) kfree(pdata); - } return err; } diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index fb39c94b6fd..a4a445fb702 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -247,15 +247,11 @@ static int __devinit keypad_probe(struct platform_device *pdev) error = -ENOMEM; goto error_input; } - input_set_drvdata(kp->input_dev, kp); kp->input_dev->name = pdev->name; kp->input_dev->dev.parent = &pdev->dev; kp->input_dev->open = keypad_start; kp->input_dev->close = keypad_stop; - kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); - if (!pdata->no_autorepeat) - kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); clk_enable(kp->clk); rev = keypad_read(kp, rev); @@ -264,15 +260,20 @@ static int __devinit keypad_probe(struct platform_device *pdev) kp->input_dev->id.version = ((rev >> 16) & 0xfff); clk_disable(kp->clk); - kp->input_dev->keycode = kp->keycodes; - kp->input_dev->keycodesize = sizeof(kp->keycodes[0]); - kp->input_dev->keycodemax = kp->rows << kp->row_shift; - - matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, - kp->input_dev->keybit); + error = matrix_keypad_build_keymap(keymap_data, NULL, + kp->rows, kp->cols, + kp->keycodes, kp->input_dev); + if (error) { + dev_err(dev, "Failed to build keymap\n"); + goto error_reg; + } + if (!pdata->no_autorepeat) + kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(kp->input_dev, kp); + error = input_register_device(kp->input_dev); if (error < 0) { dev_err(dev, "Could not register input device\n"); diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 67bec14e8b9..a2c6f79aa10 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -361,14 +361,6 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) kp->irq = platform_get_irq(pdev, 0); /* setup input device */ - __set_bit(EV_KEY, input->evbit); - - /* Enable auto repeat feature of Linux input subsystem */ - if (pdata->rep) - __set_bit(EV_REP, input->evbit); - - input_set_capability(input, EV_MSC, MSC_SCAN); - input->name = "TWL4030 Keypad"; input->phys = "twl4030_keypad/input0"; input->dev.parent = &pdev->dev; @@ -378,12 +370,19 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0003; - input->keycode = kp->keymap; - input->keycodesize = sizeof(kp->keymap[0]); - input->keycodemax = ARRAY_SIZE(kp->keymap); + error = matrix_keypad_build_keymap(keymap_data, NULL, + TWL4030_MAX_ROWS, + 1 << TWL4030_ROW_SHIFT, + kp->keymap, input); + if (error) { + dev_err(kp->dbg_dev, "Failed to build keymap\n"); + goto err1; + } - matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT, - input->keycode, input->keybit); + input_set_capability(input, EV_MSC, MSC_SCAN); + /* Enable auto repeat feature of Linux input subsystem */ + if (pdata->rep) + __set_bit(EV_REP, input->evbit); error = input_register_device(input); if (error) { diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 99bbb7e775a..085ede4d972 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -42,7 +42,8 @@ #define KGET_RAW(n) (((n) & KEY0R) >> 3) #define KGET_COLUMN(n) ((n) & KEY0C) -#define W90P910_MAX_KEY_NUM (8 * 8) +#define W90P910_NUM_ROWS 8 +#define W90P910_NUM_COLS 8 #define W90P910_ROW_SHIFT 3 struct w90p910_keypad { @@ -51,7 +52,7 @@ struct w90p910_keypad { struct input_dev *input_dev; void __iomem *mmio_base; int irq; - unsigned short keymap[W90P910_MAX_KEY_NUM]; + unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS]; }; static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, @@ -190,17 +191,13 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) input_dev->close = w90p910_keypad_close; input_dev->dev.parent = &pdev->dev; - input_dev->keycode = keypad->keymap; - input_dev->keycodesize = sizeof(keypad->keymap[0]); - input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); - - input_set_drvdata(input_dev, keypad); - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - - matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT, - input_dev->keycode, input_dev->keybit); + error = matrix_keypad_build_keymap(keymap_data, NULL, + W90P910_NUM_ROWS, W90P910_NUM_COLS, + keypad->keymap, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto failed_put_clk; + } error = request_irq(keypad->irq, w90p910_keypad_irq_handler, 0, pdev->name, keypad); @@ -209,6 +206,10 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) goto failed_put_clk; } + __set_bit(EV_REP, input_dev->evbit); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, keypad); + /* Register the input device */ error = input_register_device(input_dev); if (error) { diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 37b01d777a4..d050d9d0011 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -169,15 +169,4 @@ static struct serio_driver xtkbd_drv = { .disconnect = xtkbd_disconnect, }; -static int __init xtkbd_init(void) -{ - return serio_register_driver(&xtkbd_drv); -} - -static void __exit xtkbd_exit(void) -{ - serio_unregister_driver(&xtkbd_drv); -} - -module_init(xtkbd_init); -module_exit(xtkbd_exit); +module_serio_driver(xtkbd_drv); |