From e57130698fe3dd2b7d617d90bbf86474473cb40c Mon Sep 17 00:00:00 2001 From: Jamie Lentin Date: Tue, 20 Oct 2009 14:36:49 -0700 Subject: [PATCH 1/4] Input: atkbd - add a quirk for OQO 01+ multimedia keys OQO 01+ multimedia keys produce 6x on press, e0 6x upon release. As a result, Linux thinks that another key has been pressed (or is repeating), when it is actually a release of the same key. Mangle the release scancode when running on OQO so that driver recognizes it as such. Since the device does not have external PS/2 ports mangling is safe since there is no chance that an external keyboard is connected. Signed-off-by: Jamie Lentin Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 271c0b7045c3..e9acbe0c9e2a 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -233,6 +233,7 @@ struct atkbd { */ static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); static void *atkbd_platform_fixup_data; +static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)); @@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, input_event(dev, EV_MSC, MSC_RAW, code); + if (atkbd_platform_scancode_fixup) + code = atkbd_platform_scancode_fixup(atkbd, code); + if (atkbd->translated) { if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { @@ -922,6 +926,22 @@ static unsigned int atkbd_volume_forced_release_keys[] = { 0xae, 0xb0, -1U }; +/* + * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas + * they should be generating e4-e6 (0x80 | code). + */ +static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, + unsigned int code) +{ + if (atkbd->translated && atkbd->emul == 1 && + (code == 0x64 || code == 0x65 || code == 0x66)) { + atkbd->emul = 0; + code |= 0x80; + } + + return code; +} + /* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set @@ -1527,6 +1547,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) return 0; } +static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) +{ + atkbd_platform_scancode_fixup = id->driver_data; + + return 0; +} + static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { { .ident = "Dell Laptop", @@ -1663,6 +1690,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_forced_release, .driver_data = atkdb_soltech_ta12_forced_release_keys, }, + { + .ident = "OQO Model 01+", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "OQO"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), + }, + .callback = atkbd_setup_scancode_fixup, + .driver_data = atkbd_oqo_01plus_scancode_fixup, + }, { } }; From ee1e82cee5e463a885d3c71acb2c769490e6927f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 2 Nov 2009 21:57:40 -0800 Subject: [PATCH 2/4] Input: i8042 - try to get stable CTR value when initializing If user presses keys while i8042 is being initialized there is a chance that keyboard data will be mistaken for results of Read Control Register command causing futher troubles. Work around this issue by reading CTR several times and stop when we get matching results. Reported-and-tested-by: Dave Young Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index a31578170ccc..1df02d25aca5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -836,17 +836,32 @@ static int i8042_controller_selftest(void) static int i8042_controller_init(void) { unsigned long flags; + int n = 0; + unsigned char ctr[2]; /* - * Save the CTR for restoral on unload / reboot. + * Save the CTR for restore on unload / reboot. */ - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { - printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); - return -EIO; - } + do { + if (n >= 10) { + printk(KERN_ERR + "i8042.c: Unable to get stable CTR read.\n"); + return -EIO; + } - i8042_initial_ctr = i8042_ctr; + if (n != 0) + udelay(50); + + if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { + printk(KERN_ERR + "i8042.c: Can't read CTR while initializing i8042.\n"); + return -EIO; + } + + } while (n < 2 || ctr[0] != ctr[1]); + + i8042_initial_ctr = i8042_ctr = ctr[0]; /* * Disable the keyboard interface and interrupt. @@ -895,6 +910,12 @@ static int i8042_controller_init(void) return -EIO; } +/* + * Flush whatever accumulated while we were disabling keyboard port. + */ + + i8042_flush(); + return 0; } @@ -914,7 +935,7 @@ static void i8042_controller_reset(void) i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); - if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); /* From 0baa3de6eb677e5c9b4c38642c6619df2b4ef11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Mon, 2 Nov 2009 21:57:41 -0800 Subject: [PATCH 3/4] Input: winbond-cir - select LEDS_TRIGGERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/input/misc/winbond-cir.c depends on LEDS_TRIGGERS so add an appropriate select to drivers/input/misc/Kconfig Signed-off-by: David Härdeman Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 02f4f8f1db6f..a9bb2544b2de 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -227,6 +227,7 @@ config INPUT_WINBOND_CIR depends on X86 && PNP select NEW_LEDS select LEDS_CLASS + select LEDS_TRIGGERS select BITREVERSE help Say Y here if you want to use the IR remote functionality found From 558a5e296a02266ef43d6e933ee35df9976de987 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Mon, 2 Nov 2009 22:04:18 -0800 Subject: [PATCH 4/4] Input: gpio-keys - use IRQF_SHARED There is nothing that disallows gpio-keys to share it's IRQ line w/ other drivers. Make it use IRQF_SHARED in request_irq(). An example of other driver with which I'd like to share IRQ line for GPIO buttons is ledtrig-gpio. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a88aff3816a0..77d130914259 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -147,6 +147,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) } error = request_irq(irq, gpio_keys_isr, + IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, button->desc ? button->desc : "gpio_keys", bdata);