input: Add keypad driver for w90p910
Subsystems (4)
PATCH v3 1/1 input: Add keypad driver for w90p910
Dear Dmitry,
This is a latest keypad driver, according to your and H Hartley's advice, I fixed up my keypad driver again and merge this header file patch to keypad driver patch.
Thanks a lot for your help.
Add w90p910 keypad driver for the evaluation board based on w90p910. There is a 4x4 keypad in my evaluation board.
--- .../arm/mach-w90x900/include/mach/w90p910_keypad.h | 18 ++ drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/w90p910_keypad.c | 305 ++++++++++++++++++++ 4 files changed, 334 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-w90x900/include/mach/w90p910_keypad.h create mode 100644 drivers/input/keyboard/w90p910_keypad.c
arch/arm/mach-w90x900/include/mach/w90p910_keypad.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef __ASM_ARCH_W90P910_KEYPAD_H +#define __ASM_ARCH_W90P910_KEYPAD_H + +#include <linux/input/matrix_keypad.h> + +extern void mfp_set_groupi (struct device *dev); + +struct w90p910_keypad_platform_data { + +unsigned int prescale; +unsigned int debounce; +unsigned int matrix_key_rows; +unsigned int matrix_key_cols; +unsigned int *matrix_key_map; +int matrix_key_map_size; +}; + +#endif /* __ASM_ARCH_W90P910_KEYPAD_H */
drivers/input/keyboard/Kconfig +10 -0
@@ -361,4 +361,14 @@ config KEYBOARD_XTKBD To compile this driver as a module, choose M here: the module will be called xtkbd. +config KEYBOARD_W90P910 + tristate "W90P910 Matrix Keypad support" + depends on ARCH_W90X900 + help + Say Y here to enable the matrix keypad on evaluation board + based on W90P910. + + To compile this driver as a module, choose M here: the + module will be called w90p910_keypad. + endif
drivers/input/keyboard/Makefile +1 -0
@@ -31,3 +31,4 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o +obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
drivers/input/keyboard/w90p910_keypad.c new file +305 -0
305 lines not on this page · raw message
Signature · 1 line
1.5.6.3
Dmitry Torokhov
maintainerHi Wan,
Quoted 6 lines · Wan ZongShun
Dear Dmitry,
This is a latest keypad driver, according to your and H Hartley's advice, I fixed up my keypad driver again and merge this header file patch to keypad driver patch.
I was waiting for the matrix_keypad code to settle before applying your drive; now that it has settled I ajusted w90p910_keypad to use definitions from include/linux/input/matrix_keypad.h and I am ready to apply it to my tree.
Could you please try the patch below to verify that I did not break anything (you'll have to pull the latest Linus tree to get the correct bits of matrix_keypad)?
Thanks!
Signature · 15 lines
Dmitry Input: w90p910_keypad - adjust to use definitions from matrix_keypad.h From: Dmitry Torokhov <[email protected]> Also have the driver send MSC_SCAN events as most keyboards do to aid in updating keymap from userspace. Signed-off-by: Dmitry Torokhov <[email protected]> --- .../arm/mach-w90x900/include/mach/w90p910_keypad.h | 5 - drivers/input/keyboard/w90p910_keypad.c | 144 +++++++++----------- 2 files changed, 66 insertions(+), 83 deletions(-)
arch/arm/mach-w90x900/include/mach/w90p910_keypad.h +1 -4
@@ -6,13 +6,10 @@extern void mfp_set_groupi (struct device *dev);struct w90p910_keypad_platform_data { +const struct matrix_keymap_data *keymap_data;unsigned int prescale;unsigned int debounce; -unsigned int matrix_key_rows; -unsigned int matrix_key_cols; -unsigned int *matrix_key_map; -int matrix_key_map_size; };#endif /* __ASM_ARCH_W90P910_KEYPAD_H */
drivers/input/keyboard/w90p910_keypad.c +65 -79
240 lines not on this page · raw message
Dear Dmitry,
I have tested this patch, and it work very well.
Thank you for helping me fix my keypad driver and I appreciate this kindness.
2009/8/10 Dmitry Torokhov <[email protected]>:
Quoted 311 lines
Hi Wan,
Quoted 6 lines · Wan ZongShun
Dear Dmitry,
This is a latest keypad driver, according to your and H Hartley's advice, I fixed up my keypad driver again and merge this header file patch to keypad driver patch.
I was waiting for the
matrix_keypadcode to settle before applying your drive; now that it has settled I ajustedw90p910_keypadto use definitions frominclude/linux/input/matrix_keypad.hand I am ready to apply it to my tree.Could you please try the patch below to verify that I did not break anything (you'll have to pull the latest Linus tree to get the correct bits of
matrix_keypad)?Thanks!
--
DmitryInput:
w90p910_keypad- adjust to use definitions frommatrix_keypad.hFrom: Dmitry Torokhov <[email protected]>
Also have the driver send
MSC_SCANevents as most keyboards do to aid in updating keymap from userspace.Signed-off-by Dmitry Torokhov <[email protected]>---
.../arm/mach-w90x900/include/mach/w90p910_keypad.h | 5 -
drivers/input/keyboard/w90p910_keypad.c| 144 +++++++++-----------2 files changed, 66 insertions(+), 83 deletions(-)arch/arm/mach-w90x900/include/mach/w90p910_keypad.h +1
-4@@ -6,13 +6,10 @@ extern void mfp_set_groupi(struct device *dev); struct w90p910_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; unsigned int prescale; unsigned int debounce; - unsigned int matrix_key_rows; - unsigned int matrix_key_cols; - unsigned int *matrix_key_map; - int matrix_key_map_size; }; #endif /* __ASM_ARCH_W90P910_KEYPAD_H */drivers/input/keyboard/w90p910_keypad.c +62
-74@@ -41,58 +41,34 @@ #define KGET_RAW(n) (((n) & KEY0R) >> 3) #define KGET_COLUMN(n) ((n) & KEY0C) -#define MAX_MATRIX_KEY_NUM (8 * 8) +#define W90P910_MAX_KEY_NUM (8 * 8) +#define W90P910_ROW_SHIFT 3 struct w90p910_keypad { - struct w90p910_keypad_platform_data *pdata; + const struct w90p910_keypad_platform_data *pdata; struct clk *clk; struct input_dev *input_dev; void __iomem *mmio_base; int irq; - unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; + unsigned short keymap[W90P910_MAX_KEY_NUM]; }; -static void w90p910_keypad_build_keycode (struct w90p910_keypad *keypad) -{ - struct w90p910_keypad_platform_data *pdata = keypad->pdata; - struct input_dev *input_dev = keypad->input_dev; - unsigned int *key; - int i; - - key = &pdata->matrix_key_map[0]; - for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { - int row = KEY_ROW(*key); - int col = KEY_COL(*key); - int code = KEY_VAL(*key); - - keypad->matrix_keycodes[(row << 3) + col] = code; - __set_bit(code, input_dev->keybit); - } -} - -static inline unsigned int lookup_matrix_keycode ( - struct w90p910_keypad *keypad, int row, int col) -{ - return keypad->matrix_keycodes[(row << 3) + col]; -} - static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, unsigned int status) { - unsigned int row, col, val; - - row = KGET_RAW(status); - col = KGET_COLUMN(status); - - val = lookup_matrix_keycode(keypad, row, col); - - input_report_key(keypad->input_dev, val, 1); - - input_sync(keypad->input_dev); - - input_report_key(keypad->input_dev, val, 0); - - input_sync(keypad->input_dev); + struct input_dev *input_dev = keypad->input_dev; + unsigned int row = KGET_RAW(status); + unsigned int col = KGET_COLUMN(status); + unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); + unsigned int key = keypad->keymap[code]; + + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, key, 1); + input_sync(input_dev); + + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, key, 0); + input_sync(input_dev); } static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id)@@ -113,7 +89,7 @@ static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) static int w90p910_keypad_open(struct input_dev *dev) { struct w90p910_keypad *keypad = input_get_drvdata(dev); - struct w90p910_keypad_platform_data *pdata = keypad->pdata; + const struct w90p910_keypad_platform_data *pdata = keypad->pdata; unsigned int val, config; /* Enable unit clock */@@ -142,31 +118,39 @@ static void w90p910_keypad_close(struct input_dev *dev) static int __devinit w90p910_keypad_probe(struct platform_device *pdev) { + const struct w90p910_keypad_platform_data *pdata = + pdev->dev.platform_data; + const struct matrix_keymap_data *keymap_data = pdata->keymap_data; struct w90p910_keypad *keypad; struct input_dev *input_dev; struct resource *res; - int irq, error; - - keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); - if (keypad == NULL) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); - return -ENOMEM; - } + int irq; + int error; + int i; - keypad->pdata = pdev->dev.platform_data; - if (keypad->pdata == NULL) { + if (!pdata) { dev_err(&pdev->dev, "no platform data defined\n"); - error = -EINVAL; - goto failed_free; + return -EINVAL; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "failed to get keypad irq\n"); - error = -ENXIO; + return -ENXIO; + } + + keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!keypad || !input_dev) { + dev_err(&pdev->dev, "failed to allocate driver data\n"); + error = -ENOMEM; goto failed_free; } + keypad->pdata = pdata; + keypad->input_dev = input_dev; + keypad->irq = irq; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "failed to get I/O memory\n");@@ -185,7 +169,7 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) if (keypad->mmio_base == NULL) { dev_err(&pdev->dev, "failed to remap I/O memory\n"); error = -ENXIO; - goto failed_free_mem; + goto failed_free_res; } keypad->clk = clk_get(&pdev->dev, NULL);@@ -195,14 +179,6 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) goto failed_free_io; } - /* Create and register the input driver. */ - input_dev = input_allocate_device(); - if (!input_dev) { - dev_err(&pdev->dev, "failed to allocate input device\n"); - error = -ENOMEM; - goto failed_put_clk; - } - /* set multi-function pin for w90p910 kpi. */ mfp_set_groupi(&pdev->dev);@@ -211,26 +187,37 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) input_dev->open = w90p910_keypad_open; input_dev->close = w90p910_keypad_close; input_dev->dev.parent = &pdev->dev; - input_dev->keycode = keypad->matrix_keycodes; - input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]); - input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes); - keypad->input_dev = input_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); - w90p910_keypad_build_keycode(keypad); - platform_set_drvdata(pdev, keypad); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + + for (i = 0; i < keymap_data->keymap_size; i++) { + unsigned int key = keymap_data->keymap[i]; + unsigned int row = KEY_ROW(key); + unsigned int col = KEY_COL(key); + unsigned short keycode = KEY_VAL(key); + unsigned int scancode = MATRIX_SCAN_CODE(row, col, + W90P910_ROW_SHIFT); + + keypad->keymap[scancode] = keycode; + __set_bit(keycode, input_dev->keybit); + } + __clear_bit(KEY_RESERVED, input_dev->keybit); + - error = request_irq(irq, w90p910_keypad_irq_handler, IRQF_DISABLED, - pdev->name, keypad); + error = request_irq(keypad->irq, w90p910_keypad_irq_handler, + IRQF_DISABLED, pdev->name, keypad); if (error) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto failed_free_dev; + goto failed_put_clk; } - keypad->irq = irq; - /* Register the input device */ error = input_register_device(input_dev); if (error) {@@ -238,20 +225,19 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) goto failed_free_irq; } + platform_set_drvdata(pdev, keypad); return 0;failed_free_irq:
free_irq(irq, pdev);
-platform_set_drvdata(pdev, NULL);
-failed_free_dev:
-input_free_device(input_dev);
failed_put_clk:
clk_put(keypad->clk);
failed_free_io:
iounmap(keypad->mmio_base);drivers/input/keyboard/w90p910_keypad.c +1
-1-failed_free_mem: +failed_free_res:release_mem_region(res->start,
resource_size(res));failed_free:
+input_free_device(input_dev); kfree(keypad);
return error;
}drivers/input/keyboard/w90p910_keypad.c +1
-1@@ -268,12 +254,12 @@ static int __devexit w90p910_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input_dev); iounmap(keypad->mmio_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); kfree(keypad); + return 0; }
Signature · 5 lines
Wan z.s -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov
maintainerQuoted 5 lines · Wan ZongShun
Dear Dmitry,
I have tested this patch, and it work very well.
Thank you for helping me fix my keypad driver and I appreciate this kindness.
Great, thank you for testing Wan. The w90p910_keypad is now in my 'next' branch and should be pulled in the next merge window.
Signature · 1 line
Dmitry