diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-20 13:17:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-20 13:17:02 -0400 |
commit | 93db6294958f62643a917e44d1abc85440e600cf (patch) | |
tree | 33de2c41b0f70d209d64487d1a2bba6d673015ef /drivers/input | |
parent | 43813f399c72aa22e01a680559c1cb5274bf2140 (diff) | |
parent | eef3e4cab72eaf5345e3c73b2975c194a714f6cd (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (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
...
Diffstat (limited to 'drivers/input')
40 files changed, 4122 insertions, 217 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 7a7a026ba712..114efd8dc8f5 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -25,7 +25,6 @@ struct evdev { | |||
25 | int exist; | 25 | int exist; |
26 | int open; | 26 | int open; |
27 | int minor; | 27 | int minor; |
28 | char name[16]; | ||
29 | struct input_handle handle; | 28 | struct input_handle handle; |
30 | wait_queue_head_t wait; | 29 | wait_queue_head_t wait; |
31 | struct evdev_client *grab; | 30 | struct evdev_client *grab; |
@@ -609,7 +608,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
609 | p, compat_mode); | 608 | p, compat_mode); |
610 | 609 | ||
611 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 610 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
612 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); | 611 | return str_to_user(dev_name(&evdev->dev), |
612 | _IOC_SIZE(cmd), p); | ||
613 | 613 | ||
614 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 614 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
615 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 615 | 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 | abs.maximum = dev->absmax[t]; | 626 | abs.maximum = dev->absmax[t]; |
627 | abs.fuzz = dev->absfuzz[t]; | 627 | abs.fuzz = dev->absfuzz[t]; |
628 | abs.flat = dev->absflat[t]; | 628 | abs.flat = dev->absflat[t]; |
629 | abs.resolution = dev->absres[t]; | ||
629 | 630 | ||
630 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 631 | if (copy_to_user(p, &abs, min_t(size_t, |
632 | _IOC_SIZE(cmd), | ||
633 | sizeof(struct input_absinfo)))) | ||
631 | return -EFAULT; | 634 | return -EFAULT; |
632 | 635 | ||
633 | return 0; | 636 | return 0; |
@@ -654,8 +657,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
654 | 657 | ||
655 | t = _IOC_NR(cmd) & ABS_MAX; | 658 | t = _IOC_NR(cmd) & ABS_MAX; |
656 | 659 | ||
657 | if (copy_from_user(&abs, p, | 660 | if (copy_from_user(&abs, p, min_t(size_t, |
658 | sizeof(struct input_absinfo))) | 661 | _IOC_SIZE(cmd), |
662 | sizeof(struct input_absinfo)))) | ||
659 | return -EFAULT; | 663 | return -EFAULT; |
660 | 664 | ||
661 | /* | 665 | /* |
@@ -670,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
670 | dev->absmax[t] = abs.maximum; | 674 | dev->absmax[t] = abs.maximum; |
671 | dev->absfuzz[t] = abs.fuzz; | 675 | dev->absfuzz[t] = abs.fuzz; |
672 | dev->absflat[t] = abs.flat; | 676 | dev->absflat[t] = abs.flat; |
677 | dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ? | ||
678 | 0 : abs.resolution; | ||
673 | 679 | ||
674 | spin_unlock_irq(&dev->event_lock); | 680 | spin_unlock_irq(&dev->event_lock); |
675 | 681 | ||
@@ -807,16 +813,15 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
807 | mutex_init(&evdev->mutex); | 813 | mutex_init(&evdev->mutex); |
808 | init_waitqueue_head(&evdev->wait); | 814 | init_waitqueue_head(&evdev->wait); |
809 | 815 | ||
810 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | 816 | dev_set_name(&evdev->dev, "event%d", minor); |
811 | evdev->exist = 1; | 817 | evdev->exist = 1; |
812 | evdev->minor = minor; | 818 | evdev->minor = minor; |
813 | 819 | ||
814 | evdev->handle.dev = input_get_device(dev); | 820 | evdev->handle.dev = input_get_device(dev); |
815 | evdev->handle.name = evdev->name; | 821 | evdev->handle.name = dev_name(&evdev->dev); |
816 | evdev->handle.handler = handler; | 822 | evdev->handle.handler = handler; |
817 | evdev->handle.private = evdev; | 823 | evdev->handle.private = evdev; |
818 | 824 | ||
819 | dev_set_name(&evdev->dev, evdev->name); | ||
820 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | 825 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); |
821 | evdev->dev.class = &input_class; | 826 | evdev->dev.class = &input_class; |
822 | evdev->dev.parent = &dev->dev; | 827 | evdev->dev.parent = &dev->dev; |
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 1dec00e20dbc..8a1810f88b9e 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c | |||
@@ -167,5 +167,6 @@ module_exit(fm801_gp_exit); | |||
167 | 167 | ||
168 | MODULE_DEVICE_TABLE(pci, fm801_gp_id_table); | 168 | MODULE_DEVICE_TABLE(pci, fm801_gp_id_table); |
169 | 169 | ||
170 | MODULE_DESCRIPTION("FM801 gameport driver"); | ||
170 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | 171 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
171 | MODULE_LICENSE("GPL"); | 172 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 2d175b5928ff..ac11be08585e 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -30,16 +30,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
30 | MODULE_DESCRIPTION("Generic gameport layer"); | 30 | MODULE_DESCRIPTION("Generic gameport layer"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
33 | EXPORT_SYMBOL(__gameport_register_port); | ||
34 | EXPORT_SYMBOL(gameport_unregister_port); | ||
35 | EXPORT_SYMBOL(__gameport_register_driver); | ||
36 | EXPORT_SYMBOL(gameport_unregister_driver); | ||
37 | EXPORT_SYMBOL(gameport_open); | ||
38 | EXPORT_SYMBOL(gameport_close); | ||
39 | EXPORT_SYMBOL(gameport_set_phys); | ||
40 | EXPORT_SYMBOL(gameport_start_polling); | ||
41 | EXPORT_SYMBOL(gameport_stop_polling); | ||
42 | |||
43 | /* | 33 | /* |
44 | * gameport_mutex protects entire gameport subsystem and is taken | 34 | * gameport_mutex protects entire gameport subsystem and is taken |
45 | * every time gameport port or driver registrered or unregistered. | 35 | * every time gameport port or driver registrered or unregistered. |
@@ -162,6 +152,7 @@ void gameport_start_polling(struct gameport *gameport) | |||
162 | 152 | ||
163 | spin_unlock(&gameport->timer_lock); | 153 | spin_unlock(&gameport->timer_lock); |
164 | } | 154 | } |
155 | EXPORT_SYMBOL(gameport_start_polling); | ||
165 | 156 | ||
166 | void gameport_stop_polling(struct gameport *gameport) | 157 | void gameport_stop_polling(struct gameport *gameport) |
167 | { | 158 | { |
@@ -172,6 +163,7 @@ void gameport_stop_polling(struct gameport *gameport) | |||
172 | 163 | ||
173 | spin_unlock(&gameport->timer_lock); | 164 | spin_unlock(&gameport->timer_lock); |
174 | } | 165 | } |
166 | EXPORT_SYMBOL(gameport_stop_polling); | ||
175 | 167 | ||
176 | static void gameport_run_poll_handler(unsigned long d) | 168 | static void gameport_run_poll_handler(unsigned long d) |
177 | { | 169 | { |
@@ -516,6 +508,7 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) | |||
516 | vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args); | 508 | vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args); |
517 | va_end(args); | 509 | va_end(args); |
518 | } | 510 | } |
511 | EXPORT_SYMBOL(gameport_set_phys); | ||
519 | 512 | ||
520 | /* | 513 | /* |
521 | * Prepare gameport port for registration. | 514 | * Prepare gameport port for registration. |
@@ -658,6 +651,7 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner) | |||
658 | gameport_init_port(gameport); | 651 | gameport_init_port(gameport); |
659 | gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT); | 652 | gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT); |
660 | } | 653 | } |
654 | EXPORT_SYMBOL(__gameport_register_port); | ||
661 | 655 | ||
662 | /* | 656 | /* |
663 | * Synchronously unregisters gameport port. | 657 | * Synchronously unregisters gameport port. |
@@ -669,6 +663,7 @@ void gameport_unregister_port(struct gameport *gameport) | |||
669 | gameport_destroy_port(gameport); | 663 | gameport_destroy_port(gameport); |
670 | mutex_unlock(&gameport_mutex); | 664 | mutex_unlock(&gameport_mutex); |
671 | } | 665 | } |
666 | EXPORT_SYMBOL(gameport_unregister_port); | ||
672 | 667 | ||
673 | 668 | ||
674 | /* | 669 | /* |
@@ -728,7 +723,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner | |||
728 | * Temporarily disable automatic binding because probing | 723 | * Temporarily disable automatic binding because probing |
729 | * takes long time and we are better off doing it in kgameportd | 724 | * takes long time and we are better off doing it in kgameportd |
730 | */ | 725 | */ |
731 | drv->ignore = 1; | 726 | drv->ignore = true; |
732 | 727 | ||
733 | error = driver_register(&drv->driver); | 728 | error = driver_register(&drv->driver); |
734 | if (error) { | 729 | if (error) { |
@@ -741,7 +736,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner | |||
741 | /* | 736 | /* |
742 | * Reset ignore flag and let kgameportd bind the driver to free ports | 737 | * Reset ignore flag and let kgameportd bind the driver to free ports |
743 | */ | 738 | */ |
744 | drv->ignore = 0; | 739 | drv->ignore = false; |
745 | error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); | 740 | error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); |
746 | if (error) { | 741 | if (error) { |
747 | driver_unregister(&drv->driver); | 742 | driver_unregister(&drv->driver); |
@@ -750,6 +745,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner | |||
750 | 745 | ||
751 | return 0; | 746 | return 0; |
752 | } | 747 | } |
748 | EXPORT_SYMBOL(__gameport_register_driver); | ||
753 | 749 | ||
754 | void gameport_unregister_driver(struct gameport_driver *drv) | 750 | void gameport_unregister_driver(struct gameport_driver *drv) |
755 | { | 751 | { |
@@ -757,7 +753,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) | |||
757 | 753 | ||
758 | mutex_lock(&gameport_mutex); | 754 | mutex_lock(&gameport_mutex); |
759 | 755 | ||
760 | drv->ignore = 1; /* so gameport_find_driver ignores it */ | 756 | drv->ignore = true; /* so gameport_find_driver ignores it */ |
761 | gameport_remove_pending_events(drv); | 757 | gameport_remove_pending_events(drv); |
762 | 758 | ||
763 | start_over: | 759 | start_over: |
@@ -774,6 +770,7 @@ start_over: | |||
774 | 770 | ||
775 | mutex_unlock(&gameport_mutex); | 771 | mutex_unlock(&gameport_mutex); |
776 | } | 772 | } |
773 | EXPORT_SYMBOL(gameport_unregister_driver); | ||
777 | 774 | ||
778 | static int gameport_bus_match(struct device *dev, struct device_driver *drv) | 775 | static int gameport_bus_match(struct device *dev, struct device_driver *drv) |
779 | { | 776 | { |
@@ -812,6 +809,7 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo | |||
812 | gameport_set_drv(gameport, drv); | 809 | gameport_set_drv(gameport, drv); |
813 | return 0; | 810 | return 0; |
814 | } | 811 | } |
812 | EXPORT_SYMBOL(gameport_open); | ||
815 | 813 | ||
816 | void gameport_close(struct gameport *gameport) | 814 | void gameport_close(struct gameport *gameport) |
817 | { | 815 | { |
@@ -822,6 +820,7 @@ void gameport_close(struct gameport *gameport) | |||
822 | if (gameport->close) | 820 | if (gameport->close) |
823 | gameport->close(gameport); | 821 | gameport->close(gameport); |
824 | } | 822 | } |
823 | EXPORT_SYMBOL(gameport_close); | ||
825 | 824 | ||
826 | static int __init gameport_init(void) | 825 | static int __init gameport_init(void) |
827 | { | 826 | { |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 012a5e753991..0e12f89276a3 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -39,7 +39,6 @@ struct joydev { | |||
39 | int exist; | 39 | int exist; |
40 | int open; | 40 | int open; |
41 | int minor; | 41 | int minor; |
42 | char name[16]; | ||
43 | struct input_handle handle; | 42 | struct input_handle handle; |
44 | wait_queue_head_t wait; | 43 | wait_queue_head_t wait; |
45 | struct list_head client_list; | 44 | struct list_head client_list; |
@@ -537,12 +536,14 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
537 | default: | 536 | default: |
538 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | 537 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { |
539 | int len; | 538 | int len; |
540 | if (!dev->name) | 539 | const char *name = dev_name(&dev->dev); |
540 | |||
541 | if (!name) | ||
541 | return 0; | 542 | return 0; |
542 | len = strlen(dev->name) + 1; | 543 | len = strlen(name) + 1; |
543 | if (len > _IOC_SIZE(cmd)) | 544 | if (len > _IOC_SIZE(cmd)) |
544 | len = _IOC_SIZE(cmd); | 545 | len = _IOC_SIZE(cmd); |
545 | if (copy_to_user(argp, dev->name, len)) | 546 | if (copy_to_user(argp, name, len)) |
546 | return -EFAULT; | 547 | return -EFAULT; |
547 | return len; | 548 | return len; |
548 | } | 549 | } |
@@ -742,13 +743,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
742 | mutex_init(&joydev->mutex); | 743 | mutex_init(&joydev->mutex); |
743 | init_waitqueue_head(&joydev->wait); | 744 | init_waitqueue_head(&joydev->wait); |
744 | 745 | ||
745 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); | 746 | dev_set_name(&joydev->dev, "js%d", minor); |
746 | joydev->exist = 1; | 747 | joydev->exist = 1; |
747 | joydev->minor = minor; | 748 | joydev->minor = minor; |
748 | 749 | ||
749 | joydev->exist = 1; | 750 | joydev->exist = 1; |
750 | joydev->handle.dev = input_get_device(dev); | 751 | joydev->handle.dev = input_get_device(dev); |
751 | joydev->handle.name = joydev->name; | 752 | joydev->handle.name = dev_name(&joydev->dev); |
752 | joydev->handle.handler = handler; | 753 | joydev->handle.handler = handler; |
753 | joydev->handle.private = joydev; | 754 | joydev->handle.private = joydev; |
754 | 755 | ||
@@ -797,7 +798,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
797 | } | 798 | } |
798 | } | 799 | } |
799 | 800 | ||
800 | dev_set_name(&joydev->dev, joydev->name); | ||
801 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); | 801 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); |
802 | joydev->dev.class = &input_class; | 802 | joydev->dev.class = &input_class; |
803 | joydev->dev.parent = &dev->dev; | 803 | joydev->dev.parent = &dev->dev; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index ea2638b41982..9d8f796c6745 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -250,6 +250,17 @@ config KEYBOARD_HP7XX | |||
250 | To compile this driver as a module, choose M here: the | 250 | To compile this driver as a module, choose M here: the |
251 | module will be called jornada720_kbd. | 251 | module will be called jornada720_kbd. |
252 | 252 | ||
253 | config KEYBOARD_LM8323 | ||
254 | tristate "LM8323 keypad chip" | ||
255 | depends on I2C | ||
256 | depends on LEDS_CLASS | ||
257 | help | ||
258 | If you say yes here you get support for the National Semiconductor | ||
259 | LM8323 keypad controller. | ||
260 | |||
261 | To compile this driver as a module, choose M here: the | ||
262 | module will be called lm8323. | ||
263 | |||
253 | config KEYBOARD_OMAP | 264 | config KEYBOARD_OMAP |
254 | tristate "TI OMAP keypad support" | 265 | tristate "TI OMAP keypad support" |
255 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 266 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
@@ -332,4 +343,14 @@ config KEYBOARD_SH_KEYSC | |||
332 | 343 | ||
333 | To compile this driver as a module, choose M here: the | 344 | To compile this driver as a module, choose M here: the |
334 | module will be called sh_keysc. | 345 | module will be called sh_keysc. |
346 | |||
347 | config KEYBOARD_EP93XX | ||
348 | tristate "EP93xx Matrix Keypad support" | ||
349 | depends on ARCH_EP93XX | ||
350 | help | ||
351 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. | ||
352 | |||
353 | To compile this driver as a module, choose M here: the | ||
354 | module will be called ep93xx_keypad. | ||
355 | |||
335 | endif | 356 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 36351e1190f9..156b647a259b 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | |||
18 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 18 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o |
19 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
20 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 20 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
21 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | ||
21 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 22 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
22 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 23 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
23 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 24 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
@@ -28,3 +29,4 @@ obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | |||
28 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | 29 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o |
29 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 30 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
30 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 31 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
32 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | ||
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c new file mode 100644 index 000000000000..181d30e3018e --- /dev/null +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | * Driver for the Cirrus EP93xx matrix keypad controller. | ||
3 | * | ||
4 | * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com> | ||
5 | * | ||
6 | * Based on the pxa27x matrix keypad controller by Rodolfo Giometti. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * NOTE: | ||
13 | * | ||
14 | * The 3-key reset is triggered by pressing the 3 keys in | ||
15 | * Row 0, Columns 2, 4, and 7 at the same time. This action can | ||
16 | * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag. | ||
17 | * | ||
18 | * Normal operation for the matrix does not autorepeat the key press. | ||
19 | * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT | ||
20 | * flag. | ||
21 | */ | ||
22 | |||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/clk.h> | ||
27 | |||
28 | #include <mach/hardware.h> | ||
29 | #include <mach/gpio.h> | ||
30 | #include <mach/ep93xx_keypad.h> | ||
31 | |||
32 | /* | ||
33 | * Keypad Interface Register offsets | ||
34 | */ | ||
35 | #define KEY_INIT 0x00 /* Key Scan Initialization register */ | ||
36 | #define KEY_DIAG 0x04 /* Key Scan Diagnostic register */ | ||
37 | #define KEY_REG 0x08 /* Key Value Capture register */ | ||
38 | |||
39 | /* Key Scan Initialization Register bit defines */ | ||
40 | #define KEY_INIT_DBNC_MASK (0x00ff0000) | ||
41 | #define KEY_INIT_DBNC_SHIFT (16) | ||
42 | #define KEY_INIT_DIS3KY (1<<15) | ||
43 | #define KEY_INIT_DIAG (1<<14) | ||
44 | #define KEY_INIT_BACK (1<<13) | ||
45 | #define KEY_INIT_T2 (1<<12) | ||
46 | #define KEY_INIT_PRSCL_MASK (0x000003ff) | ||
47 | #define KEY_INIT_PRSCL_SHIFT (0) | ||
48 | |||
49 | /* Key Scan Diagnostic Register bit defines */ | ||
50 | #define KEY_DIAG_MASK (0x0000003f) | ||
51 | #define KEY_DIAG_SHIFT (0) | ||
52 | |||
53 | /* Key Value Capture Register bit defines */ | ||
54 | #define KEY_REG_K (1<<15) | ||
55 | #define KEY_REG_INT (1<<14) | ||
56 | #define KEY_REG_2KEYS (1<<13) | ||
57 | #define KEY_REG_1KEY (1<<12) | ||
58 | #define KEY_REG_KEY2_MASK (0x00000fc0) | ||
59 | #define KEY_REG_KEY2_SHIFT (6) | ||
60 | #define KEY_REG_KEY1_MASK (0x0000003f) | ||
61 | #define KEY_REG_KEY1_SHIFT (0) | ||
62 | |||
63 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | ||
64 | #define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off)) | ||
65 | |||
66 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) | ||
67 | |||
68 | struct ep93xx_keypad { | ||
69 | struct ep93xx_keypad_platform_data *pdata; | ||
70 | |||
71 | struct clk *clk; | ||
72 | struct input_dev *input_dev; | ||
73 | void __iomem *mmio_base; | ||
74 | |||
75 | int irq; | ||
76 | int enabled; | ||
77 | |||
78 | int key1; | ||
79 | int key2; | ||
80 | |||
81 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | ||
82 | }; | ||
83 | |||
84 | static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) | ||
85 | { | ||
86 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | ||
87 | struct input_dev *input_dev = keypad->input_dev; | ||
88 | int i; | ||
89 | |||
90 | for (i = 0; i < pdata->matrix_key_map_size; i++) { | ||
91 | unsigned int key = pdata->matrix_key_map[i]; | ||
92 | int row = (key >> 28) & 0xf; | ||
93 | int col = (key >> 24) & 0xf; | ||
94 | int code = key & 0xffffff; | ||
95 | |||
96 | keypad->matrix_keycodes[(row << 3) + col] = code; | ||
97 | __set_bit(code, input_dev->keybit); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) | ||
102 | { | ||
103 | struct ep93xx_keypad *keypad = dev_id; | ||
104 | struct input_dev *input_dev = keypad->input_dev; | ||
105 | unsigned int status = keypad_readl(KEY_REG); | ||
106 | int keycode, key1, key2; | ||
107 | |||
108 | keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; | ||
109 | key1 = keypad->matrix_keycodes[keycode]; | ||
110 | |||
111 | keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT; | ||
112 | key2 = keypad->matrix_keycodes[keycode]; | ||
113 | |||
114 | if (status & KEY_REG_2KEYS) { | ||
115 | if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1) | ||
116 | input_report_key(input_dev, keypad->key1, 0); | ||
117 | |||
118 | if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2) | ||
119 | input_report_key(input_dev, keypad->key2, 0); | ||
120 | |||
121 | input_report_key(input_dev, key1, 1); | ||
122 | input_report_key(input_dev, key2, 1); | ||
123 | |||
124 | keypad->key1 = key1; | ||
125 | keypad->key2 = key2; | ||
126 | |||
127 | } else if (status & KEY_REG_1KEY) { | ||
128 | if (keypad->key1 && key1 != keypad->key1) | ||
129 | input_report_key(input_dev, keypad->key1, 0); | ||
130 | |||
131 | if (keypad->key2 && key1 != keypad->key2) | ||
132 | input_report_key(input_dev, keypad->key2, 0); | ||
133 | |||
134 | input_report_key(input_dev, key1, 1); | ||
135 | |||
136 | keypad->key1 = key1; | ||
137 | keypad->key2 = 0; | ||
138 | |||
139 | } else { | ||
140 | input_report_key(input_dev, keypad->key1, 0); | ||
141 | input_report_key(input_dev, keypad->key2, 0); | ||
142 | |||
143 | keypad->key1 = keypad->key2 = 0; | ||
144 | } | ||
145 | input_sync(input_dev); | ||
146 | |||
147 | return IRQ_HANDLED; | ||
148 | } | ||
149 | |||
150 | static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) | ||
151 | { | ||
152 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | ||
153 | unsigned int val = 0; | ||
154 | |||
155 | clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV); | ||
156 | |||
157 | if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) | ||
158 | val |= KEY_INIT_DIS3KY; | ||
159 | if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE) | ||
160 | val |= KEY_INIT_DIAG; | ||
161 | if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE) | ||
162 | val |= KEY_INIT_BACK; | ||
163 | if (pdata->flags & EP93XX_KEYPAD_TEST_MODE) | ||
164 | val |= KEY_INIT_T2; | ||
165 | |||
166 | val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK); | ||
167 | |||
168 | val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); | ||
169 | |||
170 | keypad_writel(val, KEY_INIT); | ||
171 | } | ||
172 | |||
173 | static int ep93xx_keypad_open(struct input_dev *pdev) | ||
174 | { | ||
175 | struct ep93xx_keypad *keypad = input_get_drvdata(pdev); | ||
176 | |||
177 | if (!keypad->enabled) { | ||
178 | ep93xx_keypad_config(keypad); | ||
179 | clk_enable(keypad->clk); | ||
180 | keypad->enabled = 1; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static void ep93xx_keypad_close(struct input_dev *pdev) | ||
187 | { | ||
188 | struct ep93xx_keypad *keypad = input_get_drvdata(pdev); | ||
189 | |||
190 | if (keypad->enabled) { | ||
191 | clk_disable(keypad->clk); | ||
192 | keypad->enabled = 0; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | |||
197 | #ifdef CONFIG_PM | ||
198 | /* | ||
199 | * NOTE: I don't know if this is correct, or will work on the ep93xx. | ||
200 | * | ||
201 | * None of the existing ep93xx drivers have power management support. | ||
202 | * But, this is basically what the pxa27x_keypad driver does. | ||
203 | */ | ||
204 | static int ep93xx_keypad_suspend(struct platform_device *pdev, | ||
205 | pm_message_t state) | ||
206 | { | ||
207 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | ||
208 | struct input_dev *input_dev = keypad->input_dev; | ||
209 | |||
210 | mutex_lock(&input_dev->mutex); | ||
211 | |||
212 | if (keypad->enabled) { | ||
213 | clk_disable(keypad->clk); | ||
214 | keypad->enabled = 0; | ||
215 | } | ||
216 | |||
217 | mutex_unlock(&input_dev->mutex); | ||
218 | |||
219 | if (device_may_wakeup(&pdev->dev)) | ||
220 | enable_irq_wake(keypad->irq); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int ep93xx_keypad_resume(struct platform_device *pdev) | ||
226 | { | ||
227 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | ||
228 | struct input_dev *input_dev = keypad->input_dev; | ||
229 | |||
230 | if (device_may_wakeup(&pdev->dev)) | ||
231 | disable_irq_wake(keypad->irq); | ||
232 | |||
233 | mutex_lock(&input_dev->mutex); | ||
234 | |||
235 | if (input_dev->users) { | ||
236 | if (!keypad->enabled) { | ||
237 | ep93xx_keypad_config(keypad); | ||
238 | clk_enable(keypad->clk); | ||
239 | keypad->enabled = 1; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | mutex_unlock(&input_dev->mutex); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | #else /* !CONFIG_PM */ | ||
248 | #define ep93xx_keypad_suspend NULL | ||
249 | #define ep93xx_keypad_resume NULL | ||
250 | #endif /* !CONFIG_PM */ | ||
251 | |||
252 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | struct ep93xx_keypad *keypad; | ||
255 | struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data; | ||
256 | struct input_dev *input_dev; | ||
257 | struct resource *res; | ||
258 | int irq, err, i, gpio; | ||
259 | |||
260 | if (!pdata || | ||
261 | !pdata->matrix_key_rows || | ||
262 | pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS || | ||
263 | !pdata->matrix_key_cols || | ||
264 | pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) { | ||
265 | dev_err(&pdev->dev, "invalid or missing platform data\n"); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); | ||
270 | if (!keypad) { | ||
271 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | |||
275 | keypad->pdata = pdata; | ||
276 | |||
277 | irq = platform_get_irq(pdev, 0); | ||
278 | if (irq < 0) { | ||
279 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
280 | err = -ENXIO; | ||
281 | goto failed_free; | ||
282 | } | ||
283 | |||
284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
285 | if (!res) { | ||
286 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
287 | err = -ENXIO; | ||
288 | goto failed_free; | ||
289 | } | ||
290 | |||
291 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
292 | if (!res) { | ||
293 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
294 | err = -EBUSY; | ||
295 | goto failed_free; | ||
296 | } | ||
297 | |||
298 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
299 | if (keypad->mmio_base == NULL) { | ||
300 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
301 | err = -ENXIO; | ||
302 | goto failed_free_mem; | ||
303 | } | ||
304 | |||
305 | /* Request the needed GPIO's */ | ||
306 | gpio = EP93XX_GPIO_LINE_ROW0; | ||
307 | for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) { | ||
308 | err = gpio_request(gpio, pdev->name); | ||
309 | if (err) { | ||
310 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
311 | gpio); | ||
312 | goto failed_free_rows; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | gpio = EP93XX_GPIO_LINE_COL0; | ||
317 | for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) { | ||
318 | err = gpio_request(gpio, pdev->name); | ||
319 | if (err) { | ||
320 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
321 | gpio); | ||
322 | goto failed_free_cols; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | keypad->clk = clk_get(&pdev->dev, "key_clk"); | ||
327 | if (IS_ERR(keypad->clk)) { | ||
328 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
329 | err = PTR_ERR(keypad->clk); | ||
330 | goto failed_free_io; | ||
331 | } | ||
332 | |||
333 | /* Create and register the input driver */ | ||
334 | input_dev = input_allocate_device(); | ||
335 | if (!input_dev) { | ||
336 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
337 | err = -ENOMEM; | ||
338 | goto failed_put_clk; | ||
339 | } | ||
340 | |||
341 | keypad->input_dev = input_dev; | ||
342 | |||
343 | input_dev->name = pdev->name; | ||
344 | input_dev->id.bustype = BUS_HOST; | ||
345 | input_dev->open = ep93xx_keypad_open; | ||
346 | input_dev->close = ep93xx_keypad_close; | ||
347 | input_dev->dev.parent = &pdev->dev; | ||
348 | input_dev->keycode = keypad->matrix_keycodes; | ||
349 | input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]); | ||
350 | input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes); | ||
351 | |||
352 | input_set_drvdata(input_dev, keypad); | ||
353 | |||
354 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
355 | if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) | ||
356 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
357 | |||
358 | ep93xx_keypad_build_keycode(keypad); | ||
359 | platform_set_drvdata(pdev, keypad); | ||
360 | |||
361 | err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED, | ||
362 | pdev->name, keypad); | ||
363 | if (err) { | ||
364 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
365 | goto failed_free_dev; | ||
366 | } | ||
367 | |||
368 | keypad->irq = irq; | ||
369 | |||
370 | /* Register the input device */ | ||
371 | err = input_register_device(input_dev); | ||
372 | if (err) { | ||
373 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
374 | goto failed_free_irq; | ||
375 | } | ||
376 | |||
377 | device_init_wakeup(&pdev->dev, 1); | ||
378 | |||
379 | return 0; | ||
380 | |||
381 | failed_free_irq: | ||
382 | free_irq(irq, pdev); | ||
383 | platform_set_drvdata(pdev, NULL); | ||
384 | failed_free_dev: | ||
385 | input_free_device(input_dev); | ||
386 | failed_put_clk: | ||
387 | clk_put(keypad->clk); | ||
388 | failed_free_io: | ||
389 | i = keypad->pdata->matrix_key_cols - 1; | ||
390 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
391 | failed_free_cols: | ||
392 | for ( ; i >= 0; i--, gpio--) | ||
393 | gpio_free(gpio); | ||
394 | i = keypad->pdata->matrix_key_rows - 1; | ||
395 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
396 | failed_free_rows: | ||
397 | for ( ; i >= 0; i--, gpio--) | ||
398 | gpio_free(gpio); | ||
399 | iounmap(keypad->mmio_base); | ||
400 | failed_free_mem: | ||
401 | release_mem_region(res->start, resource_size(res)); | ||
402 | failed_free: | ||
403 | kfree(keypad); | ||
404 | return err; | ||
405 | } | ||
406 | |||
407 | static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) | ||
408 | { | ||
409 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | ||
410 | struct resource *res; | ||
411 | int i, gpio; | ||
412 | |||
413 | free_irq(keypad->irq, pdev); | ||
414 | |||
415 | platform_set_drvdata(pdev, NULL); | ||
416 | |||
417 | if (keypad->enabled) | ||
418 | clk_disable(keypad->clk); | ||
419 | clk_put(keypad->clk); | ||
420 | |||
421 | input_unregister_device(keypad->input_dev); | ||
422 | |||
423 | i = keypad->pdata->matrix_key_cols - 1; | ||
424 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
425 | for ( ; i >= 0; i--, gpio--) | ||
426 | gpio_free(gpio); | ||
427 | |||
428 | i = keypad->pdata->matrix_key_rows - 1; | ||
429 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
430 | for ( ; i >= 0; i--, gpio--) | ||
431 | gpio_free(gpio); | ||
432 | |||
433 | iounmap(keypad->mmio_base); | ||
434 | |||
435 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
436 | release_mem_region(res->start, resource_size(res)); | ||
437 | |||
438 | kfree(keypad); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static struct platform_driver ep93xx_keypad_driver = { | ||
444 | .driver = { | ||
445 | .name = "ep93xx-keypad", | ||
446 | .owner = THIS_MODULE, | ||
447 | }, | ||
448 | .probe = ep93xx_keypad_probe, | ||
449 | .remove = __devexit_p(ep93xx_keypad_remove), | ||
450 | .suspend = ep93xx_keypad_suspend, | ||
451 | .resume = ep93xx_keypad_resume, | ||
452 | }; | ||
453 | |||
454 | static int __init ep93xx_keypad_init(void) | ||
455 | { | ||
456 | return platform_driver_register(&ep93xx_keypad_driver); | ||
457 | } | ||
458 | |||
459 | static void __exit ep93xx_keypad_exit(void) | ||
460 | { | ||
461 | platform_driver_unregister(&ep93xx_keypad_driver); | ||
462 | } | ||
463 | |||
464 | module_init(ep93xx_keypad_init); | ||
465 | module_exit(ep93xx_keypad_exit); | ||
466 | |||
467 | MODULE_LICENSE("GPL"); | ||
468 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); | ||
469 | MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller"); | ||
470 | MODULE_ALIAS("platform:ep93xx-keypad"); | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ad67d763fdbd..2157cd7de00c 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -22,13 +22,14 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
24 | #include <linux/gpio_keys.h> | 24 | #include <linux/gpio_keys.h> |
25 | #include <linux/workqueue.h> | ||
25 | 26 | ||
26 | #include <asm/gpio.h> | 27 | #include <asm/gpio.h> |
27 | 28 | ||
28 | struct gpio_button_data { | 29 | struct gpio_button_data { |
29 | struct gpio_keys_button *button; | 30 | struct gpio_keys_button *button; |
30 | struct input_dev *input; | 31 | struct input_dev *input; |
31 | struct timer_list timer; | 32 | struct delayed_work work; |
32 | }; | 33 | }; |
33 | 34 | ||
34 | struct gpio_keys_drvdata { | 35 | struct gpio_keys_drvdata { |
@@ -36,8 +37,10 @@ struct gpio_keys_drvdata { | |||
36 | struct gpio_button_data data[0]; | 37 | struct gpio_button_data data[0]; |
37 | }; | 38 | }; |
38 | 39 | ||
39 | static void gpio_keys_report_event(struct gpio_button_data *bdata) | 40 | static void gpio_keys_report_event(struct work_struct *work) |
40 | { | 41 | { |
42 | struct gpio_button_data *bdata = | ||
43 | container_of(work, struct gpio_button_data, work.work); | ||
41 | struct gpio_keys_button *button = bdata->button; | 44 | struct gpio_keys_button *button = bdata->button; |
42 | struct input_dev *input = bdata->input; | 45 | struct input_dev *input = bdata->input; |
43 | unsigned int type = button->type ?: EV_KEY; | 46 | unsigned int type = button->type ?: EV_KEY; |
@@ -47,25 +50,17 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) | |||
47 | input_sync(input); | 50 | input_sync(input); |
48 | } | 51 | } |
49 | 52 | ||
50 | static void gpio_check_button(unsigned long _data) | ||
51 | { | ||
52 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | ||
53 | |||
54 | gpio_keys_report_event(data); | ||
55 | } | ||
56 | |||
57 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 53 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
58 | { | 54 | { |
59 | struct gpio_button_data *bdata = dev_id; | 55 | struct gpio_button_data *bdata = dev_id; |
60 | struct gpio_keys_button *button = bdata->button; | 56 | struct gpio_keys_button *button = bdata->button; |
57 | unsigned long delay; | ||
61 | 58 | ||
62 | BUG_ON(irq != gpio_to_irq(button->gpio)); | 59 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
63 | 60 | ||
64 | if (button->debounce_interval) | 61 | delay = button->debounce_interval ? |
65 | mod_timer(&bdata->timer, | 62 | msecs_to_jiffies(button->debounce_interval) : 0; |
66 | jiffies + msecs_to_jiffies(button->debounce_interval)); | 63 | schedule_delayed_work(&bdata->work, delay); |
67 | else | ||
68 | gpio_keys_report_event(bdata); | ||
69 | 64 | ||
70 | return IRQ_HANDLED; | 65 | return IRQ_HANDLED; |
71 | } | 66 | } |
@@ -112,8 +107,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
112 | 107 | ||
113 | bdata->input = input; | 108 | bdata->input = input; |
114 | bdata->button = button; | 109 | bdata->button = button; |
115 | setup_timer(&bdata->timer, | 110 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); |
116 | gpio_check_button, (unsigned long)bdata); | ||
117 | 111 | ||
118 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); | 112 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); |
119 | if (error < 0) { | 113 | if (error < 0) { |
@@ -142,8 +136,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
142 | } | 136 | } |
143 | 137 | ||
144 | error = request_irq(irq, gpio_keys_isr, | 138 | error = request_irq(irq, gpio_keys_isr, |
145 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | 139 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
146 | IRQF_TRIGGER_FALLING, | ||
147 | button->desc ? button->desc : "gpio_keys", | 140 | button->desc ? button->desc : "gpio_keys", |
148 | bdata); | 141 | bdata); |
149 | if (error) { | 142 | if (error) { |
@@ -173,8 +166,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
173 | fail2: | 166 | fail2: |
174 | while (--i >= 0) { | 167 | while (--i >= 0) { |
175 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 168 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
176 | if (pdata->buttons[i].debounce_interval) | 169 | cancel_delayed_work_sync(&ddata->data[i].work); |
177 | del_timer_sync(&ddata->data[i].timer); | ||
178 | gpio_free(pdata->buttons[i].gpio); | 170 | gpio_free(pdata->buttons[i].gpio); |
179 | } | 171 | } |
180 | 172 | ||
@@ -198,8 +190,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
198 | for (i = 0; i < pdata->nbuttons; i++) { | 190 | for (i = 0; i < pdata->nbuttons; i++) { |
199 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 191 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
200 | free_irq(irq, &ddata->data[i]); | 192 | free_irq(irq, &ddata->data[i]); |
201 | if (pdata->buttons[i].debounce_interval) | 193 | cancel_delayed_work_sync(&ddata->data[i].work); |
202 | del_timer_sync(&ddata->data[i].timer); | ||
203 | gpio_free(pdata->buttons[i].gpio); | 194 | gpio_free(pdata->buttons[i].gpio); |
204 | } | 195 | } |
205 | 196 | ||
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c new file mode 100644 index 000000000000..574eda2a4957 --- /dev/null +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -0,0 +1,878 @@ | |||
1 | /* | ||
2 | * drivers/i2c/chips/lm8323.c | ||
3 | * | ||
4 | * Copyright (C) 2007-2009 Nokia Corporation | ||
5 | * | ||
6 | * Written by Daniel Stone <daniel.stone@nokia.com> | ||
7 | * Timo O. Karjalainen <timo.o.karjalainen@nokia.com> | ||
8 | * | ||
9 | * Updated by Felipe Balbi <felipe.balbi@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation (version 2 of the License only). | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/input.h> | ||
32 | #include <linux/leds.h> | ||
33 | #include <linux/i2c/lm8323.h> | ||
34 | |||
35 | /* Commands to send to the chip. */ | ||
36 | #define LM8323_CMD_READ_ID 0x80 /* Read chip ID. */ | ||
37 | #define LM8323_CMD_WRITE_CFG 0x81 /* Set configuration item. */ | ||
38 | #define LM8323_CMD_READ_INT 0x82 /* Get interrupt status. */ | ||
39 | #define LM8323_CMD_RESET 0x83 /* Reset, same as external one */ | ||
40 | #define LM8323_CMD_WRITE_PORT_SEL 0x85 /* Set GPIO in/out. */ | ||
41 | #define LM8323_CMD_WRITE_PORT_STATE 0x86 /* Set GPIO pullup. */ | ||
42 | #define LM8323_CMD_READ_PORT_SEL 0x87 /* Get GPIO in/out. */ | ||
43 | #define LM8323_CMD_READ_PORT_STATE 0x88 /* Get GPIO pullup. */ | ||
44 | #define LM8323_CMD_READ_FIFO 0x89 /* Read byte from FIFO. */ | ||
45 | #define LM8323_CMD_RPT_READ_FIFO 0x8a /* Read FIFO (no increment). */ | ||
46 | #define LM8323_CMD_SET_ACTIVE 0x8b /* Set active time. */ | ||
47 | #define LM8323_CMD_READ_ERR 0x8c /* Get error status. */ | ||
48 | #define LM8323_CMD_READ_ROTATOR 0x8e /* Read rotator status. */ | ||
49 | #define LM8323_CMD_SET_DEBOUNCE 0x8f /* Set debouncing time. */ | ||
50 | #define LM8323_CMD_SET_KEY_SIZE 0x90 /* Set keypad size. */ | ||
51 | #define LM8323_CMD_READ_KEY_SIZE 0x91 /* Get keypad size. */ | ||
52 | #define LM8323_CMD_READ_CFG 0x92 /* Get configuration item. */ | ||
53 | #define LM8323_CMD_WRITE_CLOCK 0x93 /* Set clock config. */ | ||
54 | #define LM8323_CMD_READ_CLOCK 0x94 /* Get clock config. */ | ||
55 | #define LM8323_CMD_PWM_WRITE 0x95 /* Write PWM script. */ | ||
56 | #define LM8323_CMD_START_PWM 0x96 /* Start PWM engine. */ | ||
57 | #define LM8323_CMD_STOP_PWM 0x97 /* Stop PWM engine. */ | ||
58 | |||
59 | /* Interrupt status. */ | ||
60 | #define INT_KEYPAD 0x01 /* Key event. */ | ||
61 | #define INT_ROTATOR 0x02 /* Rotator event. */ | ||
62 | #define INT_ERROR 0x08 /* Error: use CMD_READ_ERR. */ | ||
63 | #define INT_NOINIT 0x10 /* Lost configuration. */ | ||
64 | #define INT_PWM1 0x20 /* PWM1 stopped. */ | ||
65 | #define INT_PWM2 0x40 /* PWM2 stopped. */ | ||
66 | #define INT_PWM3 0x80 /* PWM3 stopped. */ | ||
67 | |||
68 | /* Errors (signalled by INT_ERROR, read with CMD_READ_ERR). */ | ||
69 | #define ERR_BADPAR 0x01 /* Bad parameter. */ | ||
70 | #define ERR_CMDUNK 0x02 /* Unknown command. */ | ||
71 | #define ERR_KEYOVR 0x04 /* Too many keys pressed. */ | ||
72 | #define ERR_FIFOOVER 0x40 /* FIFO overflow. */ | ||
73 | |||
74 | /* Configuration keys (CMD_{WRITE,READ}_CFG). */ | ||
75 | #define CFG_MUX1SEL 0x01 /* Select MUX1_OUT input. */ | ||
76 | #define CFG_MUX1EN 0x02 /* Enable MUX1_OUT. */ | ||
77 | #define CFG_MUX2SEL 0x04 /* Select MUX2_OUT input. */ | ||
78 | #define CFG_MUX2EN 0x08 /* Enable MUX2_OUT. */ | ||
79 | #define CFG_PSIZE 0x20 /* Package size (must be 0). */ | ||
80 | #define CFG_ROTEN 0x40 /* Enable rotator. */ | ||
81 | |||
82 | /* Clock settings (CMD_{WRITE,READ}_CLOCK). */ | ||
83 | #define CLK_RCPWM_INTERNAL 0x00 | ||
84 | #define CLK_RCPWM_EXTERNAL 0x03 | ||
85 | #define CLK_SLOWCLKEN 0x08 /* Enable 32.768kHz clock. */ | ||
86 | #define CLK_SLOWCLKOUT 0x40 /* Enable slow pulse output. */ | ||
87 | |||
88 | /* The possible addresses corresponding to CONFIG1 and CONFIG2 pin wirings. */ | ||
89 | #define LM8323_I2C_ADDR00 (0x84 >> 1) /* 1000 010x */ | ||
90 | #define LM8323_I2C_ADDR01 (0x86 >> 1) /* 1000 011x */ | ||
91 | #define LM8323_I2C_ADDR10 (0x88 >> 1) /* 1000 100x */ | ||
92 | #define LM8323_I2C_ADDR11 (0x8A >> 1) /* 1000 101x */ | ||
93 | |||
94 | /* Key event fifo length */ | ||
95 | #define LM8323_FIFO_LEN 15 | ||
96 | |||
97 | /* Commands for PWM engine; feed in with PWM_WRITE. */ | ||
98 | /* Load ramp counter from duty cycle field (range 0 - 0xff). */ | ||
99 | #define PWM_SET(v) (0x4000 | ((v) & 0xff)) | ||
100 | /* Go to start of script. */ | ||
101 | #define PWM_GOTOSTART 0x0000 | ||
102 | /* | ||
103 | * Stop engine (generates interrupt). If reset is 1, clear the program | ||
104 | * counter, else leave it. | ||
105 | */ | ||
106 | #define PWM_END(reset) (0xc000 | (!!(reset) << 11)) | ||
107 | /* | ||
108 | * Ramp. If s is 1, divide clock by 512, else divide clock by 16. | ||
109 | * Take t clock scales (up to 63) per step, for n steps (up to 126). | ||
110 | * If u is set, ramp up, else ramp down. | ||
111 | */ | ||
112 | #define PWM_RAMP(s, t, n, u) ((!!(s) << 14) | ((t) & 0x3f) << 8 | \ | ||
113 | ((n) & 0x7f) | ((u) ? 0 : 0x80)) | ||
114 | /* | ||
115 | * Loop (i.e. jump back to pos) for a given number of iterations (up to 63). | ||
116 | * If cnt is zero, execute until PWM_END is encountered. | ||
117 | */ | ||
118 | #define PWM_LOOP(cnt, pos) (0xa000 | (((cnt) & 0x3f) << 7) | \ | ||
119 | ((pos) & 0x3f)) | ||
120 | /* | ||
121 | * Wait for trigger. Argument is a mask of channels, shifted by the channel | ||
122 | * number, e.g. 0xa for channels 3 and 1. Note that channels are numbered | ||
123 | * from 1, not 0. | ||
124 | */ | ||
125 | #define PWM_WAIT_TRIG(chans) (0xe000 | (((chans) & 0x7) << 6)) | ||
126 | /* Send trigger. Argument is same as PWM_WAIT_TRIG. */ | ||
127 | #define PWM_SEND_TRIG(chans) (0xe000 | ((chans) & 0x7)) | ||
128 | |||
129 | struct lm8323_pwm { | ||
130 | int id; | ||
131 | int fade_time; | ||
132 | int brightness; | ||
133 | int desired_brightness; | ||
134 | bool enabled; | ||
135 | bool running; | ||
136 | /* pwm lock */ | ||
137 | struct mutex lock; | ||
138 | struct work_struct work; | ||
139 | struct led_classdev cdev; | ||
140 | struct lm8323_chip *chip; | ||
141 | }; | ||
142 | |||
143 | struct lm8323_chip { | ||
144 | /* device lock */ | ||
145 | struct mutex lock; | ||
146 | struct i2c_client *client; | ||
147 | struct work_struct work; | ||
148 | struct input_dev *idev; | ||
149 | bool kp_enabled; | ||
150 | bool pm_suspend; | ||
151 | unsigned keys_down; | ||
152 | char phys[32]; | ||
153 | unsigned short keymap[LM8323_KEYMAP_SIZE]; | ||
154 | int size_x; | ||
155 | int size_y; | ||
156 | int debounce_time; | ||
157 | int active_time; | ||
158 | struct lm8323_pwm pwm[LM8323_NUM_PWMS]; | ||
159 | }; | ||
160 | |||
161 | #define client_to_lm8323(c) container_of(c, struct lm8323_chip, client) | ||
162 | #define dev_to_lm8323(d) container_of(d, struct lm8323_chip, client->dev) | ||
163 | #define work_to_lm8323(w) container_of(w, struct lm8323_chip, work) | ||
164 | #define cdev_to_pwm(c) container_of(c, struct lm8323_pwm, cdev) | ||
165 | #define work_to_pwm(w) container_of(w, struct lm8323_pwm, work) | ||
166 | |||
167 | #define LM8323_MAX_DATA 8 | ||
168 | |||
169 | /* | ||
170 | * To write, we just access the chip's address in write mode, and dump the | ||
171 | * command and data out on the bus. The command byte and data are taken as | ||
172 | * sequential u8s out of varargs, to a maximum of LM8323_MAX_DATA. | ||
173 | */ | ||
174 | static int lm8323_write(struct lm8323_chip *lm, int len, ...) | ||
175 | { | ||
176 | int ret, i; | ||
177 | va_list ap; | ||
178 | u8 data[LM8323_MAX_DATA]; | ||
179 | |||
180 | va_start(ap, len); | ||
181 | |||
182 | if (unlikely(len > LM8323_MAX_DATA)) { | ||
183 | dev_err(&lm->client->dev, "tried to send %d bytes\n", len); | ||
184 | va_end(ap); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | for (i = 0; i < len; i++) | ||
189 | data[i] = va_arg(ap, int); | ||
190 | |||
191 | va_end(ap); | ||
192 | |||
193 | /* | ||
194 | * If the host is asleep while we send the data, we can get a NACK | ||
195 | * back while it wakes up, so try again, once. | ||
196 | */ | ||
197 | ret = i2c_master_send(lm->client, data, len); | ||
198 | if (unlikely(ret == -EREMOTEIO)) | ||
199 | ret = i2c_master_send(lm->client, data, len); | ||
200 | if (unlikely(ret != len)) | ||
201 | dev_err(&lm->client->dev, "sent %d bytes of %d total\n", | ||
202 | len, ret); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * To read, we first send the command byte to the chip and end the transaction, | ||
209 | * then access the chip in read mode, at which point it will send the data. | ||
210 | */ | ||
211 | static int lm8323_read(struct lm8323_chip *lm, u8 cmd, u8 *buf, int len) | ||
212 | { | ||
213 | int ret; | ||
214 | |||
215 | /* | ||
216 | * If the host is asleep while we send the byte, we can get a NACK | ||
217 | * back while it wakes up, so try again, once. | ||
218 | */ | ||
219 | ret = i2c_master_send(lm->client, &cmd, 1); | ||
220 | if (unlikely(ret == -EREMOTEIO)) | ||
221 | ret = i2c_master_send(lm->client, &cmd, 1); | ||
222 | if (unlikely(ret != 1)) { | ||
223 | dev_err(&lm->client->dev, "sending read cmd 0x%02x failed\n", | ||
224 | cmd); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | ret = i2c_master_recv(lm->client, buf, len); | ||
229 | if (unlikely(ret != len)) | ||
230 | dev_err(&lm->client->dev, "wanted %d bytes, got %d\n", | ||
231 | len, ret); | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Set the chip active time (idle time before it enters halt). | ||
238 | */ | ||
239 | static void lm8323_set_active_time(struct lm8323_chip *lm, int time) | ||
240 | { | ||
241 | lm8323_write(lm, 2, LM8323_CMD_SET_ACTIVE, time >> 2); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * The signals are AT-style: the low 7 bits are the keycode, and the top | ||
246 | * bit indicates the state (1 for down, 0 for up). | ||
247 | */ | ||
248 | static inline u8 lm8323_whichkey(u8 event) | ||
249 | { | ||
250 | return event & 0x7f; | ||
251 | } | ||
252 | |||
253 | static inline int lm8323_ispress(u8 event) | ||
254 | { | ||
255 | return (event & 0x80) ? 1 : 0; | ||
256 | } | ||
257 | |||
258 | static void process_keys(struct lm8323_chip *lm) | ||
259 | { | ||
260 | u8 event; | ||
261 | u8 key_fifo[LM8323_FIFO_LEN + 1]; | ||
262 | int old_keys_down = lm->keys_down; | ||
263 | int ret; | ||
264 | int i = 0; | ||
265 | |||
266 | /* | ||
267 | * Read all key events from the FIFO at once. Next READ_FIFO clears the | ||
268 | * FIFO even if we didn't read all events previously. | ||
269 | */ | ||
270 | ret = lm8323_read(lm, LM8323_CMD_READ_FIFO, key_fifo, LM8323_FIFO_LEN); | ||
271 | |||
272 | if (ret < 0) { | ||
273 | dev_err(&lm->client->dev, "Failed reading fifo \n"); | ||
274 | return; | ||
275 | } | ||
276 | key_fifo[ret] = 0; | ||
277 | |||
278 | while ((event = key_fifo[i++])) { | ||
279 | u8 key = lm8323_whichkey(event); | ||
280 | int isdown = lm8323_ispress(event); | ||
281 | unsigned short keycode = lm->keymap[key]; | ||
282 | |||
283 | dev_vdbg(&lm->client->dev, "key 0x%02x %s\n", | ||
284 | key, isdown ? "down" : "up"); | ||
285 | |||
286 | if (lm->kp_enabled) { | ||
287 | input_event(lm->idev, EV_MSC, MSC_SCAN, key); | ||
288 | input_report_key(lm->idev, keycode, isdown); | ||
289 | input_sync(lm->idev); | ||
290 | } | ||
291 | |||
292 | if (isdown) | ||
293 | lm->keys_down++; | ||
294 | else | ||
295 | lm->keys_down--; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Errata: We need to ensure that the chip never enters halt mode | ||
300 | * during a keypress, so set active time to 0. When it's released, | ||
301 | * we can enter halt again, so set the active time back to normal. | ||
302 | */ | ||
303 | if (!old_keys_down && lm->keys_down) | ||
304 | lm8323_set_active_time(lm, 0); | ||
305 | if (old_keys_down && !lm->keys_down) | ||
306 | lm8323_set_active_time(lm, lm->active_time); | ||
307 | } | ||
308 | |||
309 | static void lm8323_process_error(struct lm8323_chip *lm) | ||
310 | { | ||
311 | u8 error; | ||
312 | |||
313 | if (lm8323_read(lm, LM8323_CMD_READ_ERR, &error, 1) == 1) { | ||
314 | if (error & ERR_FIFOOVER) | ||
315 | dev_vdbg(&lm->client->dev, "fifo overflow!\n"); | ||
316 | if (error & ERR_KEYOVR) | ||
317 | dev_vdbg(&lm->client->dev, | ||
318 | "more than two keys pressed\n"); | ||
319 | if (error & ERR_CMDUNK) | ||
320 | dev_vdbg(&lm->client->dev, | ||
321 | "unknown command submitted\n"); | ||
322 | if (error & ERR_BADPAR) | ||
323 | dev_vdbg(&lm->client->dev, "bad command parameter\n"); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | static void lm8323_reset(struct lm8323_chip *lm) | ||
328 | { | ||
329 | /* The docs say we must pass 0xAA as the data byte. */ | ||
330 | lm8323_write(lm, 2, LM8323_CMD_RESET, 0xAA); | ||
331 | } | ||
332 | |||
333 | static int lm8323_configure(struct lm8323_chip *lm) | ||
334 | { | ||
335 | int keysize = (lm->size_x << 4) | lm->size_y; | ||
336 | int clock = (CLK_SLOWCLKEN | CLK_RCPWM_EXTERNAL); | ||
337 | int debounce = lm->debounce_time >> 2; | ||
338 | int active = lm->active_time >> 2; | ||
339 | |||
340 | /* | ||
341 | * Active time must be greater than the debounce time: if it's | ||
342 | * a close-run thing, give ourselves a 12ms buffer. | ||
343 | */ | ||
344 | if (debounce >= active) | ||
345 | active = debounce + 3; | ||
346 | |||
347 | lm8323_write(lm, 2, LM8323_CMD_WRITE_CFG, 0); | ||
348 | lm8323_write(lm, 2, LM8323_CMD_WRITE_CLOCK, clock); | ||
349 | lm8323_write(lm, 2, LM8323_CMD_SET_KEY_SIZE, keysize); | ||
350 | lm8323_set_active_time(lm, lm->active_time); | ||
351 | lm8323_write(lm, 2, LM8323_CMD_SET_DEBOUNCE, debounce); | ||
352 | lm8323_write(lm, 3, LM8323_CMD_WRITE_PORT_STATE, 0xff, 0xff); | ||
353 | lm8323_write(lm, 3, LM8323_CMD_WRITE_PORT_SEL, 0, 0); | ||
354 | |||
355 | /* | ||
356 | * Not much we can do about errors at this point, so just hope | ||
357 | * for the best. | ||
358 | */ | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static void pwm_done(struct lm8323_pwm *pwm) | ||
364 | { | ||
365 | mutex_lock(&pwm->lock); | ||
366 | pwm->running = false; | ||
367 | if (pwm->desired_brightness != pwm->brightness) | ||
368 | schedule_work(&pwm->work); | ||
369 | mutex_unlock(&pwm->lock); | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * Bottom half: handle the interrupt by posting key events, or dealing with | ||
374 | * errors appropriately. | ||
375 | */ | ||
376 | static void lm8323_work(struct work_struct *work) | ||
377 | { | ||
378 | struct lm8323_chip *lm = work_to_lm8323(work); | ||
379 | u8 ints; | ||
380 | int i; | ||
381 | |||
382 | mutex_lock(&lm->lock); | ||
383 | |||
384 | while ((lm8323_read(lm, LM8323_CMD_READ_INT, &ints, 1) == 1) && ints) { | ||
385 | if (likely(ints & INT_KEYPAD)) | ||
386 | process_keys(lm); | ||
387 | if (ints & INT_ROTATOR) { | ||
388 | /* We don't currently support the rotator. */ | ||
389 | dev_vdbg(&lm->client->dev, "rotator fired\n"); | ||
390 | } | ||
391 | if (ints & INT_ERROR) { | ||
392 | dev_vdbg(&lm->client->dev, "error!\n"); | ||
393 | lm8323_process_error(lm); | ||
394 | } | ||
395 | if (ints & INT_NOINIT) { | ||
396 | dev_err(&lm->client->dev, "chip lost config; " | ||
397 | "reinitialising\n"); | ||
398 | lm8323_configure(lm); | ||
399 | } | ||
400 | for (i = 0; i < LM8323_NUM_PWMS; i++) { | ||
401 | if (ints & (1 << (INT_PWM1 + i))) { | ||
402 | dev_vdbg(&lm->client->dev, | ||
403 | "pwm%d engine completed\n", i); | ||
404 | pwm_done(&lm->pwm[i]); | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | mutex_unlock(&lm->lock); | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * We cannot use I2C in interrupt context, so we just schedule work. | ||
414 | */ | ||
415 | static irqreturn_t lm8323_irq(int irq, void *data) | ||
416 | { | ||
417 | struct lm8323_chip *lm = data; | ||
418 | |||
419 | schedule_work(&lm->work); | ||
420 | |||
421 | return IRQ_HANDLED; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Read the chip ID. | ||
426 | */ | ||
427 | static int lm8323_read_id(struct lm8323_chip *lm, u8 *buf) | ||
428 | { | ||
429 | int bytes; | ||
430 | |||
431 | bytes = lm8323_read(lm, LM8323_CMD_READ_ID, buf, 2); | ||
432 | if (unlikely(bytes != 2)) | ||
433 | return -EIO; | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static void lm8323_write_pwm_one(struct lm8323_pwm *pwm, int pos, u16 cmd) | ||
439 | { | ||
440 | lm8323_write(pwm->chip, 4, LM8323_CMD_PWM_WRITE, (pos << 2) | pwm->id, | ||
441 | (cmd & 0xff00) >> 8, cmd & 0x00ff); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Write a script into a given PWM engine, concluding with PWM_END. | ||
446 | * If 'kill' is nonzero, the engine will be shut down at the end | ||
447 | * of the script, producing a zero output. Otherwise the engine | ||
448 | * will be kept running at the final PWM level indefinitely. | ||
449 | */ | ||
450 | static void lm8323_write_pwm(struct lm8323_pwm *pwm, int kill, | ||
451 | int len, const u16 *cmds) | ||
452 | { | ||
453 | int i; | ||
454 | |||
455 | for (i = 0; i < len; i++) | ||
456 | lm8323_write_pwm_one(pwm, i, cmds[i]); | ||
457 | |||
458 | lm8323_write_pwm_one(pwm, i++, PWM_END(kill)); | ||
459 | lm8323_write(pwm->chip, 2, LM8323_CMD_START_PWM, pwm->id); | ||
460 | pwm->running = true; | ||
461 | } | ||
462 | |||
463 | static void lm8323_pwm_work(struct work_struct *work) | ||
464 | { | ||
465 | struct lm8323_pwm *pwm = work_to_pwm(work); | ||
466 | int div512, perstep, steps, hz, up, kill; | ||
467 | u16 pwm_cmds[3]; | ||
468 | int num_cmds = 0; | ||
469 | |||
470 | mutex_lock(&pwm->lock); | ||
471 | |||
472 | /* | ||
473 | * Do nothing if we're already at the requested level, | ||
474 | * or previous setting is not yet complete. In the latter | ||
475 | * case we will be called again when the previous PWM script | ||
476 | * finishes. | ||
477 | */ | ||
478 | if (pwm->running || pwm->desired_brightness == pwm->brightness) | ||
479 | goto out; | ||
480 | |||
481 | kill = (pwm->desired_brightness == 0); | ||
482 | up = (pwm->desired_brightness > pwm->brightness); | ||
483 | steps = abs(pwm->desired_brightness - pwm->brightness); | ||
484 | |||
485 | /* | ||
486 | * Convert time (in ms) into a divisor (512 or 16 on a refclk of | ||
487 | * 32768Hz), and number of ticks per step. | ||
488 | */ | ||
489 | if ((pwm->fade_time / steps) > (32768 / 512)) { | ||
490 | div512 = 1; | ||
491 | hz = 32768 / 512; | ||
492 | } else { | ||
493 | div512 = 0; | ||
494 | hz = 32768 / 16; | ||
495 | } | ||
496 | |||
497 | perstep = (hz * pwm->fade_time) / (steps * 1000); | ||
498 | |||
499 | if (perstep == 0) | ||
500 | perstep = 1; | ||
501 | else if (perstep > 63) | ||
502 | perstep = 63; | ||
503 | |||
504 | while (steps) { | ||
505 | int s; | ||
506 | |||
507 | s = min(126, steps); | ||
508 | pwm_cmds[num_cmds++] = PWM_RAMP(div512, perstep, s, up); | ||
509 | steps -= s; | ||
510 | } | ||
511 | |||
512 | lm8323_write_pwm(pwm, kill, num_cmds, pwm_cmds); | ||
513 | pwm->brightness = pwm->desired_brightness; | ||
514 | |||
515 | out: | ||
516 | mutex_unlock(&pwm->lock); | ||
517 | } | ||
518 | |||
519 | static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev, | ||
520 | enum led_brightness brightness) | ||
521 | { | ||
522 | struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev); | ||
523 | struct lm8323_chip *lm = pwm->chip; | ||
524 | |||
525 | mutex_lock(&pwm->lock); | ||
526 | pwm->desired_brightness = brightness; | ||
527 | mutex_unlock(&pwm->lock); | ||
528 | |||
529 | if (in_interrupt()) { | ||
530 | schedule_work(&pwm->work); | ||
531 | } else { | ||
532 | /* | ||
533 | * Schedule PWM work as usual unless we are going into suspend | ||
534 | */ | ||
535 | mutex_lock(&lm->lock); | ||
536 | if (likely(!lm->pm_suspend)) | ||
537 | schedule_work(&pwm->work); | ||
538 | else | ||
539 | lm8323_pwm_work(&pwm->work); | ||
540 | mutex_unlock(&lm->lock); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | static ssize_t lm8323_pwm_show_time(struct device *dev, | ||
545 | struct device_attribute *attr, char *buf) | ||
546 | { | ||
547 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
548 | struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev); | ||
549 | |||
550 | return sprintf(buf, "%d\n", pwm->fade_time); | ||
551 | } | ||
552 | |||
553 | static ssize_t lm8323_pwm_store_time(struct device *dev, | ||
554 | struct device_attribute *attr, const char *buf, size_t len) | ||
555 | { | ||
556 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
557 | struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev); | ||
558 | int ret; | ||
559 | unsigned long time; | ||
560 | |||
561 | ret = strict_strtoul(buf, 10, &time); | ||
562 | /* Numbers only, please. */ | ||
563 | if (ret) | ||
564 | return -EINVAL; | ||
565 | |||
566 | pwm->fade_time = time; | ||
567 | |||
568 | return strlen(buf); | ||
569 | } | ||
570 | static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time); | ||
571 | |||
572 | static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, | ||
573 | const char *name) | ||
574 | { | ||
575 | struct lm8323_pwm *pwm; | ||
576 | |||
577 | BUG_ON(id > 3); | ||
578 | |||
579 | pwm = &lm->pwm[id - 1]; | ||
580 | |||
581 | pwm->id = id; | ||
582 | pwm->fade_time = 0; | ||
583 | pwm->brightness = 0; | ||
584 | pwm->desired_brightness = 0; | ||
585 | pwm->running = false; | ||
586 | pwm->enabled = false; | ||
587 | INIT_WORK(&pwm->work, lm8323_pwm_work); | ||
588 | mutex_init(&pwm->lock); | ||
589 | pwm->chip = lm; | ||
590 | |||
591 | if (name) { | ||
592 | pwm->cdev.name = name; | ||
593 | pwm->cdev.brightness_set = lm8323_pwm_set_brightness; | ||
594 | if (led_classdev_register(dev, &pwm->cdev) < 0) { | ||
595 | dev_err(dev, "couldn't register PWM %d\n", id); | ||
596 | return -1; | ||
597 | } | ||
598 | if (device_create_file(pwm->cdev.dev, | ||
599 | &dev_attr_time) < 0) { | ||
600 | dev_err(dev, "couldn't register time attribute\n"); | ||
601 | led_classdev_unregister(&pwm->cdev); | ||
602 | return -1; | ||
603 | } | ||
604 | pwm->enabled = true; | ||
605 | } | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static struct i2c_driver lm8323_i2c_driver; | ||
611 | |||
612 | static ssize_t lm8323_show_disable(struct device *dev, | ||
613 | struct device_attribute *attr, char *buf) | ||
614 | { | ||
615 | struct lm8323_chip *lm = dev_get_drvdata(dev); | ||
616 | |||
617 | return sprintf(buf, "%u\n", !lm->kp_enabled); | ||
618 | } | ||
619 | |||
620 | static ssize_t lm8323_set_disable(struct device *dev, | ||
621 | struct device_attribute *attr, | ||
622 | const char *buf, size_t count) | ||
623 | { | ||
624 | struct lm8323_chip *lm = dev_get_drvdata(dev); | ||
625 | int ret; | ||
626 | unsigned long i; | ||
627 | |||
628 | ret = strict_strtoul(buf, 10, &i); | ||
629 | |||
630 | mutex_lock(&lm->lock); | ||
631 | lm->kp_enabled = !i; | ||
632 | mutex_unlock(&lm->lock); | ||
633 | |||
634 | return count; | ||
635 | } | ||
636 | static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); | ||
637 | |||
638 | static int __devinit lm8323_probe(struct i2c_client *client, | ||
639 | const struct i2c_device_id *id) | ||
640 | { | ||
641 | struct lm8323_platform_data *pdata = client->dev.platform_data; | ||
642 | struct input_dev *idev; | ||
643 | struct lm8323_chip *lm; | ||
644 | int i, err; | ||
645 | unsigned long tmo; | ||
646 | u8 data[2]; | ||
647 | |||
648 | if (!pdata || !pdata->size_x || !pdata->size_y) { | ||
649 | dev_err(&client->dev, "missing platform_data\n"); | ||
650 | return -EINVAL; | ||
651 | } | ||
652 | |||
653 | if (pdata->size_x > 8) { | ||
654 | dev_err(&client->dev, "invalid x size %d specified\n", | ||
655 | pdata->size_x); | ||
656 | return -EINVAL; | ||
657 | } | ||
658 | |||
659 | if (pdata->size_y > 12) { | ||
660 | dev_err(&client->dev, "invalid y size %d specified\n", | ||
661 | pdata->size_y); | ||
662 | return -EINVAL; | ||
663 | } | ||
664 | |||
665 | lm = kzalloc(sizeof *lm, GFP_KERNEL); | ||
666 | idev = input_allocate_device(); | ||
667 | if (!lm || !idev) { | ||
668 | err = -ENOMEM; | ||
669 | goto fail1; | ||
670 | } | ||
671 | |||
672 | i2c_set_clientdata(client, lm); | ||
673 | |||
674 | lm->client = client; | ||
675 | lm->idev = idev; | ||
676 | mutex_init(&lm->lock); | ||
677 | INIT_WORK(&lm->work, lm8323_work); | ||
678 | |||
679 | lm->size_x = pdata->size_x; | ||
680 | lm->size_y = pdata->size_y; | ||
681 | dev_vdbg(&client->dev, "Keypad size: %d x %d\n", | ||
682 | lm->size_x, lm->size_y); | ||
683 | |||
684 | lm->debounce_time = pdata->debounce_time; | ||
685 | lm->active_time = pdata->active_time; | ||
686 | |||
687 | lm8323_reset(lm); | ||
688 | |||
689 | /* Nothing's set up to service the IRQ yet, so just spin for max. | ||
690 | * 100ms until we can configure. */ | ||
691 | tmo = jiffies + msecs_to_jiffies(100); | ||
692 | while (lm8323_read(lm, LM8323_CMD_READ_INT, data, 1) == 1) { | ||
693 | if (data[0] & INT_NOINIT) | ||
694 | break; | ||
695 | |||
696 | if (time_after(jiffies, tmo)) { | ||
697 | dev_err(&client->dev, | ||
698 | "timeout waiting for initialisation\n"); | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | msleep(1); | ||
703 | } | ||
704 | |||
705 | lm8323_configure(lm); | ||
706 | |||
707 | /* If a true probe check the device */ | ||
708 | if (lm8323_read_id(lm, data) != 0) { | ||
709 | dev_err(&client->dev, "device not found\n"); | ||
710 | err = -ENODEV; | ||
711 | goto fail1; | ||
712 | } | ||
713 | |||
714 | for (i = 0; i < LM8323_NUM_PWMS; i++) { | ||
715 | err = init_pwm(lm, i + 1, &client->dev, pdata->pwm_names[i]); | ||
716 | if (err < 0) | ||
717 | goto fail2; | ||
718 | } | ||
719 | |||
720 | lm->kp_enabled = true; | ||
721 | err = device_create_file(&client->dev, &dev_attr_disable_kp); | ||
722 | if (err < 0) | ||
723 | goto fail2; | ||
724 | |||
725 | idev->name = pdata->name ? : "LM8323 keypad"; | ||
726 | snprintf(lm->phys, sizeof(lm->phys), | ||
727 | "%s/input-kp", dev_name(&client->dev)); | ||
728 | idev->phys = lm->phys; | ||
729 | |||
730 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_MSC); | ||
731 | __set_bit(MSC_SCAN, idev->mscbit); | ||
732 | for (i = 0; i < LM8323_KEYMAP_SIZE; i++) { | ||
733 | __set_bit(pdata->keymap[i], idev->keybit); | ||
734 | lm->keymap[i] = pdata->keymap[i]; | ||
735 | } | ||
736 | __clear_bit(KEY_RESERVED, idev->keybit); | ||
737 | |||
738 | if (pdata->repeat) | ||
739 | __set_bit(EV_REP, idev->evbit); | ||
740 | |||
741 | err = input_register_device(idev); | ||
742 | if (err) { | ||
743 | dev_dbg(&client->dev, "error registering input device\n"); | ||
744 | goto fail3; | ||
745 | } | ||
746 | |||
747 | err = request_irq(client->irq, lm8323_irq, | ||
748 | IRQF_TRIGGER_FALLING | IRQF_DISABLED, | ||
749 | "lm8323", lm); | ||
750 | if (err) { | ||
751 | dev_err(&client->dev, "could not get IRQ %d\n", client->irq); | ||
752 | goto fail4; | ||
753 | } | ||
754 | |||
755 | device_init_wakeup(&client->dev, 1); | ||
756 | enable_irq_wake(client->irq); | ||
757 | |||
758 | return 0; | ||
759 | |||
760 | fail4: | ||
761 | input_unregister_device(idev); | ||
762 | idev = NULL; | ||
763 | fail3: | ||
764 | device_remove_file(&client->dev, &dev_attr_disable_kp); | ||
765 | fail2: | ||
766 | while (--i >= 0) | ||
767 | if (lm->pwm[i].enabled) | ||
768 | led_classdev_unregister(&lm->pwm[i].cdev); | ||
769 | fail1: | ||
770 | input_free_device(idev); | ||
771 | kfree(lm); | ||
772 | return err; | ||
773 | } | ||
774 | |||
775 | static int __devexit lm8323_remove(struct i2c_client *client) | ||
776 | { | ||
777 | struct lm8323_chip *lm = i2c_get_clientdata(client); | ||
778 | int i; | ||
779 | |||
780 | disable_irq_wake(client->irq); | ||
781 | free_irq(client->irq, lm); | ||
782 | cancel_work_sync(&lm->work); | ||
783 | |||
784 | input_unregister_device(lm->idev); | ||
785 | |||
786 | device_remove_file(&lm->client->dev, &dev_attr_disable_kp); | ||
787 | |||
788 | for (i = 0; i < 3; i++) | ||
789 | if (lm->pwm[i].enabled) | ||
790 | led_classdev_unregister(&lm->pwm[i].cdev); | ||
791 | |||
792 | kfree(lm); | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | #ifdef CONFIG_PM | ||
798 | /* | ||
799 | * We don't need to explicitly suspend the chip, as it already switches off | ||
800 | * when there's no activity. | ||
801 | */ | ||
802 | static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg) | ||
803 | { | ||
804 | struct lm8323_chip *lm = i2c_get_clientdata(client); | ||
805 | int i; | ||
806 | |||
807 | set_irq_wake(client->irq, 0); | ||
808 | disable_irq(client->irq); | ||
809 | |||
810 | mutex_lock(&lm->lock); | ||
811 | lm->pm_suspend = true; | ||
812 | mutex_unlock(&lm->lock); | ||
813 | |||
814 | for (i = 0; i < 3; i++) | ||
815 | if (lm->pwm[i].enabled) | ||
816 | led_classdev_suspend(&lm->pwm[i].cdev); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | static int lm8323_resume(struct i2c_client *client) | ||
822 | { | ||
823 | struct lm8323_chip *lm = i2c_get_clientdata(client); | ||
824 | int i; | ||
825 | |||
826 | mutex_lock(&lm->lock); | ||
827 | lm->pm_suspend = false; | ||
828 | mutex_unlock(&lm->lock); | ||
829 | |||
830 | for (i = 0; i < 3; i++) | ||
831 | if (lm->pwm[i].enabled) | ||
832 | led_classdev_resume(&lm->pwm[i].cdev); | ||
833 | |||
834 | enable_irq(client->irq); | ||
835 | set_irq_wake(client->irq, 1); | ||
836 | |||
837 | return 0; | ||
838 | } | ||
839 | #else | ||
840 | #define lm8323_suspend NULL | ||
841 | #define lm8323_resume NULL | ||
842 | #endif | ||
843 | |||
844 | static const struct i2c_device_id lm8323_id[] = { | ||
845 | { "lm8323", 0 }, | ||
846 | { } | ||
847 | }; | ||
848 | |||
849 | static struct i2c_driver lm8323_i2c_driver = { | ||
850 | .driver = { | ||
851 | .name = "lm8323", | ||
852 | }, | ||
853 | .probe = lm8323_probe, | ||
854 | .remove = __devexit_p(lm8323_remove), | ||
855 | .suspend = lm8323_suspend, | ||
856 | .resume = lm8323_resume, | ||
857 | .id_table = lm8323_id, | ||
858 | }; | ||
859 | MODULE_DEVICE_TABLE(i2c, lm8323_id); | ||
860 | |||
861 | static int __init lm8323_init(void) | ||
862 | { | ||
863 | return i2c_add_driver(&lm8323_i2c_driver); | ||
864 | } | ||
865 | module_init(lm8323_init); | ||
866 | |||
867 | static void __exit lm8323_exit(void) | ||
868 | { | ||
869 | i2c_del_driver(&lm8323_i2c_driver); | ||
870 | } | ||
871 | module_exit(lm8323_exit); | ||
872 | |||
873 | MODULE_AUTHOR("Timo O. Karjalainen <timo.o.karjalainen@nokia.com>"); | ||
874 | MODULE_AUTHOR("Daniel Stone"); | ||
875 | MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); | ||
876 | MODULE_DESCRIPTION("LM8323 keypad driver"); | ||
877 | MODULE_LICENSE("GPL"); | ||
878 | |||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 06f46fcc0772..1acfa3a05aad 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -193,6 +193,16 @@ config INPUT_CM109 | |||
193 | To compile this driver as a module, choose M here: the module will be | 193 | To compile this driver as a module, choose M here: the module will be |
194 | called cm109. | 194 | called cm109. |
195 | 195 | ||
196 | config INPUT_TWL4030_PWRBUTTON | ||
197 | tristate "TWL4030 Power button Driver" | ||
198 | depends on TWL4030_CORE | ||
199 | help | ||
200 | Say Y here if you want to enable power key reporting via the | ||
201 | TWL4030 family of chips. | ||
202 | |||
203 | To compile this driver as a module, choose M here. The module will | ||
204 | be called twl4030_pwrbutton. | ||
205 | |||
196 | config INPUT_UINPUT | 206 | config INPUT_UINPUT |
197 | tristate "User level driver support" | 207 | tristate "User level driver support" |
198 | help | 208 | help |
@@ -250,4 +260,13 @@ config INPUT_RB532_BUTTON | |||
250 | To compile this driver as a module, choose M here: the | 260 | To compile this driver as a module, choose M here: the |
251 | module will be called rb532_button. | 261 | module will be called rb532_button. |
252 | 262 | ||
263 | config INPUT_DM355EVM | ||
264 | tristate "TI DaVinci DM355 EVM Keypad and IR Remote" | ||
265 | depends on MFD_DM355EVM_MSP | ||
266 | help | ||
267 | Supports the pushbuttons and IR remote used with | ||
268 | the DM355 EVM board. | ||
269 | |||
270 | To compile this driver as a module, choose M here: the | ||
271 | module will be called dm355evm_keys. | ||
253 | endif | 272 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index eb3f407baedf..0d979fd4cd57 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | |||
10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
11 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 11 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
13 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | ||
13 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 14 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
14 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | 15 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
15 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
@@ -21,6 +22,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | |||
21 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 22 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
22 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 23 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
23 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 24 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
25 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | ||
24 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 26 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
25 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 27 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
26 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 28 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 922c05141585..0501f0e65157 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -509,7 +509,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc | |||
509 | 509 | ||
510 | old_keycode = ar2->keycode[mode][index]; | 510 | old_keycode = ar2->keycode[mode][index]; |
511 | ar2->keycode[mode][index] = keycode; | 511 | ar2->keycode[mode][index] = keycode; |
512 | set_bit(keycode, idev->keybit); | 512 | __set_bit(keycode, idev->keybit); |
513 | 513 | ||
514 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { | 514 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { |
515 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | 515 | 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 | } | 518 | } |
519 | } | 519 | } |
520 | 520 | ||
521 | clear_bit(old_keycode, idev->keybit); | 521 | __clear_bit(old_keycode, idev->keybit); |
522 | 522 | ||
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
@@ -543,7 +543,7 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
543 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { | 543 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { |
544 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | 544 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { |
545 | ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; | 545 | ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; |
546 | set_bit(ar2->keycode[mode][index], idev->keybit); | 546 | __set_bit(ar2->keycode[mode][index], idev->keybit); |
547 | } | 547 | } |
548 | } | 548 | } |
549 | 549 | ||
@@ -554,11 +554,11 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
554 | ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; | 554 | ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; |
555 | ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; | 555 | ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; |
556 | ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; | 556 | ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; |
557 | set_bit(KEY_PROG1, idev->keybit); | 557 | __set_bit(KEY_PROG1, idev->keybit); |
558 | set_bit(KEY_PROG2, idev->keybit); | 558 | __set_bit(KEY_PROG2, idev->keybit); |
559 | set_bit(KEY_PROG3, idev->keybit); | 559 | __set_bit(KEY_PROG3, idev->keybit); |
560 | set_bit(KEY_PROG4, idev->keybit); | 560 | __set_bit(KEY_PROG4, idev->keybit); |
561 | set_bit(KEY_PC, idev->keybit); | 561 | __set_bit(KEY_PC, idev->keybit); |
562 | 562 | ||
563 | idev->rep[REP_DELAY] = 250; | 563 | idev->rep[REP_DELAY] = 250; |
564 | idev->rep[REP_PERIOD] = 33; | 564 | idev->rep[REP_PERIOD] = 33; |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c new file mode 100644 index 000000000000..a63315ce4a6c --- /dev/null +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /* | ||
2 | * dm355evm_keys.c - support buttons and IR remote on DM355 EVM board | ||
3 | * | ||
4 | * Copyright (c) 2008 by David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | |||
17 | #include <linux/i2c/dm355evm_msp.h> | ||
18 | |||
19 | |||
20 | /* | ||
21 | * The MSP430 firmware on the DM355 EVM monitors on-board pushbuttons | ||
22 | * and an IR receptor used for the remote control. When any key is | ||
23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | ||
24 | * read those events from the small (32 event) queue and reports them. | ||
25 | * | ||
26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
28 | * using a work_struct. The IRQ is active low, but we use it through | ||
29 | * the GPIO controller so we can trigger on falling edges. | ||
30 | * | ||
31 | * Note that physically there can only be one of these devices. | ||
32 | * | ||
33 | * This driver was tested with firmware revision A4. | ||
34 | */ | ||
35 | struct dm355evm_keys { | ||
36 | struct work_struct work; | ||
37 | struct input_dev *input; | ||
38 | struct device *dev; | ||
39 | int irq; | ||
40 | }; | ||
41 | |||
42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
43 | { | ||
44 | struct dm355evm_keys *keys = _keys; | ||
45 | |||
46 | schedule_work(&keys->work); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | ||
51 | static struct { | ||
52 | u16 event; | ||
53 | u16 keycode; | ||
54 | } dm355evm_keys[] = { | ||
55 | |||
56 | /* | ||
57 | * Pushbuttons on the EVM board ... note that the labels for these | ||
58 | * are SW10/SW11/etc on the PC board. The left/right orientation | ||
59 | * comes only from the firmware's documentation, and presumes the | ||
60 | * power connector is immediately in front of you and the IR sensor | ||
61 | * is to the right. (That is, rotate the board counter-clockwise | ||
62 | * by 90 degrees from the SW10/etc and "DM355 EVM" labels.) | ||
63 | */ | ||
64 | { 0x00d8, KEY_OK, }, /* SW12 */ | ||
65 | { 0x00b8, KEY_UP, }, /* SW13 */ | ||
66 | { 0x00e8, KEY_DOWN, }, /* SW11 */ | ||
67 | { 0x0078, KEY_LEFT, }, /* SW14 */ | ||
68 | { 0x00f0, KEY_RIGHT, }, /* SW10 */ | ||
69 | |||
70 | /* | ||
71 | * IR buttons ... codes assigned to match the universal remote | ||
72 | * provided with the EVM (Philips PM4S) using DVD code 0020. | ||
73 | * | ||
74 | * These event codes match firmware documentation, but other | ||
75 | * remote controls could easily send more RC5-encoded events. | ||
76 | * The PM4S manual was used in several cases to help select | ||
77 | * a keycode reflecting the intended usage. | ||
78 | * | ||
79 | * RC5 codes are 14 bits, with two start bits (0x3 prefix) | ||
80 | * and a toggle bit (masked out below). | ||
81 | */ | ||
82 | { 0x300c, KEY_POWER, }, /* NOTE: docs omit this */ | ||
83 | { 0x3000, KEY_NUMERIC_0, }, | ||
84 | { 0x3001, KEY_NUMERIC_1, }, | ||
85 | { 0x3002, KEY_NUMERIC_2, }, | ||
86 | { 0x3003, KEY_NUMERIC_3, }, | ||
87 | { 0x3004, KEY_NUMERIC_4, }, | ||
88 | { 0x3005, KEY_NUMERIC_5, }, | ||
89 | { 0x3006, KEY_NUMERIC_6, }, | ||
90 | { 0x3007, KEY_NUMERIC_7, }, | ||
91 | { 0x3008, KEY_NUMERIC_8, }, | ||
92 | { 0x3009, KEY_NUMERIC_9, }, | ||
93 | { 0x3022, KEY_ENTER, }, | ||
94 | { 0x30ec, KEY_MODE, }, /* "tv/vcr/..." */ | ||
95 | { 0x300f, KEY_SELECT, }, /* "info" */ | ||
96 | { 0x3020, KEY_CHANNELUP, }, /* "up" */ | ||
97 | { 0x302e, KEY_MENU, }, /* "in/out" */ | ||
98 | { 0x3011, KEY_VOLUMEDOWN, }, /* "left" */ | ||
99 | { 0x300d, KEY_MUTE, }, /* "ok" */ | ||
100 | { 0x3010, KEY_VOLUMEUP, }, /* "right" */ | ||
101 | { 0x301e, KEY_SUBTITLE, }, /* "cc" */ | ||
102 | { 0x3021, KEY_CHANNELDOWN, }, /* "down" */ | ||
103 | { 0x3022, KEY_PREVIOUS, }, | ||
104 | { 0x3026, KEY_SLEEP, }, | ||
105 | { 0x3172, KEY_REWIND, }, /* NOTE: docs wrongly say 0x30ca */ | ||
106 | { 0x3175, KEY_PLAY, }, | ||
107 | { 0x3174, KEY_FASTFORWARD, }, | ||
108 | { 0x3177, KEY_RECORD, }, | ||
109 | { 0x3176, KEY_STOP, }, | ||
110 | { 0x3169, KEY_PAUSE, }, | ||
111 | }; | ||
112 | |||
113 | static void dm355evm_keys_work(struct work_struct *work) | ||
114 | { | ||
115 | struct dm355evm_keys *keys; | ||
116 | int status; | ||
117 | |||
118 | keys = container_of(work, struct dm355evm_keys, work); | ||
119 | |||
120 | /* For simplicity we ignore INPUT_COUNT and just read | ||
121 | * events until we get the "queue empty" indicator. | ||
122 | * Reading INPUT_LOW decrements the count. | ||
123 | */ | ||
124 | for (;;) { | ||
125 | static u16 last_event; | ||
126 | u16 event; | ||
127 | int keycode; | ||
128 | int i; | ||
129 | |||
130 | status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH); | ||
131 | if (status < 0) { | ||
132 | dev_dbg(keys->dev, "input high err %d\n", | ||
133 | status); | ||
134 | break; | ||
135 | } | ||
136 | event = status << 8; | ||
137 | |||
138 | status = dm355evm_msp_read(DM355EVM_MSP_INPUT_LOW); | ||
139 | if (status < 0) { | ||
140 | dev_dbg(keys->dev, "input low err %d\n", | ||
141 | status); | ||
142 | break; | ||
143 | } | ||
144 | event |= status; | ||
145 | if (event == 0xdead) | ||
146 | break; | ||
147 | |||
148 | /* Press and release a button: two events, same code. | ||
149 | * Press and hold (autorepeat), then release: N events | ||
150 | * (N > 2), same code. For RC5 buttons the toggle bits | ||
151 | * distinguish (for example) "1-autorepeat" from "1 1"; | ||
152 | * but PCB buttons don't support that bit. | ||
153 | * | ||
154 | * So we must synthesize release events. We do that by | ||
155 | * mapping events to a press/release event pair; then | ||
156 | * to avoid adding extra events, skip the second event | ||
157 | * of each pair. | ||
158 | */ | ||
159 | if (event == last_event) { | ||
160 | last_event = 0; | ||
161 | continue; | ||
162 | } | ||
163 | last_event = event; | ||
164 | |||
165 | /* ignore the RC5 toggle bit */ | ||
166 | event &= ~0x0800; | ||
167 | |||
168 | /* find the key, or leave it as unknown */ | ||
169 | keycode = KEY_UNKNOWN; | ||
170 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) { | ||
171 | if (dm355evm_keys[i].event != event) | ||
172 | continue; | ||
173 | keycode = dm355evm_keys[i].keycode; | ||
174 | break; | ||
175 | } | ||
176 | dev_dbg(keys->dev, | ||
177 | "input event 0x%04x--> keycode %d\n", | ||
178 | event, keycode); | ||
179 | |||
180 | /* report press + release */ | ||
181 | input_report_key(keys->input, keycode, 1); | ||
182 | input_sync(keys->input); | ||
183 | input_report_key(keys->input, keycode, 0); | ||
184 | input_sync(keys->input); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | ||
189 | { | ||
190 | u16 old_keycode; | ||
191 | unsigned i; | ||
192 | |||
193 | if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys)) | ||
194 | return -EINVAL; | ||
195 | |||
196 | old_keycode = dm355evm_keys[index].keycode; | ||
197 | dm355evm_keys[index].keycode = keycode; | ||
198 | set_bit(keycode, dev->keybit); | ||
199 | |||
200 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) { | ||
201 | if (dm355evm_keys[index].keycode == old_keycode) | ||
202 | goto done; | ||
203 | } | ||
204 | clear_bit(old_keycode, dev->keybit); | ||
205 | done: | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode) | ||
210 | { | ||
211 | if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys)) | ||
212 | return -EINVAL; | ||
213 | |||
214 | return dm355evm_keys[index].keycode; | ||
215 | } | ||
216 | |||
217 | /*----------------------------------------------------------------------*/ | ||
218 | |||
219 | static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | ||
220 | { | ||
221 | struct dm355evm_keys *keys; | ||
222 | struct input_dev *input; | ||
223 | int status; | ||
224 | int i; | ||
225 | |||
226 | /* allocate instance struct and input dev */ | ||
227 | keys = kzalloc(sizeof *keys, GFP_KERNEL); | ||
228 | input = input_allocate_device(); | ||
229 | if (!keys || !input) { | ||
230 | status = -ENOMEM; | ||
231 | goto fail1; | ||
232 | } | ||
233 | |||
234 | keys->dev = &pdev->dev; | ||
235 | keys->input = input; | ||
236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
237 | |||
238 | /* set up "threaded IRQ handler" */ | ||
239 | status = platform_get_irq(pdev, 0); | ||
240 | if (status < 0) | ||
241 | goto fail1; | ||
242 | keys->irq = status; | ||
243 | |||
244 | input_set_drvdata(input, keys); | ||
245 | |||
246 | input->name = "DM355 EVM Controls"; | ||
247 | input->phys = "dm355evm/input0"; | ||
248 | input->dev.parent = &pdev->dev; | ||
249 | |||
250 | input->id.bustype = BUS_I2C; | ||
251 | input->id.product = 0x0355; | ||
252 | input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); | ||
253 | |||
254 | input->evbit[0] = BIT(EV_KEY); | ||
255 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) | ||
256 | __set_bit(dm355evm_keys[i].keycode, input->keybit); | ||
257 | |||
258 | input->setkeycode = dm355evm_setkeycode; | ||
259 | input->getkeycode = dm355evm_getkeycode; | ||
260 | |||
261 | /* REVISIT: flush the event queue? */ | ||
262 | |||
263 | status = request_irq(keys->irq, dm355evm_keys_irq, | ||
264 | IRQF_TRIGGER_FALLING, | ||
265 | dev_name(&pdev->dev), keys); | ||
266 | if (status < 0) | ||
267 | goto fail1; | ||
268 | |||
269 | /* register */ | ||
270 | status = input_register_device(input); | ||
271 | if (status < 0) | ||
272 | goto fail2; | ||
273 | |||
274 | platform_set_drvdata(pdev, keys); | ||
275 | |||
276 | return 0; | ||
277 | |||
278 | fail2: | ||
279 | free_irq(keys->irq, keys); | ||
280 | fail1: | ||
281 | input_free_device(input); | ||
282 | kfree(keys); | ||
283 | dev_err(&pdev->dev, "can't register, err %d\n", status); | ||
284 | |||
285 | return status; | ||
286 | } | ||
287 | |||
288 | static int __devexit dm355evm_keys_remove(struct platform_device *pdev) | ||
289 | { | ||
290 | struct dm355evm_keys *keys = platform_get_drvdata(pdev); | ||
291 | |||
292 | free_irq(keys->irq, keys); | ||
293 | input_unregister_device(keys->input); | ||
294 | kfree(keys); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | /* REVISIT: add suspend/resume when DaVinci supports it. The IRQ should | ||
300 | * be able to wake up the system. When device_may_wakeup(&pdev->dev), call | ||
301 | * enable_irq_wake() on suspend, and disable_irq_wake() on resume. | ||
302 | */ | ||
303 | |||
304 | /* | ||
305 | * I2C is used to talk to the MSP430, but this platform device is | ||
306 | * exposed by an MFD driver that manages I2C communications. | ||
307 | */ | ||
308 | static struct platform_driver dm355evm_keys_driver = { | ||
309 | .probe = dm355evm_keys_probe, | ||
310 | .remove = __devexit_p(dm355evm_keys_remove), | ||
311 | .driver = { | ||
312 | .owner = THIS_MODULE, | ||
313 | .name = "dm355evm_keys", | ||
314 | }, | ||
315 | }; | ||
316 | |||
317 | static int __init dm355evm_keys_init(void) | ||
318 | { | ||
319 | return platform_driver_register(&dm355evm_keys_driver); | ||
320 | } | ||
321 | module_init(dm355evm_keys_init); | ||
322 | |||
323 | static void __exit dm355evm_keys_exit(void) | ||
324 | { | ||
325 | platform_driver_unregister(&dm355evm_keys_driver); | ||
326 | } | ||
327 | module_exit(dm355evm_keys_exit); | ||
328 | |||
329 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 5bb3ab51b8c6..c806fbf1e174 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -26,13 +26,17 @@ | |||
26 | #define DRV_NAME "rotary-encoder" | 26 | #define DRV_NAME "rotary-encoder" |
27 | 27 | ||
28 | struct rotary_encoder { | 28 | struct rotary_encoder { |
29 | unsigned int irq_a; | ||
30 | unsigned int irq_b; | ||
31 | unsigned int pos; | ||
32 | unsigned int armed; | ||
33 | unsigned int dir; | ||
34 | struct input_dev *input; | 29 | struct input_dev *input; |
35 | struct rotary_encoder_platform_data *pdata; | 30 | struct rotary_encoder_platform_data *pdata; |
31 | |||
32 | unsigned int axis; | ||
33 | unsigned int pos; | ||
34 | |||
35 | unsigned int irq_a; | ||
36 | unsigned int irq_b; | ||
37 | |||
38 | bool armed; | ||
39 | unsigned char dir; /* 0 - clockwise, 1 - CCW */ | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | 42 | 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 | if (!encoder->armed) | 57 | if (!encoder->armed) |
54 | break; | 58 | break; |
55 | 59 | ||
56 | if (encoder->dir) { | 60 | if (pdata->relative_axis) { |
57 | /* turning counter-clockwise */ | 61 | input_report_rel(encoder->input, pdata->axis, |
58 | encoder->pos += pdata->steps; | 62 | encoder->dir ? -1 : 1); |
59 | encoder->pos--; | ||
60 | encoder->pos %= pdata->steps; | ||
61 | } else { | 63 | } else { |
62 | /* turning clockwise */ | 64 | unsigned int pos = encoder->pos; |
63 | encoder->pos++; | 65 | |
64 | encoder->pos %= pdata->steps; | 66 | if (encoder->dir) { |
67 | /* turning counter-clockwise */ | ||
68 | if (pdata->rollover) | ||
69 | pos += pdata->steps; | ||
70 | if (pos) | ||
71 | pos--; | ||
72 | } else { | ||
73 | /* turning clockwise */ | ||
74 | if (pdata->rollover || pos < pdata->steps) | ||
75 | pos++; | ||
76 | } | ||
77 | if (pdata->rollover) | ||
78 | pos %= pdata->steps; | ||
79 | encoder->pos = pos; | ||
80 | input_report_abs(encoder->input, pdata->axis, | ||
81 | encoder->pos); | ||
65 | } | 82 | } |
66 | |||
67 | input_report_abs(encoder->input, pdata->axis, encoder->pos); | ||
68 | input_sync(encoder->input); | 83 | input_sync(encoder->input); |
69 | 84 | ||
70 | encoder->armed = 0; | 85 | encoder->armed = false; |
71 | break; | 86 | break; |
72 | 87 | ||
73 | case 0x1: | 88 | case 0x1: |
@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | |||
77 | break; | 92 | break; |
78 | 93 | ||
79 | case 0x3: | 94 | case 0x3: |
80 | encoder->armed = 1; | 95 | encoder->armed = true; |
81 | break; | 96 | break; |
82 | } | 97 | } |
83 | 98 | ||
@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
113 | input->name = pdev->name; | 128 | input->name = pdev->name; |
114 | input->id.bustype = BUS_HOST; | 129 | input->id.bustype = BUS_HOST; |
115 | input->dev.parent = &pdev->dev; | 130 | input->dev.parent = &pdev->dev; |
116 | input->evbit[0] = BIT_MASK(EV_ABS); | 131 | |
117 | input_set_abs_params(encoder->input, | 132 | if (pdata->relative_axis) { |
118 | pdata->axis, 0, pdata->steps, 0, 1); | 133 | input->evbit[0] = BIT_MASK(EV_REL); |
134 | input->relbit[0] = BIT_MASK(pdata->axis); | ||
135 | } else { | ||
136 | input->evbit[0] = BIT_MASK(EV_ABS); | ||
137 | input_set_abs_params(encoder->input, | ||
138 | pdata->axis, 0, pdata->steps, 0, 1); | ||
139 | } | ||
119 | 140 | ||
120 | err = input_register_device(input); | 141 | err = input_register_device(input); |
121 | if (err) { | 142 | if (err) { |
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c new file mode 100644 index 000000000000..f5fc9974a111 --- /dev/null +++ b/drivers/input/misc/twl4030-pwrbutton.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /** | ||
2 | * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation | ||
5 | * | ||
6 | * Written by Peter De Schrijver <peter.de-schrijver@nokia.com> | ||
7 | * Several fixes by Felipe Balbi <felipe.balbi@nokia.com> | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General | ||
10 | * Public License. See the file "COPYING" in the main directory of this | ||
11 | * archive for more details. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/i2c/twl4030.h> | ||
31 | |||
32 | #define PWR_PWRON_IRQ (1 << 0) | ||
33 | |||
34 | #define STS_HW_CONDITIONS 0xf | ||
35 | |||
36 | static irqreturn_t powerbutton_irq(int irq, void *_pwr) | ||
37 | { | ||
38 | struct input_dev *pwr = _pwr; | ||
39 | int err; | ||
40 | u8 value; | ||
41 | |||
42 | #ifdef CONFIG_LOCKDEP | ||
43 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
44 | * we don't want and can't tolerate since this is a threaded | ||
45 | * IRQ and can sleep due to the i2c reads it has to issue. | ||
46 | * Although it might be friendlier not to borrow this thread | ||
47 | * context... | ||
48 | */ | ||
49 | local_irq_enable(); | ||
50 | #endif | ||
51 | |||
52 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, | ||
53 | STS_HW_CONDITIONS); | ||
54 | if (!err) { | ||
55 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); | ||
56 | input_sync(pwr); | ||
57 | } else { | ||
58 | dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading" | ||
59 | " TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err); | ||
60 | } | ||
61 | |||
62 | return IRQ_HANDLED; | ||
63 | } | ||
64 | |||
65 | static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev) | ||
66 | { | ||
67 | struct input_dev *pwr; | ||
68 | int irq = platform_get_irq(pdev, 0); | ||
69 | int err; | ||
70 | |||
71 | pwr = input_allocate_device(); | ||
72 | if (!pwr) { | ||
73 | dev_dbg(&pdev->dev, "Can't allocate power button\n"); | ||
74 | return -ENOMEM; | ||
75 | } | ||
76 | |||
77 | pwr->evbit[0] = BIT_MASK(EV_KEY); | ||
78 | pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | ||
79 | pwr->name = "twl4030_pwrbutton"; | ||
80 | pwr->phys = "twl4030_pwrbutton/input0"; | ||
81 | pwr->dev.parent = &pdev->dev; | ||
82 | |||
83 | err = request_irq(irq, powerbutton_irq, | ||
84 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
85 | "twl4030_pwrbutton", pwr); | ||
86 | if (err < 0) { | ||
87 | dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); | ||
88 | goto free_input_dev; | ||
89 | } | ||
90 | |||
91 | err = input_register_device(pwr); | ||
92 | if (err) { | ||
93 | dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); | ||
94 | goto free_irq; | ||
95 | } | ||
96 | |||
97 | platform_set_drvdata(pdev, pwr); | ||
98 | |||
99 | return 0; | ||
100 | |||
101 | free_irq: | ||
102 | free_irq(irq, NULL); | ||
103 | free_input_dev: | ||
104 | input_free_device(pwr); | ||
105 | return err; | ||
106 | } | ||
107 | |||
108 | static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev) | ||
109 | { | ||
110 | struct input_dev *pwr = platform_get_drvdata(pdev); | ||
111 | int irq = platform_get_irq(pdev, 0); | ||
112 | |||
113 | free_irq(irq, pwr); | ||
114 | input_unregister_device(pwr); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | struct platform_driver twl4030_pwrbutton_driver = { | ||
120 | .probe = twl4030_pwrbutton_probe, | ||
121 | .remove = __devexit_p(twl4030_pwrbutton_remove), | ||
122 | .driver = { | ||
123 | .name = "twl4030_pwrbutton", | ||
124 | .owner = THIS_MODULE, | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | static int __init twl4030_pwrbutton_init(void) | ||
129 | { | ||
130 | return platform_driver_register(&twl4030_pwrbutton_driver); | ||
131 | } | ||
132 | module_init(twl4030_pwrbutton_init); | ||
133 | |||
134 | static void __exit twl4030_pwrbutton_exit(void) | ||
135 | { | ||
136 | platform_driver_unregister(&twl4030_pwrbutton_driver); | ||
137 | } | ||
138 | module_exit(twl4030_pwrbutton_exit); | ||
139 | |||
140 | MODULE_ALIAS("platform:twl4030_pwrbutton"); | ||
141 | MODULE_DESCRIPTION("Triton2 Power Button"); | ||
142 | MODULE_LICENSE("GPL"); | ||
143 | MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>"); | ||
144 | MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); | ||
145 | |||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 46b7caeb2817..c5a49aba418f 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -54,27 +54,28 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i | |||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Atomically allocate an ID for the given request. Returns 0 on success. */ | ||
57 | static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) | 58 | static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) |
58 | { | 59 | { |
59 | /* Atomically allocate an ID for the given request. Returns 0 on success. */ | ||
60 | int id; | 60 | int id; |
61 | int err = -1; | 61 | int err = -1; |
62 | 62 | ||
63 | spin_lock(&udev->requests_lock); | 63 | spin_lock(&udev->requests_lock); |
64 | 64 | ||
65 | for (id = 0; id < UINPUT_NUM_REQUESTS; id++) | 65 | for (id = 0; id < UINPUT_NUM_REQUESTS; id++) { |
66 | if (!udev->requests[id]) { | 66 | if (!udev->requests[id]) { |
67 | request->id = id; | 67 | request->id = id; |
68 | udev->requests[id] = request; | 68 | udev->requests[id] = request; |
69 | err = 0; | 69 | err = 0; |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | } | ||
72 | 73 | ||
73 | spin_unlock(&udev->requests_lock); | 74 | spin_unlock(&udev->requests_lock); |
74 | return err; | 75 | return err; |
75 | } | 76 | } |
76 | 77 | ||
77 | static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id) | 78 | static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id) |
78 | { | 79 | { |
79 | /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ | 80 | /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ |
80 | if (id >= UINPUT_NUM_REQUESTS || id < 0) | 81 | if (id >= UINPUT_NUM_REQUESTS || id < 0) |
@@ -99,14 +100,51 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques | |||
99 | complete(&request->done); | 100 | complete(&request->done); |
100 | } | 101 | } |
101 | 102 | ||
102 | static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request) | 103 | static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request) |
103 | { | 104 | { |
105 | int retval; | ||
106 | |||
107 | retval = uinput_request_reserve_slot(udev, request); | ||
108 | if (retval) | ||
109 | return retval; | ||
110 | |||
111 | retval = mutex_lock_interruptible(&udev->mutex); | ||
112 | if (retval) | ||
113 | return retval; | ||
114 | |||
115 | if (udev->state != UIST_CREATED) { | ||
116 | retval = -ENODEV; | ||
117 | goto out; | ||
118 | } | ||
119 | |||
104 | /* Tell our userspace app about this new request by queueing an input event */ | 120 | /* Tell our userspace app about this new request by queueing an input event */ |
105 | uinput_dev_event(dev, EV_UINPUT, request->code, request->id); | 121 | uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id); |
122 | |||
123 | out: | ||
124 | mutex_unlock(&udev->mutex); | ||
125 | return retval; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Fail all ouitstanding requests so handlers don't wait for the userspace | ||
130 | * to finish processing them. | ||
131 | */ | ||
132 | static void uinput_flush_requests(struct uinput_device *udev) | ||
133 | { | ||
134 | struct uinput_request *request; | ||
135 | int i; | ||
136 | |||
137 | spin_lock(&udev->requests_lock); | ||
138 | |||
139 | for (i = 0; i < UINPUT_NUM_REQUESTS; i++) { | ||
140 | request = udev->requests[i]; | ||
141 | if (request) { | ||
142 | request->retval = -ENODEV; | ||
143 | uinput_request_done(udev, request); | ||
144 | } | ||
145 | } | ||
106 | 146 | ||
107 | /* Wait for the request to complete */ | 147 | spin_unlock(&udev->requests_lock); |
108 | wait_for_completion(&request->done); | ||
109 | return request->retval; | ||
110 | } | 148 | } |
111 | 149 | ||
112 | static void uinput_dev_set_gain(struct input_dev *dev, u16 gain) | 150 | 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 | 164 | ||
127 | static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) | 165 | static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) |
128 | { | 166 | { |
167 | struct uinput_device *udev = input_get_drvdata(dev); | ||
129 | struct uinput_request request; | 168 | struct uinput_request request; |
130 | int retval; | 169 | int retval; |
131 | 170 | ||
@@ -146,15 +185,18 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff | |||
146 | request.u.upload.effect = effect; | 185 | request.u.upload.effect = effect; |
147 | request.u.upload.old = old; | 186 | request.u.upload.old = old; |
148 | 187 | ||
149 | retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); | 188 | retval = uinput_request_submit(udev, &request); |
150 | if (!retval) | 189 | if (!retval) { |
151 | retval = uinput_request_submit(dev, &request); | 190 | wait_for_completion(&request.done); |
191 | retval = request.retval; | ||
192 | } | ||
152 | 193 | ||
153 | return retval; | 194 | return retval; |
154 | } | 195 | } |
155 | 196 | ||
156 | static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) | 197 | static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) |
157 | { | 198 | { |
199 | struct uinput_device *udev = input_get_drvdata(dev); | ||
158 | struct uinput_request request; | 200 | struct uinput_request request; |
159 | int retval; | 201 | int retval; |
160 | 202 | ||
@@ -166,9 +208,11 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) | |||
166 | request.code = UI_FF_ERASE; | 208 | request.code = UI_FF_ERASE; |
167 | request.u.effect_id = effect_id; | 209 | request.u.effect_id = effect_id; |
168 | 210 | ||
169 | retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); | 211 | retval = uinput_request_submit(udev, &request); |
170 | if (!retval) | 212 | if (!retval) { |
171 | retval = uinput_request_submit(dev, &request); | 213 | wait_for_completion(&request.done); |
214 | retval = request.retval; | ||
215 | } | ||
172 | 216 | ||
173 | return retval; | 217 | return retval; |
174 | } | 218 | } |
@@ -176,20 +220,24 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) | |||
176 | static void uinput_destroy_device(struct uinput_device *udev) | 220 | static void uinput_destroy_device(struct uinput_device *udev) |
177 | { | 221 | { |
178 | const char *name, *phys; | 222 | const char *name, *phys; |
223 | struct input_dev *dev = udev->dev; | ||
224 | enum uinput_state old_state = udev->state; | ||
179 | 225 | ||
180 | if (udev->dev) { | 226 | udev->state = UIST_NEW_DEVICE; |
181 | name = udev->dev->name; | 227 | |
182 | phys = udev->dev->phys; | 228 | if (dev) { |
183 | if (udev->state == UIST_CREATED) | 229 | name = dev->name; |
184 | input_unregister_device(udev->dev); | 230 | phys = dev->phys; |
185 | else | 231 | if (old_state == UIST_CREATED) { |
186 | input_free_device(udev->dev); | 232 | uinput_flush_requests(udev); |
233 | input_unregister_device(dev); | ||
234 | } else { | ||
235 | input_free_device(dev); | ||
236 | } | ||
187 | kfree(name); | 237 | kfree(name); |
188 | kfree(phys); | 238 | kfree(phys); |
189 | udev->dev = NULL; | 239 | udev->dev = NULL; |
190 | } | 240 | } |
191 | |||
192 | udev->state = UIST_NEW_DEVICE; | ||
193 | } | 241 | } |
194 | 242 | ||
195 | static int uinput_create_device(struct uinput_device *udev) | 243 | static int uinput_create_device(struct uinput_device *udev) |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index c66cc3d08c2f..8a2c5b14c8d8 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -303,4 +303,22 @@ config MOUSE_MAPLE | |||
303 | To compile this driver as a module choose M here: the module will be | 303 | To compile this driver as a module choose M here: the module will be |
304 | called maplemouse. | 304 | called maplemouse. |
305 | 305 | ||
306 | config MOUSE_SYNAPTICS_I2C | ||
307 | tristate "Synaptics I2C Touchpad support" | ||
308 | depends on I2C | ||
309 | help | ||
310 | This driver supports Synaptics I2C touchpad controller on eXeda | ||
311 | mobile device. | ||
312 | The device will not work the synaptics X11 driver because | ||
313 | (i) it reports only relative coordinates and has no capabilities | ||
314 | to report absolute coordinates | ||
315 | (ii) the eXeda device itself uses Xfbdev as X Server and it does | ||
316 | not allow using xf86-input-* drivers. | ||
317 | |||
318 | Say y here if you have eXeda device and want to use a Synaptics | ||
319 | I2C Touchpad. | ||
320 | |||
321 | To compile this driver as a module, choose M here: the | ||
322 | module will be called synaptics_i2c. | ||
323 | |||
306 | endif | 324 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 472189468d67..010f265ec152 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o | |||
18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o | 18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o |
19 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 19 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
20 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | 20 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o |
21 | obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o | ||
21 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 22 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
22 | 23 | ||
23 | psmouse-objs := psmouse-base.o synaptics.o | 24 | psmouse-objs := psmouse-base.o synaptics.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index daecc75c72e6..5547e2429fbe 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -38,25 +38,25 @@ | |||
38 | 38 | ||
39 | static const struct alps_model_info alps_model_data[] = { | 39 | static const struct alps_model_info alps_model_data[] = { |
40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
41 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 41 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
42 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 42 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
43 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 43 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
44 | { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ | 44 | { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ |
45 | { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 45 | { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
46 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 46 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
47 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ | 47 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ |
48 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ | 48 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ |
49 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ | 49 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
50 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 50 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
51 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 51 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ |
52 | { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ | 52 | { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ |
53 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 53 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
54 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ | 54 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
55 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 55 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
56 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 56 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
57 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 57 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
58 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | 58 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ |
59 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ | 59 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */ |
60 | }; | 60 | }; |
61 | 61 | ||
62 | /* | 62 | /* |
@@ -132,18 +132,23 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
132 | ges = packet[2] & 1; | 132 | ges = packet[2] & 1; |
133 | fin = packet[2] & 2; | 133 | fin = packet[2] & 2; |
134 | 134 | ||
135 | input_report_key(dev, BTN_LEFT, left); | ||
136 | input_report_key(dev, BTN_RIGHT, right); | ||
137 | input_report_key(dev, BTN_MIDDLE, middle); | ||
138 | |||
139 | if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { | 135 | if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { |
140 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 136 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
141 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 137 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
138 | |||
139 | input_report_key(dev2, BTN_LEFT, left); | ||
140 | input_report_key(dev2, BTN_RIGHT, right); | ||
141 | input_report_key(dev2, BTN_MIDDLE, middle); | ||
142 | |||
142 | input_sync(dev); | 143 | input_sync(dev); |
143 | input_sync(dev2); | 144 | input_sync(dev2); |
144 | return; | 145 | return; |
145 | } | 146 | } |
146 | 147 | ||
148 | input_report_key(dev, BTN_LEFT, left); | ||
149 | input_report_key(dev, BTN_RIGHT, right); | ||
150 | input_report_key(dev, BTN_MIDDLE, middle); | ||
151 | |||
147 | /* Convert hardware tap to a reasonable Z value */ | 152 | /* Convert hardware tap to a reasonable Z value */ |
148 | if (ges && !fin) z = 40; | 153 | if (ges && !fin) z = 40; |
149 | 154 | ||
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index e0140fdc02a5..908b5b44052f 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -361,7 +361,7 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | |||
361 | (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { | 361 | (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { |
362 | (*fingers)++; | 362 | (*fingers)++; |
363 | is_increasing = 1; | 363 | is_increasing = 1; |
364 | } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { | 364 | } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) { |
365 | is_increasing = 0; | 365 | is_increasing = 0; |
366 | } | 366 | } |
367 | 367 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 15ac3205ac05..dcd4236af1e3 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -159,21 +159,22 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | |||
159 | if (!dev2) | 159 | if (!dev2) |
160 | printk(KERN_WARNING "lifebook.c: got relative packet " | 160 | printk(KERN_WARNING "lifebook.c: got relative packet " |
161 | "but no relative device set up\n"); | 161 | "but no relative device set up\n"); |
162 | } else if (lifebook_use_6byte_proto) { | ||
163 | input_report_abs(dev1, ABS_X, | ||
164 | ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); | ||
165 | input_report_abs(dev1, ABS_Y, | ||
166 | 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); | ||
167 | } else { | 162 | } else { |
168 | input_report_abs(dev1, ABS_X, | 163 | if (lifebook_use_6byte_proto) { |
169 | (packet[1] | ((packet[0] & 0x30) << 4))); | 164 | input_report_abs(dev1, ABS_X, |
170 | input_report_abs(dev1, ABS_Y, | 165 | ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); |
171 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | 166 | input_report_abs(dev1, ABS_Y, |
167 | 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); | ||
168 | } else { | ||
169 | input_report_abs(dev1, ABS_X, | ||
170 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
171 | input_report_abs(dev1, ABS_Y, | ||
172 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
173 | } | ||
174 | input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); | ||
175 | input_sync(dev1); | ||
172 | } | 176 | } |
173 | 177 | ||
174 | input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); | ||
175 | input_sync(dev1); | ||
176 | |||
177 | if (dev2) { | 178 | if (dev2) { |
178 | if (relative_packet) { | 179 | if (relative_packet) { |
179 | input_report_rel(dev2, REL_X, | 180 | input_report_rel(dev2, REL_X, |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f8f86de694bb..b407b355dceb 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -327,7 +327,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
327 | goto out; | 327 | goto out; |
328 | } | 328 | } |
329 | 329 | ||
330 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 330 | if (psmouse->packet[1] == PSMOUSE_RET_ID || |
331 | (psmouse->type == PSMOUSE_HGPK && | ||
332 | psmouse->packet[1] == PSMOUSE_RET_BAT)) { | ||
331 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 333 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
332 | serio_reconnect(serio); | 334 | serio_reconnect(serio); |
333 | goto out; | 335 | goto out; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index f3e4f7b0240d..19984bf06cad 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -180,6 +180,29 @@ static int synaptics_identify(struct psmouse *psmouse) | |||
180 | return -1; | 180 | return -1; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* | ||
184 | * Read touchpad resolution | ||
185 | * Resolution is left zero if touchpad does not support the query | ||
186 | */ | ||
187 | static int synaptics_resolution(struct psmouse *psmouse) | ||
188 | { | ||
189 | struct synaptics_data *priv = psmouse->private; | ||
190 | unsigned char res[3]; | ||
191 | |||
192 | if (SYN_ID_MAJOR(priv->identity) < 4) | ||
193 | return 0; | ||
194 | |||
195 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res)) | ||
196 | return 0; | ||
197 | |||
198 | if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) { | ||
199 | priv->x_res = res[0]; /* x resolution in units/mm */ | ||
200 | priv->y_res = res[2]; /* y resolution in units/mm */ | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
183 | static int synaptics_query_hardware(struct psmouse *psmouse) | 206 | static int synaptics_query_hardware(struct psmouse *psmouse) |
184 | { | 207 | { |
185 | if (synaptics_identify(psmouse)) | 208 | if (synaptics_identify(psmouse)) |
@@ -188,6 +211,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse) | |||
188 | return -1; | 211 | return -1; |
189 | if (synaptics_capability(psmouse)) | 212 | if (synaptics_capability(psmouse)) |
190 | return -1; | 213 | return -1; |
214 | if (synaptics_resolution(psmouse)) | ||
215 | return -1; | ||
191 | 216 | ||
192 | return 0; | 217 | return 0; |
193 | } | 218 | } |
@@ -563,6 +588,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
563 | clear_bit(EV_REL, dev->evbit); | 588 | clear_bit(EV_REL, dev->evbit); |
564 | clear_bit(REL_X, dev->relbit); | 589 | clear_bit(REL_X, dev->relbit); |
565 | clear_bit(REL_Y, dev->relbit); | 590 | clear_bit(REL_Y, dev->relbit); |
591 | |||
592 | dev->absres[ABS_X] = priv->x_res; | ||
593 | dev->absres[ABS_Y] = priv->y_res; | ||
566 | } | 594 | } |
567 | 595 | ||
568 | static void synaptics_disconnect(struct psmouse *psmouse) | 596 | static void synaptics_disconnect(struct psmouse *psmouse) |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 02aa4cf7bc77..302382151752 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -97,6 +97,8 @@ struct synaptics_data { | |||
97 | unsigned long int capabilities; /* Capabilities */ | 97 | unsigned long int capabilities; /* Capabilities */ |
98 | unsigned long int ext_cap; /* Extended Capabilities */ | 98 | unsigned long int ext_cap; /* Extended Capabilities */ |
99 | unsigned long int identity; /* Identification */ | 99 | unsigned long int identity; /* Identification */ |
100 | int x_res; /* X resolution in units/mm */ | ||
101 | int y_res; /* Y resolution in units/mm */ | ||
100 | 102 | ||
101 | unsigned char pkt_type; /* packet type - old, new, etc */ | 103 | unsigned char pkt_type; /* packet type - old, new, etc */ |
102 | unsigned char mode; /* current mode byte */ | 104 | unsigned char mode; /* current mode byte */ |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c new file mode 100644 index 000000000000..eac9fdde7ee9 --- /dev/null +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -0,0 +1,676 @@ | |||
1 | /* | ||
2 | * Synaptics touchpad with I2C interface | ||
3 | * | ||
4 | * Copyright (C) 2009 Compulab, Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * Igor Grinberg <grinberg@compulab.co.il> | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | |||
21 | #define DRIVER_NAME "synaptics_i2c" | ||
22 | /* maximum product id is 15 characters */ | ||
23 | #define PRODUCT_ID_LENGTH 15 | ||
24 | #define REGISTER_LENGTH 8 | ||
25 | |||
26 | /* | ||
27 | * after soft reset, we should wait for 1 ms | ||
28 | * before the device becomes operational | ||
29 | */ | ||
30 | #define SOFT_RESET_DELAY_MS 3 | ||
31 | /* and after hard reset, we should wait for max 500ms */ | ||
32 | #define HARD_RESET_DELAY_MS 500 | ||
33 | |||
34 | /* Registers by SMBus address */ | ||
35 | #define PAGE_SEL_REG 0xff | ||
36 | #define DEVICE_STATUS_REG 0x09 | ||
37 | |||
38 | /* Registers by RMI address */ | ||
39 | #define DEV_CONTROL_REG 0x0000 | ||
40 | #define INTERRUPT_EN_REG 0x0001 | ||
41 | #define ERR_STAT_REG 0x0002 | ||
42 | #define INT_REQ_STAT_REG 0x0003 | ||
43 | #define DEV_COMMAND_REG 0x0004 | ||
44 | |||
45 | #define RMI_PROT_VER_REG 0x0200 | ||
46 | #define MANUFACT_ID_REG 0x0201 | ||
47 | #define PHYS_INT_VER_REG 0x0202 | ||
48 | #define PROD_PROPERTY_REG 0x0203 | ||
49 | #define INFO_QUERY_REG0 0x0204 | ||
50 | #define INFO_QUERY_REG1 (INFO_QUERY_REG0 + 1) | ||
51 | #define INFO_QUERY_REG2 (INFO_QUERY_REG0 + 2) | ||
52 | #define INFO_QUERY_REG3 (INFO_QUERY_REG0 + 3) | ||
53 | |||
54 | #define PRODUCT_ID_REG0 0x0210 | ||
55 | #define PRODUCT_ID_REG1 (PRODUCT_ID_REG0 + 1) | ||
56 | #define PRODUCT_ID_REG2 (PRODUCT_ID_REG0 + 2) | ||
57 | #define PRODUCT_ID_REG3 (PRODUCT_ID_REG0 + 3) | ||
58 | #define PRODUCT_ID_REG4 (PRODUCT_ID_REG0 + 4) | ||
59 | #define PRODUCT_ID_REG5 (PRODUCT_ID_REG0 + 5) | ||
60 | #define PRODUCT_ID_REG6 (PRODUCT_ID_REG0 + 6) | ||
61 | #define PRODUCT_ID_REG7 (PRODUCT_ID_REG0 + 7) | ||
62 | #define PRODUCT_ID_REG8 (PRODUCT_ID_REG0 + 8) | ||
63 | #define PRODUCT_ID_REG9 (PRODUCT_ID_REG0 + 9) | ||
64 | #define PRODUCT_ID_REG10 (PRODUCT_ID_REG0 + 10) | ||
65 | #define PRODUCT_ID_REG11 (PRODUCT_ID_REG0 + 11) | ||
66 | #define PRODUCT_ID_REG12 (PRODUCT_ID_REG0 + 12) | ||
67 | #define PRODUCT_ID_REG13 (PRODUCT_ID_REG0 + 13) | ||
68 | #define PRODUCT_ID_REG14 (PRODUCT_ID_REG0 + 14) | ||
69 | #define PRODUCT_ID_REG15 (PRODUCT_ID_REG0 + 15) | ||
70 | |||
71 | #define DATA_REG0 0x0400 | ||
72 | #define ABS_PRESSURE_REG 0x0401 | ||
73 | #define ABS_MSB_X_REG 0x0402 | ||
74 | #define ABS_LSB_X_REG (ABS_MSB_X_REG + 1) | ||
75 | #define ABS_MSB_Y_REG 0x0404 | ||
76 | #define ABS_LSB_Y_REG (ABS_MSB_Y_REG + 1) | ||
77 | #define REL_X_REG 0x0406 | ||
78 | #define REL_Y_REG 0x0407 | ||
79 | |||
80 | #define DEV_QUERY_REG0 0x1000 | ||
81 | #define DEV_QUERY_REG1 (DEV_QUERY_REG0 + 1) | ||
82 | #define DEV_QUERY_REG2 (DEV_QUERY_REG0 + 2) | ||
83 | #define DEV_QUERY_REG3 (DEV_QUERY_REG0 + 3) | ||
84 | #define DEV_QUERY_REG4 (DEV_QUERY_REG0 + 4) | ||
85 | #define DEV_QUERY_REG5 (DEV_QUERY_REG0 + 5) | ||
86 | #define DEV_QUERY_REG6 (DEV_QUERY_REG0 + 6) | ||
87 | #define DEV_QUERY_REG7 (DEV_QUERY_REG0 + 7) | ||
88 | #define DEV_QUERY_REG8 (DEV_QUERY_REG0 + 8) | ||
89 | |||
90 | #define GENERAL_2D_CONTROL_REG 0x1041 | ||
91 | #define SENSOR_SENSITIVITY_REG 0x1044 | ||
92 | #define SENS_MAX_POS_MSB_REG 0x1046 | ||
93 | #define SENS_MAX_POS_LSB_REG (SENS_MAX_POS_UPPER_REG + 1) | ||
94 | |||
95 | /* Register bits */ | ||
96 | /* Device Control Register Bits */ | ||
97 | #define REPORT_RATE_1ST_BIT 6 | ||
98 | |||
99 | /* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ | ||
100 | #define F10_ABS_INT_ENA 0 | ||
101 | #define F10_REL_INT_ENA 1 | ||
102 | #define F20_INT_ENA 2 | ||
103 | |||
104 | /* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */ | ||
105 | #define F10_ABS_INT_REQ 0 | ||
106 | #define F10_REL_INT_REQ 1 | ||
107 | #define F20_INT_REQ 2 | ||
108 | /* Device Status Register Bits (DEVICE_STATUS_REG) */ | ||
109 | #define STAT_CONFIGURED 6 | ||
110 | #define STAT_ERROR 7 | ||
111 | |||
112 | /* Device Command Register Bits (DEV_COMMAND_REG) */ | ||
113 | #define RESET_COMMAND 0x01 | ||
114 | #define REZERO_COMMAND 0x02 | ||
115 | |||
116 | /* Data Register 0 Bits (DATA_REG0) */ | ||
117 | #define GESTURE 3 | ||
118 | |||
119 | /* Device Query Registers Bits */ | ||
120 | /* DEV_QUERY_REG3 */ | ||
121 | #define HAS_PALM_DETECT 1 | ||
122 | #define HAS_MULTI_FING 2 | ||
123 | #define HAS_SCROLLER 4 | ||
124 | #define HAS_2D_SCROLL 5 | ||
125 | |||
126 | /* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ | ||
127 | #define NO_DECELERATION 1 | ||
128 | #define REDUCE_REPORTING 3 | ||
129 | #define NO_FILTER 5 | ||
130 | |||
131 | /* Function Masks */ | ||
132 | /* Device Control Register Masks (DEV_CONTROL_REG) */ | ||
133 | #define REPORT_RATE_MSK 0xc0 | ||
134 | #define SLEEP_MODE_MSK 0x07 | ||
135 | |||
136 | /* Device Sleep Modes */ | ||
137 | #define FULL_AWAKE 0x0 | ||
138 | #define NORMAL_OP 0x1 | ||
139 | #define LOW_PWR_OP 0x2 | ||
140 | #define VERY_LOW_PWR_OP 0x3 | ||
141 | #define SENS_SLEEP 0x4 | ||
142 | #define SLEEP_MOD 0x5 | ||
143 | #define DEEP_SLEEP 0x6 | ||
144 | #define HIBERNATE 0x7 | ||
145 | |||
146 | /* Interrupt Register Mask */ | ||
147 | /* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ | ||
148 | #define INT_ENA_REQ_MSK 0x07 | ||
149 | #define INT_ENA_ABS_MSK 0x01 | ||
150 | #define INT_ENA_REL_MSK 0x02 | ||
151 | #define INT_ENA_F20_MSK 0x04 | ||
152 | |||
153 | /* Device Status Register Masks (DEVICE_STATUS_REG) */ | ||
154 | #define CONFIGURED_MSK 0x40 | ||
155 | #define ERROR_MSK 0x80 | ||
156 | |||
157 | /* Data Register 0 Masks */ | ||
158 | #define FINGER_WIDTH_MSK 0xf0 | ||
159 | #define GESTURE_MSK 0x08 | ||
160 | #define SENSOR_STATUS_MSK 0x07 | ||
161 | |||
162 | /* | ||
163 | * MSB Position Register Masks | ||
164 | * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | | ||
165 | * DEV_QUERY_REG3 | DEV_QUERY_REG5 | ||
166 | */ | ||
167 | #define MSB_POSITION_MSK 0x1f | ||
168 | |||
169 | /* Device Query Registers Masks */ | ||
170 | |||
171 | /* DEV_QUERY_REG2 */ | ||
172 | #define NUM_EXTRA_POS_MSK 0x07 | ||
173 | |||
174 | /* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ | ||
175 | #define THREAD_IRQ_SLEEP_SECS 2 | ||
176 | #define THREAD_IRQ_SLEEP_MSECS (THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) | ||
177 | |||
178 | /* | ||
179 | * When in Polling mode and no data received for NO_DATA_THRES msecs | ||
180 | * reduce the polling rate to NO_DATA_SLEEP_MSECS | ||
181 | */ | ||
182 | #define NO_DATA_THRES (MSEC_PER_SEC) | ||
183 | #define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) | ||
184 | |||
185 | /* Control touchpad's No Deceleration option */ | ||
186 | static int no_decel = 1; | ||
187 | module_param(no_decel, bool, 0644); | ||
188 | MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); | ||
189 | |||
190 | /* Control touchpad's Reduced Reporting option */ | ||
191 | static int reduce_report; | ||
192 | module_param(reduce_report, bool, 0644); | ||
193 | MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); | ||
194 | |||
195 | /* Control touchpad's No Filter option */ | ||
196 | static int no_filter; | ||
197 | module_param(no_filter, bool, 0644); | ||
198 | MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | ||
199 | |||
200 | /* | ||
201 | * touchpad Attention line is Active Low and Open Drain, | ||
202 | * therefore should be connected to pulled up line | ||
203 | * and the irq configuration should be set to Falling Edge Trigger | ||
204 | */ | ||
205 | /* Control IRQ / Polling option */ | ||
206 | static int polling_req; | ||
207 | module_param(polling_req, bool, 0444); | ||
208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); | ||
209 | |||
210 | /* Control Polling Rate */ | ||
211 | static int scan_rate = 80; | ||
212 | module_param(scan_rate, int, 0644); | ||
213 | MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80"); | ||
214 | |||
215 | /* The main device structure */ | ||
216 | struct synaptics_i2c { | ||
217 | struct i2c_client *client; | ||
218 | struct input_dev *input; | ||
219 | struct delayed_work dwork; | ||
220 | int no_data_count; | ||
221 | int no_decel_param; | ||
222 | int reduce_report_param; | ||
223 | int no_filter_param; | ||
224 | int scan_rate_param; | ||
225 | int scan_ms; | ||
226 | }; | ||
227 | |||
228 | static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate) | ||
229 | { | ||
230 | touch->scan_ms = MSEC_PER_SEC / scan_rate; | ||
231 | touch->scan_rate_param = scan_rate; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Driver's initial design makes no race condition possible on i2c bus, | ||
236 | * so there is no need in any locking. | ||
237 | * Keep it in mind, while playing with the code. | ||
238 | */ | ||
239 | static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) | ||
240 | { | ||
241 | int ret; | ||
242 | |||
243 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
244 | if (ret == 0) | ||
245 | ret = i2c_smbus_read_byte_data(client, reg & 0xff); | ||
246 | |||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) | ||
251 | { | ||
252 | int ret; | ||
253 | |||
254 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
255 | if (ret == 0) | ||
256 | ret = i2c_smbus_write_byte_data(client, reg & 0xff, val); | ||
257 | |||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) | ||
262 | { | ||
263 | int ret; | ||
264 | |||
265 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
266 | if (ret == 0) | ||
267 | ret = i2c_smbus_read_word_data(client, reg & 0xff); | ||
268 | |||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | static int synaptics_i2c_config(struct i2c_client *client) | ||
273 | { | ||
274 | int ret, control; | ||
275 | u8 int_en; | ||
276 | |||
277 | /* set Report Rate to Device Highest (>=80) and Sleep to normal */ | ||
278 | ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); | ||
279 | if (ret) | ||
280 | return ret; | ||
281 | |||
282 | /* set Interrupt Disable to Func20 / Enable to Func10) */ | ||
283 | int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; | ||
284 | ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
288 | control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); | ||
289 | /* No Deceleration */ | ||
290 | control |= no_decel ? 1 << NO_DECELERATION : 0; | ||
291 | /* Reduced Reporting */ | ||
292 | control |= reduce_report ? 1 << REDUCE_REPORTING : 0; | ||
293 | /* No Filter */ | ||
294 | control |= no_filter ? 1 << NO_FILTER : 0; | ||
295 | ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); | ||
296 | if (ret) | ||
297 | return ret; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int synaptics_i2c_reset_config(struct i2c_client *client) | ||
303 | { | ||
304 | int ret; | ||
305 | |||
306 | /* Reset the Touchpad */ | ||
307 | ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); | ||
308 | if (ret) { | ||
309 | dev_err(&client->dev, "Unable to reset device\n"); | ||
310 | } else { | ||
311 | msleep(SOFT_RESET_DELAY_MS); | ||
312 | ret = synaptics_i2c_config(client); | ||
313 | if (ret) | ||
314 | dev_err(&client->dev, "Unable to config device\n"); | ||
315 | } | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int synaptics_i2c_check_error(struct i2c_client *client) | ||
321 | { | ||
322 | int status, ret = 0; | ||
323 | |||
324 | status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & | ||
325 | (CONFIGURED_MSK | ERROR_MSK); | ||
326 | |||
327 | if (status != CONFIGURED_MSK) | ||
328 | ret = synaptics_i2c_reset_config(client); | ||
329 | |||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) | ||
334 | { | ||
335 | struct input_dev *input = touch->input; | ||
336 | int xy_delta, gesture; | ||
337 | s32 data; | ||
338 | s8 x_delta, y_delta; | ||
339 | |||
340 | /* Deal with spontanious resets and errors */ | ||
341 | if (synaptics_i2c_check_error(touch->client)) | ||
342 | return 0; | ||
343 | |||
344 | /* Get Gesture Bit */ | ||
345 | data = synaptics_i2c_reg_get(touch->client, DATA_REG0); | ||
346 | gesture = (data >> GESTURE) & 0x1; | ||
347 | |||
348 | /* | ||
349 | * Get Relative axes. we have to get them in one shot, | ||
350 | * so we get 2 bytes starting from REL_X_REG. | ||
351 | */ | ||
352 | xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; | ||
353 | |||
354 | /* Separate X from Y */ | ||
355 | x_delta = xy_delta & 0xff; | ||
356 | y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff; | ||
357 | |||
358 | /* Report the button event */ | ||
359 | input_report_key(input, BTN_LEFT, gesture); | ||
360 | |||
361 | /* Report the deltas */ | ||
362 | input_report_rel(input, REL_X, x_delta); | ||
363 | input_report_rel(input, REL_Y, -y_delta); | ||
364 | input_sync(input); | ||
365 | |||
366 | return xy_delta || gesture; | ||
367 | } | ||
368 | |||
369 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | ||
370 | { | ||
371 | struct synaptics_i2c *touch = dev_id; | ||
372 | |||
373 | /* | ||
374 | * We want to have the work run immediately but it might have | ||
375 | * already been scheduled with a delay, that's why we have to | ||
376 | * cancel it first. | ||
377 | */ | ||
378 | cancel_delayed_work(&touch->dwork); | ||
379 | schedule_delayed_work(&touch->dwork, 0); | ||
380 | |||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | static void synaptics_i2c_check_params(struct synaptics_i2c *touch) | ||
385 | { | ||
386 | bool reset = false; | ||
387 | |||
388 | if (scan_rate != touch->scan_rate_param) | ||
389 | set_scan_rate(touch, scan_rate); | ||
390 | |||
391 | if (no_decel != touch->no_decel_param) { | ||
392 | touch->no_decel_param = no_decel; | ||
393 | reset = true; | ||
394 | } | ||
395 | |||
396 | if (no_filter != touch->no_filter_param) { | ||
397 | touch->no_filter_param = no_filter; | ||
398 | reset = true; | ||
399 | } | ||
400 | |||
401 | if (reduce_report != touch->reduce_report_param) { | ||
402 | touch->reduce_report_param = reduce_report; | ||
403 | reset = true; | ||
404 | } | ||
405 | |||
406 | if (reset) | ||
407 | synaptics_i2c_reset_config(touch->client); | ||
408 | } | ||
409 | |||
410 | /* Control the Device polling rate / Work Handler sleep time */ | ||
411 | unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, | ||
412 | bool have_data) | ||
413 | { | ||
414 | unsigned long delay, nodata_count_thres; | ||
415 | |||
416 | if (polling_req) { | ||
417 | delay = touch->scan_ms; | ||
418 | if (have_data) { | ||
419 | touch->no_data_count = 0; | ||
420 | } else { | ||
421 | nodata_count_thres = NO_DATA_THRES / touch->scan_ms; | ||
422 | if (touch->no_data_count < nodata_count_thres) | ||
423 | touch->no_data_count++; | ||
424 | else | ||
425 | delay = NO_DATA_SLEEP_MSECS; | ||
426 | } | ||
427 | return msecs_to_jiffies(delay); | ||
428 | } else { | ||
429 | delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); | ||
430 | return round_jiffies_relative(delay); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /* Work Handler */ | ||
435 | static void synaptics_i2c_work_handler(struct work_struct *work) | ||
436 | { | ||
437 | bool have_data; | ||
438 | struct synaptics_i2c *touch = | ||
439 | container_of(work, struct synaptics_i2c, dwork.work); | ||
440 | unsigned long delay; | ||
441 | |||
442 | synaptics_i2c_check_params(touch); | ||
443 | |||
444 | have_data = synaptics_i2c_get_input(touch); | ||
445 | delay = synaptics_i2c_adjust_delay(touch, have_data); | ||
446 | |||
447 | /* | ||
448 | * While interrupt driven, there is no real need to poll the device. | ||
449 | * But touchpads are very sensitive, so there could be errors | ||
450 | * related to physical environment and the attention line isn't | ||
451 | * neccesarily asserted. In such case we can lose the touchpad. | ||
452 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | ||
453 | * if error is detected, we try to reset and reconfigure the touchpad. | ||
454 | */ | ||
455 | schedule_delayed_work(&touch->dwork, delay); | ||
456 | } | ||
457 | |||
458 | static int synaptics_i2c_open(struct input_dev *input) | ||
459 | { | ||
460 | struct synaptics_i2c *touch = input_get_drvdata(input); | ||
461 | int ret; | ||
462 | |||
463 | ret = synaptics_i2c_reset_config(touch->client); | ||
464 | if (ret) | ||
465 | return ret; | ||
466 | |||
467 | if (polling_req) | ||
468 | schedule_delayed_work(&touch->dwork, | ||
469 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static void synaptics_i2c_close(struct input_dev *input) | ||
475 | { | ||
476 | struct synaptics_i2c *touch = input_get_drvdata(input); | ||
477 | |||
478 | if (!polling_req) | ||
479 | synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); | ||
480 | |||
481 | cancel_delayed_work_sync(&touch->dwork); | ||
482 | |||
483 | /* Save some power */ | ||
484 | synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | ||
485 | } | ||
486 | |||
487 | static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) | ||
488 | { | ||
489 | struct input_dev *input = touch->input; | ||
490 | |||
491 | input->name = touch->client->name; | ||
492 | input->phys = touch->client->adapter->name; | ||
493 | input->id.bustype = BUS_I2C; | ||
494 | input->id.version = synaptics_i2c_word_get(touch->client, | ||
495 | INFO_QUERY_REG0); | ||
496 | input->dev.parent = &touch->client->dev; | ||
497 | input->open = synaptics_i2c_open; | ||
498 | input->close = synaptics_i2c_close; | ||
499 | input_set_drvdata(input, touch); | ||
500 | |||
501 | /* Register the device as mouse */ | ||
502 | __set_bit(EV_REL, input->evbit); | ||
503 | __set_bit(REL_X, input->relbit); | ||
504 | __set_bit(REL_Y, input->relbit); | ||
505 | |||
506 | /* Register device's buttons and keys */ | ||
507 | __set_bit(EV_KEY, input->evbit); | ||
508 | __set_bit(BTN_LEFT, input->keybit); | ||
509 | } | ||
510 | |||
511 | struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | ||
512 | { | ||
513 | struct synaptics_i2c *touch; | ||
514 | |||
515 | touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); | ||
516 | if (!touch) | ||
517 | return NULL; | ||
518 | |||
519 | touch->client = client; | ||
520 | touch->no_decel_param = no_decel; | ||
521 | touch->scan_rate_param = scan_rate; | ||
522 | set_scan_rate(touch, scan_rate); | ||
523 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); | ||
524 | |||
525 | return touch; | ||
526 | } | ||
527 | |||
528 | static int __devinit synaptics_i2c_probe(struct i2c_client *client, | ||
529 | const struct i2c_device_id *dev_id) | ||
530 | { | ||
531 | int ret; | ||
532 | struct synaptics_i2c *touch; | ||
533 | |||
534 | touch = synaptics_i2c_touch_create(client); | ||
535 | if (!touch) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | i2c_set_clientdata(client, touch); | ||
539 | |||
540 | ret = synaptics_i2c_reset_config(client); | ||
541 | if (ret) | ||
542 | goto err_mem_free; | ||
543 | |||
544 | if (client->irq < 1) | ||
545 | polling_req = 1; | ||
546 | |||
547 | touch->input = input_allocate_device(); | ||
548 | if (!touch->input) { | ||
549 | ret = -ENOMEM; | ||
550 | goto err_mem_free; | ||
551 | } | ||
552 | |||
553 | synaptics_i2c_set_input_params(touch); | ||
554 | |||
555 | if (!polling_req) { | ||
556 | dev_dbg(&touch->client->dev, | ||
557 | "Requesting IRQ: %d\n", touch->client->irq); | ||
558 | |||
559 | ret = request_irq(touch->client->irq, synaptics_i2c_irq, | ||
560 | IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING, | ||
561 | DRIVER_NAME, touch); | ||
562 | if (ret) { | ||
563 | dev_warn(&touch->client->dev, | ||
564 | "IRQ request failed: %d, " | ||
565 | "falling back to polling\n", ret); | ||
566 | polling_req = 1; | ||
567 | synaptics_i2c_reg_set(touch->client, | ||
568 | INTERRUPT_EN_REG, 0); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (polling_req) | ||
573 | dev_dbg(&touch->client->dev, | ||
574 | "Using polling at rate: %d times/sec\n", scan_rate); | ||
575 | |||
576 | /* Register the device in input subsystem */ | ||
577 | ret = input_register_device(touch->input); | ||
578 | if (ret) { | ||
579 | dev_err(&client->dev, | ||
580 | "Input device register failed: %d\n", ret); | ||
581 | goto err_input_free; | ||
582 | } | ||
583 | return 0; | ||
584 | |||
585 | err_input_free: | ||
586 | input_free_device(touch->input); | ||
587 | err_mem_free: | ||
588 | i2c_set_clientdata(client, NULL); | ||
589 | kfree(touch); | ||
590 | |||
591 | return ret; | ||
592 | } | ||
593 | |||
594 | static int __devexit synaptics_i2c_remove(struct i2c_client *client) | ||
595 | { | ||
596 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
597 | |||
598 | if (!polling_req) | ||
599 | free_irq(touch->client->irq, touch); | ||
600 | |||
601 | input_unregister_device(touch->input); | ||
602 | i2c_set_clientdata(client, NULL); | ||
603 | kfree(touch); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | #ifdef CONFIG_PM | ||
609 | static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | ||
610 | { | ||
611 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
612 | |||
613 | cancel_delayed_work_sync(&touch->dwork); | ||
614 | |||
615 | /* Save some power */ | ||
616 | synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static int synaptics_i2c_resume(struct i2c_client *client) | ||
622 | { | ||
623 | int ret; | ||
624 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
625 | |||
626 | ret = synaptics_i2c_reset_config(client); | ||
627 | if (ret) | ||
628 | return ret; | ||
629 | |||
630 | schedule_delayed_work(&touch->dwork, | ||
631 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | #else | ||
636 | #define synaptics_i2c_suspend NULL | ||
637 | #define synaptics_i2c_resume NULL | ||
638 | #endif | ||
639 | |||
640 | static const struct i2c_device_id synaptics_i2c_id_table[] = { | ||
641 | { "synaptics_i2c", 0 }, | ||
642 | { }, | ||
643 | }; | ||
644 | MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); | ||
645 | |||
646 | static struct i2c_driver synaptics_i2c_driver = { | ||
647 | .driver = { | ||
648 | .name = DRIVER_NAME, | ||
649 | .owner = THIS_MODULE, | ||
650 | }, | ||
651 | |||
652 | .probe = synaptics_i2c_probe, | ||
653 | .remove = __devexit_p(synaptics_i2c_remove), | ||
654 | |||
655 | .suspend = synaptics_i2c_suspend, | ||
656 | .resume = synaptics_i2c_resume, | ||
657 | .id_table = synaptics_i2c_id_table, | ||
658 | }; | ||
659 | |||
660 | static int __init synaptics_i2c_init(void) | ||
661 | { | ||
662 | return i2c_add_driver(&synaptics_i2c_driver); | ||
663 | } | ||
664 | |||
665 | static void __exit synaptics_i2c_exit(void) | ||
666 | { | ||
667 | i2c_del_driver(&synaptics_i2c_driver); | ||
668 | } | ||
669 | |||
670 | module_init(synaptics_i2c_init); | ||
671 | module_exit(synaptics_i2c_exit); | ||
672 | |||
673 | MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); | ||
674 | MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); | ||
675 | MODULE_LICENSE("GPL"); | ||
676 | |||
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 17fd6d46d082..966b8868f792 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -60,7 +60,6 @@ struct mousedev { | |||
60 | int exist; | 60 | int exist; |
61 | int open; | 61 | int open; |
62 | int minor; | 62 | int minor; |
63 | char name[16]; | ||
64 | struct input_handle handle; | 63 | struct input_handle handle; |
65 | wait_queue_head_t wait; | 64 | wait_queue_head_t wait; |
66 | struct list_head client_list; | 65 | struct list_head client_list; |
@@ -863,19 +862,17 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
863 | init_waitqueue_head(&mousedev->wait); | 862 | init_waitqueue_head(&mousedev->wait); |
864 | 863 | ||
865 | if (minor == MOUSEDEV_MIX) | 864 | if (minor == MOUSEDEV_MIX) |
866 | strlcpy(mousedev->name, "mice", sizeof(mousedev->name)); | 865 | dev_set_name(&mousedev->dev, "mice"); |
867 | else | 866 | else |
868 | snprintf(mousedev->name, sizeof(mousedev->name), | 867 | dev_set_name(&mousedev->dev, "mouse%d", minor); |
869 | "mouse%d", minor); | ||
870 | 868 | ||
871 | mousedev->minor = minor; | 869 | mousedev->minor = minor; |
872 | mousedev->exist = 1; | 870 | mousedev->exist = 1; |
873 | mousedev->handle.dev = input_get_device(dev); | 871 | mousedev->handle.dev = input_get_device(dev); |
874 | mousedev->handle.name = mousedev->name; | 872 | mousedev->handle.name = dev_name(&mousedev->dev); |
875 | mousedev->handle.handler = handler; | 873 | mousedev->handle.handler = handler; |
876 | mousedev->handle.private = mousedev; | 874 | mousedev->handle.private = mousedev; |
877 | 875 | ||
878 | dev_set_name(&mousedev->dev, mousedev->name); | ||
879 | mousedev->dev.class = &input_class; | 876 | mousedev->dev.class = &input_class; |
880 | if (dev) | 877 | if (dev) |
881 | mousedev->dev.parent = &dev->dev; | 878 | mousedev->dev.parent = &dev->dev; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 3cffb704e374..f919bf57293c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * the Free Software Foundation. | 10 | * the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/types.h> | ||
13 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
@@ -921,6 +922,9 @@ static void i8042_dritek_enable(void) | |||
921 | #endif | 922 | #endif |
922 | 923 | ||
923 | #ifdef CONFIG_PM | 924 | #ifdef CONFIG_PM |
925 | |||
926 | static bool i8042_suspended; | ||
927 | |||
924 | /* | 928 | /* |
925 | * Here we try to restore the original BIOS settings. We only want to | 929 | * Here we try to restore the original BIOS settings. We only want to |
926 | * do that once, when we really suspend, not when we taking memory | 930 | * do that once, when we really suspend, not when we taking memory |
@@ -930,11 +934,9 @@ static void i8042_dritek_enable(void) | |||
930 | 934 | ||
931 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) |
932 | { | 936 | { |
933 | if (dev->dev.power.power_state.event != state.event) { | 937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { |
934 | if (state.event == PM_EVENT_SUSPEND) | 938 | i8042_controller_reset(); |
935 | i8042_controller_reset(); | 939 | i8042_suspended = true; |
936 | |||
937 | dev->dev.power.power_state = state; | ||
938 | } | 940 | } |
939 | 941 | ||
940 | return 0; | 942 | return 0; |
@@ -952,7 +954,7 @@ static int i8042_resume(struct platform_device *dev) | |||
952 | /* | 954 | /* |
953 | * Do not bother with restoring state if we haven't suspened yet | 955 | * Do not bother with restoring state if we haven't suspened yet |
954 | */ | 956 | */ |
955 | if (dev->dev.power.power_state.event == PM_EVENT_ON) | 957 | if (!i8042_suspended) |
956 | return 0; | 958 | return 0; |
957 | 959 | ||
958 | error = i8042_controller_check(); | 960 | error = i8042_controller_check(); |
@@ -998,10 +1000,9 @@ static int i8042_resume(struct platform_device *dev) | |||
998 | if (i8042_ports[I8042_KBD_PORT_NO].serio) | 1000 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
999 | i8042_enable_kbd_port(); | 1001 | i8042_enable_kbd_port(); |
1000 | 1002 | ||
1003 | i8042_suspended = false; | ||
1001 | i8042_interrupt(0, NULL); | 1004 | i8042_interrupt(0, NULL); |
1002 | 1005 | ||
1003 | dev->dev.power.power_state = PMSG_ON; | ||
1004 | |||
1005 | return 0; | 1006 | return 0; |
1006 | } | 1007 | } |
1007 | #endif /* CONFIG_PM */ | 1008 | #endif /* CONFIG_PM */ |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index bc033250dfcd..fb17573f8f2d 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -41,17 +41,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
41 | MODULE_DESCRIPTION("Serio abstraction core"); | 41 | MODULE_DESCRIPTION("Serio abstraction core"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | EXPORT_SYMBOL(serio_interrupt); | ||
45 | EXPORT_SYMBOL(__serio_register_port); | ||
46 | EXPORT_SYMBOL(serio_unregister_port); | ||
47 | EXPORT_SYMBOL(serio_unregister_child_port); | ||
48 | EXPORT_SYMBOL(__serio_register_driver); | ||
49 | EXPORT_SYMBOL(serio_unregister_driver); | ||
50 | EXPORT_SYMBOL(serio_open); | ||
51 | EXPORT_SYMBOL(serio_close); | ||
52 | EXPORT_SYMBOL(serio_rescan); | ||
53 | EXPORT_SYMBOL(serio_reconnect); | ||
54 | |||
55 | /* | 44 | /* |
56 | * serio_mutex protects entire serio subsystem and is taken every time | 45 | * serio_mutex protects entire serio subsystem and is taken every time |
57 | * serio port or driver registrered or unregistered. | 46 | * 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 | 495 | ||
507 | retval = count; | 496 | retval = count; |
508 | if (!strncmp(buf, "manual", count)) { | 497 | if (!strncmp(buf, "manual", count)) { |
509 | serio->manual_bind = 1; | 498 | serio->manual_bind = true; |
510 | } else if (!strncmp(buf, "auto", count)) { | 499 | } else if (!strncmp(buf, "auto", count)) { |
511 | serio->manual_bind = 0; | 500 | serio->manual_bind = false; |
512 | } else { | 501 | } else { |
513 | retval = -EINVAL; | 502 | retval = -EINVAL; |
514 | } | 503 | } |
@@ -581,7 +570,7 @@ static void serio_add_port(struct serio *serio) | |||
581 | "serio: device_add() failed for %s (%s), error: %d\n", | 570 | "serio: device_add() failed for %s (%s), error: %d\n", |
582 | serio->phys, serio->name, error); | 571 | serio->phys, serio->name, error); |
583 | else { | 572 | else { |
584 | serio->registered = 1; | 573 | serio->registered = true; |
585 | error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); | 574 | error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); |
586 | if (error) | 575 | if (error) |
587 | printk(KERN_ERR | 576 | printk(KERN_ERR |
@@ -617,7 +606,7 @@ static void serio_destroy_port(struct serio *serio) | |||
617 | if (serio->registered) { | 606 | if (serio->registered) { |
618 | sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); | 607 | sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); |
619 | device_del(&serio->dev); | 608 | device_del(&serio->dev); |
620 | serio->registered = 0; | 609 | serio->registered = false; |
621 | } | 610 | } |
622 | 611 | ||
623 | list_del_init(&serio->node); | 612 | list_del_init(&serio->node); |
@@ -692,11 +681,13 @@ void serio_rescan(struct serio *serio) | |||
692 | { | 681 | { |
693 | serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); | 682 | serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); |
694 | } | 683 | } |
684 | EXPORT_SYMBOL(serio_rescan); | ||
695 | 685 | ||
696 | void serio_reconnect(struct serio *serio) | 686 | void serio_reconnect(struct serio *serio) |
697 | { | 687 | { |
698 | serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); | 688 | serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); |
699 | } | 689 | } |
690 | EXPORT_SYMBOL(serio_reconnect); | ||
700 | 691 | ||
701 | /* | 692 | /* |
702 | * Submits register request to kseriod for subsequent execution. | 693 | * Submits register request to kseriod for subsequent execution. |
@@ -707,6 +698,7 @@ void __serio_register_port(struct serio *serio, struct module *owner) | |||
707 | serio_init_port(serio); | 698 | serio_init_port(serio); |
708 | serio_queue_event(serio, owner, SERIO_REGISTER_PORT); | 699 | serio_queue_event(serio, owner, SERIO_REGISTER_PORT); |
709 | } | 700 | } |
701 | EXPORT_SYMBOL(__serio_register_port); | ||
710 | 702 | ||
711 | /* | 703 | /* |
712 | * Synchronously unregisters serio port. | 704 | * Synchronously unregisters serio port. |
@@ -718,6 +710,7 @@ void serio_unregister_port(struct serio *serio) | |||
718 | serio_destroy_port(serio); | 710 | serio_destroy_port(serio); |
719 | mutex_unlock(&serio_mutex); | 711 | mutex_unlock(&serio_mutex); |
720 | } | 712 | } |
713 | EXPORT_SYMBOL(serio_unregister_port); | ||
721 | 714 | ||
722 | /* | 715 | /* |
723 | * Safely unregisters child port if one is present. | 716 | * Safely unregisters child port if one is present. |
@@ -731,6 +724,7 @@ void serio_unregister_child_port(struct serio *serio) | |||
731 | } | 724 | } |
732 | mutex_unlock(&serio_mutex); | 725 | mutex_unlock(&serio_mutex); |
733 | } | 726 | } |
727 | EXPORT_SYMBOL(serio_unregister_child_port); | ||
734 | 728 | ||
735 | 729 | ||
736 | /* | 730 | /* |
@@ -756,9 +750,9 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char | |||
756 | 750 | ||
757 | retval = count; | 751 | retval = count; |
758 | if (!strncmp(buf, "manual", count)) { | 752 | if (!strncmp(buf, "manual", count)) { |
759 | serio_drv->manual_bind = 1; | 753 | serio_drv->manual_bind = true; |
760 | } else if (!strncmp(buf, "auto", count)) { | 754 | } else if (!strncmp(buf, "auto", count)) { |
761 | serio_drv->manual_bind = 0; | 755 | serio_drv->manual_bind = false; |
762 | } else { | 756 | } else { |
763 | retval = -EINVAL; | 757 | retval = -EINVAL; |
764 | } | 758 | } |
@@ -818,7 +812,7 @@ static void serio_attach_driver(struct serio_driver *drv) | |||
818 | 812 | ||
819 | int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) | 813 | int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) |
820 | { | 814 | { |
821 | int manual_bind = drv->manual_bind; | 815 | bool manual_bind = drv->manual_bind; |
822 | int error; | 816 | int error; |
823 | 817 | ||
824 | drv->driver.bus = &serio_bus; | 818 | drv->driver.bus = &serio_bus; |
@@ -829,7 +823,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons | |||
829 | * Temporarily disable automatic binding because probing | 823 | * Temporarily disable automatic binding because probing |
830 | * takes long time and we are better off doing it in kseriod | 824 | * takes long time and we are better off doing it in kseriod |
831 | */ | 825 | */ |
832 | drv->manual_bind = 1; | 826 | drv->manual_bind = true; |
833 | 827 | ||
834 | error = driver_register(&drv->driver); | 828 | error = driver_register(&drv->driver); |
835 | if (error) { | 829 | if (error) { |
@@ -844,7 +838,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons | |||
844 | * driver to free ports | 838 | * driver to free ports |
845 | */ | 839 | */ |
846 | if (!manual_bind) { | 840 | if (!manual_bind) { |
847 | drv->manual_bind = 0; | 841 | drv->manual_bind = false; |
848 | error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); | 842 | error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); |
849 | if (error) { | 843 | if (error) { |
850 | driver_unregister(&drv->driver); | 844 | driver_unregister(&drv->driver); |
@@ -854,6 +848,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons | |||
854 | 848 | ||
855 | return 0; | 849 | return 0; |
856 | } | 850 | } |
851 | EXPORT_SYMBOL(__serio_register_driver); | ||
857 | 852 | ||
858 | void serio_unregister_driver(struct serio_driver *drv) | 853 | void serio_unregister_driver(struct serio_driver *drv) |
859 | { | 854 | { |
@@ -861,7 +856,7 @@ void serio_unregister_driver(struct serio_driver *drv) | |||
861 | 856 | ||
862 | mutex_lock(&serio_mutex); | 857 | mutex_lock(&serio_mutex); |
863 | 858 | ||
864 | drv->manual_bind = 1; /* so serio_find_driver ignores it */ | 859 | drv->manual_bind = true; /* so serio_find_driver ignores it */ |
865 | serio_remove_pending_events(drv); | 860 | serio_remove_pending_events(drv); |
866 | 861 | ||
867 | start_over: | 862 | start_over: |
@@ -877,6 +872,7 @@ start_over: | |||
877 | driver_unregister(&drv->driver); | 872 | driver_unregister(&drv->driver); |
878 | mutex_unlock(&serio_mutex); | 873 | mutex_unlock(&serio_mutex); |
879 | } | 874 | } |
875 | EXPORT_SYMBOL(serio_unregister_driver); | ||
880 | 876 | ||
881 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) | 877 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) |
882 | { | 878 | { |
@@ -937,11 +933,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
937 | #ifdef CONFIG_PM | 933 | #ifdef CONFIG_PM |
938 | static int serio_suspend(struct device *dev, pm_message_t state) | 934 | static int serio_suspend(struct device *dev, pm_message_t state) |
939 | { | 935 | { |
940 | if (dev->power.power_state.event != state.event) { | 936 | struct serio *serio = to_serio_port(dev); |
941 | if (state.event == PM_EVENT_SUSPEND) | ||
942 | serio_cleanup(to_serio_port(dev)); | ||
943 | 937 | ||
944 | dev->power.power_state = state; | 938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { |
939 | serio_cleanup(serio); | ||
940 | serio->suspended = true; | ||
945 | } | 941 | } |
946 | 942 | ||
947 | return 0; | 943 | return 0; |
@@ -949,14 +945,15 @@ static int serio_suspend(struct device *dev, pm_message_t state) | |||
949 | 945 | ||
950 | static int serio_resume(struct device *dev) | 946 | static int serio_resume(struct device *dev) |
951 | { | 947 | { |
948 | struct serio *serio = to_serio_port(dev); | ||
949 | |||
952 | /* | 950 | /* |
953 | * Driver reconnect can take a while, so better let kseriod | 951 | * Driver reconnect can take a while, so better let kseriod |
954 | * deal with it. | 952 | * deal with it. |
955 | */ | 953 | */ |
956 | if (dev->power.power_state.event != PM_EVENT_ON) { | 954 | if (serio->suspended) { |
957 | dev->power.power_state = PMSG_ON; | 955 | serio->suspended = false; |
958 | serio_queue_event(to_serio_port(dev), NULL, | 956 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
959 | SERIO_RECONNECT_PORT); | ||
960 | } | 957 | } |
961 | 958 | ||
962 | return 0; | 959 | return 0; |
@@ -974,6 +971,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv) | |||
974 | } | 971 | } |
975 | return 0; | 972 | return 0; |
976 | } | 973 | } |
974 | EXPORT_SYMBOL(serio_open); | ||
977 | 975 | ||
978 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ | 976 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ |
979 | void serio_close(struct serio *serio) | 977 | void serio_close(struct serio *serio) |
@@ -983,6 +981,7 @@ void serio_close(struct serio *serio) | |||
983 | 981 | ||
984 | serio_set_drv(serio, NULL); | 982 | serio_set_drv(serio, NULL); |
985 | } | 983 | } |
984 | EXPORT_SYMBOL(serio_close); | ||
986 | 985 | ||
987 | irqreturn_t serio_interrupt(struct serio *serio, | 986 | irqreturn_t serio_interrupt(struct serio *serio, |
988 | unsigned char data, unsigned int dfl) | 987 | unsigned char data, unsigned int dfl) |
@@ -1003,6 +1002,7 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
1003 | 1002 | ||
1004 | return ret; | 1003 | return ret; |
1005 | } | 1004 | } |
1005 | EXPORT_SYMBOL(serio_interrupt); | ||
1006 | 1006 | ||
1007 | static struct bus_type serio_bus = { | 1007 | static struct bus_type serio_bus = { |
1008 | .name = "serio", | 1008 | .name = "serio", |
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 2e18a1c0c351..3d32d3f4e486 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c | |||
@@ -1050,4 +1050,5 @@ static void __exit gtco_exit(void) | |||
1050 | module_init(gtco_init); | 1050 | module_init(gtco_init); |
1051 | module_exit(gtco_exit); | 1051 | module_exit(gtco_exit); |
1052 | 1052 | ||
1053 | MODULE_DESCRIPTION("GTCO digitizer USB driver"); | ||
1053 | MODULE_LICENSE("GPL"); | 1054 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 9710bfd49cf9..9114ae1c7488 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -68,6 +68,7 @@ | |||
68 | * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX | 68 | * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX |
69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) | 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) |
70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 | 70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 |
71 | * v1.51 (pc) - Added support for Intuos4 | ||
71 | */ | 72 | */ |
72 | 73 | ||
73 | /* | 74 | /* |
@@ -88,7 +89,7 @@ | |||
88 | /* | 89 | /* |
89 | * Version Information | 90 | * Version Information |
90 | */ | 91 | */ |
91 | #define DRIVER_VERSION "v1.50" | 92 | #define DRIVER_VERSION "v1.51" |
92 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 93 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
93 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 94 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
94 | #define DRIVER_LICENSE "GPL" | 95 | #define DRIVER_LICENSE "GPL" |
@@ -128,6 +129,8 @@ extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac | |||
128 | extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 129 | extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
129 | extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 130 | extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
130 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 131 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
132 | extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
133 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
131 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 134 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
132 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 135 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
133 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 136 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b8624f27abf9..a9d5031b855e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -229,6 +229,19 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
229 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); | 229 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); |
230 | } | 230 | } |
231 | 231 | ||
232 | void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
233 | { | ||
234 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); | ||
235 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); | ||
236 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6); | ||
237 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
238 | } | ||
239 | |||
240 | void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
241 | { | ||
242 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8); | ||
243 | } | ||
244 | |||
232 | void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 245 | void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
233 | { | 246 | { |
234 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); | 247 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 2638811c61ac..38bf86384aeb 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -283,10 +283,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
283 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | 283 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) |
284 | { | 284 | { |
285 | unsigned char *data = wacom->data; | 285 | unsigned char *data = wacom->data; |
286 | int idx; | 286 | int idx = 0; |
287 | 287 | ||
288 | /* tool number */ | 288 | /* tool number */ |
289 | idx = data[1] & 0x01; | 289 | if (wacom->features->type == INTUOS) |
290 | idx = data[1] & 0x01; | ||
290 | 291 | ||
291 | /* Enter report */ | 292 | /* Enter report */ |
292 | if ((data[1] & 0xfc) == 0xc0) { | 293 | if ((data[1] & 0xfc) == 0xc0) { |
@@ -299,6 +300,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
299 | switch (wacom->id[idx]) { | 300 | switch (wacom->id[idx]) { |
300 | case 0x812: /* Inking pen */ | 301 | case 0x812: /* Inking pen */ |
301 | case 0x801: /* Intuos3 Inking pen */ | 302 | case 0x801: /* Intuos3 Inking pen */ |
303 | case 0x20802: /* Intuos4 Classic Pen */ | ||
302 | case 0x012: | 304 | case 0x012: |
303 | wacom->tool[idx] = BTN_TOOL_PENCIL; | 305 | wacom->tool[idx] = BTN_TOOL_PENCIL; |
304 | break; | 306 | break; |
@@ -308,6 +310,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
308 | case 0x823: /* Intuos3 Grip Pen */ | 310 | case 0x823: /* Intuos3 Grip Pen */ |
309 | case 0x813: /* Intuos3 Classic Pen */ | 311 | case 0x813: /* Intuos3 Classic Pen */ |
310 | case 0x885: /* Intuos3 Marker Pen */ | 312 | case 0x885: /* Intuos3 Marker Pen */ |
313 | case 0x802: /* Intuos4 Grip Pen Eraser */ | ||
314 | case 0x804: /* Intuos4 Marker Pen */ | ||
315 | case 0x40802: /* Intuos4 Classic Pen */ | ||
311 | case 0x022: | 316 | case 0x022: |
312 | wacom->tool[idx] = BTN_TOOL_PEN; | 317 | wacom->tool[idx] = BTN_TOOL_PEN; |
313 | break; | 318 | break; |
@@ -319,10 +324,12 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
319 | case 0x09c: | 324 | case 0x09c: |
320 | case 0x094: | 325 | case 0x094: |
321 | case 0x017: /* Intuos3 2D Mouse */ | 326 | case 0x017: /* Intuos3 2D Mouse */ |
327 | case 0x806: /* Intuos4 Mouse */ | ||
322 | wacom->tool[idx] = BTN_TOOL_MOUSE; | 328 | wacom->tool[idx] = BTN_TOOL_MOUSE; |
323 | break; | 329 | break; |
324 | case 0x096: /* Lens cursor */ | 330 | case 0x096: /* Lens cursor */ |
325 | case 0x097: /* Intuos3 Lens cursor */ | 331 | case 0x097: /* Intuos3 Lens cursor */ |
332 | case 0x006: /* Intuos4 Lens cursor */ | ||
326 | wacom->tool[idx] = BTN_TOOL_LENS; | 333 | wacom->tool[idx] = BTN_TOOL_LENS; |
327 | break; | 334 | break; |
328 | case 0x82a: /* Eraser */ | 335 | case 0x82a: /* Eraser */ |
@@ -333,12 +340,17 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
333 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | 340 | case 0x82b: /* Intuos3 Grip Pen Eraser */ |
334 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | 341 | case 0x81b: /* Intuos3 Classic Pen Eraser */ |
335 | case 0x91b: /* Intuos3 Airbrush Eraser */ | 342 | case 0x91b: /* Intuos3 Airbrush Eraser */ |
343 | case 0x80c: /* Intuos4 Marker Pen Eraser */ | ||
344 | case 0x80a: /* Intuos4 Grip Pen Eraser */ | ||
345 | case 0x4080a: /* Intuos4 Classic Pen Eraser */ | ||
346 | case 0x90a: /* Intuos4 Airbrush Eraser */ | ||
336 | wacom->tool[idx] = BTN_TOOL_RUBBER; | 347 | wacom->tool[idx] = BTN_TOOL_RUBBER; |
337 | break; | 348 | break; |
338 | case 0xd12: | 349 | case 0xd12: |
339 | case 0x912: | 350 | case 0x912: |
340 | case 0x112: | 351 | case 0x112: |
341 | case 0x913: /* Intuos3 Airbrush */ | 352 | case 0x913: /* Intuos3 Airbrush */ |
353 | case 0x902: /* Intuos4 Airbrush */ | ||
342 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | 354 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; |
343 | break; | 355 | break; |
344 | default: /* Unknown tool */ | 356 | default: /* Unknown tool */ |
@@ -349,9 +361,15 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
349 | 361 | ||
350 | /* Exit report */ | 362 | /* Exit report */ |
351 | if ((data[1] & 0xfe) == 0x80) { | 363 | if ((data[1] & 0xfe) == 0x80) { |
364 | /* | ||
365 | * Reset all states otherwise we lose the initial states | ||
366 | * when in-prox next time | ||
367 | */ | ||
352 | wacom_report_abs(wcombo, ABS_X, 0); | 368 | wacom_report_abs(wcombo, ABS_X, 0); |
353 | wacom_report_abs(wcombo, ABS_Y, 0); | 369 | wacom_report_abs(wcombo, ABS_Y, 0); |
354 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | 370 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); |
371 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | ||
372 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | ||
355 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | 373 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { |
356 | wacom_report_key(wcombo, BTN_LEFT, 0); | 374 | wacom_report_key(wcombo, BTN_LEFT, 0); |
357 | wacom_report_key(wcombo, BTN_MIDDLE, 0); | 375 | wacom_report_key(wcombo, BTN_MIDDLE, 0); |
@@ -362,8 +380,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
362 | wacom_report_abs(wcombo, ABS_RZ, 0); | 380 | wacom_report_abs(wcombo, ABS_RZ, 0); |
363 | } else { | 381 | } else { |
364 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 382 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); |
365 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | ||
366 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | ||
367 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 383 | wacom_report_key(wcombo, BTN_STYLUS, 0); |
368 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
369 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 385 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
@@ -372,6 +388,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
372 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 388 | wacom_report_key(wcombo, wacom->tool[idx], 0); |
373 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 389 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ |
374 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 390 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
391 | wacom->id[idx] = 0; | ||
375 | return 2; | 392 | return 2; |
376 | } | 393 | } |
377 | return 0; | 394 | return 0; |
@@ -385,6 +402,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | |||
385 | /* general pen packet */ | 402 | /* general pen packet */ |
386 | if ((data[1] & 0xb8) == 0xa0) { | 403 | if ((data[1] & 0xb8) == 0xa0) { |
387 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 404 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
405 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) | ||
406 | t = (t << 1) | (data[1] & 1); | ||
388 | wacom_report_abs(wcombo, ABS_PRESSURE, t); | 407 | wacom_report_abs(wcombo, ABS_PRESSURE, t); |
389 | wacom_report_abs(wcombo, ABS_TILT_X, | 408 | wacom_report_abs(wcombo, ABS_TILT_X, |
390 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 409 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
@@ -409,7 +428,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
409 | { | 428 | { |
410 | unsigned char *data = wacom->data; | 429 | unsigned char *data = wacom->data; |
411 | unsigned int t; | 430 | unsigned int t; |
412 | int idx, result; | 431 | int idx = 0, result; |
413 | 432 | ||
414 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | 433 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { |
415 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 434 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); |
@@ -417,7 +436,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
417 | } | 436 | } |
418 | 437 | ||
419 | /* tool number */ | 438 | /* tool number */ |
420 | idx = data[1] & 0x01; | 439 | if (wacom->features->type == INTUOS) |
440 | idx = data[1] & 0x01; | ||
421 | 441 | ||
422 | /* pad packets. Works as a second tool and is always in prox */ | 442 | /* pad packets. Works as a second tool and is always in prox */ |
423 | if (data[0] == 12) { | 443 | if (data[0] == 12) { |
@@ -425,25 +445,54 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
425 | if (wacom->tool[1] != BTN_TOOL_FINGER) | 445 | if (wacom->tool[1] != BTN_TOOL_FINGER) |
426 | wacom->tool[1] = BTN_TOOL_FINGER; | 446 | wacom->tool[1] = BTN_TOOL_FINGER; |
427 | 447 | ||
428 | wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | 448 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { |
429 | wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | 449 | wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); |
430 | wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | 450 | wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); |
431 | wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | 451 | wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); |
432 | wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | 452 | wacom_report_key(wcombo, BTN_3, (data[3] & 0x04)); |
433 | wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | 453 | wacom_report_key(wcombo, BTN_4, (data[3] & 0x08)); |
434 | wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | 454 | wacom_report_key(wcombo, BTN_5, (data[3] & 0x10)); |
435 | wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | 455 | wacom_report_key(wcombo, BTN_6, (data[3] & 0x20)); |
436 | wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); | 456 | if (data[1] & 0x80) { |
437 | wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); | 457 | wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f)); |
438 | wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | 458 | } else { |
439 | wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | 459 | /* Out of proximity, clear wheel value. */ |
440 | 460 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | |
441 | if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | | 461 | } |
442 | data[2] | (data[3] & 0x1f) | data[4]) | 462 | if (wacom->features->type != INTUOS4S) { |
443 | wacom_report_key(wcombo, wacom->tool[1], 1); | 463 | wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); |
444 | else | 464 | wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); |
445 | wacom_report_key(wcombo, wacom->tool[1], 0); | 465 | } |
446 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | 466 | if (data[1] | (data[2] & 0x01) | data[3]) { |
467 | wacom_report_key(wcombo, wacom->tool[1], 1); | ||
468 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
469 | } else { | ||
470 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
471 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
472 | } | ||
473 | } else { | ||
474 | wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | ||
475 | wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | ||
476 | wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | ||
477 | wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | ||
478 | wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | ||
479 | wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | ||
480 | wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | ||
481 | wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | ||
482 | wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); | ||
483 | wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); | ||
484 | wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | ||
485 | wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | ||
486 | |||
487 | if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | | ||
488 | data[2] | (data[3] & 0x1f) | data[4]) { | ||
489 | wacom_report_key(wcombo, wacom->tool[1], 1); | ||
490 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
491 | } else { | ||
492 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
493 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
494 | } | ||
495 | } | ||
447 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | 496 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); |
448 | return 1; | 497 | return 1; |
449 | } | 498 | } |
@@ -453,10 +502,16 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
453 | if (result) | 502 | if (result) |
454 | return result-1; | 503 | return result-1; |
455 | 504 | ||
456 | /* Only large I3 and I1 & I2 support Lense Cursor */ | 505 | /* don't proceed if we don't know the ID */ |
506 | if (!wacom->id[idx]) | ||
507 | return 0; | ||
508 | |||
509 | /* Only large Intuos support Lense Cursor */ | ||
457 | if ((wacom->tool[idx] == BTN_TOOL_LENS) | 510 | if ((wacom->tool[idx] == BTN_TOOL_LENS) |
458 | && ((wacom->features->type == INTUOS3) | 511 | && ((wacom->features->type == INTUOS3) |
459 | || (wacom->features->type == INTUOS3S))) | 512 | || (wacom->features->type == INTUOS3S) |
513 | || (wacom->features->type == INTUOS4) | ||
514 | || (wacom->features->type == INTUOS4S))) | ||
460 | return 0; | 515 | return 0; |
461 | 516 | ||
462 | /* Cintiq doesn't send data when RDY bit isn't set */ | 517 | /* Cintiq doesn't send data when RDY bit isn't set */ |
@@ -476,8 +531,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
476 | /* process general packets */ | 531 | /* process general packets */ |
477 | wacom_intuos_general(wacom, wcombo); | 532 | wacom_intuos_general(wacom, wcombo); |
478 | 533 | ||
479 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ | 534 | /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */ |
480 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { | 535 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) { |
481 | 536 | ||
482 | if (data[1] & 0x02) { | 537 | if (data[1] & 0x02) { |
483 | /* Rotation packet */ | 538 | /* Rotation packet */ |
@@ -506,20 +561,36 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
506 | wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | 561 | wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); |
507 | 562 | ||
508 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | 563 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
509 | /* 2D mouse packet */ | 564 | /* I4 mouse */ |
510 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); | 565 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { |
511 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | 566 | wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); |
512 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); | 567 | wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); |
513 | wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | 568 | wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); |
569 | wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7) | ||
570 | - ((data[7] & 0x40) >> 6)); | ||
571 | wacom_report_key(wcombo, BTN_SIDE, data[6] & 0x08); | ||
572 | wacom_report_key(wcombo, BTN_EXTRA, data[6] & 0x10); | ||
573 | |||
574 | wacom_report_abs(wcombo, ABS_TILT_X, | ||
575 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
576 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | ||
577 | } else { | ||
578 | /* 2D mouse packet */ | ||
579 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); | ||
580 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | ||
581 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); | ||
582 | wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | ||
514 | - ((data[8] & 0x02) >> 1)); | 583 | - ((data[8] & 0x02) >> 1)); |
515 | 584 | ||
516 | /* I3 2D mouse side buttons */ | 585 | /* I3 2D mouse side buttons */ |
517 | if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { | 586 | if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { |
518 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); | 587 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); |
519 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); | 588 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); |
589 | } | ||
520 | } | 590 | } |
521 | 591 | } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L || | |
522 | } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) { | 592 | wacom->features->type == INTUOS4L) && |
593 | wacom->tool[idx] == BTN_TOOL_LENS) { | ||
523 | /* Lens cursor packets */ | 594 | /* Lens cursor packets */ |
524 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | 595 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); |
525 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 596 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); |
@@ -581,6 +652,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
581 | } | 652 | } |
582 | } else if (touchOut || !prox) { /* force touch out-prox */ | 653 | } else if (touchOut || !prox) { /* force touch out-prox */ |
583 | wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); | 654 | wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); |
655 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
584 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 656 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
585 | touchOut = 0; | 657 | touchOut = 0; |
586 | touchInProx = 1; | 658 | touchInProx = 1; |
@@ -669,6 +741,9 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
669 | case INTUOS3S: | 741 | case INTUOS3S: |
670 | case INTUOS3: | 742 | case INTUOS3: |
671 | case INTUOS3L: | 743 | case INTUOS3L: |
744 | case INTUOS4S: | ||
745 | case INTUOS4: | ||
746 | case INTUOS4L: | ||
672 | case CINTIQ: | 747 | case CINTIQ: |
673 | case WACOM_BEE: | 748 | case WACOM_BEE: |
674 | return wacom_intuos_irq(wacom_wac, wcombo); | 749 | return wacom_intuos_irq(wacom_wac, wcombo); |
@@ -706,6 +781,14 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
706 | case INTUOS: | 781 | case INTUOS: |
707 | input_dev_i(input_dev, wacom_wac); | 782 | input_dev_i(input_dev, wacom_wac); |
708 | break; | 783 | break; |
784 | case INTUOS4: | ||
785 | case INTUOS4L: | ||
786 | input_dev_i4(input_dev, wacom_wac); | ||
787 | /* fall through */ | ||
788 | case INTUOS4S: | ||
789 | input_dev_i4s(input_dev, wacom_wac); | ||
790 | input_dev_i(input_dev, wacom_wac); | ||
791 | break; | ||
709 | case PL: | 792 | case PL: |
710 | case PTU: | 793 | case PTU: |
711 | case TABLETPC: | 794 | case TABLETPC: |
@@ -766,6 +849,10 @@ static struct wacom_features wacom_features[] = { | |||
766 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, | 849 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, |
767 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, | 850 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, |
768 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, | 851 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, |
852 | { "Wacom Intuos4 4x6", 10, 31496, 19685, 2047, 63, INTUOS4S }, | ||
853 | { "Wacom Intuos4 6x9", 10, 44704, 27940, 2047, 63, INTUOS4 }, | ||
854 | { "Wacom Intuos4 8x13", 10, 65024, 40640, 2047, 63, INTUOS4L }, | ||
855 | { "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L }, | ||
769 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, | 856 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, |
770 | { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE }, | 857 | { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE }, |
771 | { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, | 858 | { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, |
@@ -825,6 +912,10 @@ static struct usb_device_id wacom_ids[] = { | |||
825 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | 912 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, |
826 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | 913 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, |
827 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, | 914 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, |
915 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) }, | ||
916 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) }, | ||
917 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) }, | ||
918 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) }, | ||
828 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | 919 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, |
829 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, | 920 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, |
830 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, | 921 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index f9c8b69673b7..c10235aba7e5 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -25,6 +25,9 @@ enum { | |||
25 | INTUOS3S, | 25 | INTUOS3S, |
26 | INTUOS3, | 26 | INTUOS3, |
27 | INTUOS3L, | 27 | INTUOS3L, |
28 | INTUOS4S, | ||
29 | INTUOS4, | ||
30 | INTUOS4L, | ||
28 | CINTIQ, | 31 | CINTIQ, |
29 | WACOM_BEE, | 32 | WACOM_BEE, |
30 | WACOM_MO, | 33 | WACOM_MO, |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b01fd61dadcc..72e2712c7e2a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -111,6 +111,15 @@ config TOUCHSCREEN_DA9034 | |||
111 | Say Y here to enable the support for the touchscreen found | 111 | Say Y here to enable the support for the touchscreen found |
112 | on Dialog Semiconductor DA9034 PMIC. | 112 | on Dialog Semiconductor DA9034 PMIC. |
113 | 113 | ||
114 | config TOUCHSCREEN_EETI | ||
115 | tristate "EETI touchscreen panel support" | ||
116 | depends on I2C | ||
117 | help | ||
118 | Say Y here to enable support for I2C connected EETI touch panels. | ||
119 | |||
120 | To compile this driver as a module, choose M here: the | ||
121 | module will be called eeti_ts. | ||
122 | |||
114 | config TOUCHSCREEN_FUJITSU | 123 | config TOUCHSCREEN_FUJITSU |
115 | tristate "Fujitsu serial touchscreen" | 124 | tristate "Fujitsu serial touchscreen" |
116 | select SERIO | 125 | select SERIO |
@@ -341,6 +350,21 @@ config TOUCHSCREEN_WM9713 | |||
341 | Say Y here to enable support for the Wolfson Microelectronics | 350 | Say Y here to enable support for the Wolfson Microelectronics |
342 | WM9713 touchscreen controller. | 351 | WM9713 touchscreen controller. |
343 | 352 | ||
353 | config TOUCHSCREEN_WM97XX_ATMEL | ||
354 | tristate "WM97xx Atmel accelerated touch" | ||
355 | depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91) | ||
356 | help | ||
357 | Say Y here for support for streaming mode with WM97xx touchscreens | ||
358 | on Atmel AT91 or AVR32 systems with an AC97C module. | ||
359 | |||
360 | Be aware that this will use channel B in the controller for | ||
361 | streaming data, this must not conflict with other AC97C drivers. | ||
362 | |||
363 | If unsure, say N. | ||
364 | |||
365 | To compile this driver as a module, choose M here: the module will | ||
366 | be called atmel-wm97xx. | ||
367 | |||
344 | config TOUCHSCREEN_WM97XX_MAINSTONE | 368 | config TOUCHSCREEN_WM97XX_MAINSTONE |
345 | tristate "WM97xx Mainstone accelerated touch" | 369 | tristate "WM97xx Mainstone accelerated touch" |
346 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA | 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA |
@@ -466,4 +490,12 @@ config TOUCHSCREEN_TSC2007 | |||
466 | To compile this driver as a module, choose M here: the | 490 | To compile this driver as a module, choose M here: the |
467 | module will be called tsc2007. | 491 | module will be called tsc2007. |
468 | 492 | ||
493 | config TOUCHSCREEN_W90X900 | ||
494 | tristate "W90P910 touchscreen driver" | ||
495 | help | ||
496 | Say Y here if you have a W90P910 based touchscreen. | ||
497 | |||
498 | To compile this driver as a module, choose M here: the | ||
499 | module will be called w90p910_ts. | ||
500 | |||
469 | endif | 501 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6700f7b9d165..3e1c5e0b952f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | |||
13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
14 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 14 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
15 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 15 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
16 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | ||
16 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
17 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
18 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
@@ -35,5 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | |||
35 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o | 36 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o |
36 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o | 37 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o |
37 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o | 38 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o |
39 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | ||
38 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 40 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
39 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 41 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
42 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 2b01e56568f8..ba9d38c3f412 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -83,6 +83,7 @@ struct ads7846_packet { | |||
83 | struct ads7846 { | 83 | struct ads7846 { |
84 | struct input_dev *input; | 84 | struct input_dev *input; |
85 | char phys[32]; | 85 | char phys[32]; |
86 | char name[32]; | ||
86 | 87 | ||
87 | struct spi_device *spi; | 88 | struct spi_device *spi; |
88 | 89 | ||
@@ -97,6 +98,8 @@ struct ads7846 { | |||
97 | u16 x_plate_ohms; | 98 | u16 x_plate_ohms; |
98 | u16 pressure_max; | 99 | u16 pressure_max; |
99 | 100 | ||
101 | bool swap_xy; | ||
102 | |||
100 | struct ads7846_packet *packet; | 103 | struct ads7846_packet *packet; |
101 | 104 | ||
102 | struct spi_transfer xfer[18]; | 105 | struct spi_transfer xfer[18]; |
@@ -599,6 +602,10 @@ static void ads7846_rx(void *ads) | |||
599 | dev_dbg(&ts->spi->dev, "DOWN\n"); | 602 | dev_dbg(&ts->spi->dev, "DOWN\n"); |
600 | #endif | 603 | #endif |
601 | } | 604 | } |
605 | |||
606 | if (ts->swap_xy) | ||
607 | swap(x, y); | ||
608 | |||
602 | input_report_abs(input, ABS_X, x); | 609 | input_report_abs(input, ABS_X, x); |
603 | input_report_abs(input, ABS_Y, y); | 610 | input_report_abs(input, ABS_Y, y); |
604 | input_report_abs(input, ABS_PRESSURE, Rt); | 611 | input_report_abs(input, ABS_PRESSURE, Rt); |
@@ -917,6 +924,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
917 | ts->spi = spi; | 924 | ts->spi = spi; |
918 | ts->input = input_dev; | 925 | ts->input = input_dev; |
919 | ts->vref_mv = pdata->vref_mv; | 926 | ts->vref_mv = pdata->vref_mv; |
927 | ts->swap_xy = pdata->swap_xy; | ||
920 | 928 | ||
921 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 929 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
922 | ts->timer.function = ads7846_timer; | 930 | ts->timer.function = ads7846_timer; |
@@ -958,8 +966,9 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
958 | ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; | 966 | ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; |
959 | 967 | ||
960 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); | 968 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); |
969 | snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model); | ||
961 | 970 | ||
962 | input_dev->name = "ADS784x Touchscreen"; | 971 | input_dev->name = ts->name; |
963 | input_dev->phys = ts->phys; | 972 | input_dev->phys = ts->phys; |
964 | input_dev->dev.parent = &spi->dev; | 973 | input_dev->dev.parent = &spi->dev; |
965 | 974 | ||
@@ -1141,9 +1150,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1141 | 1150 | ||
1142 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, | 1151 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, |
1143 | spi->dev.driver->name, ts)) { | 1152 | spi->dev.driver->name, ts)) { |
1144 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | 1153 | dev_info(&spi->dev, |
1145 | err = -EBUSY; | 1154 | "trying pin change workaround on irq %d\n", spi->irq); |
1146 | goto err_free_gpio; | 1155 | err = request_irq(spi->irq, ads7846_irq, |
1156 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
1157 | spi->dev.driver->name, ts); | ||
1158 | if (err) { | ||
1159 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | ||
1160 | goto err_free_gpio; | ||
1161 | } | ||
1147 | } | 1162 | } |
1148 | 1163 | ||
1149 | err = ads784x_hwmon_register(spi, ts); | 1164 | err = ads784x_hwmon_register(spi, ts); |
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c new file mode 100644 index 000000000000..35377f583e28 --- /dev/null +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* | ||
2 | * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97 | ||
3 | * codecs. | ||
4 | * | ||
5 | * Copyright (C) 2008 - 2009 Atmel Corporation | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/moduleparam.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/wm97xx.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #define AC97C_ICA 0x10 | ||
24 | #define AC97C_CBRHR 0x30 | ||
25 | #define AC97C_CBSR 0x38 | ||
26 | #define AC97C_CBMR 0x3c | ||
27 | #define AC97C_IER 0x54 | ||
28 | #define AC97C_IDR 0x58 | ||
29 | |||
30 | #define AC97C_RXRDY (1 << 4) | ||
31 | #define AC97C_OVRUN (1 << 5) | ||
32 | |||
33 | #define AC97C_CMR_SIZE_20 (0 << 16) | ||
34 | #define AC97C_CMR_SIZE_18 (1 << 16) | ||
35 | #define AC97C_CMR_SIZE_16 (2 << 16) | ||
36 | #define AC97C_CMR_SIZE_10 (3 << 16) | ||
37 | #define AC97C_CMR_CEM_LITTLE (1 << 18) | ||
38 | #define AC97C_CMR_CEM_BIG (0 << 18) | ||
39 | #define AC97C_CMR_CENA (1 << 21) | ||
40 | |||
41 | #define AC97C_INT_CBEVT (1 << 4) | ||
42 | |||
43 | #define AC97C_SR_CAEVT (1 << 3) | ||
44 | |||
45 | #define AC97C_CH_MASK(slot) \ | ||
46 | (0x7 << (3 * (slot - 3))) | ||
47 | #define AC97C_CH_ASSIGN(slot, channel) \ | ||
48 | (AC97C_CHANNEL_##channel << (3 * (slot - 3))) | ||
49 | #define AC97C_CHANNEL_NONE 0x0 | ||
50 | #define AC97C_CHANNEL_B 0x2 | ||
51 | |||
52 | #define ac97c_writel(chip, reg, val) \ | ||
53 | __raw_writel((val), (chip)->regs + AC97C_##reg) | ||
54 | #define ac97c_readl(chip, reg) \ | ||
55 | __raw_readl((chip)->regs + AC97C_##reg) | ||
56 | |||
57 | #ifdef CONFIG_CPU_AT32AP700X | ||
58 | #define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800) | ||
59 | #define ATMEL_WM97XX_AC97C_IRQ (29) | ||
60 | #define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */ | ||
61 | #else | ||
62 | #error Unkown CPU, this driver only supports AT32AP700X CPUs. | ||
63 | #endif | ||
64 | |||
65 | struct continuous { | ||
66 | u16 id; /* codec id */ | ||
67 | u8 code; /* continuous code */ | ||
68 | u8 reads; /* number of coord reads per read cycle */ | ||
69 | u32 speed; /* number of coords per second */ | ||
70 | }; | ||
71 | |||
72 | #define WM_READS(sp) ((sp / HZ) + 1) | ||
73 | |||
74 | static const struct continuous cinfo[] = { | ||
75 | {WM9705_ID2, 0, WM_READS(94), 94}, | ||
76 | {WM9705_ID2, 1, WM_READS(188), 188}, | ||
77 | {WM9705_ID2, 2, WM_READS(375), 375}, | ||
78 | {WM9705_ID2, 3, WM_READS(750), 750}, | ||
79 | {WM9712_ID2, 0, WM_READS(94), 94}, | ||
80 | {WM9712_ID2, 1, WM_READS(188), 188}, | ||
81 | {WM9712_ID2, 2, WM_READS(375), 375}, | ||
82 | {WM9712_ID2, 3, WM_READS(750), 750}, | ||
83 | {WM9713_ID2, 0, WM_READS(94), 94}, | ||
84 | {WM9713_ID2, 1, WM_READS(120), 120}, | ||
85 | {WM9713_ID2, 2, WM_READS(154), 154}, | ||
86 | {WM9713_ID2, 3, WM_READS(188), 188}, | ||
87 | }; | ||
88 | |||
89 | /* Continuous speed index. */ | ||
90 | static int sp_idx; | ||
91 | |||
92 | /* | ||
93 | * Pen sampling frequency (Hz) in continuous mode. | ||
94 | */ | ||
95 | static int cont_rate = 188; | ||
96 | module_param(cont_rate, int, 0); | ||
97 | MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); | ||
98 | |||
99 | /* | ||
100 | * Pen down detection. | ||
101 | * | ||
102 | * This driver can either poll or use an interrupt to indicate a pen down | ||
103 | * event. If the irq request fails then it will fall back to polling mode. | ||
104 | */ | ||
105 | static int pen_int = 1; | ||
106 | module_param(pen_int, int, 0); | ||
107 | MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)"); | ||
108 | |||
109 | /* | ||
110 | * Pressure readback. | ||
111 | * | ||
112 | * Set to 1 to read back pen down pressure. | ||
113 | */ | ||
114 | static int pressure; | ||
115 | module_param(pressure, int, 0); | ||
116 | MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); | ||
117 | |||
118 | /* | ||
119 | * AC97 touch data slot. | ||
120 | * | ||
121 | * Touch screen readback data ac97 slot. | ||
122 | */ | ||
123 | static int ac97_touch_slot = 5; | ||
124 | module_param(ac97_touch_slot, int, 0); | ||
125 | MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); | ||
126 | |||
127 | /* | ||
128 | * GPIO line number. | ||
129 | * | ||
130 | * Set to GPIO number where the signal from the WM97xx device is hooked up. | ||
131 | */ | ||
132 | static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT; | ||
133 | module_param(atmel_gpio_line, int, 0); | ||
134 | MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx"); | ||
135 | |||
136 | struct atmel_wm97xx { | ||
137 | struct wm97xx *wm; | ||
138 | struct timer_list pen_timer; | ||
139 | void __iomem *regs; | ||
140 | unsigned long ac97c_irq; | ||
141 | unsigned long gpio_pen; | ||
142 | unsigned long gpio_irq; | ||
143 | unsigned short x; | ||
144 | unsigned short y; | ||
145 | }; | ||
146 | |||
147 | static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id) | ||
148 | { | ||
149 | struct atmel_wm97xx *atmel_wm97xx = dev_id; | ||
150 | struct wm97xx *wm = atmel_wm97xx->wm; | ||
151 | int status = ac97c_readl(atmel_wm97xx, CBSR); | ||
152 | irqreturn_t retval = IRQ_NONE; | ||
153 | |||
154 | if (status & AC97C_OVRUN) { | ||
155 | dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n"); | ||
156 | ac97c_readl(atmel_wm97xx, CBRHR); | ||
157 | retval = IRQ_HANDLED; | ||
158 | } else if (status & AC97C_RXRDY) { | ||
159 | u16 data; | ||
160 | u16 value; | ||
161 | u16 source; | ||
162 | u16 pen_down; | ||
163 | |||
164 | data = ac97c_readl(atmel_wm97xx, CBRHR); | ||
165 | value = data & 0x0fff; | ||
166 | source = data & WM97XX_ADCSRC_MASK; | ||
167 | pen_down = (data & WM97XX_PEN_DOWN) >> 8; | ||
168 | |||
169 | if (source == WM97XX_ADCSEL_X) | ||
170 | atmel_wm97xx->x = value; | ||
171 | if (source == WM97XX_ADCSEL_Y) | ||
172 | atmel_wm97xx->y = value; | ||
173 | |||
174 | if (!pressure && source == WM97XX_ADCSEL_Y) { | ||
175 | input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x); | ||
176 | input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y); | ||
177 | input_report_key(wm->input_dev, BTN_TOUCH, pen_down); | ||
178 | input_sync(wm->input_dev); | ||
179 | } else if (pressure && source == WM97XX_ADCSEL_PRES) { | ||
180 | input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x); | ||
181 | input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y); | ||
182 | input_report_abs(wm->input_dev, ABS_PRESSURE, value); | ||
183 | input_report_key(wm->input_dev, BTN_TOUCH, value); | ||
184 | input_sync(wm->input_dev); | ||
185 | } | ||
186 | |||
187 | retval = IRQ_HANDLED; | ||
188 | } | ||
189 | |||
190 | return retval; | ||
191 | } | ||
192 | |||
193 | static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm) | ||
194 | { | ||
195 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev); | ||
196 | struct input_dev *input_dev = wm->input_dev; | ||
197 | int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen); | ||
198 | |||
199 | if (pen_down != 0) { | ||
200 | mod_timer(&atmel_wm97xx->pen_timer, | ||
201 | jiffies + msecs_to_jiffies(1)); | ||
202 | } else { | ||
203 | if (pressure) | ||
204 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
205 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
206 | input_sync(input_dev); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | static void atmel_wm97xx_pen_timer(unsigned long data) | ||
211 | { | ||
212 | atmel_wm97xx_acc_pen_up((struct wm97xx *)data); | ||
213 | } | ||
214 | |||
215 | static int atmel_wm97xx_acc_startup(struct wm97xx *wm) | ||
216 | { | ||
217 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev); | ||
218 | int idx = 0; | ||
219 | |||
220 | if (wm->ac97 == NULL) | ||
221 | return -ENODEV; | ||
222 | |||
223 | for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { | ||
224 | if (wm->id != cinfo[idx].id) | ||
225 | continue; | ||
226 | |||
227 | sp_idx = idx; | ||
228 | |||
229 | if (cont_rate <= cinfo[idx].speed) | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | wm->acc_rate = cinfo[sp_idx].code; | ||
234 | wm->acc_slot = ac97_touch_slot; | ||
235 | dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, " | ||
236 | "%d samples/sec\n", cinfo[sp_idx].speed); | ||
237 | |||
238 | if (pen_int) { | ||
239 | unsigned long reg; | ||
240 | |||
241 | wm->pen_irq = atmel_wm97xx->gpio_irq; | ||
242 | |||
243 | switch (wm->id) { | ||
244 | case WM9712_ID2: /* Fall through. */ | ||
245 | case WM9713_ID2: | ||
246 | /* | ||
247 | * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3 | ||
248 | * (PENDOWN). | ||
249 | */ | ||
250 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | ||
251 | WM97XX_GPIO_POL_HIGH, | ||
252 | WM97XX_GPIO_STICKY, | ||
253 | WM97XX_GPIO_WAKE); | ||
254 | wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT, | ||
255 | WM97XX_GPIO_POL_HIGH, | ||
256 | WM97XX_GPIO_NOTSTICKY, | ||
257 | WM97XX_GPIO_NOWAKE); | ||
258 | case WM9705_ID2: /* Fall through. */ | ||
259 | /* | ||
260 | * Enable touch data slot in AC97 controller channel B. | ||
261 | */ | ||
262 | reg = ac97c_readl(atmel_wm97xx, ICA); | ||
263 | reg &= ~AC97C_CH_MASK(wm->acc_slot); | ||
264 | reg |= AC97C_CH_ASSIGN(wm->acc_slot, B); | ||
265 | ac97c_writel(atmel_wm97xx, ICA, reg); | ||
266 | |||
267 | /* | ||
268 | * Enable channel and interrupt for RXRDY and OVERRUN. | ||
269 | */ | ||
270 | ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA | ||
271 | | AC97C_CMR_CEM_BIG | ||
272 | | AC97C_CMR_SIZE_16 | ||
273 | | AC97C_OVRUN | ||
274 | | AC97C_RXRDY); | ||
275 | /* Dummy read to empty RXRHR. */ | ||
276 | ac97c_readl(atmel_wm97xx, CBRHR); | ||
277 | /* | ||
278 | * Enable interrupt for channel B in the AC97 | ||
279 | * controller. | ||
280 | */ | ||
281 | ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT); | ||
282 | break; | ||
283 | default: | ||
284 | dev_err(&wm->touch_dev->dev, "pen down irq not " | ||
285 | "supported on this device\n"); | ||
286 | pen_int = 0; | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm) | ||
295 | { | ||
296 | if (pen_int) { | ||
297 | struct atmel_wm97xx *atmel_wm97xx = | ||
298 | platform_get_drvdata(wm->touch_dev); | ||
299 | unsigned long ica; | ||
300 | |||
301 | switch (wm->id & 0xffff) { | ||
302 | case WM9705_ID2: /* Fall through. */ | ||
303 | case WM9712_ID2: /* Fall through. */ | ||
304 | case WM9713_ID2: | ||
305 | /* Disable slot and turn off channel B interrupts. */ | ||
306 | ica = ac97c_readl(atmel_wm97xx, ICA); | ||
307 | ica &= ~AC97C_CH_MASK(wm->acc_slot); | ||
308 | ac97c_writel(atmel_wm97xx, ICA, ica); | ||
309 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | ||
310 | ac97c_writel(atmel_wm97xx, CBMR, 0); | ||
311 | wm->pen_irq = 0; | ||
312 | break; | ||
313 | default: | ||
314 | dev_err(&wm->touch_dev->dev, "unknown codec\n"); | ||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | |||
320 | static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable) | ||
321 | { | ||
322 | /* Intentionally left empty. */ | ||
323 | } | ||
324 | |||
325 | static struct wm97xx_mach_ops atmel_mach_ops = { | ||
326 | .acc_enabled = 1, | ||
327 | .acc_pen_up = atmel_wm97xx_acc_pen_up, | ||
328 | .acc_startup = atmel_wm97xx_acc_startup, | ||
329 | .acc_shutdown = atmel_wm97xx_acc_shutdown, | ||
330 | .irq_enable = atmel_wm97xx_irq_enable, | ||
331 | .irq_gpio = WM97XX_GPIO_3, | ||
332 | }; | ||
333 | |||
334 | static int __init atmel_wm97xx_probe(struct platform_device *pdev) | ||
335 | { | ||
336 | struct wm97xx *wm = platform_get_drvdata(pdev); | ||
337 | struct atmel_wm97xx *atmel_wm97xx; | ||
338 | int ret; | ||
339 | |||
340 | atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL); | ||
341 | if (!atmel_wm97xx) { | ||
342 | dev_dbg(&pdev->dev, "out of memory\n"); | ||
343 | return -ENOMEM; | ||
344 | } | ||
345 | |||
346 | atmel_wm97xx->wm = wm; | ||
347 | atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM; | ||
348 | atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ; | ||
349 | atmel_wm97xx->gpio_pen = atmel_gpio_line; | ||
350 | atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen); | ||
351 | |||
352 | setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, | ||
353 | (unsigned long)wm); | ||
354 | |||
355 | ret = request_irq(atmel_wm97xx->ac97c_irq, | ||
356 | atmel_wm97xx_channel_b_interrupt, | ||
357 | IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx); | ||
358 | if (ret) { | ||
359 | dev_dbg(&pdev->dev, "could not request ac97c irq\n"); | ||
360 | goto err; | ||
361 | } | ||
362 | |||
363 | platform_set_drvdata(pdev, atmel_wm97xx); | ||
364 | |||
365 | ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops); | ||
366 | if (ret) | ||
367 | goto err_irq; | ||
368 | |||
369 | return ret; | ||
370 | |||
371 | err_irq: | ||
372 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); | ||
373 | err: | ||
374 | platform_set_drvdata(pdev, NULL); | ||
375 | kfree(atmel_wm97xx); | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | static int __exit atmel_wm97xx_remove(struct platform_device *pdev) | ||
380 | { | ||
381 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | ||
382 | struct wm97xx *wm = atmel_wm97xx->wm; | ||
383 | |||
384 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | ||
385 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); | ||
386 | del_timer_sync(&atmel_wm97xx->pen_timer); | ||
387 | wm97xx_unregister_mach_ops(wm); | ||
388 | platform_set_drvdata(pdev, NULL); | ||
389 | kfree(atmel_wm97xx); | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | #ifdef CONFIG_PM | ||
395 | static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) | ||
396 | { | ||
397 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | ||
398 | |||
399 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | ||
400 | disable_irq(atmel_wm97xx->gpio_irq); | ||
401 | del_timer_sync(&atmel_wm97xx->pen_timer); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int atmel_wm97xx_resume(struct platform_device *pdev) | ||
407 | { | ||
408 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | ||
409 | struct wm97xx *wm = atmel_wm97xx->wm; | ||
410 | |||
411 | if (wm->input_dev->users) { | ||
412 | enable_irq(atmel_wm97xx->gpio_irq); | ||
413 | ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT); | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | #else | ||
419 | #define atmel_wm97xx_suspend NULL | ||
420 | #define atmel_wm97xx_resume NULL | ||
421 | #endif | ||
422 | |||
423 | static struct platform_driver atmel_wm97xx_driver = { | ||
424 | .remove = __exit_p(atmel_wm97xx_remove), | ||
425 | .driver = { | ||
426 | .name = "wm97xx-touch", | ||
427 | }, | ||
428 | .suspend = atmel_wm97xx_suspend, | ||
429 | .resume = atmel_wm97xx_resume, | ||
430 | }; | ||
431 | |||
432 | static int __init atmel_wm97xx_init(void) | ||
433 | { | ||
434 | return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe); | ||
435 | } | ||
436 | module_init(atmel_wm97xx_init); | ||
437 | |||
438 | static void __exit atmel_wm97xx_exit(void) | ||
439 | { | ||
440 | platform_driver_unregister(&atmel_wm97xx_driver); | ||
441 | } | ||
442 | module_exit(atmel_wm97xx_exit); | ||
443 | |||
444 | MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); | ||
445 | MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); | ||
446 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c new file mode 100644 index 000000000000..3ab92222a525 --- /dev/null +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Touch Screen driver for EETI's I2C connected touch screen panels | ||
3 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
4 | * | ||
5 | * See EETI's software guide for the protocol specification: | ||
6 | * http://home.eeti.com.tw/web20/eg/guide.htm | ||
7 | * | ||
8 | * Based on migor_ts.c | ||
9 | * Copyright (c) 2008 Magnus Damm | ||
10 | * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com> | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public | ||
14 | * License as published by the Free Software Foundation; either | ||
15 | * version 2 of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This file is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public | ||
23 | * License along with this library; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/gpio.h> | ||
35 | |||
36 | static int flip_x; | ||
37 | module_param(flip_x, bool, 0644); | ||
38 | MODULE_PARM_DESC(flip_x, "flip x coordinate"); | ||
39 | |||
40 | static int flip_y; | ||
41 | module_param(flip_y, bool, 0644); | ||
42 | MODULE_PARM_DESC(flip_y, "flip y coordinate"); | ||
43 | |||
44 | struct eeti_ts_priv { | ||
45 | struct i2c_client *client; | ||
46 | struct input_dev *input; | ||
47 | struct work_struct work; | ||
48 | struct mutex mutex; | ||
49 | int irq; | ||
50 | }; | ||
51 | |||
52 | #define EETI_TS_BITDEPTH (11) | ||
53 | #define EETI_MAXVAL ((1 << (EETI_TS_BITDEPTH + 1)) - 1) | ||
54 | |||
55 | #define REPORT_BIT_PRESSED (1 << 0) | ||
56 | #define REPORT_BIT_AD0 (1 << 1) | ||
57 | #define REPORT_BIT_AD1 (1 << 2) | ||
58 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) | ||
59 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) | ||
60 | |||
61 | static void eeti_ts_read(struct work_struct *work) | ||
62 | { | ||
63 | char buf[6]; | ||
64 | unsigned int x, y, res, pressed, to = 100; | ||
65 | struct eeti_ts_priv *priv = | ||
66 | container_of(work, struct eeti_ts_priv, work); | ||
67 | |||
68 | mutex_lock(&priv->mutex); | ||
69 | |||
70 | while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to) | ||
71 | i2c_master_recv(priv->client, buf, sizeof(buf)); | ||
72 | |||
73 | if (!to) { | ||
74 | dev_err(&priv->client->dev, | ||
75 | "unable to clear IRQ - line stuck?\n"); | ||
76 | goto out; | ||
77 | } | ||
78 | |||
79 | /* drop non-report packets */ | ||
80 | if (!(buf[0] & 0x80)) | ||
81 | goto out; | ||
82 | |||
83 | pressed = buf[0] & REPORT_BIT_PRESSED; | ||
84 | res = REPORT_RES_BITS(buf[0] & (REPORT_BIT_AD0 | REPORT_BIT_AD1)); | ||
85 | x = buf[2] | (buf[1] << 8); | ||
86 | y = buf[4] | (buf[3] << 8); | ||
87 | |||
88 | /* fix the range to 11 bits */ | ||
89 | x >>= res - EETI_TS_BITDEPTH; | ||
90 | y >>= res - EETI_TS_BITDEPTH; | ||
91 | |||
92 | if (flip_x) | ||
93 | x = EETI_MAXVAL - x; | ||
94 | |||
95 | if (flip_y) | ||
96 | y = EETI_MAXVAL - y; | ||
97 | |||
98 | if (buf[0] & REPORT_BIT_HAS_PRESSURE) | ||
99 | input_report_abs(priv->input, ABS_PRESSURE, buf[5]); | ||
100 | |||
101 | input_report_abs(priv->input, ABS_X, x); | ||
102 | input_report_abs(priv->input, ABS_Y, y); | ||
103 | input_report_key(priv->input, BTN_TOUCH, !!pressed); | ||
104 | input_sync(priv->input); | ||
105 | |||
106 | out: | ||
107 | mutex_unlock(&priv->mutex); | ||
108 | } | ||
109 | |||
110 | static irqreturn_t eeti_ts_isr(int irq, void *dev_id) | ||
111 | { | ||
112 | struct eeti_ts_priv *priv = dev_id; | ||
113 | |||
114 | /* postpone I2C transactions as we are atomic */ | ||
115 | schedule_work(&priv->work); | ||
116 | |||
117 | return IRQ_HANDLED; | ||
118 | } | ||
119 | |||
120 | static int eeti_ts_open(struct input_dev *dev) | ||
121 | { | ||
122 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
123 | |||
124 | enable_irq(priv->irq); | ||
125 | |||
126 | /* Read the events once to arm the IRQ */ | ||
127 | eeti_ts_read(&priv->work); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static void eeti_ts_close(struct input_dev *dev) | ||
133 | { | ||
134 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
135 | |||
136 | disable_irq(priv->irq); | ||
137 | cancel_work_sync(&priv->work); | ||
138 | } | ||
139 | |||
140 | static int __devinit eeti_ts_probe(struct i2c_client *client, | ||
141 | const struct i2c_device_id *idp) | ||
142 | { | ||
143 | struct eeti_ts_priv *priv; | ||
144 | struct input_dev *input; | ||
145 | int err = -ENOMEM; | ||
146 | |||
147 | /* In contrast to what's described in the datasheet, there seems | ||
148 | * to be no way of probing the presence of that device using I2C | ||
149 | * commands. So we need to blindly believe it is there, and wait | ||
150 | * for interrupts to occur. */ | ||
151 | |||
152 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
153 | if (!priv) { | ||
154 | dev_err(&client->dev, "failed to allocate driver data\n"); | ||
155 | goto err0; | ||
156 | } | ||
157 | |||
158 | mutex_init(&priv->mutex); | ||
159 | input = input_allocate_device(); | ||
160 | |||
161 | if (!input) { | ||
162 | dev_err(&client->dev, "Failed to allocate input device.\n"); | ||
163 | goto err1; | ||
164 | } | ||
165 | |||
166 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
167 | input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
168 | |||
169 | input_set_abs_params(input, ABS_X, 0, EETI_MAXVAL, 0, 0); | ||
170 | input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0); | ||
171 | input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 0, 0); | ||
172 | |||
173 | input->name = client->name; | ||
174 | input->id.bustype = BUS_I2C; | ||
175 | input->dev.parent = &client->dev; | ||
176 | input->open = eeti_ts_open; | ||
177 | input->close = eeti_ts_close; | ||
178 | |||
179 | priv->client = client; | ||
180 | priv->input = input; | ||
181 | priv->irq = client->irq; | ||
182 | |||
183 | INIT_WORK(&priv->work, eeti_ts_read); | ||
184 | i2c_set_clientdata(client, priv); | ||
185 | input_set_drvdata(input, priv); | ||
186 | |||
187 | err = input_register_device(input); | ||
188 | if (err) | ||
189 | goto err1; | ||
190 | |||
191 | err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING, | ||
192 | client->name, priv); | ||
193 | if (err) { | ||
194 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | ||
195 | goto err2; | ||
196 | } | ||
197 | |||
198 | /* Disable the irq for now. It will be enabled once the input device | ||
199 | * is opened. */ | ||
200 | disable_irq(priv->irq); | ||
201 | |||
202 | device_init_wakeup(&client->dev, 0); | ||
203 | return 0; | ||
204 | |||
205 | err2: | ||
206 | input_unregister_device(input); | ||
207 | input = NULL; /* so we dont try to free it below */ | ||
208 | err1: | ||
209 | input_free_device(input); | ||
210 | i2c_set_clientdata(client, NULL); | ||
211 | kfree(priv); | ||
212 | err0: | ||
213 | return err; | ||
214 | } | ||
215 | |||
216 | static int __devexit eeti_ts_remove(struct i2c_client *client) | ||
217 | { | ||
218 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | ||
219 | |||
220 | free_irq(priv->irq, priv); | ||
221 | input_unregister_device(priv->input); | ||
222 | i2c_set_clientdata(client, NULL); | ||
223 | kfree(priv); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | #ifdef CONFIG_PM | ||
229 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | ||
230 | { | ||
231 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | ||
232 | |||
233 | if (device_may_wakeup(&client->dev)) | ||
234 | enable_irq_wake(priv->irq); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int eeti_ts_resume(struct i2c_client *client) | ||
240 | { | ||
241 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | ||
242 | |||
243 | if (device_may_wakeup(&client->dev)) | ||
244 | disable_irq_wake(priv->irq); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | #else | ||
249 | #define eeti_ts_suspend NULL | ||
250 | #define eeti_ts_resume NULL | ||
251 | #endif | ||
252 | |||
253 | static const struct i2c_device_id eeti_ts_id[] = { | ||
254 | { "eeti_ts", 0 }, | ||
255 | { } | ||
256 | }; | ||
257 | MODULE_DEVICE_TABLE(i2c, eeti_ts_id); | ||
258 | |||
259 | static struct i2c_driver eeti_ts_driver = { | ||
260 | .driver = { | ||
261 | .name = "eeti_ts", | ||
262 | }, | ||
263 | .probe = eeti_ts_probe, | ||
264 | .remove = __devexit_p(eeti_ts_remove), | ||
265 | .suspend = eeti_ts_suspend, | ||
266 | .resume = eeti_ts_resume, | ||
267 | .id_table = eeti_ts_id, | ||
268 | }; | ||
269 | |||
270 | static int __init eeti_ts_init(void) | ||
271 | { | ||
272 | return i2c_add_driver(&eeti_ts_driver); | ||
273 | } | ||
274 | |||
275 | static void __exit eeti_ts_exit(void) | ||
276 | { | ||
277 | i2c_del_driver(&eeti_ts_driver); | ||
278 | } | ||
279 | |||
280 | MODULE_DESCRIPTION("EETI Touchscreen driver"); | ||
281 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
282 | MODULE_LICENSE("GPL"); | ||
283 | |||
284 | module_init(eeti_ts_init); | ||
285 | module_exit(eeti_ts_exit); | ||
286 | |||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 948e167557f1..880f58c6a7c4 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -257,7 +257,7 @@ static int tsc2007_probe(struct i2c_client *client, | |||
257 | struct input_dev *input_dev; | 257 | struct input_dev *input_dev; |
258 | int err; | 258 | int err; |
259 | 259 | ||
260 | if (!pdata) { | 260 | if (!pdata || !pdata->get_pendown_state) { |
261 | dev_err(&client->dev, "platform data is required!\n"); | 261 | dev_err(&client->dev, "platform data is required!\n"); |
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | } | 263 | } |
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c new file mode 100644 index 000000000000..6071f5882572 --- /dev/null +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -0,0 +1,350 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | /* ADC controller bit defines */ | ||
20 | #define ADC_DELAY 0xf00 | ||
21 | #define ADC_DOWN 0x01 | ||
22 | #define ADC_TSC_Y (0x01 << 8) | ||
23 | #define ADC_TSC_X (0x00 << 8) | ||
24 | #define TSC_FOURWIRE (~(0x03 << 1)) | ||
25 | #define ADC_CLK_EN (0x01 << 28) /* ADC clock enable */ | ||
26 | #define ADC_READ_CON (0x01 << 12) | ||
27 | #define ADC_CONV (0x01 << 13) | ||
28 | #define ADC_SEMIAUTO (0x01 << 14) | ||
29 | #define ADC_WAITTRIG (0x03 << 14) | ||
30 | #define ADC_RST1 (0x01 << 16) | ||
31 | #define ADC_RST0 (0x00 << 16) | ||
32 | #define ADC_EN (0x01 << 17) | ||
33 | #define ADC_INT (0x01 << 18) | ||
34 | #define WT_INT (0x01 << 20) | ||
35 | #define ADC_INT_EN (0x01 << 21) | ||
36 | #define LVD_INT_EN (0x01 << 22) | ||
37 | #define WT_INT_EN (0x01 << 23) | ||
38 | #define ADC_DIV (0x04 << 1) /* div = 6 */ | ||
39 | |||
40 | enum ts_state { | ||
41 | TS_WAIT_NEW_PACKET, /* We are waiting next touch report */ | ||
42 | TS_WAIT_X_COORD, /* We are waiting for ADC to report X coord */ | ||
43 | TS_WAIT_Y_COORD, /* We are waiting for ADC to report Y coord */ | ||
44 | TS_IDLE, /* Input device is closed, don't do anything */ | ||
45 | }; | ||
46 | |||
47 | struct w90p910_ts { | ||
48 | struct input_dev *input; | ||
49 | struct timer_list timer; | ||
50 | int irq_num; | ||
51 | void __iomem *clocken; | ||
52 | void __iomem *ts_reg; | ||
53 | spinlock_t lock; | ||
54 | enum ts_state state; | ||
55 | }; | ||
56 | |||
57 | static void w90p910_report_event(struct w90p910_ts *w90p910_ts, bool down) | ||
58 | { | ||
59 | struct input_dev *dev = w90p910_ts->input; | ||
60 | |||
61 | if (down) { | ||
62 | input_report_abs(dev, ABS_X, | ||
63 | __raw_readl(w90p910_ts->ts_reg + 0x0c)); | ||
64 | input_report_abs(dev, ABS_Y, | ||
65 | __raw_readl(w90p910_ts->ts_reg + 0x10)); | ||
66 | } | ||
67 | |||
68 | input_report_key(dev, BTN_TOUCH, down); | ||
69 | input_sync(dev); | ||
70 | } | ||
71 | |||
72 | static void w90p910_prepare_x_reading(struct w90p910_ts *w90p910_ts) | ||
73 | { | ||
74 | unsigned long ctlreg; | ||
75 | |||
76 | __raw_writel(ADC_TSC_X, w90p910_ts->ts_reg + 0x04); | ||
77 | ctlreg = __raw_readl(w90p910_ts->ts_reg); | ||
78 | ctlreg &= ~(ADC_WAITTRIG | WT_INT | WT_INT_EN); | ||
79 | ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV; | ||
80 | __raw_writel(ctlreg, w90p910_ts->ts_reg); | ||
81 | |||
82 | w90p910_ts->state = TS_WAIT_X_COORD; | ||
83 | } | ||
84 | |||
85 | static void w90p910_prepare_y_reading(struct w90p910_ts *w90p910_ts) | ||
86 | { | ||
87 | unsigned long ctlreg; | ||
88 | |||
89 | __raw_writel(ADC_TSC_Y, w90p910_ts->ts_reg + 0x04); | ||
90 | ctlreg = __raw_readl(w90p910_ts->ts_reg); | ||
91 | ctlreg &= ~(ADC_WAITTRIG | ADC_INT | WT_INT_EN); | ||
92 | ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV; | ||
93 | __raw_writel(ctlreg, w90p910_ts->ts_reg); | ||
94 | |||
95 | w90p910_ts->state = TS_WAIT_Y_COORD; | ||
96 | } | ||
97 | |||
98 | static void w90p910_prepare_next_packet(struct w90p910_ts *w90p910_ts) | ||
99 | { | ||
100 | unsigned long ctlreg; | ||
101 | |||
102 | ctlreg = __raw_readl(w90p910_ts->ts_reg); | ||
103 | ctlreg &= ~(ADC_INT | ADC_INT_EN | ADC_SEMIAUTO | ADC_CONV); | ||
104 | ctlreg |= ADC_WAITTRIG | WT_INT_EN; | ||
105 | __raw_writel(ctlreg, w90p910_ts->ts_reg); | ||
106 | |||
107 | w90p910_ts->state = TS_WAIT_NEW_PACKET; | ||
108 | } | ||
109 | |||
110 | static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id) | ||
111 | { | ||
112 | struct w90p910_ts *w90p910_ts = dev_id; | ||
113 | unsigned long flags; | ||
114 | |||
115 | spin_lock_irqsave(&w90p910_ts->lock, flags); | ||
116 | |||
117 | switch (w90p910_ts->state) { | ||
118 | case TS_WAIT_NEW_PACKET: | ||
119 | /* | ||
120 | * The controller only generates interrupts when pen | ||
121 | * is down. | ||
122 | */ | ||
123 | del_timer(&w90p910_ts->timer); | ||
124 | w90p910_prepare_x_reading(w90p910_ts); | ||
125 | break; | ||
126 | |||
127 | |||
128 | case TS_WAIT_X_COORD: | ||
129 | w90p910_prepare_y_reading(w90p910_ts); | ||
130 | break; | ||
131 | |||
132 | case TS_WAIT_Y_COORD: | ||
133 | w90p910_report_event(w90p910_ts, true); | ||
134 | w90p910_prepare_next_packet(w90p910_ts); | ||
135 | mod_timer(&w90p910_ts->timer, jiffies + msecs_to_jiffies(100)); | ||
136 | break; | ||
137 | |||
138 | case TS_IDLE: | ||
139 | break; | ||
140 | } | ||
141 | |||
142 | spin_unlock_irqrestore(&w90p910_ts->lock, flags); | ||
143 | |||
144 | return IRQ_HANDLED; | ||
145 | } | ||
146 | |||
147 | static void w90p910_check_pen_up(unsigned long data) | ||
148 | { | ||
149 | struct w90p910_ts *w90p910_ts = (struct w90p910_ts *) data; | ||
150 | unsigned long flags; | ||
151 | |||
152 | spin_lock_irqsave(&w90p910_ts->lock, flags); | ||
153 | |||
154 | if (w90p910_ts->state == TS_WAIT_NEW_PACKET && | ||
155 | !(__raw_readl(w90p910_ts->ts_reg + 0x04) & ADC_DOWN)) { | ||
156 | |||
157 | w90p910_report_event(w90p910_ts, false); | ||
158 | } | ||
159 | |||
160 | spin_unlock_irqrestore(&w90p910_ts->lock, flags); | ||
161 | } | ||
162 | |||
163 | static int w90p910_open(struct input_dev *dev) | ||
164 | { | ||
165 | struct w90p910_ts *w90p910_ts = input_get_drvdata(dev); | ||
166 | unsigned long val; | ||
167 | |||
168 | /* enable the ADC clock */ | ||
169 | val = __raw_readl(w90p910_ts->clocken); | ||
170 | __raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken); | ||
171 | |||
172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); | ||
173 | msleep(1); | ||
174 | __raw_writel(ADC_RST0, w90p910_ts->ts_reg); | ||
175 | msleep(1); | ||
176 | |||
177 | /* set delay and screen type */ | ||
178 | val = __raw_readl(w90p910_ts->ts_reg + 0x04); | ||
179 | __raw_writel(val & TSC_FOURWIRE, w90p910_ts->ts_reg + 0x04); | ||
180 | __raw_writel(ADC_DELAY, w90p910_ts->ts_reg + 0x08); | ||
181 | |||
182 | w90p910_ts->state = TS_WAIT_NEW_PACKET; | ||
183 | wmb(); | ||
184 | |||
185 | /* set trigger mode */ | ||
186 | val = __raw_readl(w90p910_ts->ts_reg); | ||
187 | val |= ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN; | ||
188 | __raw_writel(val, w90p910_ts->ts_reg); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void w90p910_close(struct input_dev *dev) | ||
194 | { | ||
195 | struct w90p910_ts *w90p910_ts = input_get_drvdata(dev); | ||
196 | unsigned long val; | ||
197 | |||
198 | /* disable trigger mode */ | ||
199 | |||
200 | spin_lock_irq(&w90p910_ts->lock); | ||
201 | |||
202 | w90p910_ts->state = TS_IDLE; | ||
203 | |||
204 | val = __raw_readl(w90p910_ts->ts_reg); | ||
205 | val &= ~(ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN | ADC_INT_EN); | ||
206 | __raw_writel(val, w90p910_ts->ts_reg); | ||
207 | |||
208 | spin_unlock_irq(&w90p910_ts->lock); | ||
209 | |||
210 | /* Now that interrupts are shut off we can safely delete timer */ | ||
211 | del_timer_sync(&w90p910_ts->timer); | ||
212 | |||
213 | /* stop the ADC clock */ | ||
214 | val = __raw_readl(w90p910_ts->clocken); | ||
215 | __raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken); | ||
216 | } | ||
217 | |||
218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) | ||
219 | { | ||
220 | struct w90p910_ts *w90p910_ts; | ||
221 | struct input_dev *input_dev; | ||
222 | struct resource *res; | ||
223 | int err; | ||
224 | |||
225 | w90p910_ts = kzalloc(sizeof(struct w90p910_ts), GFP_KERNEL); | ||
226 | input_dev = input_allocate_device(); | ||
227 | if (!w90p910_ts || !input_dev) { | ||
228 | err = -ENOMEM; | ||
229 | goto fail1; | ||
230 | } | ||
231 | |||
232 | w90p910_ts->input = input_dev; | ||
233 | w90p910_ts->state = TS_IDLE; | ||
234 | spin_lock_init(&w90p910_ts->lock); | ||
235 | setup_timer(&w90p910_ts->timer, w90p910_check_pen_up, | ||
236 | (unsigned long)&w90p910_ts); | ||
237 | |||
238 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
239 | if (!res) { | ||
240 | err = -ENXIO; | ||
241 | goto fail1; | ||
242 | } | ||
243 | |||
244 | if (!request_mem_region(res->start, res->end - res->start + 1, | ||
245 | pdev->name)) { | ||
246 | err = -EBUSY; | ||
247 | goto fail1; | ||
248 | } | ||
249 | |||
250 | w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1); | ||
251 | if (!w90p910_ts->ts_reg) { | ||
252 | err = -ENOMEM; | ||
253 | goto fail2; | ||
254 | } | ||
255 | |||
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
257 | if (!res) { | ||
258 | err = -ENXIO; | ||
259 | goto fail3; | ||
260 | } | ||
261 | |||
262 | w90p910_ts->clocken = (void __iomem *)res->start; | ||
263 | |||
264 | input_dev->name = "W90P910 TouchScreen"; | ||
265 | input_dev->phys = "w90p910ts/event0"; | ||
266 | input_dev->id.bustype = BUS_HOST; | ||
267 | input_dev->id.vendor = 0x0005; | ||
268 | input_dev->id.product = 0x0001; | ||
269 | input_dev->id.version = 0x0100; | ||
270 | input_dev->dev.parent = &pdev->dev; | ||
271 | input_dev->open = w90p910_open; | ||
272 | input_dev->close = w90p910_close; | ||
273 | |||
274 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
275 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
276 | |||
277 | input_set_abs_params(input_dev, ABS_X, 0, 0x400, 0, 0); | ||
278 | input_set_abs_params(input_dev, ABS_Y, 0, 0x400, 0, 0); | ||
279 | |||
280 | input_set_drvdata(input_dev, w90p910_ts); | ||
281 | |||
282 | w90p910_ts->irq_num = platform_get_irq(pdev, 0); | ||
283 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | ||
284 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | ||
285 | err = -EBUSY; | ||
286 | goto fail3; | ||
287 | } | ||
288 | |||
289 | err = input_register_device(w90p910_ts->input); | ||
290 | if (err) | ||
291 | goto fail4; | ||
292 | |||
293 | platform_set_drvdata(pdev, w90p910_ts); | ||
294 | |||
295 | return 0; | ||
296 | |||
297 | fail4: free_irq(w90p910_ts->irq_num, w90p910_ts); | ||
298 | fail3: iounmap(w90p910_ts->ts_reg); | ||
299 | fail2: release_mem_region(res->start, res->end - res->start + 1); | ||
300 | fail1: input_free_device(input_dev); | ||
301 | kfree(w90p910_ts); | ||
302 | return err; | ||
303 | } | ||
304 | |||
305 | static int __devexit w90x900ts_remove(struct platform_device *pdev) | ||
306 | { | ||
307 | struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev); | ||
308 | struct resource *res; | ||
309 | |||
310 | free_irq(w90p910_ts->irq_num, w90p910_ts); | ||
311 | del_timer_sync(&w90p910_ts->timer); | ||
312 | iounmap(w90p910_ts->ts_reg); | ||
313 | |||
314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
315 | release_mem_region(res->start, res->end - res->start + 1); | ||
316 | |||
317 | input_unregister_device(w90p910_ts->input); | ||
318 | kfree(w90p910_ts); | ||
319 | |||
320 | platform_set_drvdata(pdev, NULL); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static struct platform_driver w90x900ts_driver = { | ||
326 | .probe = w90x900ts_probe, | ||
327 | .remove = __devexit_p(w90x900ts_remove), | ||
328 | .driver = { | ||
329 | .name = "w90x900-ts", | ||
330 | .owner = THIS_MODULE, | ||
331 | }, | ||
332 | }; | ||
333 | |||
334 | static int __init w90x900ts_init(void) | ||
335 | { | ||
336 | return platform_driver_register(&w90x900ts_driver); | ||
337 | } | ||
338 | |||
339 | static void __exit w90x900ts_exit(void) | ||
340 | { | ||
341 | platform_driver_unregister(&w90x900ts_driver); | ||
342 | } | ||
343 | |||
344 | module_init(w90x900ts_init); | ||
345 | module_exit(w90x900ts_exit); | ||
346 | |||
347 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
348 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); | ||
349 | MODULE_LICENSE("GPL"); | ||
350 | MODULE_ALIAS("platform:w90p910-ts"); | ||