Commit 93db6294 authored by Linus Torvalds's avatar Linus Torvalds

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: (35 commits)
  Input: add driver for Synaptics I2C touchpad
  Input: synaptics - add support for reporting x/y resolution
  Input: ALPS - handle touchpoints buttons correctly
  Input: gpio-keys - change timer to workqueue
  Input: ads7846 - pin change interrupt support
  Input: add support for touchscreen on W90P910 ARM platform
  Input: appletouch - improve finger detection
  Input: wacom - clear Intuos4 wheel data when finger leaves proximity
  Input: ucb1400 - move static function from header into core
  Input: add driver for EETI touchpanels
  Input: ads7846 - more detailed model name in sysfs
  Input: ads7846 - support swapping x and y axes
  Input: ati_remote2 - use non-atomic bitops
  Input: introduce lm8323 keypad driver
  Input: psmouse - ESD workaround fix for OLPC XO touchpad
  Input: tsc2007 - make sure platform provides get_pendown_state()
  Input: uinput - flush all pending ff effects before destroying device
  Input: simplify name handling for certain input handles
  Input: serio - do not use deprecated dev.power.power_state
  Input: wacom - add support for Intuos4 tablets
  ...
parents 43813f39 eef3e4ca
...@@ -278,7 +278,7 @@ struct input_event { ...@@ -278,7 +278,7 @@ struct input_event {
}; };
'time' is the timestamp, it returns the time at which the event happened. 'time' is the timestamp, it returns the time at which the event happened.
Type is for example EV_REL for relative moment, REL_KEY for a keypress or Type is for example EV_REL for relative moment, EV_KEY for a keypress or
release. More types are defined in include/linux/input.h. release. More types are defined in include/linux/input.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete 'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
......
...@@ -67,7 +67,12 @@ data with it. ...@@ -67,7 +67,12 @@ data with it.
struct rotary_encoder_platform_data is declared in struct rotary_encoder_platform_data is declared in
include/linux/rotary-encoder.h and needs to be filled with the number of include/linux/rotary-encoder.h and needs to be filled with the number of
steps the encoder has and can carry information about externally inverted steps the encoder has and can carry information about externally inverted
signals (because of used invertig buffer or other reasons). signals (because of an inverting buffer or other reasons). The encoder
can be set up to deliver input information as either an absolute or relative
axes. For relative axes the input event returns +/-1 for each step. For
absolute axes the position of the encoder can either roll over between zero
and the number of steps or will clamp at the maximum and zero depending on
the configuration.
Because GPIO to IRQ mapping is platform specific, this information must Because GPIO to IRQ mapping is platform specific, this information must
be given in seperately to the driver. See the example below. be given in seperately to the driver. See the example below.
...@@ -85,6 +90,8 @@ be given in seperately to the driver. See the example below. ...@@ -85,6 +90,8 @@ be given in seperately to the driver. See the example below.
static struct rotary_encoder_platform_data my_rotary_encoder_info = { static struct rotary_encoder_platform_data my_rotary_encoder_info = {
.steps = 24, .steps = 24,
.axis = ABS_X, .axis = ABS_X,
.relative_axis = false,
.rollover = false,
.gpio_a = GPIO_ROTARY_A, .gpio_a = GPIO_ROTARY_A,
.gpio_b = GPIO_ROTARY_B, .gpio_b = GPIO_ROTARY_B,
.inverted_a = 0, .inverted_a = 0,
......
/*
* arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
*/
#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
#define __ASM_ARCH_EP93XX_KEYPAD_H
#define MAX_MATRIX_KEY_ROWS (8)
#define MAX_MATRIX_KEY_COLS (8)
/* flags for the ep93xx_keypad driver */
#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */
#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */
#define EP93XX_KEYPAD_BACK_DRIVE (1<<2) /* back driving mode */
#define EP93XX_KEYPAD_TEST_MODE (1<<3) /* scan only column 0 */
#define EP93XX_KEYPAD_KDIV (1<<4) /* 1/4 clock or 1/16 clock */
#define EP93XX_KEYPAD_AUTOREPEAT (1<<5) /* enable key autorepeat */
/**
* struct ep93xx_keypad_platform_data - platform specific device structure
* @matrix_key_rows: number of rows in the keypad matrix
* @matrix_key_cols: number of columns in the keypad matrix
* @matrix_key_map: array of keycodes defining the keypad matrix
* @matrix_key_map_size: ARRAY_SIZE(matrix_key_map)
* @debounce: debounce start count; terminal count is 0xff
* @prescale: row/column counter pre-scaler load value
* @flags: see above
*/
struct ep93xx_keypad_platform_data {
unsigned int matrix_key_rows;
unsigned int matrix_key_cols;
unsigned int *matrix_key_map;
int matrix_key_map_size;
unsigned int debounce;
unsigned int prescale;
unsigned int flags;
};
/* macro for creating the matrix_key_map table */
#define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val))
#endif /* __ASM_ARCH_EP93XX_KEYPAD_H */
...@@ -1123,8 +1123,6 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, ...@@ -1123,8 +1123,6 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
#define HW_RAW(dev) 0 #define HW_RAW(dev) 0
#warning "Cannot generate rawmode keyboard for your architecture yet."
static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
{ {
if (keycode > 127) if (keycode > 127)
......
...@@ -25,7 +25,6 @@ struct evdev { ...@@ -25,7 +25,6 @@ struct evdev {
int exist; int exist;
int open; int open;
int minor; int minor;
char name[16];
struct input_handle handle; struct input_handle handle;
wait_queue_head_t wait; wait_queue_head_t wait;
struct evdev_client *grab; struct evdev_client *grab;
...@@ -609,7 +608,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -609,7 +608,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
p, compat_mode); p, compat_mode);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
return str_to_user(dev->name, _IOC_SIZE(cmd), p); return str_to_user(dev_name(&evdev->dev),
_IOC_SIZE(cmd), p);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
return str_to_user(dev->phys, _IOC_SIZE(cmd), p); return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
...@@ -626,8 +626,11 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -626,8 +626,11 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
abs.maximum = dev->absmax[t]; abs.maximum = dev->absmax[t];
abs.fuzz = dev->absfuzz[t]; abs.fuzz = dev->absfuzz[t];
abs.flat = dev->absflat[t]; abs.flat = dev->absflat[t];
abs.resolution = dev->absres[t];
if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) if (copy_to_user(p, &abs, min_t(size_t,
_IOC_SIZE(cmd),
sizeof(struct input_absinfo))))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -654,8 +657,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -654,8 +657,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
t = _IOC_NR(cmd) & ABS_MAX; t = _IOC_NR(cmd) & ABS_MAX;
if (copy_from_user(&abs, p, if (copy_from_user(&abs, p, min_t(size_t,
sizeof(struct input_absinfo))) _IOC_SIZE(cmd),
sizeof(struct input_absinfo))))
return -EFAULT; return -EFAULT;
/* /*
...@@ -670,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -670,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
dev->absmax[t] = abs.maximum; dev->absmax[t] = abs.maximum;
dev->absfuzz[t] = abs.fuzz; dev->absfuzz[t] = abs.fuzz;
dev->absflat[t] = abs.flat; dev->absflat[t] = abs.flat;
dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
0 : abs.resolution;
spin_unlock_irq(&dev->event_lock); spin_unlock_irq(&dev->event_lock);
...@@ -807,16 +813,15 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -807,16 +813,15 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
mutex_init(&evdev->mutex); mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait); init_waitqueue_head(&evdev->wait);
snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); dev_set_name(&evdev->dev, "event%d", minor);
evdev->exist = 1; evdev->exist = 1;
evdev->minor = minor; evdev->minor = minor;
evdev->handle.dev = input_get_device(dev); evdev->handle.dev = input_get_device(dev);
evdev->handle.name = evdev->name; evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler; evdev->handle.handler = handler;
evdev->handle.private = evdev; evdev->handle.private = evdev;
dev_set_name(&evdev->dev, evdev->name);
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.class = &input_class; evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev; evdev->dev.parent = &dev->dev;
......
...@@ -167,5 +167,6 @@ module_exit(fm801_gp_exit); ...@@ -167,5 +167,6 @@ module_exit(fm801_gp_exit);
MODULE_DEVICE_TABLE(pci, fm801_gp_id_table); MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
MODULE_DESCRIPTION("FM801 gameport driver");
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -30,16 +30,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -30,16 +30,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Generic gameport layer"); MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(__gameport_register_port);
EXPORT_SYMBOL(gameport_unregister_port);
EXPORT_SYMBOL(__gameport_register_driver);
EXPORT_SYMBOL(gameport_unregister_driver);
EXPORT_SYMBOL(gameport_open);
EXPORT_SYMBOL(gameport_close);
EXPORT_SYMBOL(gameport_set_phys);
EXPORT_SYMBOL(gameport_start_polling);
EXPORT_SYMBOL(gameport_stop_polling);
/* /*
* gameport_mutex protects entire gameport subsystem and is taken * gameport_mutex protects entire gameport subsystem and is taken
* every time gameport port or driver registrered or unregistered. * every time gameport port or driver registrered or unregistered.
...@@ -162,6 +152,7 @@ void gameport_start_polling(struct gameport *gameport) ...@@ -162,6 +152,7 @@ void gameport_start_polling(struct gameport *gameport)
spin_unlock(&gameport->timer_lock); spin_unlock(&gameport->timer_lock);
} }
EXPORT_SYMBOL(gameport_start_polling);
void gameport_stop_polling(struct gameport *gameport) void gameport_stop_polling(struct gameport *gameport)
{ {
...@@ -172,6 +163,7 @@ void gameport_stop_polling(struct gameport *gameport) ...@@ -172,6 +163,7 @@ void gameport_stop_polling(struct gameport *gameport)
spin_unlock(&gameport->timer_lock); spin_unlock(&gameport->timer_lock);
} }
EXPORT_SYMBOL(gameport_stop_polling);
static void gameport_run_poll_handler(unsigned long d) static void gameport_run_poll_handler(unsigned long d)
{ {
...@@ -516,6 +508,7 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) ...@@ -516,6 +508,7 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args); vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(gameport_set_phys);
/* /*
* Prepare gameport port for registration. * Prepare gameport port for registration.
...@@ -658,6 +651,7 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner) ...@@ -658,6 +651,7 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
gameport_init_port(gameport); gameport_init_port(gameport);
gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT); gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
} }
EXPORT_SYMBOL(__gameport_register_port);
/* /*
* Synchronously unregisters gameport port. * Synchronously unregisters gameport port.
...@@ -669,6 +663,7 @@ void gameport_unregister_port(struct gameport *gameport) ...@@ -669,6 +663,7 @@ void gameport_unregister_port(struct gameport *gameport)
gameport_destroy_port(gameport); gameport_destroy_port(gameport);
mutex_unlock(&gameport_mutex); mutex_unlock(&gameport_mutex);
} }
EXPORT_SYMBOL(gameport_unregister_port);
/* /*
...@@ -728,7 +723,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner ...@@ -728,7 +723,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
* Temporarily disable automatic binding because probing * Temporarily disable automatic binding because probing
* takes long time and we are better off doing it in kgameportd * takes long time and we are better off doing it in kgameportd
*/ */
drv->ignore = 1; drv->ignore = true;
error = driver_register(&drv->driver); error = driver_register(&drv->driver);
if (error) { if (error) {
...@@ -741,7 +736,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner ...@@ -741,7 +736,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
/* /*
* Reset ignore flag and let kgameportd bind the driver to free ports * Reset ignore flag and let kgameportd bind the driver to free ports
*/ */
drv->ignore = 0; drv->ignore = false;
error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
if (error) { if (error) {
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
...@@ -750,6 +745,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner ...@@ -750,6 +745,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
return 0; return 0;
} }
EXPORT_SYMBOL(__gameport_register_driver);
void gameport_unregister_driver(struct gameport_driver *drv) void gameport_unregister_driver(struct gameport_driver *drv)
{ {
...@@ -757,7 +753,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) ...@@ -757,7 +753,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
mutex_lock(&gameport_mutex); mutex_lock(&gameport_mutex);
drv->ignore = 1; /* so gameport_find_driver ignores it */ drv->ignore = true; /* so gameport_find_driver ignores it */
gameport_remove_pending_events(drv); gameport_remove_pending_events(drv);
start_over: start_over:
...@@ -774,6 +770,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) ...@@ -774,6 +770,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
mutex_unlock(&gameport_mutex); mutex_unlock(&gameport_mutex);
} }
EXPORT_SYMBOL(gameport_unregister_driver);
static int gameport_bus_match(struct device *dev, struct device_driver *drv) static int gameport_bus_match(struct device *dev, struct device_driver *drv)
{ {
...@@ -812,6 +809,7 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo ...@@ -812,6 +809,7 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo
gameport_set_drv(gameport, drv); gameport_set_drv(gameport, drv);
return 0; return 0;
} }
EXPORT_SYMBOL(gameport_open);
void gameport_close(struct gameport *gameport) void gameport_close(struct gameport *gameport)
{ {
...@@ -822,6 +820,7 @@ void gameport_close(struct gameport *gameport) ...@@ -822,6 +820,7 @@ void gameport_close(struct gameport *gameport)
if (gameport->close) if (gameport->close)
gameport->close(gameport); gameport->close(gameport);
} }
EXPORT_SYMBOL(gameport_close);
static int __init gameport_init(void) static int __init gameport_init(void)
{ {
......
...@@ -39,7 +39,6 @@ struct joydev { ...@@ -39,7 +39,6 @@ struct joydev {
int exist; int exist;
int open; int open;
int minor; int minor;
char name[16];
struct input_handle handle; struct input_handle handle;
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head client_list; struct list_head client_list;
...@@ -537,12 +536,14 @@ static int joydev_ioctl_common(struct joydev *joydev, ...@@ -537,12 +536,14 @@ static int joydev_ioctl_common(struct joydev *joydev,
default: default:
if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
int len; int len;
if (!dev->name) const char *name = dev_name(&dev->dev);
if (!name)
return 0; return 0;
len = strlen(dev->name) + 1; len = strlen(name) + 1;
if (len > _IOC_SIZE(cmd)) if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd); len = _IOC_SIZE(cmd);
if (copy_to_user(argp, dev->name, len)) if (copy_to_user(argp, name, len))
return -EFAULT; return -EFAULT;
return len; return len;
} }
...@@ -742,13 +743,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -742,13 +743,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
mutex_init(&joydev->mutex); mutex_init(&joydev->mutex);
init_waitqueue_head(&joydev->wait); init_waitqueue_head(&joydev->wait);
snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); dev_set_name(&joydev->dev, "js%d", minor);
joydev->exist = 1; joydev->exist = 1;
joydev->minor = minor; joydev->minor = minor;
joydev->exist = 1; joydev->exist = 1;
joydev->handle.dev = input_get_device(dev); joydev->handle.dev = input_get_device(dev);
joydev->handle.name = joydev->name; joydev->handle.name = dev_name(&joydev->dev);
joydev->handle.handler = handler; joydev->handle.handler = handler;
joydev->handle.private = joydev; joydev->handle.private = joydev;
...@@ -797,7 +798,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -797,7 +798,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
} }
} }
dev_set_name(&joydev->dev, joydev->name);
joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.class = &input_class; joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev; joydev->dev.parent = &dev->dev;
......
...@@ -250,6 +250,17 @@ config KEYBOARD_HP7XX ...@@ -250,6 +250,17 @@ config KEYBOARD_HP7XX
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called jornada720_kbd. module will be called jornada720_kbd.
config KEYBOARD_LM8323
tristate "LM8323 keypad chip"
depends on I2C
depends on LEDS_CLASS
help
If you say yes here you get support for the National Semiconductor
LM8323 keypad controller.
To compile this driver as a module, choose M here: the
module will be called lm8323.
config KEYBOARD_OMAP config KEYBOARD_OMAP
tristate "TI OMAP keypad support" tristate "TI OMAP keypad support"
depends on (ARCH_OMAP1 || ARCH_OMAP2) depends on (ARCH_OMAP1 || ARCH_OMAP2)
...@@ -332,4 +343,14 @@ config KEYBOARD_SH_KEYSC ...@@ -332,4 +343,14 @@ config KEYBOARD_SH_KEYSC
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called sh_keysc. module will be called sh_keysc.
config KEYBOARD_EP93XX
tristate "EP93xx Matrix Keypad support"
depends on ARCH_EP93XX
help
Say Y here to enable the matrix keypad on the Cirrus EP93XX.
To compile this driver as a module, choose M here: the
module will be called ep93xx_keypad.
endif endif
...@@ -18,6 +18,7 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
...@@ -28,3 +29,4 @@ obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o ...@@ -28,3 +29,4 @@ obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
This diff is collapsed.
...@@ -22,13 +22,14 @@ ...@@ -22,13 +22,14 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <asm/gpio.h> #include <asm/gpio.h>
struct gpio_button_data { struct gpio_button_data {
struct gpio_keys_button *button; struct gpio_keys_button *button;
struct input_dev *input; struct input_dev *input;
struct timer_list timer; struct delayed_work work;
}; };
struct gpio_keys_drvdata { struct gpio_keys_drvdata {
...@@ -36,8 +37,10 @@ struct gpio_keys_drvdata { ...@@ -36,8 +37,10 @@ struct gpio_keys_drvdata {
struct gpio_button_data data[0]; struct gpio_button_data data[0];
}; };
static void gpio_keys_report_event(struct gpio_button_data *bdata) static void gpio_keys_report_event(struct work_struct *work)
{ {
struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work.work);
struct gpio_keys_button *button = bdata->button; struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input; struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY; unsigned int type = button->type ?: EV_KEY;
...@@ -47,25 +50,17 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) ...@@ -47,25 +50,17 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata)
input_sync(input); input_sync(input);
} }
static void gpio_check_button(unsigned long _data)
{
struct gpio_button_data *data = (struct gpio_button_data *)_data;
gpio_keys_report_event(data);
}
static irqreturn_t gpio_keys_isr(int irq, void *dev_id) static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{ {
struct gpio_button_data *bdata = dev_id; struct gpio_button_data *bdata = dev_id;
struct gpio_keys_button *button = bdata->button; struct gpio_keys_button *button = bdata->button;
unsigned long delay;
BUG_ON(irq != gpio_to_irq(button->gpio)); BUG_ON(irq != gpio_to_irq(button->gpio));
if (button->debounce_interval) delay = button->debounce_interval ?
mod_timer(&bdata->timer, msecs_to_jiffies(button->debounce_interval) : 0;
jiffies + msecs_to_jiffies(button->debounce_interval)); schedule_delayed_work(&bdata->work, delay);
else
gpio_keys_report_event(bdata);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -112,8 +107,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -112,8 +107,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
bdata->input = input; bdata->input = input;
bdata->button = button; bdata->button = button;
setup_timer(&bdata->timer, INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event);
gpio_check_button, (unsigned long)bdata);
error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
if (error < 0) { if (error < 0) {
...@@ -142,8 +136,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -142,8 +136,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
} }
error = request_irq(irq, gpio_keys_isr, error = request_irq(irq, gpio_keys_isr,
IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys", button->desc ? button->desc : "gpio_keys",
bdata); bdata);
if (error) { if (error) {
...@@ -173,8 +166,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -173,8 +166,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail2: fail2:
while (--i >= 0) { while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
if (pdata->buttons[i].debounce_interval) cancel_delayed_work_sync(&ddata->data[i].work);
del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio); gpio_free(pdata->buttons[i].gpio);
} }
...@@ -198,8 +190,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) ...@@ -198,8 +190,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio); int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, &ddata->data[i]); free_irq(irq, &ddata->data[i]);
if (pdata->buttons[i].debounce_interval) cancel_delayed_work_sync(&ddata->data[i].work);
del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio); gpio_free(pdata->buttons[i].gpio);
} }
......
This diff is collapsed.
...@@ -193,6 +193,16 @@ config INPUT_CM109 ...@@ -193,6 +193,16 @@ config INPUT_CM109
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called cm109. called cm109.
config INPUT_TWL4030_PWRBUTTON
tristate "TWL4030 Power button Driver"
depends on TWL4030_CORE
help
Say Y here if you want to enable power key reporting via the
TWL4030 family of chips.
To compile this driver as a module, choose M here. The module will
be called twl4030_pwrbutton.
config INPUT_UINPUT config INPUT_UINPUT
tristate "User level driver support" tristate "User level driver support"
help help
...@@ -250,4 +260,13 @@ config INPUT_RB532_BUTTON ...@@ -250,4 +260,13 @@ config INPUT_RB532_BUTTON
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called rb532_button. module will be called rb532_button.
config INPUT_DM355EVM
tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
depends on MFD_DM355EVM_MSP
help
Supports the pushbuttons and IR remote used with
the DM355 EVM board.
To compile this driver as a module, choose M here: the
module will be called dm355evm_keys.
endif endif
...@@ -10,6 +10,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o ...@@ -10,6 +10,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_CM109) += cm109.o obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
...@@ -21,6 +22,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o ...@@ -21,6 +22,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o
...@@ -509,7 +509,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc ...@@ -509,7 +509,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc
old_keycode = ar2->keycode[mode][index]; old_keycode = ar2->keycode[mode][index];
ar2->keycode[mode][index] = keycode; ar2->keycode[mode][index] = keycode;
set_bit(keycode, idev->keybit); __set_bit(keycode, idev->keybit);
for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
...@@ -518,7 +518,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc ...@@ -518,7 +518,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc
} }
} }
clear_bit(old_keycode, idev->keybit); __clear_bit(old_keycode, idev->keybit);
return 0; return 0;
} }
...@@ -543,7 +543,7 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) ...@@ -543,7 +543,7 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode;
set_bit(ar2->keycode[mode][index], idev->keybit); __set_bit(ar2->keycode[mode][index], idev->keybit);
} }
} }
...@@ -554,11 +554,11 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) ...@@ -554,11 +554,11 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3;
ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4;
ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC;
set_bit(KEY_PROG1, idev->keybit); __set_bit(KEY_PROG1, idev->keybit);
set_bit(KEY_PROG2, idev->keybit); __set_bit(KEY_PROG2, idev->keybit);
set_bit(KEY_PROG3, idev->keybit); __set_bit(KEY_PROG3, idev->keybit);
set_bit(KEY_PROG4, idev->keybit); __set_bit(KEY_PROG4, idev->keybit);
set_bit(KEY_PC, idev->keybit); __set_bit(KEY_PC, idev->keybit);
idev->rep[REP_DELAY] = 250; idev->rep[REP_DELAY] = 250;
idev->rep[REP_PERIOD] = 33; idev->rep[REP_PERIOD] = 33;
......
/*
* dm355evm_keys.c - support buttons and IR remote on DM355 EVM board
*
* Copyright (c) 2008 by David Brownell
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c/dm355evm_msp.h>
/*
* The MSP430 firmware on the DM355 EVM monitors on-board pushbuttons
* and an IR receptor used for the remote control. When any key is
* pressed, or its autorepeat kicks in, an event is sent. This driver
* read those events from the small (32 event) queue and reports them.
*
* Because we communicate with the MSP430 using I2C, and all I2C calls
* in Linux sleep, we need to cons up a kind of threaded IRQ handler
* using a work_struct. The IRQ is active low, but we use it through
* the GPIO controller so we can trigger on falling edges.
*
* Note that physically there can only be one of these devices.
*
* This driver was tested with firmware revision A4.
*/
struct dm355evm_keys {
struct work_struct work;
struct input_dev *input;
struct device *dev;
int irq;
};
static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
{
struct dm355evm_keys *keys = _keys;
schedule_work(&keys->work);
return IRQ_HANDLED;
}
/* These initial keycodes can be remapped by dm355evm_setkeycode(). */
static struct {
u16 event;
u16 keycode;
} dm355evm_keys[] = {
/*
* Pushbuttons on the EVM board ... note that the labels for these
* are SW10/SW11/etc on the PC board. The left/right orientation
* comes only from the firmware's documentation, and presumes the
* power connector is immediately in front of you and the IR sensor
* is to the right. (That is, rotate the board counter-clockwise
* by 90 degrees from the SW10/etc and "DM355 EVM" labels.)
*/
{ 0x00d8, KEY_OK, }, /* SW12 */
{ 0x00b8, KEY_UP, }, /* SW13 */
{ 0x00e8, KEY_DOWN, }, /* SW11 */
{ 0x0078, KEY_LEFT, }, /* SW14 */
{ 0x00f0, KEY_RIGHT, }, /* SW10 */
/*
* IR buttons ... codes assigned to match the universal remote
* provided with the EVM (Philips PM4S) using DVD code 0020.
*
* These event codes match firmware documentation, but other
* remote controls could easily send more RC5-encoded events.
* The PM4S manual was used in several cases to help select
* a keycode reflecting the intended usage.
*
* RC5 codes are 14 bits, with two start bits (0x3 prefix)
* and a toggle bit (masked out below).
*/
{ 0x300c, KEY_POWER, }, /* NOTE: docs omit this */
{ 0x3000, KEY_NUMERIC_0, },
{ 0x3001, KEY_NUMERIC_1, },
{ 0x3002, KEY_NUMERIC_2, },
{ 0x3003, KEY_NUMERIC_3, },
{ 0x3004, KEY_NUMERIC_4, },
{ 0x3005, KEY_NUMERIC_5, },
{ 0x3006, KEY_NUMERIC_6, },
{ 0x3007, KEY_NUMERIC_7, },
{ 0x3008, KEY_NUMERIC_8, },
{ 0x3009, KEY_NUMERIC_9, },
{ 0x3022, KEY_ENTER, },
{ 0x30ec, KEY_MODE, }, /* "tv/vcr/..." */
{ 0x300f, KEY_SELECT, }, /* "info" */
{ 0x3020, KEY_CHANNELUP, }, /* "up" */
{ 0x302e, KEY_MENU, }, /* "in/out" */
{ 0x3011, KEY_VOLUMEDOWN, }, /* "left" */
{ 0x300d, KEY_MUTE, }, /* "ok" */
{ 0x3010, KEY_VOLUMEUP, }, /* "right" */
{ 0x301e, KEY_SUBTITLE, }, /* "cc" */
{ 0x3021, KEY_CHANNELDOWN, }, /* "down" */
{ 0x3022, KEY_PREVIOUS, },
{ 0x3026, KEY_SLEEP, },
{ 0x3172, KEY_REWIND, }, /* NOTE: docs wrongly say 0x30ca */
{ 0x3175, KEY_PLAY, },
{ 0x3174, KEY_FASTFORWARD, },
{ 0x3177, KEY_RECORD, },
{ 0x3176, KEY_STOP, },
{ 0x3169, KEY_PAUSE, },
};
static void dm355evm_keys_work(struct work_struct *work)
{
struct dm355evm_keys *keys;
int status;
keys = container_of(work, struct dm355evm_keys, work);
/* For simplicity we ignore INPUT_COUNT and just read
* events until we get the "queue empty" indicator.
* Reading INPUT_LOW decrements the count.
*/
for (;;) {
static u16 last_event;
u16 event;
int keycode;
int i;
status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
if (status < 0) {
dev_dbg(keys->dev, "input high err %d\n",
status);
break;
}
event = status << 8;
status = dm355evm_msp_read(DM355EVM_MSP_INPUT_LOW);
if (status < 0) {
dev_dbg(keys->dev, "input low err %d\n",
status);
break;
}
event |= status;
if (event == 0xdead)
break;
/* Press and release a button: two events, same code.
* Press and hold (autorepeat), then release: N events
* (N > 2), same code. For RC5 buttons the toggle bits
* distinguish (for example) "1-autorepeat" from "1 1";
* but PCB buttons don't support that bit.
*
* So we must synthesize release events. We do that by
* mapping events to a press/release event pair; then
* to avoid adding extra events, skip the second event
* of each pair.
*/
if (event == last_event) {
last_event = 0;
continue;
}
last_event = event;
/* ignore the RC5 toggle bit */
event &= ~0x0800;
/* find the key, or leave it as unknown */
keycode = KEY_UNKNOWN;
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
if (dm355evm_keys[i].event != event)
continue;
keycode = dm355evm_keys[i].keycode;
break;
}
dev_dbg(keys->dev,
"input event 0x%04x--> keycode %d\n",
event, keycode);
/* report press + release */
input_report_key(keys->input, keycode, 1);
input_sync(keys->input);
input_report_key(keys->input, keycode, 0);
input_sync(keys->input);
}
}
static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
{
u16 old_keycode;
unsigned i;
if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
return -EINVAL;
old_keycode = dm355evm_keys[index].keycode;
dm355evm_keys[index].keycode = keycode;
set_bit(keycode, dev->keybit);
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
if (dm355evm_keys[index].keycode == old_keycode)
goto done;
}
clear_bit(old_keycode, dev->keybit);
done:
return 0;
}
static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
{
if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
return -EINVAL;
return dm355evm_keys[index].keycode;
}
/*----------------------------------------------------------------------*/
static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
{
struct dm355evm_keys *keys;
struct input_dev *input;
int status;
int i;
/* allocate instance struct and input dev */
keys = kzalloc(sizeof *keys, GFP_KERNEL);
input = input_allocate_device();
if (!keys || !input) {
status = -ENOMEM;
goto fail1;
}
keys->dev = &pdev->dev;
keys->input = input;
INIT_WORK(&keys->work, dm355evm_keys_work);
/* set up "threaded IRQ handler" */
status = platform_get_irq(pdev, 0);
if (status < 0)
goto fail1;
keys->irq = status;
input_set_drvdata(input, keys);
input->name = "DM355 EVM Controls";
input->phys = "dm355evm/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_I2C;
input->id.product = 0x0355;
input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
input->evbit[0] = BIT(EV_KEY);
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
__set_bit(dm355evm_keys[i].keycode, input->keybit);
input->setkeycode = dm355evm_setkeycode;
input->getkeycode = dm355evm_getkeycode;
/* REVISIT: flush the event queue? */
status = request_irq(keys->irq, dm355evm_keys_irq,
IRQF_TRIGGER_FALLING,
dev_name(&pdev->dev), keys);
if (status < 0)
goto fail1;
/* register */
status = input_register_device(input);
if (status < 0)
goto fail2;
platform_set_drvdata(pdev, keys);
return 0;
fail2:
free_irq(keys->irq, keys);
fail1:
input_free_device(input);
kfree(keys);
dev_err(&pdev->dev, "can't register, err %d\n", status);
return status;
}
static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
{
struct dm355evm_keys *keys = platform_get_drvdata(pdev);
free_irq(keys->irq, keys);
input_unregister_device(keys->input);
kfree(keys);
return 0;
}
/* REVISIT: add suspend/resume when DaVinci supports it. The IRQ should
* be able to wake up the system. When device_may_wakeup(&pdev->dev), call
* enable_irq_wake() on suspend, and disable_irq_wake() on resume.
*/
/*
* I2C is used to talk to the MSP430, but this platform device is
* exposed by an MFD driver that manages I2C communications.
*/
static struct platform_driver dm355evm_keys_driver = {
.probe = dm355evm_keys_probe,
.remove = __devexit_p(dm355evm_keys_remove),
.driver = {
.owner = THIS_MODULE,
.name = "dm355evm_keys",
},
};
static int __init dm355evm_keys_init(void)
{
return platform_driver_register(&dm355evm_keys_driver);
}
module_init(dm355evm_keys_init);
static void __exit dm355evm_keys_exit(void)
{
platform_driver_unregister(&dm355evm_keys_driver);
}
module_exit(dm355evm_keys_exit);
MODULE_LICENSE("GPL");
...@@ -26,13 +26,17 @@ ...@@ -26,13 +26,17 @@
#define DRV_NAME "rotary-encoder" #define DRV_NAME "rotary-encoder"
struct rotary_encoder { struct rotary_encoder {
unsigned int irq_a;
unsigned int irq_b;
unsigned int pos;
unsigned int armed;
unsigned int dir;
struct input_dev *input; struct input_dev *input;
struct rotary_encoder_platform_data *pdata; struct rotary_encoder_platform_data *pdata;
unsigned int axis;
unsigned int pos;
unsigned int irq_a;
unsigned int irq_b;
bool armed;
unsigned char dir; /* 0 - clockwise, 1 - CCW */
}; };
static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
...@@ -53,21 +57,32 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) ...@@ -53,21 +57,32 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
if (!encoder->armed) if (!encoder->armed)
break; break;
if (pdata->relative_axis) {
input_report_rel(encoder->input, pdata->axis,
encoder->dir ? -1 : 1);
} else {
unsigned int pos = encoder->pos;
if (encoder->dir) { if (encoder->dir) {
/* turning counter-clockwise */ /* turning counter-clockwise */
encoder->pos += pdata->steps; if (pdata->rollover)
encoder->pos--; pos += pdata->steps;
encoder->pos %= pdata->steps; if (pos)
pos--;
} else { } else {
/* turning clockwise */ /* turning clockwise */
encoder->pos++; if (pdata->rollover || pos < pdata->steps)
encoder->pos %= pdata->steps; pos++;
}
if (pdata->rollover)
pos %= pdata->steps;
encoder->pos = pos;
input_report_abs(encoder->input, pdata->axis,
encoder->pos);
} }
input_report_abs(encoder->input, pdata->axis, encoder->pos);
input_sync(encoder->input); input_sync(encoder->input);
encoder->armed = 0; encoder->armed = false;
break; break;
case 0x1: case 0x1:
...@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) ...@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break; break;
case 0x3: case 0x3:
encoder->armed = 1; encoder->armed = true;
break; break;
} }
...@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) ...@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
input->name = pdev->name; input->name = pdev->name;
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev; input->dev.parent = &pdev->dev;
if (pdata->relative_axis) {
input->evbit[0] = BIT_MASK(EV_REL);
input->relbit[0] = BIT_MASK(pdata->axis);
} else {
input->evbit[0] = BIT_MASK(EV_ABS); input->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(encoder->input, input_set_abs_params(encoder->input,
pdata->axis, 0, pdata->steps, 0, 1); pdata->axis, 0, pdata->steps, 0, 1);
}
err = input_register_device(input); err = input_register_device(input);
if (err) { if (err) {
......
/**
* twl4030-pwrbutton.c - TWL4030 Power Button Input Driver
*
* Copyright (C) 2008-2009 Nokia Corporation
*
* Written by Peter De Schrijver <peter.de-schrijver@nokia.com>
* Several fixes by Felipe Balbi <felipe.balbi@nokia.com>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
* archive for more details.
*
* 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
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c/twl4030.h>
#define PWR_PWRON_IRQ (1 << 0)
#define STS_HW_CONDITIONS 0xf
static irqreturn_t powerbutton_irq(int irq, void *_pwr)
{
struct input_dev *pwr = _pwr;
int err;
u8 value;
#ifdef CONFIG_LOCKDEP
/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
* we don't want and can't tolerate since this is a threaded
* IRQ and can sleep due to the i2c reads it has to issue.
* Although it might be friendlier not to borrow this thread
* context...
*/
local_irq_enable();
#endif
err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
STS_HW_CONDITIONS);
if (!err) {
input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
input_sync(pwr);
} else {
dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
" TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);
}
return IRQ_HANDLED;
}
static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
int irq = platform_get_irq(pdev, 0);
int err;
pwr = input_allocate_device();
if (!pwr) {
dev_dbg(&pdev->dev, "Can't allocate power button\n");
return -ENOMEM;
}
pwr->evbit[0] = BIT_MASK(EV_KEY);
pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
pwr->name = "twl4030_pwrbutton";
pwr->phys = "twl4030_pwrbutton/input0";
pwr->dev.parent = &pdev->dev;
err = request_irq(irq, powerbutton_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"twl4030_pwrbutton", pwr);
if (err < 0) {
dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
goto free_input_dev;
}
err = input_register_device(pwr);
if (err) {
dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
goto free_irq;
}
platform_set_drvdata(pdev, pwr);
return 0;
free_irq:
free_irq(irq, NULL);
free_input_dev:
input_free_device(pwr);
return err;
}
static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev)
{
struct input_dev *pwr = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
free_irq(irq, pwr);
input_unregister_device(pwr);
return 0;
}
struct platform_driver twl4030_pwrbutton_driver = {
.probe = twl4030_pwrbutton_probe,
.remove = __devexit_p(twl4030_pwrbutton_remove),
.driver = {
.name = "twl4030_pwrbutton",
.owner = THIS_MODULE,
},
};
static int __init twl4030_pwrbutton_init(void)
{
return platform_driver_register(&twl4030_pwrbutton_driver);
}
module_init(twl4030_pwrbutton_init);
static void __exit twl4030_pwrbutton_exit(void)
{
platform_driver_unregister(&twl4030_pwrbutton_driver);
}
module_exit(twl4030_pwrbutton_exit);
MODULE_ALIAS("platform:twl4030_pwrbutton");
MODULE_DESCRIPTION("Triton2 Power Button");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>");
MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
...@@ -54,27 +54,28 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i ...@@ -54,27 +54,28 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i
return 0; return 0;
} }
/* Atomically allocate an ID for the given request. Returns 0 on success. */
static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
{ {
/* Atomically allocate an ID for the given request. Returns 0 on success. */
int id; int id;
int err = -1; int err = -1;
spin_lock(&udev->requests_lock); spin_lock(&udev->requests_lock);
for (id = 0; id < UINPUT_NUM_REQUESTS; id++) for (id = 0; id < UINPUT_NUM_REQUESTS; id++) {
if (!udev->requests[id]) { if (!udev->requests[id]) {
request->id = id; request->id = id;
udev->requests[id] = request; udev->requests[id] = request;
err = 0; err = 0;
break; break;
} }
}
spin_unlock(&udev->requests_lock); spin_unlock(&udev->requests_lock);
return err; return err;
} }
static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id) static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id)
{ {
/* Find an input request, by ID. Returns NULL if the ID isn't valid. */ /* Find an input request, by ID. Returns NULL if the ID isn't valid. */
if (id >= UINPUT_NUM_REQUESTS || id < 0) if (id >= UINPUT_NUM_REQUESTS || id < 0)
...@@ -99,14 +100,51 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques ...@@ -99,14 +100,51 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques
complete(&request->done); complete(&request->done);
} }
static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request) static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request)
{ {
int retval;
retval = uinput_request_reserve_slot(udev, request);
if (retval)
return retval;
retval = mutex_lock_interruptible(&udev->mutex);
if (retval)
return retval;
if (udev->state != UIST_CREATED) {
retval = -ENODEV;
goto out;
}
/* Tell our userspace app about this new request by queueing an input event */ /* Tell our userspace app about this new request by queueing an input event */
uinput_dev_event(dev, EV_UINPUT, request->code, request->id); uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
out:
mutex_unlock(&udev->mutex);
return retval;
}
/*
* Fail all ouitstanding requests so handlers don't wait for the userspace
* to finish processing them.
*/
static void uinput_flush_requests(struct uinput_device *udev)
{
struct uinput_request *request;
int i;
/* Wait for the request to complete */ spin_lock(&udev->requests_lock);
wait_for_completion(&request->done);
return request->retval; for (i = 0; i < UINPUT_NUM_REQUESTS; i++) {
request = udev->requests[i];
if (request) {
request->retval = -ENODEV;
uinput_request_done(udev, request);
}
}
spin_unlock(&udev->requests_lock);
} }
static void uinput_dev_set_gain(struct input_dev *dev, u16 gain) static void uinput_dev_set_gain(struct input_dev *dev, u16 gain)
...@@ -126,6 +164,7 @@ static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value) ...@@ -126,6 +164,7 @@ static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value)
static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
{ {
struct uinput_device *udev = input_get_drvdata(dev);
struct uinput_request request; struct uinput_request request;
int retval; int retval;
...@@ -146,15 +185,18 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff ...@@ -146,15 +185,18 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
request.u.upload.effect = effect; request.u.upload.effect = effect;
request.u.upload.old = old; request.u.upload.old = old;
retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); retval = uinput_request_submit(udev, &request);
if (!retval) if (!retval) {
retval = uinput_request_submit(dev, &request); wait_for_completion(&request.done);
retval = request.retval;
}
return retval; return retval;
} }
static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
{ {
struct uinput_device *udev = input_get_drvdata(dev);
struct uinput_request request; struct uinput_request request;
int retval; int retval;
...@@ -166,9 +208,11 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) ...@@ -166,9 +208,11 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
request.code = UI_FF_ERASE; request.code = UI_FF_ERASE;
request.u.effect_id = effect_id; request.u.effect_id = effect_id;
retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); retval = uinput_request_submit(udev, &request);
if (!retval) if (!retval) {
retval = uinput_request_submit(dev, &request); wait_for_completion(&request.done);
retval = request.retval;
}
return retval; return retval;
} }
...@@ -176,20 +220,24 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) ...@@ -176,20 +220,24 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
static void uinput_destroy_device(struct uinput_device *udev) static void uinput_destroy_device(struct uinput_device *udev)
{ {
const char *name, *phys; const char *name, *phys;
struct input_dev *dev = udev->dev;
enum uinput_state old_state = udev->state;
if (udev->dev) { udev->state = UIST_NEW_DEVICE;
name = udev->dev->name;
phys = udev->dev->phys; if (dev) {
if (udev->state == UIST_CREATED) name = dev->name;
input_unregister_device(udev->dev); phys = dev->phys;
else if (old_state == UIST_CREATED) {
input_free_device(udev->dev); uinput_flush_requests(udev);
input_unregister_device(dev);
} else {
input_free_device(dev);
}
kfree(name); kfree(name);
kfree(phys); kfree(phys);
udev->dev = NULL; udev->dev = NULL;
} }
udev->state = UIST_NEW_DEVICE;
} }
static int uinput_create_device(struct uinput_device *udev) static int uinput_create_device(struct uinput_device *udev)
......
...@@ -303,4 +303,22 @@ config MOUSE_MAPLE ...@@ -303,4 +303,22 @@ config MOUSE_MAPLE
To compile this driver as a module choose M here: the module will be To compile this driver as a module choose M here: the module will be
called maplemouse. called maplemouse.
config MOUSE_SYNAPTICS_I2C
tristate "Synaptics I2C Touchpad support"
depends on I2C
help
This driver supports Synaptics I2C touchpad controller on eXeda
mobile device.
The device will not work the synaptics X11 driver because
(i) it reports only relative coordinates and has no capabilities
to report absolute coordinates
(ii) the eXeda device itself uses Xfbdev as X Server and it does
not allow using xf86-input-* drivers.
Say y here if you have eXeda device and want to use a Synaptics
I2C Touchpad.
To compile this driver as a module, choose M here: the
module will be called synaptics_i2c.
endif endif
...@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
psmouse-objs := psmouse-base.o synaptics.o psmouse-objs := psmouse-base.o synaptics.o
......
...@@ -48,7 +48,7 @@ static const struct alps_model_info alps_model_data[] = { ...@@ -48,7 +48,7 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */
{ { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
...@@ -56,7 +56,7 @@ static const struct alps_model_info alps_model_data[] = { ...@@ -56,7 +56,7 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */
}; };
/* /*
...@@ -132,18 +132,23 @@ static void alps_process_packet(struct psmouse *psmouse) ...@@ -132,18 +132,23 @@ static void alps_process_packet(struct psmouse *psmouse)
ges = packet[2] & 1; ges = packet[2] & 1;
fin = packet[2] & 2; fin = packet[2] & 2;
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
input_report_key(dev, BTN_MIDDLE, middle);
if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
input_report_key(dev2, BTN_LEFT, left);
input_report_key(dev2, BTN_RIGHT, right);
input_report_key(dev2, BTN_MIDDLE, middle);
input_sync(dev); input_sync(dev);
input_sync(dev2); input_sync(dev2);
return; return;
} }
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
input_report_key(dev, BTN_MIDDLE, middle);
/* Convert hardware tap to a reasonable Z value */ /* Convert hardware tap to a reasonable Z value */
if (ges && !fin) z = 40; if (ges && !fin) z = 40;
......
...@@ -361,7 +361,7 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, ...@@ -361,7 +361,7 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
(!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
(*fingers)++; (*fingers)++;
is_increasing = 1; is_increasing = 1;
} else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) {
is_increasing = 0; is_increasing = 0;
} }
......
...@@ -159,7 +159,8 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) ...@@ -159,7 +159,8 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
if (!dev2) if (!dev2)
printk(KERN_WARNING "lifebook.c: got relative packet " printk(KERN_WARNING "lifebook.c: got relative packet "
"but no relative device set up\n"); "but no relative device set up\n");
} else if (lifebook_use_6byte_proto) { } else {
if (lifebook_use_6byte_proto) {
input_report_abs(dev1, ABS_X, input_report_abs(dev1, ABS_X,
((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
input_report_abs(dev1, ABS_Y, input_report_abs(dev1, ABS_Y,
...@@ -170,9 +171,9 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) ...@@ -170,9 +171,9 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
input_report_abs(dev1, ABS_Y, input_report_abs(dev1, ABS_Y,
1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
} }
input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
input_sync(dev1); input_sync(dev1);
}
if (dev2) { if (dev2) {
if (relative_packet) { if (relative_packet) {
......
...@@ -327,7 +327,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -327,7 +327,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out; goto out;
} }
if (psmouse->packet[1] == PSMOUSE_RET_ID) { if (psmouse->packet[1] == PSMOUSE_RET_ID ||
(psmouse->type == PSMOUSE_HGPK &&
psmouse->packet[1] == PSMOUSE_RET_BAT)) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE); __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(serio); serio_reconnect(serio);
goto out; goto out;
......
...@@ -180,6 +180,29 @@ static int synaptics_identify(struct psmouse *psmouse) ...@@ -180,6 +180,29 @@ static int synaptics_identify(struct psmouse *psmouse)
return -1; return -1;
} }
/*
* Read touchpad resolution
* Resolution is left zero if touchpad does not support the query
*/
static int synaptics_resolution(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
unsigned char res[3];
if (SYN_ID_MAJOR(priv->identity) < 4)
return 0;
if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res))
return 0;
if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) {
priv->x_res = res[0]; /* x resolution in units/mm */
priv->y_res = res[2]; /* y resolution in units/mm */
}
return 0;
}
static int synaptics_query_hardware(struct psmouse *psmouse) static int synaptics_query_hardware(struct psmouse *psmouse)
{ {
if (synaptics_identify(psmouse)) if (synaptics_identify(psmouse))
...@@ -188,6 +211,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse) ...@@ -188,6 +211,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
return -1; return -1;
if (synaptics_capability(psmouse)) if (synaptics_capability(psmouse))
return -1; return -1;
if (synaptics_resolution(psmouse))
return -1;
return 0; return 0;
} }
...@@ -563,6 +588,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -563,6 +588,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit(EV_REL, dev->evbit); clear_bit(EV_REL, dev->evbit);
clear_bit(REL_X, dev->relbit); clear_bit(REL_X, dev->relbit);
clear_bit(REL_Y, dev->relbit); clear_bit(REL_Y, dev->relbit);
dev->absres[ABS_X] = priv->x_res;
dev->absres[ABS_Y] = priv->y_res;
} }
static void synaptics_disconnect(struct psmouse *psmouse) static void synaptics_disconnect(struct psmouse *psmouse)
......
...@@ -97,6 +97,8 @@ struct synaptics_data { ...@@ -97,6 +97,8 @@ struct synaptics_data {
unsigned long int capabilities; /* Capabilities */ unsigned long int capabilities; /* Capabilities */
unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */ unsigned long int identity; /* Identification */
int x_res; /* X resolution in units/mm */
int y_res; /* Y resolution in units/mm */
unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */ unsigned char mode; /* current mode byte */
......
This diff is collapsed.
...@@ -60,7 +60,6 @@ struct mousedev { ...@@ -60,7 +60,6 @@ struct mousedev {
int exist; int exist;
int open; int open;
int minor; int minor;
char name[16];
struct input_handle handle; struct input_handle handle;
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head client_list; struct list_head client_list;
...@@ -863,19 +862,17 @@ static struct mousedev *mousedev_create(struct input_dev *dev, ...@@ -863,19 +862,17 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
init_waitqueue_head(&mousedev->wait); init_waitqueue_head(&mousedev->wait);
if (minor == MOUSEDEV_MIX) if (minor == MOUSEDEV_MIX)
strlcpy(mousedev->name, "mice", sizeof(mousedev->name)); dev_set_name(&mousedev->dev, "mice");
else else
snprintf(mousedev->name, sizeof(mousedev->name), dev_set_name(&mousedev->dev, "mouse%d", minor);
"mouse%d", minor);
mousedev->minor = minor; mousedev->minor = minor;
mousedev->exist = 1; mousedev->exist = 1;
mousedev->handle.dev = input_get_device(dev); mousedev->handle.dev = input_get_device(dev);
mousedev->handle.name = mousedev->name; mousedev->handle.name = dev_name(&mousedev->dev);
mousedev->handle.handler = handler; mousedev->handle.handler = handler;
mousedev->handle.private = mousedev; mousedev->handle.private = mousedev;
dev_set_name(&mousedev->dev, mousedev->name);
mousedev->dev.class = &input_class; mousedev->dev.class = &input_class;
if (dev) if (dev)
mousedev->dev.parent = &dev->dev; mousedev->dev.parent = &dev->dev;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* the Free Software Foundation. * the Free Software Foundation.
*/ */
#include <linux/types.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -921,6 +922,9 @@ static void i8042_dritek_enable(void) ...@@ -921,6 +922,9 @@ static void i8042_dritek_enable(void)
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
static bool i8042_suspended;
/* /*
* Here we try to restore the original BIOS settings. We only want to * Here we try to restore the original BIOS settings. We only want to
* do that once, when we really suspend, not when we taking memory * do that once, when we really suspend, not when we taking memory
...@@ -930,11 +934,9 @@ static void i8042_dritek_enable(void) ...@@ -930,11 +934,9 @@ static void i8042_dritek_enable(void)
static int i8042_suspend(struct platform_device *dev, pm_message_t state) static int i8042_suspend(struct platform_device *dev, pm_message_t state)
{ {
if (dev->dev.power.power_state.event != state.event) { if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) {
if (state.event == PM_EVENT_SUSPEND)
i8042_controller_reset(); i8042_controller_reset();
i8042_suspended = true;
dev->dev.power.power_state = state;
} }
return 0; return 0;
...@@ -952,7 +954,7 @@ static int i8042_resume(struct platform_device *dev) ...@@ -952,7 +954,7 @@ static int i8042_resume(struct platform_device *dev)
/* /*
* Do not bother with restoring state if we haven't suspened yet * Do not bother with restoring state if we haven't suspened yet
*/ */
if (dev->dev.power.power_state.event == PM_EVENT_ON) if (!i8042_suspended)
return 0; return 0;
error = i8042_controller_check(); error = i8042_controller_check();
...@@ -998,10 +1000,9 @@ static int i8042_resume(struct platform_device *dev) ...@@ -998,10 +1000,9 @@ static int i8042_resume(struct platform_device *dev)
if (i8042_ports[I8042_KBD_PORT_NO].serio) if (i8042_ports[I8042_KBD_PORT_NO].serio)
i8042_enable_kbd_port(); i8042_enable_kbd_port();
i8042_suspended = false;
i8042_interrupt(0, NULL); i8042_interrupt(0, NULL);
dev->dev.power.power_state = PMSG_ON;
return 0; return 0;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
...@@ -41,17 +41,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -41,17 +41,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core"); MODULE_DESCRIPTION("Serio abstraction core");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_child_port);
EXPORT_SYMBOL(__serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect);
/* /*
* serio_mutex protects entire serio subsystem and is taken every time * serio_mutex protects entire serio subsystem and is taken every time
* serio port or driver registrered or unregistered. * serio port or driver registrered or unregistered.
...@@ -506,9 +495,9 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute * ...@@ -506,9 +495,9 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
retval = count; retval = count;
if (!strncmp(buf, "manual", count)) { if (!strncmp(buf, "manual", count)) {
serio->manual_bind = 1; serio->manual_bind = true;
} else if (!strncmp(buf, "auto", count)) { } else if (!strncmp(buf, "auto", count)) {
serio->manual_bind = 0; serio->manual_bind = false;
} else { } else {
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -581,7 +570,7 @@ static void serio_add_port(struct serio *serio) ...@@ -581,7 +570,7 @@ static void serio_add_port(struct serio *serio)
"serio: device_add() failed for %s (%s), error: %d\n", "serio: device_add() failed for %s (%s), error: %d\n",
serio->phys, serio->name, error); serio->phys, serio->name, error);
else { else {
serio->registered = 1; serio->registered = true;
error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
if (error) if (error)
printk(KERN_ERR printk(KERN_ERR
...@@ -617,7 +606,7 @@ static void serio_destroy_port(struct serio *serio) ...@@ -617,7 +606,7 @@ static void serio_destroy_port(struct serio *serio)
if (serio->registered) { if (serio->registered) {
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev); device_del(&serio->dev);
serio->registered = 0; serio->registered = false;
} }
list_del_init(&serio->node); list_del_init(&serio->node);
...@@ -692,11 +681,13 @@ void serio_rescan(struct serio *serio) ...@@ -692,11 +681,13 @@ void serio_rescan(struct serio *serio)
{ {
serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
} }
EXPORT_SYMBOL(serio_rescan);
void serio_reconnect(struct serio *serio) void serio_reconnect(struct serio *serio)
{ {
serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
} }
EXPORT_SYMBOL(serio_reconnect);
/* /*
* Submits register request to kseriod for subsequent execution. * Submits register request to kseriod for subsequent execution.
...@@ -707,6 +698,7 @@ void __serio_register_port(struct serio *serio, struct module *owner) ...@@ -707,6 +698,7 @@ void __serio_register_port(struct serio *serio, struct module *owner)
serio_init_port(serio); serio_init_port(serio);
serio_queue_event(serio, owner, SERIO_REGISTER_PORT); serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
} }
EXPORT_SYMBOL(__serio_register_port);
/* /*
* Synchronously unregisters serio port. * Synchronously unregisters serio port.
...@@ -718,6 +710,7 @@ void serio_unregister_port(struct serio *serio) ...@@ -718,6 +710,7 @@ void serio_unregister_port(struct serio *serio)
serio_destroy_port(serio); serio_destroy_port(serio);
mutex_unlock(&serio_mutex); mutex_unlock(&serio_mutex);
} }
EXPORT_SYMBOL(serio_unregister_port);
/* /*
* Safely unregisters child port if one is present. * Safely unregisters child port if one is present.
...@@ -731,6 +724,7 @@ void serio_unregister_child_port(struct serio *serio) ...@@ -731,6 +724,7 @@ void serio_unregister_child_port(struct serio *serio)
} }
mutex_unlock(&serio_mutex); mutex_unlock(&serio_mutex);
} }
EXPORT_SYMBOL(serio_unregister_child_port);
/* /*
...@@ -756,9 +750,9 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char ...@@ -756,9 +750,9 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char
retval = count; retval = count;
if (!strncmp(buf, "manual", count)) { if (!strncmp(buf, "manual", count)) {
serio_drv->manual_bind = 1; serio_drv->manual_bind = true;
} else if (!strncmp(buf, "auto", count)) { } else if (!strncmp(buf, "auto", count)) {
serio_drv->manual_bind = 0; serio_drv->manual_bind = false;
} else { } else {
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -818,7 +812,7 @@ static void serio_attach_driver(struct serio_driver *drv) ...@@ -818,7 +812,7 @@ static void serio_attach_driver(struct serio_driver *drv)
int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
{ {
int manual_bind = drv->manual_bind; bool manual_bind = drv->manual_bind;
int error; int error;
drv->driver.bus = &serio_bus; drv->driver.bus = &serio_bus;
...@@ -829,7 +823,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons ...@@ -829,7 +823,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
* Temporarily disable automatic binding because probing * Temporarily disable automatic binding because probing
* takes long time and we are better off doing it in kseriod * takes long time and we are better off doing it in kseriod
*/ */
drv->manual_bind = 1; drv->manual_bind = true;
error = driver_register(&drv->driver); error = driver_register(&drv->driver);
if (error) { if (error) {
...@@ -844,7 +838,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons ...@@ -844,7 +838,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
* driver to free ports * driver to free ports
*/ */
if (!manual_bind) { if (!manual_bind) {
drv->manual_bind = 0; drv->manual_bind = false;
error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
if (error) { if (error) {
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
...@@ -854,6 +848,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons ...@@ -854,6 +848,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
return 0; return 0;
} }
EXPORT_SYMBOL(__serio_register_driver);
void serio_unregister_driver(struct serio_driver *drv) void serio_unregister_driver(struct serio_driver *drv)
{ {
...@@ -861,7 +856,7 @@ void serio_unregister_driver(struct serio_driver *drv) ...@@ -861,7 +856,7 @@ void serio_unregister_driver(struct serio_driver *drv)
mutex_lock(&serio_mutex); mutex_lock(&serio_mutex);
drv->manual_bind = 1; /* so serio_find_driver ignores it */ drv->manual_bind = true; /* so serio_find_driver ignores it */
serio_remove_pending_events(drv); serio_remove_pending_events(drv);
start_over: start_over:
...@@ -877,6 +872,7 @@ void serio_unregister_driver(struct serio_driver *drv) ...@@ -877,6 +872,7 @@ void serio_unregister_driver(struct serio_driver *drv)
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
mutex_unlock(&serio_mutex); mutex_unlock(&serio_mutex);
} }
EXPORT_SYMBOL(serio_unregister_driver);
static void serio_set_drv(struct serio *serio, struct serio_driver *drv) static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{ {
...@@ -937,11 +933,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -937,11 +933,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int serio_suspend(struct device *dev, pm_message_t state) static int serio_suspend(struct device *dev, pm_message_t state)
{ {
if (dev->power.power_state.event != state.event) { struct serio *serio = to_serio_port(dev);
if (state.event == PM_EVENT_SUSPEND)
serio_cleanup(to_serio_port(dev));
dev->power.power_state = state; if (!serio->suspended && state.event == PM_EVENT_SUSPEND) {
serio_cleanup(serio);
serio->suspended = true;
} }
return 0; return 0;
...@@ -949,14 +945,15 @@ static int serio_suspend(struct device *dev, pm_message_t state) ...@@ -949,14 +945,15 @@ static int serio_suspend(struct device *dev, pm_message_t state)
static int serio_resume(struct device *dev) static int serio_resume(struct device *dev)
{ {
struct serio *serio = to_serio_port(dev);
/* /*
* Driver reconnect can take a while, so better let kseriod * Driver reconnect can take a while, so better let kseriod
* deal with it. * deal with it.
*/ */
if (dev->power.power_state.event != PM_EVENT_ON) { if (serio->suspended) {
dev->power.power_state = PMSG_ON; serio->suspended = false;
serio_queue_event(to_serio_port(dev), NULL, serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
SERIO_RECONNECT_PORT);
} }
return 0; return 0;
...@@ -974,6 +971,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv) ...@@ -974,6 +971,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
} }
return 0; return 0;
} }
EXPORT_SYMBOL(serio_open);
/* called from serio_driver->connect/disconnect methods under serio_mutex */ /* called from serio_driver->connect/disconnect methods under serio_mutex */
void serio_close(struct serio *serio) void serio_close(struct serio *serio)
...@@ -983,6 +981,7 @@ void serio_close(struct serio *serio) ...@@ -983,6 +981,7 @@ void serio_close(struct serio *serio)
serio_set_drv(serio, NULL); serio_set_drv(serio, NULL);
} }
EXPORT_SYMBOL(serio_close);
irqreturn_t serio_interrupt(struct serio *serio, irqreturn_t serio_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl) unsigned char data, unsigned int dfl)
...@@ -1003,6 +1002,7 @@ irqreturn_t serio_interrupt(struct serio *serio, ...@@ -1003,6 +1002,7 @@ irqreturn_t serio_interrupt(struct serio *serio,
return ret; return ret;
} }
EXPORT_SYMBOL(serio_interrupt);
static struct bus_type serio_bus = { static struct bus_type serio_bus = {
.name = "serio", .name = "serio",
......
...@@ -1050,4 +1050,5 @@ static void __exit gtco_exit(void) ...@@ -1050,4 +1050,5 @@ static void __exit gtco_exit(void)
module_init(gtco_init); module_init(gtco_init);
module_exit(gtco_exit); module_exit(gtco_exit);
MODULE_DESCRIPTION("GTCO digitizer USB driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
* v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
* v1.51 (pc) - Added support for Intuos4
*/ */
/* /*
...@@ -88,7 +89,7 @@ ...@@ -88,7 +89,7 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v1.50" #define DRIVER_VERSION "v1.51"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL" #define DRIVER_LICENSE "GPL"
...@@ -128,6 +129,8 @@ extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac ...@@ -128,6 +129,8 @@ extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac
extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
......
...@@ -229,6 +229,19 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) ...@@ -229,6 +229,19 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
} }
void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
}
void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
}
void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{ {
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
......
This diff is collapsed.
...@@ -25,6 +25,9 @@ enum { ...@@ -25,6 +25,9 @@ enum {
INTUOS3S, INTUOS3S,
INTUOS3, INTUOS3,
INTUOS3L, INTUOS3L,
INTUOS4S,
INTUOS4,
INTUOS4L,
CINTIQ, CINTIQ,
WACOM_BEE, WACOM_BEE,
WACOM_MO, WACOM_MO,
......
...@@ -111,6 +111,15 @@ config TOUCHSCREEN_DA9034 ...@@ -111,6 +111,15 @@ config TOUCHSCREEN_DA9034
Say Y here to enable the support for the touchscreen found Say Y here to enable the support for the touchscreen found
on Dialog Semiconductor DA9034 PMIC. on Dialog Semiconductor DA9034 PMIC.
config TOUCHSCREEN_EETI
tristate "EETI touchscreen panel support"
depends on I2C
help
Say Y here to enable support for I2C connected EETI touch panels.
To compile this driver as a module, choose M here: the
module will be called eeti_ts.
config TOUCHSCREEN_FUJITSU config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen" tristate "Fujitsu serial touchscreen"
select SERIO select SERIO
...@@ -341,6 +350,21 @@ config TOUCHSCREEN_WM9713 ...@@ -341,6 +350,21 @@ config TOUCHSCREEN_WM9713
Say Y here to enable support for the Wolfson Microelectronics Say Y here to enable support for the Wolfson Microelectronics
WM9713 touchscreen controller. WM9713 touchscreen controller.
config TOUCHSCREEN_WM97XX_ATMEL
tristate "WM97xx Atmel accelerated touch"
depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
help
Say Y here for support for streaming mode with WM97xx touchscreens
on Atmel AT91 or AVR32 systems with an AC97C module.
Be aware that this will use channel B in the controller for
streaming data, this must not conflict with other AC97C drivers.
If unsure, say N.
To compile this driver as a module, choose M here: the module will
be called atmel-wm97xx.
config TOUCHSCREEN_WM97XX_MAINSTONE config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone accelerated touch" tristate "WM97xx Mainstone accelerated touch"
depends on TOUCHSCREEN_WM97XX && ARCH_PXA depends on TOUCHSCREEN_WM97XX && ARCH_PXA
...@@ -466,4 +490,12 @@ config TOUCHSCREEN_TSC2007 ...@@ -466,4 +490,12 @@ config TOUCHSCREEN_TSC2007
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called tsc2007. module will be called tsc2007.
config TOUCHSCREEN_W90X900
tristate "W90P910 touchscreen driver"
help
Say Y here if you have a W90P910 based touchscreen.
To compile this driver as a module, choose M here: the
module will be called w90p910_ts.
endif endif
...@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
...@@ -35,5 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o ...@@ -35,5 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
...@@ -83,6 +83,7 @@ struct ads7846_packet { ...@@ -83,6 +83,7 @@ struct ads7846_packet {
struct ads7846 { struct ads7846 {
struct input_dev *input; struct input_dev *input;
char phys[32]; char phys[32];
char name[32];
struct spi_device *spi; struct spi_device *spi;
...@@ -97,6 +98,8 @@ struct ads7846 { ...@@ -97,6 +98,8 @@ struct ads7846 {
u16 x_plate_ohms; u16 x_plate_ohms;
u16 pressure_max; u16 pressure_max;
bool swap_xy;
struct ads7846_packet *packet; struct ads7846_packet *packet;
struct spi_transfer xfer[18]; struct spi_transfer xfer[18];
...@@ -599,6 +602,10 @@ static void ads7846_rx(void *ads) ...@@ -599,6 +602,10 @@ static void ads7846_rx(void *ads)
dev_dbg(&ts->spi->dev, "DOWN\n"); dev_dbg(&ts->spi->dev, "DOWN\n");
#endif #endif
} }
if (ts->swap_xy)
swap(x, y);
input_report_abs(input, ABS_X, x); input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y); input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, Rt); input_report_abs(input, ABS_PRESSURE, Rt);
...@@ -917,6 +924,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) ...@@ -917,6 +924,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->spi = spi; ts->spi = spi;
ts->input = input_dev; ts->input = input_dev;
ts->vref_mv = pdata->vref_mv; ts->vref_mv = pdata->vref_mv;
ts->swap_xy = pdata->swap_xy;
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts->timer.function = ads7846_timer; ts->timer.function = ads7846_timer;
...@@ -958,8 +966,9 @@ static int __devinit ads7846_probe(struct spi_device *spi) ...@@ -958,8 +966,9 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
input_dev->name = "ADS784x Touchscreen"; input_dev->name = ts->name;
input_dev->phys = ts->phys; input_dev->phys = ts->phys;
input_dev->dev.parent = &spi->dev; input_dev->dev.parent = &spi->dev;
...@@ -1141,10 +1150,16 @@ static int __devinit ads7846_probe(struct spi_device *spi) ...@@ -1141,10 +1150,16 @@ static int __devinit ads7846_probe(struct spi_device *spi)
if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
spi->dev.driver->name, ts)) { spi->dev.driver->name, ts)) {
dev_info(&spi->dev,
"trying pin change workaround on irq %d\n", spi->irq);
err = request_irq(spi->irq, ads7846_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
spi->dev.driver->name, ts);
if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
err = -EBUSY;
goto err_free_gpio; goto err_free_gpio;
} }
}
err = ads784x_hwmon_register(spi, ts); err = ads784x_hwmon_register(spi, ts);
if (err) if (err)
......
This diff is collapsed.
/*
* Touch Screen driver for EETI's I2C connected touch screen panels
* Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
*
* See EETI's software guide for the protocol specification:
* http://home.eeti.com.tw/web20/eg/guide.htm
*
* Based on migor_ts.c
* Copyright (c) 2008 Magnus Damm
* Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>
*
* This file 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 file 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/gpio.h>
static int flip_x;
module_param(flip_x, bool, 0644);
MODULE_PARM_DESC(flip_x, "flip x coordinate");
static int flip_y;
module_param(flip_y, bool, 0644);
MODULE_PARM_DESC(flip_y, "flip y coordinate");
struct eeti_ts_priv {
struct i2c_client *client;
struct input_dev *input;
struct work_struct work;
struct mutex mutex;
int irq;
};
#define EETI_TS_BITDEPTH (11)
#define EETI_MAXVAL ((1 << (EETI_TS_BITDEPTH + 1)) - 1)
#define REPORT_BIT_PRESSED (1 << 0)
#define REPORT_BIT_AD0 (1 << 1)
#define REPORT_BIT_AD1 (1 << 2)
#define REPORT_BIT_HAS_PRESSURE (1 << 6)
#define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH)
static void eeti_ts_read(struct work_struct *work)
{
char buf[6];
unsigned int x, y, res, pressed, to = 100;
struct eeti_ts_priv *priv =
container_of(work, struct eeti_ts_priv, work);
mutex_lock(&priv->mutex);
while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to)
i2c_master_recv(priv->client, buf, sizeof(buf));
if (!to) {
dev_err(&priv->client->dev,
"unable to clear IRQ - line stuck?\n");
goto out;
}
/* drop non-report packets */
if (!(buf[0] & 0x80))
goto out;
pressed = buf[0] & REPORT_BIT_PRESSED;
res = REPORT_RES_BITS(buf[0] & (REPORT_BIT_AD0 | REPORT_BIT_AD1));
x = buf[2] | (buf[1] << 8);
y = buf[4] | (buf[3] << 8);
/* fix the range to 11 bits */
x >>= res - EETI_TS_BITDEPTH;
y >>= res - EETI_TS_BITDEPTH;
if (flip_x)
x = EETI_MAXVAL - x;
if (flip_y)
y = EETI_MAXVAL - y;
if (buf[0] & REPORT_BIT_HAS_PRESSURE)
input_report_abs(priv->input, ABS_PRESSURE, buf[5]);
input_report_abs(priv->input, ABS_X, x);
input_report_abs(priv->input, ABS_Y, y);
input_report_key(priv->input, BTN_TOUCH, !!pressed);
input_sync(priv->input);
out:
mutex_unlock(&priv->mutex);
}
static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
{
struct eeti_ts_priv *priv = dev_id;
/* postpone I2C transactions as we are atomic */
schedule_work(&priv->work);
return IRQ_HANDLED;
}
static int eeti_ts_open(struct input_dev *dev)
{
struct eeti_ts_priv *priv = input_get_drvdata(dev);
enable_irq(priv->irq);
/* Read the events once to arm the IRQ */
eeti_ts_read(&priv->work);
return 0;
}
static void eeti_ts_close(struct input_dev *dev)
{
struct eeti_ts_priv *priv = input_get_drvdata(dev);
disable_irq(priv->irq);
cancel_work_sync(&priv->work);
}
static int __devinit eeti_ts_probe(struct i2c_client *client,
const struct i2c_device_id *idp)
{
struct eeti_ts_priv *priv;
struct input_dev *input;
int err = -ENOMEM;
/* In contrast to what's described in the datasheet, there seems
* to be no way of probing the presence of that device using I2C
* commands. So we need to blindly believe it is there, and wait
* for interrupts to occur. */
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&client->dev, "failed to allocate driver data\n");
goto err0;
}
mutex_init(&priv->mutex);
input = input_allocate_device();
if (!input) {
dev_err(&client->dev, "Failed to allocate input device.\n");
goto err1;
}
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input, ABS_X, 0, EETI_MAXVAL, 0, 0);
input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0);
input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 0, 0);
input->name = client->name;
input->id.bustype = BUS_I2C;
input->dev.parent = &client->dev;
input->open = eeti_ts_open;
input->close = eeti_ts_close;
priv->client = client;
priv->input = input;
priv->irq = client->irq;
INIT_WORK(&priv->work, eeti_ts_read);
i2c_set_clientdata(client, priv);
input_set_drvdata(input, priv);
err = input_register_device(input);
if (err)
goto err1;
err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING,
client->name, priv);
if (err) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
goto err2;
}
/* Disable the irq for now. It will be enabled once the input device
* is opened. */
disable_irq(priv->irq);
device_init_wakeup(&client->dev, 0);
return 0;
err2:
input_unregister_device(input);
input = NULL; /* so we dont try to free it below */
err1:
input_free_device(input);
i2c_set_clientdata(client, NULL);
kfree(priv);
err0:
return err;
}
static int __devexit eeti_ts_remove(struct i2c_client *client)
{
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
free_irq(priv->irq, priv);
input_unregister_device(priv->input);
i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
#ifdef CONFIG_PM
static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
enable_irq_wake(priv->irq);
return 0;
}
static int eeti_ts_resume(struct i2c_client *client)
{
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
disable_irq_wake(priv->irq);
return 0;
}
#else
#define eeti_ts_suspend NULL
#define eeti_ts_resume NULL
#endif
static const struct i2c_device_id eeti_ts_id[] = {
{ "eeti_ts", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
static struct i2c_driver eeti_ts_driver = {
.driver = {
.name = "eeti_ts",
},
.probe = eeti_ts_probe,
.remove = __devexit_p(eeti_ts_remove),
.suspend = eeti_ts_suspend,
.resume = eeti_ts_resume,
.id_table = eeti_ts_id,
};
static int __init eeti_ts_init(void)
{
return i2c_add_driver(&eeti_ts_driver);
}
static void __exit eeti_ts_exit(void)
{
i2c_del_driver(&eeti_ts_driver);
}
MODULE_DESCRIPTION("EETI Touchscreen driver");
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_LICENSE("GPL");
module_init(eeti_ts_init);
module_exit(eeti_ts_exit);
...@@ -257,7 +257,7 @@ static int tsc2007_probe(struct i2c_client *client, ...@@ -257,7 +257,7 @@ static int tsc2007_probe(struct i2c_client *client,
struct input_dev *input_dev; struct input_dev *input_dev;
int err; int err;
if (!pdata) { if (!pdata || !pdata->get_pendown_state) {
dev_err(&client->dev, "platform data is required!\n"); dev_err(&client->dev, "platform data is required!\n");
return -EINVAL; return -EINVAL;
} }
......
This diff is collapsed.
...@@ -23,6 +23,26 @@ ...@@ -23,6 +23,26 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/ucb1400.h> #include <linux/ucb1400.h>
unsigned int ucb1400_adc_read(struct snd_ac97 *ac97, u16 adc_channel,
int adcsync)
{
unsigned int val;
if (adcsync)
adc_channel |= UCB_ADC_SYNC_ENA;
ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel |
UCB_ADC_START);
while (!((val = ucb1400_reg_read(ac97, UCB_ADC_DATA))
& UCB_ADC_DAT_VALID))
schedule_timeout_uninterruptible(1);
return val & UCB_ADC_DAT_MASK;
}
EXPORT_SYMBOL_GPL(ucb1400_adc_read);
static int ucb1400_core_probe(struct device *dev) static int ucb1400_core_probe(struct device *dev)
{ {
int err; int err;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/io.h> #include <asm/io.h>
#include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -62,7 +63,7 @@ struct gameport_driver { ...@@ -62,7 +63,7 @@ struct gameport_driver {
struct device_driver driver; struct device_driver driver;
unsigned int ignore; bool ignore;
}; };
#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver) #define to_gameport_driver(d) container_of(d, struct gameport_driver, driver)
......
/*
* lm8323.h - Configuration for LM8323 keypad driver.
*
* 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 (version 2 of the License only).
*
* 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 __LINUX_LM8323_H
#define __LINUX_LM8323_H
#include <linux/types.h>
/*
* Largest keycode that the chip can send, plus one,
* so keys can be mapped directly at the index of the
* LM8323 keycode instead of subtracting one.
*/
#define LM8323_KEYMAP_SIZE (0x7f + 1)
#define LM8323_NUM_PWMS 3
struct lm8323_platform_data {
int debounce_time; /* Time to watch for key bouncing, in ms. */
int active_time; /* Idle time until sleep, in ms. */
int size_x;
int size_y;
bool repeat;
const unsigned short *keymap;
const char *pwm_names[LM8323_NUM_PWMS];
const char *name; /* Device name. */
};
#endif /* __LINUX_LM8323_H */
...@@ -53,6 +53,7 @@ struct input_absinfo { ...@@ -53,6 +53,7 @@ struct input_absinfo {
__s32 maximum; __s32 maximum;
__s32 fuzz; __s32 fuzz;
__s32 flat; __s32 flat;
__s32 resolution;
}; };
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
...@@ -1109,6 +1110,7 @@ struct input_dev { ...@@ -1109,6 +1110,7 @@ struct input_dev {
int absmin[ABS_MAX + 1]; int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1]; int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1]; int absflat[ABS_MAX + 1];
int absres[ABS_MAX + 1];
int (*open)(struct input_dev *dev); int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev); void (*close)(struct input_dev *dev);
......
...@@ -8,6 +8,8 @@ struct rotary_encoder_platform_data { ...@@ -8,6 +8,8 @@ struct rotary_encoder_platform_data {
unsigned int gpio_b; unsigned int gpio_b;
unsigned int inverted_a; unsigned int inverted_a;
unsigned int inverted_b; unsigned int inverted_b;
bool relative_axis;
bool rollover;
}; };
#endif /* __ROTARY_ENCODER_H__ */ #endif /* __ROTARY_ENCODER_H__ */
This diff is collapsed.
...@@ -17,6 +17,7 @@ struct ads7846_platform_data { ...@@ -17,6 +17,7 @@ struct ads7846_platform_data {
u16 vref_mv; /* external vref value, milliVolts */ u16 vref_mv; /* external vref value, milliVolts */
bool keep_vref_on; /* set to keep vref on for differential bool keep_vref_on; /* set to keep vref on for differential
* measurements as well */ * measurements as well */
bool swap_xy; /* swap x and y axes */
/* Settling time of the analog signals; a function of Vcc and the /* Settling time of the analog signals; a function of Vcc and the
* capacitance on the X/Y drivers. If set to non-zero, two samples * capacitance on the X/Y drivers. If set to non-zero, two samples
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment