From aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 Mon Sep 17 00:00:00 2001 From: merge Date: Thu, 22 Jan 2009 13:55:32 +0000 Subject: MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage: From: merge MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage: From: merge MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage: From: Andy Green fix-stray-endmenu.patch Signed-off-by: Andy Green --- drivers/input/keyboard/Kconfig | 9 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/atkbd.c | 89 +++++++++++++- drivers/input/keyboard/gpio_keys.c | 4 + drivers/input/keyboard/hil_kbd.c | 1 + drivers/input/keyboard/omap-keypad.c | 14 +-- drivers/input/keyboard/pxa27x_keypad.c | 2 +- drivers/input/keyboard/pxa930_rotary.c | 212 +++++++++++++++++++++++++++++++++ drivers/input/keyboard/sh_keysc.c | 28 ++++- 9 files changed, 343 insertions(+), 17 deletions(-) create mode 100644 drivers/input/keyboard/pxa930_rotary.c (limited to 'drivers/input/keyboard') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index bc7aac33e3c..1fb03db8ede 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 63a8972dc68..a4fc5d23b97 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -22,6 +22,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 22016ca1535..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] = { @@ -824,7 +824,7 @@ static void atkbd_disconnect(struct serio *serio) atkbd_disable(atkbd); /* make sure we don't have a command in flight */ - flush_scheduled_work(); + cancel_delayed_work_sync(&atkbd->event_work); sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); input_unregister_device(atkbd->dev); @@ -867,6 +867,55 @@ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) atkbd->force_release_mask); } +/* + * Inventec system with broken key release on volume keys + */ +static void atkbd_inventec_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); +} + +/* + * 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 @@ -1459,6 +1508,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_fixup, .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 = { @@ -1468,6 +1526,33 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_fixup, .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"), + DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), + }, + .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 09b70bbc3af..1b21537ccf8 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 "); 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 69e674ecf19..3f3d1198cdb 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -101,7 +101,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) if (cpu_is_omap24xx()) { int i; for (i = 0; i < omap_kp->rows; i++) - disable_irq(OMAP_GPIO_IRQ(row_gpios[i])); + disable_irq(gpio_to_irq(row_gpios[i])); } else /* disable keyboard interrupt and schedule for handling */ omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); @@ -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); @@ -224,7 +220,7 @@ static void omap_kp_tasklet(unsigned long data) if (cpu_is_omap24xx()) { int i; for (i = 0; i < omap_kp_data->rows; i++) - enable_irq(OMAP_GPIO_IRQ(row_gpios[i])); + enable_irq(gpio_to_irq(row_gpios[i])); } else { omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); kp_cur_group = -1; @@ -397,7 +393,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); } else { for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { - if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), + if (request_irq(gpio_to_irq(row_gpios[irq_idx]), omap_kp_interrupt, IRQF_TRIGGER_FALLING, "omap-keypad", omap_kp) < 0) @@ -438,7 +434,7 @@ static int omap_kp_remove(struct platform_device *pdev) gpio_free(col_gpios[i]); for (i = 0; i < omap_kp->rows; i++) { gpio_free(row_gpios[i]); - free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); + free_irq(gpio_to_irq(row_gpios[i]), 0); } } else { omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 6d30c6d334c..0d2fc64a5e1 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -475,7 +475,7 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) goto failed_free_mem; } - keypad->clk = clk_get(&pdev->dev, "KBDCLK"); + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get keypad clock\n"); error = PTR_ERR(keypad->clk); 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 +#include +#include +#include +#include +#include +#include + +#include + +#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 "); diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index c600ab7f93e..5c8a1bcf7ca 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ static const struct { struct sh_keysc_priv { void __iomem *iomem_base; + struct clk *clk; unsigned long last_keys; struct input_dev *input; struct sh_keysc_info pdata; @@ -125,6 +127,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) struct sh_keysc_info *pdata; struct resource *res; struct input_dev *input; + char clk_name[8]; int i, k; int irq, error; @@ -165,11 +168,19 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) goto err1; } + snprintf(clk_name, sizeof(clk_name), "keysc%d", pdev->id); + priv->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + error = PTR_ERR(priv->clk); + goto err2; + } + priv->input = input_allocate_device(); if (!priv->input) { dev_err(&pdev->dev, "failed to allocate input device\n"); error = -ENOMEM; - goto err2; + goto err3; } input = priv->input; @@ -187,7 +198,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); if (error) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto err3; + goto err4; } for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { @@ -199,18 +210,22 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) error = input_register_device(input); if (error) { dev_err(&pdev->dev, "failed to register input device\n"); - goto err4; + goto err5; } + clk_enable(priv->clk); + iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); return 0; - err4: + err5: free_irq(irq, pdev); - err3: + err4: input_free_device(input); + err3: + clk_put(priv->clk); err2: iounmap(priv->iomem_base); err1: @@ -230,6 +245,9 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) free_irq(platform_get_irq(pdev, 0), pdev); iounmap(priv->iomem_base); + clk_disable(priv->clk); + clk_put(priv->clk); + platform_set_drvdata(pdev, NULL); kfree(priv); return 0; -- cgit v1.2.3