diff options
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 62 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 4 | ||||
-rw-r--r-- | drivers/input/keyboard/hil_kbd.c | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/omap-keypad.c | 6 | ||||
-rw-r--r-- | drivers/input/keyboard/pxa930_rotary.c | 212 |
7 files changed, 289 insertions, 6 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index efd70a97459..35561689ff3 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -268,6 +268,15 @@ config KEYBOARD_PXA27x To compile this driver as a module, choose M here: the module will be called pxa27x_keypad. +config KEYBOARD_PXA930_ROTARY + tristate "PXA930/PXA935 Enhanced Rotary Controller Support" + depends on CPU_PXA930 || CPU_PXA935 + help + Enable support for PXA930/PXA935 Enhanced Rotary Controller. + + To compile this driver as a module, choose M here: the + module will be called pxa930_rotary. + config KEYBOARD_AAED2000 tristate "AAED-2000 keyboard" depends on MACH_AAED2000 diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0edc8f285d1..36351e1190f 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o +obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 379b7ff354e..c3c8b9bc40a 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -65,7 +65,7 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and /* * Scancode to keycode tables. These are just the default setting, and - * are loadable via an userland utility. + * are loadable via a userland utility. */ static const unsigned short atkbd_set2_keycode[512] = { @@ -884,6 +884,39 @@ static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd) } /* + * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release + * for its volume buttons + */ +static void atkbd_hp_zv6100_keymap_fixup(struct atkbd *atkbd) +{ + const unsigned int forced_release_keys[] = { + 0xae, 0xb0, + }; + int i; + + if (atkbd->set == 2) + for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) + __set_bit(forced_release_keys[i], + atkbd->force_release_mask); +} + +/* + * Samsung NC10 with Fn+F? key release not working + */ +static void atkbd_samsung_keymap_fixup(struct atkbd *atkbd) +{ + const unsigned int forced_release_keys[] = { + 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, + }; + int i; + + if (atkbd->set == 2) + for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) + __set_bit(forced_release_keys[i], + atkbd->force_release_mask); +} + +/* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set */ @@ -1476,6 +1509,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .driver_data = atkbd_dell_laptop_keymap_fixup, }, { + .ident = "Dell Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ + }, + .callback = atkbd_setup_fixup, + .driver_data = atkbd_dell_laptop_keymap_fixup, + }, + { .ident = "HP 2133", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -1485,6 +1527,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .driver_data = atkbd_hp_keymap_fixup, }, { + .ident = "HP Pavilion ZV6100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), + }, + .callback = atkbd_setup_fixup, + .driver_data = atkbd_hp_zv6100_keymap_fixup, + }, + { .ident = "Inventec Symphony", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), @@ -1493,6 +1544,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_fixup, .driver_data = atkbd_inventec_keymap_fixup, }, + { + .ident = "Samsung NC10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), + }, + .callback = atkbd_setup_fixup, + .driver_data = atkbd_samsung_keymap_fixup, + }, { } }; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 05f3f43582c..ad67d763fdb 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -98,6 +98,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0100; + /* Enable auto repeat feature of Linux input subsystem */ + if (pdata->rep) + __set_bit(EV_REP, input->evbit); + ddata->input = input; for (i = 0; i < pdata->nbuttons; i++) { diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 71c1971abf8..6f356705ee3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -47,6 +47,7 @@ MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("serio:ty03pr25id00ex*"); #define HIL_KBD_MAX_LENGTH 16 diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index db22fd9b4cf..3f3d1198cdb 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -122,14 +122,10 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state) /* read the keypad status */ if (cpu_is_omap24xx()) { - int i; - for (i = 0; i < omap_kp->rows; i++) - disable_irq(OMAP_GPIO_IRQ(row_gpios[i])); - /* read the keypad status */ for (col = 0; col < omap_kp->cols; col++) { set_col_gpio_val(omap_kp, ~(1 << col)); - state[col] = ~(get_row_gpio_val(omap_kp)) & 0x3f; + state[col] = ~(get_row_gpio_val(omap_kp)) & 0xff; } set_col_gpio_val(omap_kp, 0); diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c new file mode 100644 index 00000000000..95fbba470e6 --- /dev/null +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -0,0 +1,212 @@ +/* + * Driver for the enhanced rotary controller on pxa930 and pxa935 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <mach/pxa930_rotary.h> + +#define SBCR (0x04) +#define ERCR (0x0c) + +#define SBCR_ERSB (1 << 5) + +struct pxa930_rotary { + struct input_dev *input_dev; + void __iomem *mmio_base; + int last_ercr; + + struct pxa930_rotary_platform_data *pdata; +}; + +static void clear_sbcr(struct pxa930_rotary *r) +{ + uint32_t sbcr = __raw_readl(r->mmio_base + SBCR); + + __raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR); + __raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR); +} + +static irqreturn_t rotary_irq(int irq, void *dev_id) +{ + struct pxa930_rotary *r = dev_id; + struct pxa930_rotary_platform_data *pdata = r->pdata; + int ercr, delta, key; + + ercr = __raw_readl(r->mmio_base + ERCR) & 0xf; + clear_sbcr(r); + + delta = ercr - r->last_ercr; + if (delta == 0) + return IRQ_HANDLED; + + r->last_ercr = ercr; + + if (pdata->up_key && pdata->down_key) { + key = (delta > 0) ? pdata->up_key : pdata->down_key; + input_report_key(r->input_dev, key, 1); + input_sync(r->input_dev); + input_report_key(r->input_dev, key, 0); + } else + input_report_rel(r->input_dev, pdata->rel_code, delta); + + input_sync(r->input_dev); + + return IRQ_HANDLED; +} + +static int pxa930_rotary_open(struct input_dev *dev) +{ + struct pxa930_rotary *r = input_get_drvdata(dev); + + clear_sbcr(r); + + return 0; +} + +static void pxa930_rotary_close(struct input_dev *dev) +{ + struct pxa930_rotary *r = input_get_drvdata(dev); + + clear_sbcr(r); +} + +static int __devinit pxa930_rotary_probe(struct platform_device *pdev) +{ + struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data; + struct pxa930_rotary *r; + struct input_dev *input_dev; + struct resource *res; + int irq; + int err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq for rotary controller\n"); + return -ENXIO; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no I/O memory defined\n"); + return -ENXIO; + } + + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL); + if (!r) + return -ENOMEM; + + r->mmio_base = ioremap_nocache(res->start, resource_size(res)); + if (r->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to remap IO memory\n"); + err = -ENXIO; + goto failed_free; + } + + r->pdata = pdata; + platform_set_drvdata(pdev, r); + + /* allocate and register the input device */ + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + err = -ENOMEM; + goto failed_free_io; + } + + input_dev->name = pdev->name; + input_dev->id.bustype = BUS_HOST; + input_dev->open = pxa930_rotary_open; + input_dev->close = pxa930_rotary_close; + input_dev->dev.parent = &pdev->dev; + + if (pdata->up_key && pdata->down_key) { + __set_bit(pdata->up_key, input_dev->keybit); + __set_bit(pdata->down_key, input_dev->keybit); + __set_bit(EV_KEY, input_dev->evbit); + } else { + __set_bit(pdata->rel_code, input_dev->relbit); + __set_bit(EV_REL, input_dev->evbit); + } + + r->input_dev = input_dev; + input_set_drvdata(input_dev, r); + + err = request_irq(irq, rotary_irq, IRQF_DISABLED, + "enhanced rotary", r); + if (err) { + dev_err(&pdev->dev, "failed to request IRQ\n"); + goto failed_free_input; + } + + err = input_register_device(input_dev); + if (err) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto failed_free_irq; + } + + return 0; + +failed_free_irq: + free_irq(irq, r); +failed_free_input: + input_free_device(input_dev); +failed_free_io: + iounmap(r->mmio_base); +failed_free: + kfree(r); + return err; +} + +static int __devexit pxa930_rotary_remove(struct platform_device *pdev) +{ + struct pxa930_rotary *r = platform_get_drvdata(pdev); + + free_irq(platform_get_irq(pdev, 0), r); + input_unregister_device(r->input_dev); + iounmap(r->mmio_base); + platform_set_drvdata(pdev, NULL); + kfree(r); + + return 0; +} + +static struct platform_driver pxa930_rotary_driver = { + .driver = { + .name = "pxa930-rotary", + .owner = THIS_MODULE, + }, + .probe = pxa930_rotary_probe, + .remove = __devexit_p(pxa930_rotary_remove), +}; + +static int __init pxa930_rotary_init(void) +{ + return platform_driver_register(&pxa930_rotary_driver); +} +module_init(pxa930_rotary_init); + +static void __exit pxa930_rotary_exit(void) +{ + platform_driver_unregister(&pxa930_rotary_driver); +} +module_exit(pxa930_rotary_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller"); +MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>"); |