diff options
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 101 | ||||
-rw-r--r-- | drivers/input/keyboard/corgikbd.c | 6 | ||||
-rw-r--r-- | drivers/input/keyboard/spitzkbd.c | 27 |
5 files changed, 85 insertions, 60 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4a917748fd9f..3b0ac3b43c54 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -143,16 +143,6 @@ config KEYBOARD_SPITZ To compile this driver as a module, choose M here: the module will be called spitzkbd. -config KEYBOARD_MAPLE - tristate "Maple bus keyboard" - depends on SH_DREAMCAST && MAPLE - help - Say Y here if you have a DreamCast console running Linux and have - a keyboard attached to its Maple bus. - - To compile this driver as a module, choose M here: the - module will be called maple_keyb. - config KEYBOARD_AMIGA tristate "Amiga keyboard" depends on AMIGA diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 9ce0b87f2fac..6e0afbb22383 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -5,7 +5,6 @@ # Each configuration option enables a list of files. obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o -obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 820c7fd9a604..ffacf6eca5f5 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -166,6 +166,9 @@ static unsigned char atkbd_unxlate_table[128] = { #define ATKBD_SPECIAL 248 +#define ATKBD_LED_EVENT_BIT 0 +#define ATKBD_REP_EVENT_BIT 1 + static struct { unsigned char keycode; unsigned char set2; @@ -211,6 +214,10 @@ struct atkbd { unsigned char err_xl; unsigned int last; unsigned long time; + + struct work_struct event_work; + struct semaphore event_sem; + unsigned long event_mask; }; static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, @@ -314,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, switch (code) { case ATKBD_RET_BAT: atkbd->enabled = 0; - serio_rescan(atkbd->ps2dev.serio); + serio_reconnect(atkbd->ps2dev.serio); goto out; case ATKBD_RET_EMUL0: atkbd->emul = 1; @@ -424,58 +431,86 @@ out: } /* - * Event callback from the input module. Events that change the state of - * the hardware are processed here. + * atkbd_event_work() is used to complete processing of events that + * can not be processed by input_event() which is often called from + * interrupt context. */ -static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +static void atkbd_event_work(void *data) { - struct atkbd *atkbd = dev->private; const short period[32] = { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125, 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 }; const short delay[4] = { 250, 500, 750, 1000 }; + + struct atkbd *atkbd = data; + struct input_dev *dev = atkbd->dev; unsigned char param[2]; int i, j; + down(&atkbd->event_sem); + + if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) { + param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) + | (test_bit(LED_NUML, dev->led) ? 2 : 0) + | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS); + + if (atkbd->extra) { + param[0] = 0; + param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) + | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) + | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) + | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) + | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS); + } + } + + if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) { + i = j = 0; + while (i < 31 && period[i] < dev->rep[REP_PERIOD]) + i++; + while (j < 3 && delay[j] < dev->rep[REP_DELAY]) + j++; + dev->rep[REP_PERIOD] = period[i]; + dev->rep[REP_DELAY] = delay[j]; + param[0] = i | (j << 5); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); + } + + up(&atkbd->event_sem); +} + +/* + * Event callback from the input module. Events that change the state of + * the hardware are processed here. If action can not be performed in + * interrupt context it is offloaded to atkbd_event_work. + */ + +static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + struct atkbd *atkbd = dev->private; + if (!atkbd->write) return -1; switch (type) { case EV_LED: - - param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) - | (test_bit(LED_NUML, dev->led) ? 2 : 0) - | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); - ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS); - - if (atkbd->extra) { - param[0] = 0; - param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) - | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) - | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) - | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) - | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); - ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS); - } - + set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask); + wmb(); + schedule_work(&atkbd->event_work); return 0; case EV_REP: - if (atkbd->softrepeat) return 0; - - i = j = 0; - while (i < 31 && period[i] < dev->rep[REP_PERIOD]) - i++; - while (j < 3 && delay[j] < dev->rep[REP_DELAY]) - j++; - dev->rep[REP_PERIOD] = period[i]; - dev->rep[REP_DELAY] = delay[j]; - param[0] = i | (j << 5); - ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); + if (!atkbd->softrepeat) { + set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask); + wmb(); + schedule_work(&atkbd->event_work); + } return 0; } @@ -810,6 +845,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); + INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); + init_MUTEX(&atkbd->event_sem); switch (serio->id.type) { diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 64672d491222..e301ee4ca264 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -19,7 +19,6 @@ #include <linux/jiffies.h> #include <linux/module.h> #include <linux/slab.h> -#include <asm/irq.h> #include <asm/arch/corgi.h> #include <asm/arch/hardware.h> @@ -343,10 +342,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - SA_INTERRUPT, "corgikbd", corgikbd)) + SA_INTERRUPT | SA_TRIGGER_RISING, + "corgikbd", corgikbd)) printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); - else - set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING); } /* Set Strobe lines as outputs - set high */ diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 6a15fe3bc527..83999d583122 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -19,7 +19,6 @@ #include <linux/jiffies.h> #include <linux/module.h> #include <linux/slab.h> -#include <asm/irq.h> #include <asm/arch/spitz.h> #include <asm/arch/hardware.h> @@ -407,10 +406,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { pxa_gpio_mode(spitz_senses[i] | GPIO_IN); if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, - SA_INTERRUPT, "Spitzkbd Sense", spitzkbd)) + SA_INTERRUPT|SA_TRIGGER_RISING, + "Spitzkbd Sense", spitzkbd)) printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); - else - set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING); } /* Set Strobe lines as outputs - set high */ @@ -422,15 +420,18 @@ static int __init spitzkbd_probe(struct platform_device *dev) pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); - request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd); - - set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE); - set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE); - set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE); - set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE); + request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, + SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + "Spitzkbd Sync", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, + SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + "Spitzkbd PwrOn", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, + SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + "Spitzkbd SWA", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, + SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + "Spitzkbd SWB", spitzkbd); printk(KERN_INFO "input: Spitz Keyboard Registered\n"); |