diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:52:01 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:52:01 -0800 |
commit | fa395aaec823b9d1a5800913a6b5d0e6d1c5ced2 (patch) | |
tree | d599abe9f4f48f1737da50fa9a48dadfd08100e3 | |
parent | 3e7468313758913c5e4d372f35b271b96bad1298 (diff) | |
parent | 1f26978afd123deb22dd3c7dc75771a02f6e03f6 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (51 commits)
Input: appletouch - give up maintainership
Input: dm355evm_kbd - switch to using sparse keymap library
Input: wistron_btns - switch to using sparse keymap library
Input: add generic support for sparse keymaps
Input: fix memory leak in force feedback core
Input: wistron - remove identification strings from DMI table
Input: psmouse - remove identification strings from DMI tables
Input: atkbd - remove identification strings from DMI table
Input: i8042 - remove identification strings from DMI tables
DMI: allow omitting ident strings in DMI tables
Input: psmouse - do not carry DMI data around
Input: matrix-keypad - switch to using dev_pm_ops
Input: keyboard - fix lack of locking when traversing handler->h_list
Input: gpio_keys - scan gpio state at probe and resume time
Input: keyboard - add locking around event handling
Input: usbtouchscreen - add support for ET&T TC5UH touchscreen controller
Input: xpad - add two new Xbox 360 devices
Input: polled device - do not start polling if interval is zero
Input: polled device - schedule first poll immediately
Input: add S3C24XX touchscreen driver
...
63 files changed, 3110 insertions, 1167 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 94a20fe8fed..f9a6e2c75f1 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -293,10 +293,23 @@ X!Idrivers/video/console/fonts.c <chapter id="input_subsystem"> <title>Input Subsystem</title> + <sect1><title>Input core</title> !Iinclude/linux/input.h !Edrivers/input/input.c !Edrivers/input/ff-core.c !Edrivers/input/ff-memless.c + </sect1> + <sect1><title>Polled input devices</title> +!Iinclude/linux/input-polldev.h +!Edrivers/input/input-polldev.c + </sect1> + <sect1><title>Matrix keyboars/keypads</title> +!Iinclude/linux/input/matrix_keypad.h + </sect1> + <sect1><title>Sparse keymap support</title> +!Iinclude/linux/input/sparse-keymap.h +!Edrivers/input/sparse-keymap.c + </sect1> </chapter> <chapter id="spi"> diff --git a/MAINTAINERS b/MAINTAINERS index f7b0ced8111..107a5a5a017 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -486,13 +486,6 @@ S: Maintained F: drivers/net/appletalk/ F: net/appletalk/ -APPLETOUCH TOUCHPAD DRIVER -M: Johannes Berg <johannes@sipsolutions.net> -L: linux-input@vger.kernel.org -S: Maintained -F: Documentation/input/appletouch.txt -F: drivers/input/mouse/appletouch.c - ARC FRAMEBUFFER DRIVER M: Jaya Kumar <jayalk@intworks.biz> S: Maintained diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index a57af3e99c7..809114d5a5a 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -866,6 +866,57 @@ static void __init at91_add_device_rtc(void) {} /* -------------------------------------------------------------------- + * Touchscreen + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE) +static u64 tsadcc_dmamask = DMA_BIT_MASK(32); +static struct at91_tsadcc_data tsadcc_data; + +static struct resource tsadcc_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TSC, + .end = AT91SAM9G45_BASE_TSC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_TSC, + .end = AT91SAM9G45_ID_TSC, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device at91sam9g45_tsadcc_device = { + .name = "atmel_tsadcc", + .id = -1, + .dev = { + .dma_mask = &tsadcc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &tsadcc_data, + }, + .resource = tsadcc_resources, + .num_resources = ARRAY_SIZE(tsadcc_resources), +}; + +void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) +{ + if (!data) + return; + + at91_set_gpio_input(AT91_PIN_PD20, 0); /* AD0_XR */ + at91_set_gpio_input(AT91_PIN_PD21, 0); /* AD1_XL */ + at91_set_gpio_input(AT91_PIN_PD22, 0); /* AD2_YT */ + at91_set_gpio_input(AT91_PIN_PD23, 0); /* AD3_TB */ + + tsadcc_data = *data; + platform_device_register(&at91sam9g45_tsadcc_device); +} +#else +void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- * RTT * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index d345f5453db..53aaa94df75 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -622,6 +622,7 @@ static void __init at91_add_device_tc(void) { } #if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE) static u64 tsadcc_dmamask = DMA_BIT_MASK(32); +static struct at91_tsadcc_data tsadcc_data; static struct resource tsadcc_resources[] = { [0] = { @@ -642,22 +643,27 @@ static struct platform_device at91sam9rl_tsadcc_device = { .dev = { .dma_mask = &tsadcc_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &tsadcc_data, }, .resource = tsadcc_resources, .num_resources = ARRAY_SIZE(tsadcc_resources), }; -void __init at91_add_device_tsadcc(void) +void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) { + if (!data) + return; + at91_set_A_periph(AT91_PIN_PA17, 0); /* AD0_XR */ at91_set_A_periph(AT91_PIN_PA18, 0); /* AD1_XL */ at91_set_A_periph(AT91_PIN_PA19, 0); /* AD2_YT */ at91_set_A_periph(AT91_PIN_PA20, 0); /* AD3_TB */ + tsadcc_data = *data; platform_device_register(&at91sam9rl_tsadcc_device); } #else -void __init at91_add_device_tsadcc(void) {} +void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {} #endif diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 1cf4d868107..98f9f4bc939 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -229,6 +229,16 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data; /* + * Touchscreen + */ +static struct at91_tsadcc_data ek_tsadcc_data = { + .adc_clock = 300000, + .pendet_debounce = 0x0d, + .ts_sample_hold_time = 0x0a, +}; + + +/* * GPIO Buttons */ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) @@ -379,6 +389,8 @@ static void __init ek_board_init(void) at91_add_device_i2c(0, NULL, 0); /* LCD Controller */ at91_add_device_lcdc(&ek_lcdc_data); + /* Touch Screen */ + at91_add_device_tsadcc(&ek_tsadcc_data); /* Push Buttons */ ek_add_device_buttons(); /* AC97 */ diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index bd28e989e54..7ac20f3a206 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -243,6 +243,16 @@ static struct gpio_led ek_leds[] = { /* + * Touchscreen + */ +static struct at91_tsadcc_data ek_tsadcc_data = { + .adc_clock = 1000000, + .pendet_debounce = 0x0f, + .ts_sample_hold_time = 0x03, +}; + + +/* * GPIO Buttons */ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) @@ -310,7 +320,7 @@ static void __init ek_board_init(void) /* AC97 */ at91_add_device_ac97(&ek_ac97_data); /* Touch Screen Controller */ - at91_add_device_tsadcc(); + at91_add_device_tsadcc(&ek_tsadcc_data); /* LEDs */ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); /* Push Buttons */ diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 2295d80dd89..bb6f6a7ba5e 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -187,7 +187,12 @@ extern void __init at91_add_device_ac97(struct ac97c_platform_data *data); extern void __init at91_add_device_isi(void); /* Touchscreen Controller */ -extern void __init at91_add_device_tsadcc(void); +struct at91_tsadcc_data { + unsigned int adc_clock; + u8 pendet_debounce; + u8 ts_sample_hold_time; +}; +extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data); /* CAN */ struct at91_can_data { diff --git a/arch/arm/mach-davinci/include/mach/keyscan.h b/arch/arm/mach-davinci/include/mach/keyscan.h new file mode 100644 index 00000000000..b4e21a2976d --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/keyscan.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 Texas Instruments, Inc + * + * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DAVINCI_KEYSCAN_H +#define DAVINCI_KEYSCAN_H + +#include <linux/io.h> + +enum davinci_matrix_types { + DAVINCI_KEYSCAN_MATRIX_4X4, + DAVINCI_KEYSCAN_MATRIX_5X3, +}; + +struct davinci_ks_platform_data { + unsigned short *keymap; + u32 keymapsize; + u8 rep:1; + u8 strobe; + u8 interval; + u8 matrix_type; +}; + +#endif + diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 950837cf9e9..5619007e7e0 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -46,8 +46,6 @@ extern void ctrl_alt_del(void); -#define to_handle_h(n) container_of(n, struct input_handle, h_node) - /* * Exported functions/variables */ @@ -132,6 +130,7 @@ int shift_state = 0; */ static struct input_handler kbd_handler; +static DEFINE_SPINLOCK(kbd_event_lock); static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static int dead_key_next; @@ -190,78 +189,85 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier); * etc.). So this means that scancodes for the extra function keys won't * be valid for the first event device, but will be for the second. */ + +struct getset_keycode_data { + unsigned int scancode; + unsigned int keycode; + int error; +}; + +static int getkeycode_helper(struct input_handle *handle, void *data) +{ + struct getset_keycode_data *d = data; + + d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); + + return d->error == 0; /* stop as soon as we successfully get one */ +} + int getkeycode(unsigned int scancode) { - struct input_handle *handle; - int keycode; - int error = -ENODEV; + struct getset_keycode_data d = { scancode, 0, -ENODEV }; - list_for_each_entry(handle, &kbd_handler.h_list, h_node) { - error = input_get_keycode(handle->dev, scancode, &keycode); - if (!error) - return keycode; - } + input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); - return error; + return d.error ?: d.keycode; +} + +static int setkeycode_helper(struct input_handle *handle, void *data) +{ + struct getset_keycode_data *d = data; + + d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); + + return d->error == 0; /* stop as soon as we successfully set one */ } int setkeycode(unsigned int scancode, unsigned int keycode) { - struct input_handle *handle; - int error = -ENODEV; + struct getset_keycode_data d = { scancode, keycode, -ENODEV }; - list_for_each_entry(handle, &kbd_handler.h_list, h_node) { - error = input_set_keycode(handle->dev, scancode, keycode); - if (!error) - break; - } + input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); - return error; + return d.error; } /* * Making beeps and bells. */ -static void kd_nosound(unsigned long ignored) + +static int kd_sound_helper(struct input_handle *handle, void *data) { - struct input_handle *handle; + unsigned int *hz = data; + struct input_dev *dev = handle->dev; - list_for_each_entry(handle, &kbd_handler.h_list, h_node) { - if (test_bit(EV_SND, handle->dev->evbit)) { - if (test_bit(SND_TONE, handle->dev->sndbit)) - input_inject_event(handle, EV_SND, SND_TONE, 0); - if (test_bit(SND_BELL, handle->dev->sndbit)) - input_inject_event(handle, EV_SND, SND_BELL, 0); - } + if (test_bit(EV_SND, dev->evbit)) { + if (test_bit(SND_TONE, dev->sndbit)) + input_inject_event(handle, EV_SND, SND_TONE, *hz); + if (test_bit(SND_BELL, handle->dev->sndbit)) + input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0); } + + return 0; +} + +static void kd_nosound(unsigned long ignored) +{ + static unsigned int zero; + + input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper); } static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0); void kd_mksound(unsigned int hz, unsigned int ticks) { - struct list_head *node; + del_timer_sync(&kd_mksound_timer); - del_timer(&kd_mksound_timer); + input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper); - if (hz) { - list_for_each_prev(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - if (test_bit(EV_SND, handle->dev->evbit)) { - if (test_bit(SND_TONE, handle->dev->sndbit)) { - input_inject_event(handle, EV_SND, SND_TONE, hz); - break; - } - if (test_bit(SND_BELL, handle->dev->sndbit)) { - input_inject_event(handle, EV_SND, SND_BELL, 1); - break; - } - } - } - if (ticks) - mod_timer(&kd_mksound_timer, jiffies + ticks); - } else - kd_nosound(0); + if (hz && ticks) + mod_timer(&kd_mksound_timer, jiffies + ticks); } EXPORT_SYMBOL(kd_mksound); @@ -269,27 +275,34 @@ EXPORT_SYMBOL(kd_mksound); * Setting the keyboard rate. */ -int kbd_rate(struct kbd_repeat *rep) +static int kbd_rate_helper(struct input_handle *handle, void *data) { - struct list_head *node; - unsigned int d = 0; - unsigned int p = 0; - - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - struct input_dev *dev = handle->dev; - - if (test_bit(EV_REP, dev->evbit)) { - if (rep->delay > 0) - input_inject_event(handle, EV_REP, REP_DELAY, rep->delay); - if (rep->period > 0) - input_inject_event(handle, EV_REP, REP_PERIOD, rep->period); - d = dev->rep[REP_DELAY]; - p = dev->rep[REP_PERIOD]; - } + struct input_dev *dev = handle->dev; + struct kbd_repeat *rep = data; + + if (test_bit(EV_REP, dev->evbit)) { + + if (rep[0].delay > 0) + input_inject_event(handle, + EV_REP, REP_DELAY, rep[0].delay); + if (rep[0].period > 0) + input_inject_event(handle, + EV_REP, REP_PERIOD, rep[0].period); + + rep[1].delay = dev->rep[REP_DELAY]; + rep[1].period = dev->rep[REP_PERIOD]; } - rep->delay = d; - rep->period = p; + + return 0; +} + +int kbd_rate(struct kbd_repeat *rep) +{ + struct kbd_repeat data[2] = { *rep }; + + input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper); + *rep = data[1]; /* Copy currently used settings */ + return 0; } @@ -997,36 +1010,36 @@ static inline unsigned char getleds(void) return leds; } +static int kbd_update_leds_helper(struct input_handle *handle, void *data) +{ + unsigned char leds = *(unsigned char *)data; + + if (test_bit(EV_LED, handle->dev->evbit)) { + input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); + input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_inject_event(handle, EV_SYN, SYN_REPORT, 0); + } + + return 0; +} + /* - * This routine is the bottom half of the keyboard interrupt - * routine, and runs with all interrupts enabled. It does - * console changing, led setting and copy_to_cooked, which can - * take a reasonably long time. - * - * Aside from timing (which isn't really that important for - * keyboard interrupts as they happen often), using the software - * interrupt routines for this thing allows us to easily mask - * this when we don't want any of the above to happen. - * This allows for easy and efficient race-condition prevention - * for kbd_start => input_inject_event(dev, EV_LED, ...) => ... + * This is the tasklet that updates LED state on all keyboards + * attached to the box. The reason we use tasklet is that we + * need to handle the scenario when keyboard handler is not + * registered yet but we already getting updates form VT to + * update led state. */ - static void kbd_bh(unsigned long dummy) { - struct list_head *node; unsigned char leds = getleds(); if (leds != ledstate) { - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); - input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_inject_event(handle, EV_SYN, SYN_REPORT, 0); - } + input_handler_for_each_handle(&kbd_handler, &leds, + kbd_update_leds_helper); + ledstate = leds; } - - ledstate = leds; } DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); @@ -1136,7 +1149,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u static void kbd_rawcode(unsigned char data) { struct vc_data *vc = vc_cons[fg_console].d; - kbd = kbd_table + fg_console; + kbd = kbd_table + vc->vc_num; if (kbd->kbdmode == VC_RAW) put_queue(vc, data); } @@ -1157,7 +1170,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) tty->driver_data = vc; } - kbd = kbd_table + fg_console; + kbd = kbd_table + vc->vc_num; if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTAL |