diff options
Diffstat (limited to 'drivers/input')
121 files changed, 8767 insertions, 4637 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 07c2cd43109c..23e82e46656d 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Input device support" | |||
6 | depends on !S390 | 6 | depends on !S390 |
7 | 7 | ||
8 | config INPUT | 8 | config INPUT |
9 | tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED | 9 | tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT |
10 | default y | 10 | default y |
11 | help | 11 | help |
12 | Say Y here if you have any input device (mouse, keyboard, tablet, | 12 | Say Y here if you have any input device (mouse, keyboard, tablet, |
@@ -67,7 +67,7 @@ config INPUT_SPARSEKMAP | |||
67 | comment "Userland interfaces" | 67 | comment "Userland interfaces" |
68 | 68 | ||
69 | config INPUT_MOUSEDEV | 69 | config INPUT_MOUSEDEV |
70 | tristate "Mouse interface" if EMBEDDED | 70 | tristate "Mouse interface" if EXPERT |
71 | default y | 71 | default y |
72 | help | 72 | help |
73 | Say Y here if you want your mouse to be accessible as char devices | 73 | Say Y here if you want your mouse to be accessible as char devices |
@@ -150,7 +150,7 @@ config INPUT_EVBUG | |||
150 | module will be called evbug. | 150 | module will be called evbug. |
151 | 151 | ||
152 | config INPUT_APMPOWER | 152 | config INPUT_APMPOWER |
153 | tristate "Input Power Event -> APM Bridge" if EMBEDDED | 153 | tristate "Input Power Event -> APM Bridge" if EXPERT |
154 | depends on INPUT && APM_EMULATION | 154 | depends on INPUT && APM_EMULATION |
155 | help | 155 | help |
156 | Say Y here if you want suspend key events to trigger a user | 156 | Say Y here if you want suspend key events to trigger a user |
@@ -161,16 +161,6 @@ config INPUT_APMPOWER | |||
161 | To compile this driver as a module, choose M here: the | 161 | To compile this driver as a module, choose M here: the |
162 | module will be called apm-power. | 162 | module will be called apm-power. |
163 | 163 | ||
164 | config XEN_KBDDEV_FRONTEND | ||
165 | tristate "Xen virtual keyboard and mouse support" | ||
166 | depends on XEN_FBDEV_FRONTEND | ||
167 | default y | ||
168 | select XEN_XENBUS_FRONTEND | ||
169 | help | ||
170 | This driver implements the front-end of the Xen virtual | ||
171 | keyboard and mouse device driver. It communicates with a back-end | ||
172 | in another domain. | ||
173 | |||
174 | comment "Input Device Drivers" | 164 | comment "Input Device Drivers" |
175 | 165 | ||
176 | source "drivers/input/keyboard/Kconfig" | 166 | source "drivers/input/keyboard/Kconfig" |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 7ad212d31f99..0c789490e0b3 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_INPUT) += input-core.o | 7 | obj-$(CONFIG_INPUT) += input-core.o |
8 | input-core-objs := input.o input-compat.o ff-core.o | 8 | input-core-y := input.o input-compat.o input-mt.o ff-core.o |
9 | 9 | ||
10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o | 10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o |
11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | 11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o |
@@ -24,5 +24,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ | |||
24 | obj-$(CONFIG_INPUT_MISC) += misc/ | 24 | obj-$(CONFIG_INPUT_MISC) += misc/ |
25 | 25 | ||
26 | obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o | 26 | obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o |
27 | |||
28 | obj-$(CONFIG_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o | ||
diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c index 7d61a9660806..e90ee3d30613 100644 --- a/drivers/input/apm-power.c +++ b/drivers/input/apm-power.c | |||
@@ -9,6 +9,8 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
12 | #include <linux/module.h> | 14 | #include <linux/module.h> |
13 | #include <linux/input.h> | 15 | #include <linux/input.h> |
14 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
@@ -23,8 +25,7 @@ static void system_power_event(unsigned int keycode) | |||
23 | switch (keycode) { | 25 | switch (keycode) { |
24 | case KEY_SUSPEND: | 26 | case KEY_SUSPEND: |
25 | apm_queue_event(APM_USER_SUSPEND); | 27 | apm_queue_event(APM_USER_SUSPEND); |
26 | 28 | pr_info("Requesting system suspend...\n"); | |
27 | printk(KERN_INFO "apm-power: Requesting system suspend...\n"); | ||
28 | break; | 29 | break; |
29 | default: | 30 | default: |
30 | break; | 31 | break; |
@@ -65,18 +66,15 @@ static int apmpower_connect(struct input_handler *handler, | |||
65 | 66 | ||
66 | error = input_register_handle(handle); | 67 | error = input_register_handle(handle); |
67 | if (error) { | 68 | if (error) { |
68 | printk(KERN_ERR | 69 | pr_err("Failed to register input power handler, error %d\n", |
69 | "apm-power: Failed to register input power handler, " | 70 | error); |
70 | "error %d\n", error); | ||
71 | kfree(handle); | 71 | kfree(handle); |
72 | return error; | 72 | return error; |
73 | } | 73 | } |
74 | 74 | ||
75 | error = input_open_device(handle); | 75 | error = input_open_device(handle); |
76 | if (error) { | 76 | if (error) { |
77 | printk(KERN_ERR | 77 | pr_err("Failed to open input power device, error %d\n", error); |
78 | "apm-power: Failed to open input power device, " | ||
79 | "error %d\n", error); | ||
80 | input_unregister_handle(handle); | 78 | input_unregister_handle(handle); |
81 | kfree(handle); | 79 | kfree(handle); |
82 | return error; | 80 | return error; |
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index f7c5c14ec12a..cd4e6679d61a 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c | |||
@@ -26,6 +26,8 @@ | |||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
30 | |||
29 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
30 | #include <linux/module.h> | 32 | #include <linux/module.h> |
31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
@@ -38,8 +40,8 @@ MODULE_LICENSE("GPL"); | |||
38 | 40 | ||
39 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 41 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) |
40 | { | 42 | { |
41 | printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", | 43 | printk(KERN_DEBUG pr_fmt("Event. Dev: %s, Type: %d, Code: %d, Value: %d\n"), |
42 | dev_name(&handle->dev->dev), type, code, value); | 44 | dev_name(&handle->dev->dev), type, code, value); |
43 | } | 45 | } |
44 | 46 | ||
45 | static int evbug_connect(struct input_handler *handler, struct input_dev *dev, | 47 | static int evbug_connect(struct input_handler *handler, struct input_dev *dev, |
@@ -64,10 +66,10 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev, | |||
64 | if (error) | 66 | if (error) |
65 | goto err_unregister_handle; | 67 | goto err_unregister_handle; |
66 | 68 | ||
67 | printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n", | 69 | printk(KERN_DEBUG pr_fmt("Connected device: %s (%s at %s)\n"), |
68 | dev_name(&dev->dev), | 70 | dev_name(&dev->dev), |
69 | dev->name ?: "unknown", | 71 | dev->name ?: "unknown", |
70 | dev->phys ?: "unknown"); | 72 | dev->phys ?: "unknown"); |
71 | 73 | ||
72 | return 0; | 74 | return 0; |
73 | 75 | ||
@@ -80,8 +82,8 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev, | |||
80 | 82 | ||
81 | static void evbug_disconnect(struct input_handle *handle) | 83 | static void evbug_disconnect(struct input_handle *handle) |
82 | { | 84 | { |
83 | printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", | 85 | printk(KERN_DEBUG pr_fmt("Disconnected device: %s\n"), |
84 | dev_name(&handle->dev->dev)); | 86 | dev_name(&handle->dev->dev)); |
85 | 87 | ||
86 | input_close_device(handle); | 88 | input_close_device(handle); |
87 | input_unregister_handle(handle); | 89 | input_unregister_handle(handle); |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f9565..88d8e4cb419a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * the Free Software Foundation. | 8 | * the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
12 | |||
11 | #define EVDEV_MINOR_BASE 64 | 13 | #define EVDEV_MINOR_BASE 64 |
12 | #define EVDEV_MINORS 32 | 14 | #define EVDEV_MINORS 32 |
13 | #define EVDEV_MIN_BUFFER_SIZE 64U | 15 | #define EVDEV_MIN_BUFFER_SIZE 64U |
@@ -37,13 +39,13 @@ struct evdev { | |||
37 | }; | 39 | }; |
38 | 40 | ||
39 | struct evdev_client { | 41 | struct evdev_client { |
40 | int head; | 42 | unsigned int head; |
41 | int tail; | 43 | unsigned int tail; |
42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | 44 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ |
43 | struct fasync_struct *fasync; | 45 | struct fasync_struct *fasync; |
44 | struct evdev *evdev; | 46 | struct evdev *evdev; |
45 | struct list_head node; | 47 | struct list_head node; |
46 | int bufsize; | 48 | unsigned int bufsize; |
47 | struct input_event buffer[]; | 49 | struct input_event buffer[]; |
48 | }; | 50 | }; |
49 | 51 | ||
@@ -53,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex); | |||
53 | static void evdev_pass_event(struct evdev_client *client, | 55 | static void evdev_pass_event(struct evdev_client *client, |
54 | struct input_event *event) | 56 | struct input_event *event) |
55 | { | 57 | { |
56 | /* | 58 | /* Interrupts are disabled, just acquire the lock. */ |
57 | * Interrupts are disabled, just acquire the lock. | ||
58 | * Make sure we don't leave with the client buffer | ||
59 | * "empty" by having client->head == client->tail. | ||
60 | */ | ||
61 | spin_lock(&client->buffer_lock); | 59 | spin_lock(&client->buffer_lock); |
62 | do { | 60 | |
63 | client->buffer[client->head++] = *event; | 61 | client->buffer[client->head++] = *event; |
64 | client->head &= client->bufsize - 1; | 62 | client->head &= client->bufsize - 1; |
65 | } while (client->head == client->tail); | 63 | |
64 | if (unlikely(client->head == client->tail)) { | ||
65 | /* | ||
66 | * This effectively "drops" all unconsumed events, leaving | ||
67 | * EV_SYN/SYN_DROPPED plus the newest event in the queue. | ||
68 | */ | ||
69 | client->tail = (client->head - 2) & (client->bufsize - 1); | ||
70 | |||
71 | client->buffer[client->tail].time = event->time; | ||
72 | client->buffer[client->tail].type = EV_SYN; | ||
73 | client->buffer[client->tail].code = SYN_DROPPED; | ||
74 | client->buffer[client->tail].value = 0; | ||
75 | } | ||
76 | |||
66 | spin_unlock(&client->buffer_lock); | 77 | spin_unlock(&client->buffer_lock); |
67 | 78 | ||
68 | if (event->type == EV_SYN) | 79 | if (event->type == EV_SYN) |
@@ -319,6 +330,9 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
319 | struct input_event event; | 330 | struct input_event event; |
320 | int retval; | 331 | int retval; |
321 | 332 | ||
333 | if (count < input_event_size()) | ||
334 | return -EINVAL; | ||
335 | |||
322 | retval = mutex_lock_interruptible(&evdev->mutex); | 336 | retval = mutex_lock_interruptible(&evdev->mutex); |
323 | if (retval) | 337 | if (retval) |
324 | return retval; | 338 | return retval; |
@@ -328,17 +342,16 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
328 | goto out; | 342 | goto out; |
329 | } | 343 | } |
330 | 344 | ||
331 | while (retval < count) { | 345 | do { |
332 | |||
333 | if (input_event_from_user(buffer + retval, &event)) { | 346 | if (input_event_from_user(buffer + retval, &event)) { |
334 | retval = -EFAULT; | 347 | retval = -EFAULT; |
335 | goto out; | 348 | goto out; |
336 | } | 349 | } |
350 | retval += input_event_size(); | ||
337 | 351 | ||
338 | input_inject_event(&evdev->handle, | 352 | input_inject_event(&evdev->handle, |
339 | event.type, event.code, event.value); | 353 | event.type, event.code, event.value); |
340 | retval += input_event_size(); | 354 | } while (retval + input_event_size() <= count); |
341 | } | ||
342 | 355 | ||
343 | out: | 356 | out: |
344 | mutex_unlock(&evdev->mutex); | 357 | mutex_unlock(&evdev->mutex); |
@@ -522,88 +535,84 @@ static int handle_eviocgbit(struct input_dev *dev, | |||
522 | if (type == EV_KEY && size == OLD_KEY_MAX) { | 535 | if (type == EV_KEY && size == OLD_KEY_MAX) { |
523 | len = OLD_KEY_MAX; | 536 | len = OLD_KEY_MAX; |
524 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) | 537 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) |
525 | printk(KERN_WARNING | 538 | pr_warning("(EVIOCGBIT): Suspicious buffer size %u, " |
526 | "evdev.c(EVIOCGBIT): Suspicious buffer size %u, " | 539 | "limiting output to %zu bytes. See " |
527 | "limiting output to %zu bytes. See " | 540 | "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", |
528 | "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", | 541 | OLD_KEY_MAX, |
529 | OLD_KEY_MAX, | 542 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); |
530 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); | ||
531 | } | 543 | } |
532 | 544 | ||
533 | return bits_to_user(bits, len, size, p, compat_mode); | 545 | return bits_to_user(bits, len, size, p, compat_mode); |
534 | } | 546 | } |
535 | #undef OLD_KEY_MAX | 547 | #undef OLD_KEY_MAX |
536 | 548 | ||
537 | static int evdev_handle_get_keycode(struct input_dev *dev, | 549 | static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) |
538 | void __user *p, size_t size) | ||
539 | { | 550 | { |
540 | struct input_keymap_entry ke; | 551 | struct input_keymap_entry ke = { |
552 | .len = sizeof(unsigned int), | ||
553 | .flags = 0, | ||
554 | }; | ||
555 | int __user *ip = (int __user *)p; | ||
541 | int error; | 556 | int error; |
542 | 557 | ||
543 | memset(&ke, 0, sizeof(ke)); | 558 | /* legacy case */ |
544 | 559 | if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) | |
545 | if (size == sizeof(unsigned int[2])) { | 560 | return -EFAULT; |
546 | /* legacy case */ | ||
547 | int __user *ip = (int __user *)p; | ||
548 | 561 | ||
549 | if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) | 562 | error = input_get_keycode(dev, &ke); |
550 | return -EFAULT; | 563 | if (error) |
564 | return error; | ||
551 | 565 | ||
552 | ke.len = sizeof(unsigned int); | 566 | if (put_user(ke.keycode, ip + 1)) |
553 | ke.flags = 0; | 567 | return -EFAULT; |
554 | 568 | ||
555 | error = input_get_keycode(dev, &ke); | 569 | return 0; |
556 | if (error) | 570 | } |
557 | return error; | ||
558 | 571 | ||
559 | if (put_user(ke.keycode, ip + 1)) | 572 | static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) |
560 | return -EFAULT; | 573 | { |
574 | struct input_keymap_entry ke; | ||
575 | int error; | ||
561 | 576 | ||
562 | } else { | 577 | if (copy_from_user(&ke, p, sizeof(ke))) |
563 | size = min(size, sizeof(ke)); | 578 | return -EFAULT; |
564 | 579 | ||
565 | if (copy_from_user(&ke, p, size)) | 580 | error = input_get_keycode(dev, &ke); |
566 | return -EFAULT; | 581 | if (error) |
582 | return error; | ||
567 | 583 | ||
568 | error = input_get_keycode(dev, &ke); | 584 | if (copy_to_user(p, &ke, sizeof(ke))) |
569 | if (error) | 585 | return -EFAULT; |
570 | return error; | ||
571 | 586 | ||
572 | if (copy_to_user(p, &ke, size)) | ||
573 | return -EFAULT; | ||
574 | } | ||
575 | return 0; | 587 | return 0; |
576 | } | 588 | } |
577 | 589 | ||
578 | static int evdev_handle_set_keycode(struct input_dev *dev, | 590 | static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p) |
579 | void __user *p, size_t size) | ||
580 | { | 591 | { |
581 | struct input_keymap_entry ke; | 592 | struct input_keymap_entry ke = { |
582 | 593 | .len = sizeof(unsigned int), | |
583 | memset(&ke, 0, sizeof(ke)); | 594 | .flags = 0, |
595 | }; | ||
596 | int __user *ip = (int __user *)p; | ||
584 | 597 | ||
585 | if (size == sizeof(unsigned int[2])) { | 598 | if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) |
586 | /* legacy case */ | 599 | return -EFAULT; |
587 | int __user *ip = (int __user *)p; | ||
588 | 600 | ||
589 | if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) | 601 | if (get_user(ke.keycode, ip + 1)) |
590 | return -EFAULT; | 602 | return -EFAULT; |
591 | 603 | ||
592 | if (get_user(ke.keycode, ip + 1)) | 604 | return input_set_keycode(dev, &ke); |
593 | return -EFAULT; | 605 | } |
594 | |||
595 | ke.len = sizeof(unsigned int); | ||
596 | ke.flags = 0; | ||
597 | 606 | ||
598 | } else { | 607 | static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) |
599 | size = min(size, sizeof(ke)); | 608 | { |
609 | struct input_keymap_entry ke; | ||
600 | 610 | ||
601 | if (copy_from_user(&ke, p, size)) | 611 | if (copy_from_user(&ke, p, sizeof(ke))) |
602 | return -EFAULT; | 612 | return -EFAULT; |
603 | 613 | ||
604 | if (ke.len > sizeof(ke.scancode)) | 614 | if (ke.len > sizeof(ke.scancode)) |
605 | return -EINVAL; | 615 | return -EINVAL; |
606 | } | ||
607 | 616 | ||
608 | return input_set_keycode(dev, &ke); | 617 | return input_set_keycode(dev, &ke); |
609 | } | 618 | } |
@@ -669,6 +678,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
669 | return evdev_grab(evdev, client); | 678 | return evdev_grab(evdev, client); |
670 | else | 679 | else |
671 | return evdev_ungrab(evdev, client); | 680 | return evdev_ungrab(evdev, client); |
681 | |||
682 | case EVIOCGKEYCODE: | ||
683 | return evdev_handle_get_keycode(dev, p); | ||
684 | |||
685 | case EVIOCSKEYCODE: | ||
686 | return evdev_handle_set_keycode(dev, p); | ||
687 | |||
688 | case EVIOCGKEYCODE_V2: | ||
689 | return evdev_handle_get_keycode_v2(dev, p); | ||
690 | |||
691 | case EVIOCSKEYCODE_V2: | ||
692 | return evdev_handle_set_keycode_v2(dev, p); | ||
672 | } | 693 | } |
673 | 694 | ||
674 | size = _IOC_SIZE(cmd); | 695 | size = _IOC_SIZE(cmd); |
@@ -677,6 +698,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
677 | #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) | 698 | #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) |
678 | switch (EVIOC_MASK_SIZE(cmd)) { | 699 | switch (EVIOC_MASK_SIZE(cmd)) { |
679 | 700 | ||
701 | case EVIOCGPROP(0): | ||
702 | return bits_to_user(dev->propbit, INPUT_PROP_MAX, | ||
703 | size, p, compat_mode); | ||
704 | |||
680 | case EVIOCGKEY(0): | 705 | case EVIOCGKEY(0): |
681 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); | 706 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); |
682 | 707 | ||
@@ -708,12 +733,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
708 | return -EFAULT; | 733 | return -EFAULT; |
709 | 734 | ||
710 | return error; | 735 | return error; |
711 | |||
712 | case EVIOC_MASK_SIZE(EVIOCGKEYCODE): | ||
713 | return evdev_handle_get_keycode(dev, p, size); | ||
714 | |||
715 | case EVIOC_MASK_SIZE(EVIOCSKEYCODE): | ||
716 | return evdev_handle_set_keycode(dev, p, size); | ||
717 | } | 736 | } |
718 | 737 | ||
719 | /* Multi-number variable-length handlers */ | 738 | /* Multi-number variable-length handlers */ |
@@ -894,7 +913,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
894 | break; | 913 | break; |
895 | 914 | ||
896 | if (minor == EVDEV_MINORS) { | 915 | if (minor == EVDEV_MINORS) { |
897 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 916 | pr_err("no more free evdev devices\n"); |
898 | return -ENFILE; | 917 | return -ENFILE; |
899 | } | 918 | } |
900 | 919 | ||
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 03078c08309a..3367f760d75a 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* #define DEBUG */ | 24 | /* #define DEBUG */ |
25 | 25 | ||
26 | #define debug(format, arg...) pr_debug("ff-core: " format "\n", ## arg) | 26 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt |
27 | 27 | ||
28 | #include <linux/input.h> | 28 | #include <linux/input.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -116,7 +116,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, | |||
116 | 116 | ||
117 | if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX || | 117 | if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX || |
118 | !test_bit(effect->type, dev->ffbit)) { | 118 | !test_bit(effect->type, dev->ffbit)) { |
119 | debug("invalid or not supported effect type in upload"); | 119 | pr_debug("invalid or not supported effect type in upload\n"); |
120 | return -EINVAL; | 120 | return -EINVAL; |
121 | } | 121 | } |
122 | 122 | ||
@@ -124,7 +124,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, | |||
124 | (effect->u.periodic.waveform < FF_WAVEFORM_MIN || | 124 | (effect->u.periodic.waveform < FF_WAVEFORM_MIN || |
125 | effect->u.periodic.waveform > FF_WAVEFORM_MAX || | 125 | effect->u.periodic.waveform > FF_WAVEFORM_MAX || |
126 | !test_bit(effect->u.periodic.waveform, dev->ffbit))) { | 126 | !test_bit(effect->u.periodic.waveform, dev->ffbit))) { |
127 | debug("invalid or not supported wave form in upload"); | 127 | pr_debug("invalid or not supported wave form in upload\n"); |
128 | return -EINVAL; | 128 | return -EINVAL; |
129 | } | 129 | } |
130 | 130 | ||
@@ -246,7 +246,7 @@ static int flush_effects(struct input_dev *dev, struct file *file) | |||
246 | struct ff_device *ff = dev->ff; | 246 | struct ff_device *ff = dev->ff; |
247 | int i; | 247 | int i; |
248 | 248 | ||
249 | debug("flushing now"); | 249 | pr_debug("flushing now\n"); |
250 | 250 | ||
251 | mutex_lock(&ff->mutex); | 251 | mutex_lock(&ff->mutex); |
252 | 252 | ||
@@ -315,8 +315,7 @@ int input_ff_create(struct input_dev *dev, int max_effects) | |||
315 | int i; | 315 | int i; |
316 | 316 | ||
317 | if (!max_effects) { | 317 | if (!max_effects) { |
318 | printk(KERN_ERR | 318 | pr_err("cannot allocate device without any effects\n"); |
319 | "ff-core: cannot allocate device without any effects\n"); | ||
320 | return -EINVAL; | 319 | return -EINVAL; |
321 | } | 320 | } |
322 | 321 | ||
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 1d881c96ba8f..117a59aaa70e 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* #define DEBUG */ | 24 | /* #define DEBUG */ |
25 | 25 | ||
26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) | 26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
27 | 27 | ||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/input.h> | 29 | #include <linux/input.h> |
@@ -129,7 +129,7 @@ static void ml_schedule_timer(struct ml_device *ml) | |||
129 | int events = 0; | 129 | int events = 0; |
130 | int i; | 130 | int i; |
131 | 131 | ||
132 | debug("calculating next timer"); | 132 | pr_debug("calculating next timer\n"); |
133 | 133 | ||
134 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { | 134 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { |
135 | 135 | ||
@@ -149,10 +149,10 @@ static void ml_schedule_timer(struct ml_device *ml) | |||
149 | } | 149 | } |
150 | 150 | ||
151 | if (!events) { | 151 | if (!events) { |
152 | debug("no actions"); | 152 | pr_debug("no actions\n"); |
153 | del_timer(&ml->timer); | 153 | del_timer(&ml->timer); |
154 | } else { | 154 | } else { |
155 | debug("timer set"); | 155 | pr_debug("timer set\n"); |
156 | mod_timer(&ml->timer, earliest); | 156 | mod_timer(&ml->timer, earliest); |
157 | } | 157 | } |
158 | } | 158 | } |
@@ -173,8 +173,8 @@ static int apply_envelope(struct ml_effect_state *state, int value, | |||
173 | if (envelope->attack_length && | 173 | if (envelope->attack_length && |
174 | time_before(now, | 174 | time_before(now, |
175 | state->play_at + msecs_to_jiffies(envelope->attack_length))) { | 175 | state->play_at + msecs_to_jiffies(envelope->attack_length))) { |
176 | debug("value = 0x%x, attack_level = 0x%x", value, | 176 | pr_debug("value = 0x%x, attack_level = 0x%x\n", |
177 | envelope->attack_level); | 177 | value, envelope->attack_level); |
178 | time_from_level = jiffies_to_msecs(now - state->play_at); | 178 | time_from_level = jiffies_to_msecs(now - state->play_at); |
179 | time_of_envelope = envelope->attack_length; | 179 | time_of_envelope = envelope->attack_length; |
180 | envelope_level = min_t(__s16, envelope->attack_level, 0x7fff); | 180 | envelope_level = min_t(__s16, envelope->attack_level, 0x7fff); |
@@ -191,13 +191,13 @@ static int apply_envelope(struct ml_effect_state *state, int value, | |||
191 | 191 | ||
192 | difference = abs(value) - envelope_level; | 192 | difference = abs(value) - envelope_level; |
193 | 193 | ||
194 | debug("difference = %d", difference); | 194 | pr_debug("difference = %d\n", difference); |
195 | debug("time_from_level = 0x%x", time_from_level); | 195 | pr_debug("time_from_level = 0x%x\n", time_from_level); |
196 | debug("time_of_envelope = 0x%x", time_of_envelope); | 196 | pr_debug("time_of_envelope = 0x%x\n", time_of_envelope); |
197 | 197 | ||
198 | difference = difference * time_from_level / time_of_envelope; | 198 | difference = difference * time_from_level / time_of_envelope; |
199 | 199 | ||
200 | debug("difference = %d", difference); | 200 | pr_debug("difference = %d\n", difference); |
201 | 201 | ||
202 | return value < 0 ? | 202 | return value < 0 ? |
203 | -(difference + envelope_level) : (difference + envelope_level); | 203 | -(difference + envelope_level) : (difference + envelope_level); |
@@ -215,8 +215,7 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) | |||
215 | if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) | 215 | if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) |
216 | return FF_RUMBLE; | 216 | return FF_RUMBLE; |
217 | 217 | ||
218 | printk(KERN_ERR | 218 | pr_err("invalid type in get_compatible_type()\n"); |
219 | "ff-memless: invalid type in get_compatible_type()\n"); | ||
220 | 219 | ||
221 | return 0; | 220 | return 0; |
222 | } | 221 | } |
@@ -312,7 +311,7 @@ static void ml_combine_effects(struct ff_effect *effect, | |||
312 | break; | 311 | break; |
313 | 312 | ||
314 | default: | 313 | default: |
315 | printk(KERN_ERR "ff-memless: invalid type in ml_combine_effects()\n"); | 314 | pr_err("invalid type in ml_combine_effects()\n"); |
316 | break; | 315 | break; |
317 | } | 316 | } |
318 | 317 | ||
@@ -406,7 +405,7 @@ static void ml_effect_timer(unsigned long timer_data) | |||
406 | struct ml_device *ml = dev->ff->private; | 405 | struct ml_device *ml = dev->ff->private; |
407 | unsigned long flags; | 406 | unsigned long flags; |
408 | 407 | ||
409 | debug("timer: updating effects"); | 408 | pr_debug("timer: updating effects\n"); |
410 | 409 | ||
411 | spin_lock_irqsave(&dev->event_lock, flags); | 410 | spin_lock_irqsave(&dev->event_lock, flags); |
412 | ml_play_effects(ml); | 411 | ml_play_effects(ml); |
@@ -438,7 +437,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
438 | struct ml_effect_state *state = &ml->states[effect_id]; | 437 | struct ml_effect_state *state = &ml->states[effect_id]; |
439 | 438 | ||
440 | if (value > 0) { | 439 | if (value > 0) { |
441 | debug("initiated play"); | 440 | pr_debug("initiated play\n"); |
442 | 441 | ||
443 | __set_bit(FF_EFFECT_STARTED, &state->flags); | 442 | __set_bit(FF_EFFECT_STARTED, &state->flags); |
444 | state->count = value; | 443 | state->count = value; |
@@ -449,7 +448,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
449 | state->adj_at = state->play_at; | 448 | state->adj_at = state->play_at; |
450 | 449 | ||
451 | } else { | 450 | } else { |
452 | debug("initiated stop"); | 451 | pr_debug("initiated stop\n"); |
453 | 452 | ||
454 | if (test_bit(FF_EFFECT_PLAYING, &state->flags)) | 453 | if (test_bit(FF_EFFECT_PLAYING, &state->flags)) |
455 | __set_bit(FF_EFFECT_ABORTING, &state->flags); | 454 | __set_bit(FF_EFFECT_ABORTING, &state->flags); |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 46239e47a260..5b8f59d6c3e8 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -18,13 +18,11 @@ | |||
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/gameport.h> | 20 | #include <linux/gameport.h> |
21 | #include <linux/wait.h> | ||
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
23 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
24 | #include <linux/kthread.h> | 23 | #include <linux/workqueue.h> |
25 | #include <linux/sched.h> /* HZ */ | 24 | #include <linux/sched.h> /* HZ */ |
26 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
27 | #include <linux/freezer.h> | ||
28 | 26 | ||
29 | /*#include <asm/io.h>*/ | 27 | /*#include <asm/io.h>*/ |
30 | 28 | ||
@@ -123,7 +121,7 @@ static int gameport_measure_speed(struct gameport *gameport) | |||
123 | } | 121 | } |
124 | 122 | ||
125 | gameport_close(gameport); | 123 | gameport_close(gameport); |
126 | return (cpu_data(raw_smp_processor_id()).loops_per_jiffy * | 124 | return (this_cpu_read(cpu_info.loops_per_jiffy) * |
127 | (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); | 125 | (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); |
128 | 126 | ||
129 | #else | 127 | #else |
@@ -234,58 +232,22 @@ struct gameport_event { | |||
234 | 232 | ||
235 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ | 233 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ |
236 | static LIST_HEAD(gameport_event_list); | 234 | static LIST_HEAD(gameport_event_list); |
237 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | ||
238 | static struct task_struct *gameport_task; | ||
239 | 235 | ||
240 | static int gameport_queue_event(void *object, struct module *owner, | 236 | static struct gameport_event *gameport_get_event(void) |
241 | enum gameport_event_type event_type) | ||
242 | { | 237 | { |
238 | struct gameport_event *event = NULL; | ||
243 | unsigned long flags; | 239 | unsigned long flags; |
244 | struct gameport_event *event; | ||
245 | int retval = 0; | ||
246 | 240 | ||
247 | spin_lock_irqsave(&gameport_event_lock, flags); | 241 | spin_lock_irqsave(&gameport_event_lock, flags); |
248 | 242 | ||
249 | /* | 243 | if (!list_empty(&gameport_event_list)) { |
250 | * Scan event list for the other events for the same gameport port, | 244 | event = list_first_entry(&gameport_event_list, |
251 | * starting with the most recent one. If event is the same we | 245 | struct gameport_event, node); |
252 | * do not need add new one. If event is of different type we | 246 | list_del_init(&event->node); |
253 | * need to add this event and should not look further because | ||
254 | * we need to preseve sequence of distinct events. | ||
255 | */ | ||
256 | list_for_each_entry_reverse(event, &gameport_event_list, node) { | ||
257 | if (event->object == object) { | ||
258 | if (event->type == event_type) | ||
259 | goto out; | ||
260 | break; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); | ||
265 | if (!event) { | ||
266 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
267 | retval = -ENOMEM; | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | if (!try_module_get(owner)) { | ||
272 | pr_warning("Can't get module reference, dropping event %d\n", | ||
273 | event_type); | ||
274 | kfree(event); | ||
275 | retval = -EINVAL; | ||
276 | goto out; | ||
277 | } | 247 | } |
278 | 248 | ||
279 | event->type = event_type; | ||
280 | event->object = object; | ||
281 | event->owner = owner; | ||
282 | |||
283 | list_add_tail(&event->node, &gameport_event_list); | ||
284 | wake_up(&gameport_wait); | ||
285 | |||
286 | out: | ||
287 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 249 | spin_unlock_irqrestore(&gameport_event_lock, flags); |
288 | return retval; | 250 | return event; |
289 | } | 251 | } |
290 | 252 | ||
291 | static void gameport_free_event(struct gameport_event *event) | 253 | static void gameport_free_event(struct gameport_event *event) |
@@ -319,24 +281,8 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) | |||
319 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 281 | spin_unlock_irqrestore(&gameport_event_lock, flags); |
320 | } | 282 | } |
321 | 283 | ||
322 | static struct gameport_event *gameport_get_event(void) | ||
323 | { | ||
324 | struct gameport_event *event = NULL; | ||
325 | unsigned long flags; | ||
326 | |||
327 | spin_lock_irqsave(&gameport_event_lock, flags); | ||
328 | |||
329 | if (!list_empty(&gameport_event_list)) { | ||
330 | event = list_first_entry(&gameport_event_list, | ||
331 | struct gameport_event, node); | ||
332 | list_del_init(&event->node); | ||
333 | } | ||
334 | |||
335 | spin_unlock_irqrestore(&gameport_event_lock, flags); | ||
336 | return event; | ||
337 | } | ||
338 | 284 | ||
339 | static void gameport_handle_event(void) | 285 | static void gameport_handle_events(struct work_struct *work) |
340 | { | 286 | { |
341 | struct gameport_event *event; | 287 | struct gameport_event *event; |
342 | 288 | ||
@@ -368,6 +314,59 @@ static void gameport_handle_event(void) | |||
368 | mutex_unlock(&gameport_mutex); | 314 | mutex_unlock(&gameport_mutex); |
369 | } | 315 | } |
370 | 316 | ||
317 | static DECLARE_WORK(gameport_event_work, gameport_handle_events); | ||
318 | |||
319 | static int gameport_queue_event(void *object, struct module *owner, | ||
320 | enum gameport_event_type event_type) | ||
321 | { | ||
322 | unsigned long flags; | ||
323 | struct gameport_event *event; | ||
324 | int retval = 0; | ||
325 | |||
326 | spin_lock_irqsave(&gameport_event_lock, flags); | ||
327 | |||
328 | /* | ||
329 | * Scan event list for the other events for the same gameport port, | ||
330 | * starting with the most recent one. If event is the same we | ||
331 | * do not need add new one. If event is of different type we | ||
332 | * need to add this event and should not look further because | ||
333 | * we need to preserve sequence of distinct events. | ||
334 | */ | ||
335 | list_for_each_entry_reverse(event, &gameport_event_list, node) { | ||
336 | if (event->object == object) { | ||
337 | if (event->type == event_type) | ||
338 | goto out; | ||
339 | break; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); | ||
344 | if (!event) { | ||
345 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
346 | retval = -ENOMEM; | ||
347 | goto out; | ||
348 | } | ||
349 | |||
350 | if (!try_module_get(owner)) { | ||
351 | pr_warning("Can't get module reference, dropping event %d\n", | ||
352 | event_type); | ||
353 | kfree(event); | ||
354 | retval = -EINVAL; | ||
355 | goto out; | ||
356 | } | ||
357 | |||
358 | event->type = event_type; | ||
359 | event->object = object; | ||
360 | event->owner = owner; | ||
361 | |||
362 | list_add_tail(&event->node, &gameport_event_list); | ||
363 | queue_work(system_long_wq, &gameport_event_work); | ||
364 | |||
365 | out: | ||
366 | spin_unlock_irqrestore(&gameport_event_lock, flags); | ||
367 | return retval; | ||
368 | } | ||
369 | |||
371 | /* | 370 | /* |
372 | * Remove all events that have been submitted for a given object, | 371 | * Remove all events that have been submitted for a given object, |
373 | * be it a gameport port or a driver. | 372 | * be it a gameport port or a driver. |
@@ -419,19 +418,6 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) | |||
419 | return child; | 418 | return child; |
420 | } | 419 | } |
421 | 420 | ||
422 | static int gameport_thread(void *nothing) | ||
423 | { | ||
424 | set_freezable(); | ||
425 | do { | ||
426 | gameport_handle_event(); | ||
427 | wait_event_freezable(gameport_wait, | ||
428 | kthread_should_stop() || !list_empty(&gameport_event_list)); | ||
429 | } while (!kthread_should_stop()); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | |||
435 | /* | 421 | /* |
436 | * Gameport port operations | 422 | * Gameport port operations |
437 | */ | 423 | */ |
@@ -814,13 +800,6 @@ static int __init gameport_init(void) | |||
814 | return error; | 800 | return error; |
815 | } | 801 | } |
816 | 802 | ||
817 | gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); | ||
818 | if (IS_ERR(gameport_task)) { | ||
819 | bus_unregister(&gameport_bus); | ||
820 | error = PTR_ERR(gameport_task); | ||
821 | pr_err("Failed to start kgameportd, error: %d\n", error); | ||
822 | return error; | ||
823 | } | ||
824 | 803 | ||
825 | return 0; | 804 | return 0; |
826 | } | 805 | } |
@@ -828,7 +807,12 @@ static int __init gameport_init(void) | |||
828 | static void __exit gameport_exit(void) | 807 | static void __exit gameport_exit(void) |
829 | { | 808 | { |
830 | bus_unregister(&gameport_bus); | 809 | bus_unregister(&gameport_bus); |
831 | kthread_stop(gameport_task); | 810 | |
811 | /* | ||
812 | * There should not be any outstanding events but work may | ||
813 | * still be scheduled so simply cancel it. | ||
814 | */ | ||
815 | cancel_work_sync(&gameport_event_work); | ||
832 | } | 816 | } |
833 | 817 | ||
834 | subsys_initcall(gameport_init); | 818 | subsys_initcall(gameport_init); |
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c new file mode 100644 index 000000000000..c48c81f0308d --- /dev/null +++ b/drivers/input/input-mt.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * Input Multitouch Library | ||
3 | * | ||
4 | * Copyright (c) 2008-2010 Henrik Rydberg | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/input/mt.h> | ||
12 | #include <linux/slab.h> | ||
13 | |||
14 | #define TRKID_SGN ((TRKID_MAX + 1) >> 1) | ||
15 | |||
16 | /** | ||
17 | * input_mt_init_slots() - initialize MT input slots | ||
18 | * @dev: input device supporting MT events and finger tracking | ||
19 | * @num_slots: number of slots used by the device | ||
20 | * | ||
21 | * This function allocates all necessary memory for MT slot handling | ||
22 | * in the input device, prepares the ABS_MT_SLOT and | ||
23 | * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. | ||
24 | * May be called repeatedly. Returns -EINVAL if attempting to | ||
25 | * reinitialize with a different number of slots. | ||
26 | */ | ||
27 | int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | if (!num_slots) | ||
32 | return 0; | ||
33 | if (dev->mt) | ||
34 | return dev->mtsize != num_slots ? -EINVAL : 0; | ||
35 | |||
36 | dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); | ||
37 | if (!dev->mt) | ||
38 | return -ENOMEM; | ||
39 | |||
40 | dev->mtsize = num_slots; | ||
41 | input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); | ||
42 | input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); | ||
43 | input_set_events_per_packet(dev, 6 * num_slots); | ||
44 | |||
45 | /* Mark slots as 'unused' */ | ||
46 | for (i = 0; i < num_slots; i++) | ||
47 | input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | EXPORT_SYMBOL(input_mt_init_slots); | ||
52 | |||
53 | /** | ||
54 | * input_mt_destroy_slots() - frees the MT slots of the input device | ||
55 | * @dev: input device with allocated MT slots | ||
56 | * | ||
57 | * This function is only needed in error path as the input core will | ||
58 | * automatically free the MT slots when the device is destroyed. | ||
59 | */ | ||
60 | void input_mt_destroy_slots(struct input_dev *dev) | ||
61 | { | ||
62 | kfree(dev->mt); | ||
63 | dev->mt = NULL; | ||
64 | dev->mtsize = 0; | ||
65 | dev->slot = 0; | ||
66 | dev->trkid = 0; | ||
67 | } | ||
68 | EXPORT_SYMBOL(input_mt_destroy_slots); | ||
69 | |||
70 | /** | ||
71 | * input_mt_report_slot_state() - report contact state | ||
72 | * @dev: input device with allocated MT slots | ||
73 | * @tool_type: the tool type to use in this slot | ||
74 | * @active: true if contact is active, false otherwise | ||
75 | * | ||
76 | * Reports a contact via ABS_MT_TRACKING_ID, and optionally | ||
77 | * ABS_MT_TOOL_TYPE. If active is true and the slot is currently | ||
78 | * inactive, or if the tool type is changed, a new tracking id is | ||
79 | * assigned to the slot. The tool type is only reported if the | ||
80 | * corresponding absbit field is set. | ||
81 | */ | ||
82 | void input_mt_report_slot_state(struct input_dev *dev, | ||
83 | unsigned int tool_type, bool active) | ||
84 | { | ||
85 | struct input_mt_slot *mt; | ||
86 | int id; | ||
87 | |||
88 | if (!dev->mt || !active) { | ||
89 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | mt = &dev->mt[dev->slot]; | ||
94 | id = input_mt_get_value(mt, ABS_MT_TRACKING_ID); | ||
95 | if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type) | ||
96 | id = input_mt_new_trkid(dev); | ||
97 | |||
98 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); | ||
99 | input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type); | ||
100 | } | ||
101 | EXPORT_SYMBOL(input_mt_report_slot_state); | ||
102 | |||
103 | /** | ||
104 | * input_mt_report_finger_count() - report contact count | ||
105 | * @dev: input device with allocated MT slots | ||
106 | * @count: the number of contacts | ||
107 | * | ||
108 | * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, | ||
109 | * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP. | ||
110 | * | ||
111 | * The input core ensures only the KEY events already setup for | ||
112 | * this device will produce output. | ||
113 | */ | ||
114 | void input_mt_report_finger_count(struct input_dev *dev, int count) | ||
115 | { | ||
116 | input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1); | ||
117 | input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); | ||
118 | input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); | ||
119 | input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); | ||
120 | } | ||
121 | EXPORT_SYMBOL(input_mt_report_finger_count); | ||
122 | |||
123 | /** | ||
124 | * input_mt_report_pointer_emulation() - common pointer emulation | ||
125 | * @dev: input device with allocated MT slots | ||
126 | * @use_count: report number of active contacts as finger count | ||
127 | * | ||
128 | * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and | ||
129 | * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true. | ||
130 | * | ||
131 | * The input core ensures only the KEY and ABS axes already setup for | ||
132 | * this device will produce output. | ||
133 | */ | ||
134 | void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) | ||
135 | { | ||
136 | struct input_mt_slot *oldest = 0; | ||
137 | int oldid = dev->trkid; | ||
138 | int count = 0; | ||
139 | int i; | ||
140 | |||
141 | for (i = 0; i < dev->mtsize; ++i) { | ||
142 | struct input_mt_slot *ps = &dev->mt[i]; | ||
143 | int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); | ||
144 | |||
145 | if (id < 0) | ||
146 | continue; | ||
147 | if ((id - oldid) & TRKID_SGN) { | ||
148 | oldest = ps; | ||
149 | oldid = id; | ||
150 | } | ||
151 | count++; | ||
152 | } | ||
153 | |||
154 | input_event(dev, EV_KEY, BTN_TOUCH, count > 0); | ||
155 | if (use_count) | ||
156 | input_mt_report_finger_count(dev, count); | ||
157 | |||
158 | if (oldest) { | ||
159 | int x = input_mt_get_value(oldest, ABS_MT_POSITION_X); | ||
160 | int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y); | ||
161 | int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); | ||
162 | |||
163 | input_event(dev, EV_ABS, ABS_X, x); | ||
164 | input_event(dev, EV_ABS, ABS_Y, y); | ||
165 | input_event(dev, EV_ABS, ABS_PRESSURE, p); | ||
166 | } else { | ||
167 | input_event(dev, EV_ABS, ABS_PRESSURE, 0); | ||
168 | } | ||
169 | } | ||
170 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); | ||
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 10c9b0a845f0..3037842a60d8 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * the Free Software Foundation. | 8 | * the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
12 | |||
11 | #include <linux/jiffies.h> | 13 | #include <linux/jiffies.h> |
12 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
13 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
@@ -33,8 +35,7 @@ static int input_polldev_start_workqueue(void) | |||
33 | if (!polldev_users) { | 35 | if (!polldev_users) { |
34 | polldev_wq = create_singlethread_workqueue("ipolldevd"); | 36 | polldev_wq = create_singlethread_workqueue("ipolldevd"); |
35 | if (!polldev_wq) { | 37 | if (!polldev_wq) { |
36 | printk(KERN_ERR "input-polldev: failed to create " | 38 | pr_err("failed to create ipolldevd workqueue\n"); |
37 | "ipolldevd workqueue\n"); | ||
38 | retval = -ENOMEM; | 39 | retval = -ENOMEM; |
39 | goto out; | 40 | goto out; |
40 | } | 41 | } |
@@ -191,7 +192,7 @@ static struct attribute_group input_polldev_attribute_group = { | |||
191 | }; | 192 | }; |
192 | 193 | ||
193 | /** | 194 | /** |
194 | * input_allocate_polled_device - allocated memory polled device | 195 | * input_allocate_polled_device - allocate memory for polled device |
195 | * | 196 | * |
196 | * The function allocates memory for a polled device and also | 197 | * The function allocates memory for a polled device and also |
197 | * for an input device associated with this polled device. | 198 | * for an input device associated with this polled device. |
@@ -238,7 +239,7 @@ EXPORT_SYMBOL(input_free_polled_device); | |||
238 | * with input layer. The device should be allocated with call to | 239 | * with input layer. The device should be allocated with call to |
239 | * input_allocate_polled_device(). Callers should also set up poll() | 240 | * input_allocate_polled_device(). Callers should also set up poll() |
240 | * method and set up capabilities (id, name, phys, bits) of the | 241 | * method and set up capabilities (id, name, phys, bits) of the |
241 | * corresponing input_dev structure. | 242 | * corresponding input_dev structure. |
242 | */ | 243 | */ |
243 | int input_register_polled_device(struct input_polled_dev *dev) | 244 | int input_register_polled_device(struct input_polled_dev *dev) |
244 | { | 245 | { |
diff --git a/drivers/input/input.c b/drivers/input/input.c index db409d6bd5d2..ebbceedc92f4 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -10,9 +10,11 @@ | |||
10 | * the Free Software Foundation. | 10 | * the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt | ||
14 | |||
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
14 | #include <linux/types.h> | 16 | #include <linux/types.h> |
15 | #include <linux/input.h> | 17 | #include <linux/input/mt.h> |
16 | #include <linux/module.h> | 18 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
18 | #include <linux/random.h> | 20 | #include <linux/random.h> |
@@ -73,7 +75,6 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) | |||
73 | * dev->event_lock held and interrupts disabled. | 75 | * dev->event_lock held and interrupts disabled. |
74 | */ | 76 | */ |
75 | static void input_pass_event(struct input_dev *dev, | 77 | static void input_pass_event(struct input_dev *dev, |
76 | struct input_handler *src_handler, | ||
77 | unsigned int type, unsigned int code, int value) | 78 | unsigned int type, unsigned int code, int value) |
78 | { | 79 | { |
79 | struct input_handler *handler; | 80 | struct input_handler *handler; |
@@ -92,15 +93,6 @@ static void input_pass_event(struct input_dev *dev, | |||
92 | continue; | 93 | continue; |
93 | 94 | ||
94 | handler = handle->handler; | 95 | handler = handle->handler; |
95 | |||
96 | /* | ||
97 | * If this is the handler that injected this | ||
98 | * particular event we want to skip it to avoid | ||
99 | * filters firing again and again. | ||
100 | */ | ||
101 | if (handler == src_handler) | ||
102 | continue; | ||
103 | |||
104 | if (!handler->filter) { | 96 | if (!handler->filter) { |
105 | if (filtered) | 97 | if (filtered) |
106 | break; | 98 | break; |
@@ -130,7 +122,7 @@ static void input_repeat_key(unsigned long data) | |||
130 | if (test_bit(dev->repeat_key, dev->key) && | 122 | if (test_bit(dev->repeat_key, dev->key) && |
131 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { | 123 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { |
132 | 124 | ||
133 | input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2); | 125 | input_pass_event(dev, EV_KEY, dev->repeat_key, 2); |
134 | 126 | ||
135 | if (dev->sync) { | 127 | if (dev->sync) { |
136 | /* | 128 | /* |
@@ -139,7 +131,7 @@ static void input_repeat_key(unsigned long data) | |||
139 | * Otherwise assume that the driver will send | 131 | * Otherwise assume that the driver will send |
140 | * SYN_REPORT once it's done. | 132 | * SYN_REPORT once it's done. |
141 | */ | 133 | */ |
142 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); | 134 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); |
143 | } | 135 | } |
144 | 136 | ||
145 | if (dev->rep[REP_PERIOD]) | 137 | if (dev->rep[REP_PERIOD]) |
@@ -172,7 +164,6 @@ static void input_stop_autorepeat(struct input_dev *dev) | |||
172 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) | 164 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) |
173 | 165 | ||
174 | static int input_handle_abs_event(struct input_dev *dev, | 166 | static int input_handle_abs_event(struct input_dev *dev, |
175 | struct input_handler *src_handler, | ||
176 | unsigned int code, int *pval) | 167 | unsigned int code, int *pval) |
177 | { | 168 | { |
178 | bool is_mt_event; | 169 | bool is_mt_event; |
@@ -216,15 +207,13 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
216 | /* Flush pending "slot" event */ | 207 | /* Flush pending "slot" event */ |
217 | if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { | 208 | if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { |
218 | input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); | 209 | input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); |
219 | input_pass_event(dev, src_handler, | 210 | input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); |
220 | EV_ABS, ABS_MT_SLOT, dev->slot); | ||
221 | } | 211 | } |
222 | 212 | ||
223 | return INPUT_PASS_TO_HANDLERS; | 213 | return INPUT_PASS_TO_HANDLERS; |
224 | } | 214 | } |
225 | 215 | ||
226 | static void input_handle_event(struct input_dev *dev, | 216 | static void input_handle_event(struct input_dev *dev, |
227 | struct input_handler *src_handler, | ||
228 | unsigned int type, unsigned int code, int value) | 217 | unsigned int type, unsigned int code, int value) |
229 | { | 218 | { |
230 | int disposition = INPUT_IGNORE_EVENT; | 219 | int disposition = INPUT_IGNORE_EVENT; |
@@ -277,8 +266,7 @@ static void input_handle_event(struct input_dev *dev, | |||
277 | 266 | ||
278 | case EV_ABS: | 267 | case EV_ABS: |
279 | if (is_event_supported(code, dev->absbit, ABS_MAX)) | 268 | if (is_event_supported(code, dev->absbit, ABS_MAX)) |
280 | disposition = input_handle_abs_event(dev, src_handler, | 269 | disposition = input_handle_abs_event(dev, code, &value); |
281 | code, &value); | ||
282 | 270 | ||
283 | break; | 271 | break; |
284 | 272 | ||
@@ -336,7 +324,7 @@ static void input_handle_event(struct input_dev *dev, | |||
336 | dev->event(dev, type, code, value); | 324 | dev->event(dev, type, code, value); |
337 | 325 | ||
338 | if (disposition & INPUT_PASS_TO_HANDLERS) | 326 | if (disposition & INPUT_PASS_TO_HANDLERS) |
339 | input_pass_event(dev, src_handler, type, code, value); | 327 | input_pass_event(dev, type, code, value); |
340 | } | 328 | } |
341 | 329 | ||
342 | /** | 330 | /** |
@@ -365,7 +353,7 @@ void input_event(struct input_dev *dev, | |||
365 | 353 | ||
366 | spin_lock_irqsave(&dev->event_lock, flags); | 354 | spin_lock_irqsave(&dev->event_lock, flags); |
367 | add_input_randomness(type, code, value); | 355 | add_input_randomness(type, code, value); |
368 | input_handle_event(dev, NULL, type, code, value); | 356 | input_handle_event(dev, type, code, value); |
369 | spin_unlock_irqrestore(&dev->event_lock, flags); | 357 | spin_unlock_irqrestore(&dev->event_lock, flags); |
370 | } | 358 | } |
371 | } | 359 | } |
@@ -395,8 +383,7 @@ void input_inject_event(struct input_handle *handle, | |||
395 | rcu_read_lock(); | 383 | rcu_read_lock(); |
396 | grab = rcu_dereference(dev->grab); | 384 | grab = rcu_dereference(dev->grab); |
397 | if (!grab || grab == handle) | 385 | if (!grab || grab == handle) |
398 | input_handle_event(dev, handle->handler, | 386 | input_handle_event(dev, type, code, value); |
399 | type, code, value); | ||
400 | rcu_read_unlock(); | 387 | rcu_read_unlock(); |
401 | 388 | ||
402 | spin_unlock_irqrestore(&dev->event_lock, flags); | 389 | spin_unlock_irqrestore(&dev->event_lock, flags); |
@@ -609,10 +596,10 @@ static void input_dev_release_keys(struct input_dev *dev) | |||
609 | for (code = 0; code <= KEY_MAX; code++) { | 596 | for (code = 0; code <= KEY_MAX; code++) { |
610 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | 597 | if (is_event_supported(code, dev->keybit, KEY_MAX) && |
611 | __test_and_clear_bit(code, dev->key)) { | 598 | __test_and_clear_bit(code, dev->key)) { |
612 | input_pass_event(dev, NULL, EV_KEY, code, 0); | 599 | input_pass_event(dev, EV_KEY, code, 0); |
613 | } | 600 | } |
614 | } | 601 | } |
615 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); | 602 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); |
616 | } | 603 | } |
617 | } | 604 | } |
618 | 605 | ||
@@ -804,22 +791,9 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) | |||
804 | int retval; | 791 | int retval; |
805 | 792 | ||
806 | spin_lock_irqsave(&dev->event_lock, flags); | 793 | spin_lock_irqsave(&dev->event_lock, flags); |
807 | 794 | retval = dev->getkeycode(dev, ke); | |
808 | if (dev->getkeycode) { | ||
809 | /* | ||
810 | * Support for legacy drivers, that don't implement the new | ||
811 | * ioctls | ||
812 | */ | ||
813 | u32 scancode = ke->index; | ||
814 | |||
815 | memcpy(ke->scancode, &scancode, sizeof(scancode)); | ||
816 | ke->len = sizeof(scancode); | ||
817 | retval = dev->getkeycode(dev, scancode, &ke->keycode); | ||
818 | } else { | ||
819 | retval = dev->getkeycode_new(dev, ke); | ||
820 | } | ||
821 | |||
822 | spin_unlock_irqrestore(&dev->event_lock, flags); | 795 | spin_unlock_irqrestore(&dev->event_lock, flags); |
796 | |||
823 | return retval; | 797 | return retval; |
824 | } | 798 | } |
825 | EXPORT_SYMBOL(input_get_keycode); | 799 | EXPORT_SYMBOL(input_get_keycode); |
@@ -844,35 +818,7 @@ int input_set_keycode(struct input_dev *dev, | |||
844 | 818 | ||
845 | spin_lock_irqsave(&dev->event_lock, flags); | 819 | spin_lock_irqsave(&dev->event_lock, flags); |
846 | 820 | ||
847 | if (dev->setkeycode) { | 821 | retval = dev->setkeycode(dev, ke, &old_keycode); |
848 | /* | ||
849 | * Support for legacy drivers, that don't implement the new | ||
850 | * ioctls | ||
851 | */ | ||
852 | unsigned int scancode; | ||
853 | |||
854 | retval = input_scancode_to_scalar(ke, &scancode); | ||
855 | if (retval) | ||
856 | goto out; | ||
857 | |||
858 | /* | ||
859 | * We need to know the old scancode, in order to generate a | ||
860 | * keyup effect, if the set operation happens successfully | ||
861 | */ | ||
862 | if (!dev->getkeycode) { | ||
863 | retval = -EINVAL; | ||
864 | goto out; | ||
865 | } | ||
866 | |||
867 | retval = dev->getkeycode(dev, scancode, &old_keycode); | ||
868 | if (retval) | ||
869 | goto out; | ||
870 | |||
871 | retval = dev->setkeycode(dev, scancode, ke->keycode); | ||
872 | } else { | ||
873 | retval = dev->setkeycode_new(dev, ke, &old_keycode); | ||
874 | } | ||
875 | |||
876 | if (retval) | 822 | if (retval) |
877 | goto out; | 823 | goto out; |
878 | 824 | ||
@@ -887,9 +833,9 @@ int input_set_keycode(struct input_dev *dev, | |||
887 | !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && | 833 | !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && |
888 | __test_and_clear_bit(old_keycode, dev->key)) { | 834 | __test_and_clear_bit(old_keycode, dev->key)) { |
889 | 835 | ||
890 | input_pass_event(dev, NULL, EV_KEY, old_keycode, 0); | 836 | input_pass_event(dev, EV_KEY, old_keycode, 0); |
891 | if (dev->sync) | 837 | if (dev->sync) |
892 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); | 838 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); |
893 | } | 839 | } |
894 | 840 | ||
895 | out: | 841 | out: |
@@ -958,10 +904,8 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han | |||
958 | 904 | ||
959 | error = handler->connect(handler, dev, id); | 905 | error = handler->connect(handler, dev, id); |
960 | if (error && error != -ENODEV) | 906 | if (error && error != -ENODEV) |
961 | printk(KERN_ERR | 907 | pr_err("failed to attach handler %s to device %s, error: %d\n", |
962 | "input: failed to attach handler %s to device %s, " | 908 | handler->name, kobject_name(&dev->dev.kobj), error); |
963 | "error: %d\n", | ||
964 | handler->name, kobject_name(&dev->dev.kobj), error); | ||
965 | 909 | ||
966 | return error; | 910 | return error; |
967 | } | 911 | } |
@@ -1109,6 +1053,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) | |||
1109 | seq_printf(seq, "%s ", handle->name); | 1053 | seq_printf(seq, "%s ", handle->name); |
1110 | seq_putc(seq, '\n'); | 1054 | seq_putc(seq, '\n'); |
1111 | 1055 | ||
1056 | input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX); | ||
1057 | |||
1112 | input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); | 1058 | input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); |
1113 | if (test_bit(EV_KEY, dev->evbit)) | 1059 | if (test_bit(EV_KEY, dev->evbit)) |
1114 | input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); | 1060 | input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); |
@@ -1332,11 +1278,26 @@ static ssize_t input_dev_show_modalias(struct device *dev, | |||
1332 | } | 1278 | } |
1333 | static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 1279 | static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
1334 | 1280 | ||
1281 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | ||
1282 | int max, int add_cr); | ||
1283 | |||
1284 | static ssize_t input_dev_show_properties(struct device *dev, | ||
1285 | struct device_attribute *attr, | ||
1286 | char *buf) | ||
1287 | { | ||
1288 | struct input_dev *input_dev = to_input_dev(dev); | ||
1289 | int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit, | ||
1290 | INPUT_PROP_MAX, true); | ||
1291 | return min_t(int, len, PAGE_SIZE); | ||
1292 | } | ||
1293 | static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL); | ||
1294 | |||
1335 | static struct attribute *input_dev_attrs[] = { | 1295 | static struct attribute *input_dev_attrs[] = { |
1336 | &dev_attr_name.attr, | 1296 | &dev_attr_name.attr, |
1337 | &dev_attr_phys.attr, | 1297 | &dev_attr_phys.attr, |
1338 | &dev_attr_uniq.attr, | 1298 | &dev_attr_uniq.attr, |
1339 | &dev_attr_modalias.attr, | 1299 | &dev_attr_modalias.attr, |
1300 | &dev_attr_properties.attr, | ||
1340 | NULL | 1301 | NULL |
1341 | }; | 1302 | }; |
1342 | 1303 | ||
@@ -1470,7 +1431,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, | |||
1470 | { | 1431 | { |
1471 | int len; | 1432 | int len; |
1472 | 1433 | ||
1473 | if (add_uevent_var(env, "%s=", name)) | 1434 | if (add_uevent_var(env, "%s", name)) |
1474 | return -ENOMEM; | 1435 | return -ENOMEM; |
1475 | 1436 | ||
1476 | len = input_print_bitmap(&env->buf[env->buflen - 1], | 1437 | len = input_print_bitmap(&env->buf[env->buflen - 1], |
@@ -1536,6 +1497,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) | |||
1536 | if (dev->uniq) | 1497 | if (dev->uniq) |
1537 | INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq); | 1498 | INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq); |
1538 | 1499 | ||
1500 | INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX); | ||
1501 | |||
1539 | INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX); | 1502 | INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX); |
1540 | if (test_bit(EV_KEY, dev->evbit)) | 1503 | if (test_bit(EV_KEY, dev->evbit)) |
1541 | INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX); | 1504 | INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX); |
@@ -1725,52 +1688,6 @@ void input_free_device(struct input_dev *dev) | |||
1725 | EXPORT_SYMBOL(input_free_device); | 1688 | EXPORT_SYMBOL(input_free_device); |
1726 | 1689 | ||
1727 | /** | 1690 | /** |
1728 | * input_mt_create_slots() - create MT input slots | ||
1729 | * @dev: input device supporting MT events and finger tracking | ||
1730 | * @num_slots: number of slots used by the device | ||
1731 | * | ||
1732 | * This function allocates all necessary memory for MT slot handling in the | ||
1733 | * input device, and adds ABS_MT_SLOT to the device capabilities. All slots | ||
1734 | * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1. | ||
1735 | */ | ||
1736 | int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) | ||
1737 | { | ||
1738 | int i; | ||
1739 | |||
1740 | if (!num_slots) | ||
1741 | return 0; | ||
1742 | |||
1743 | dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); | ||
1744 | if (!dev->mt) | ||
1745 | return -ENOMEM; | ||
1746 | |||
1747 | dev->mtsize = num_slots; | ||
1748 | input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); | ||
1749 | |||
1750 | /* Mark slots as 'unused' */ | ||
1751 | for (i = 0; i < num_slots; i++) | ||
1752 | dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1; | ||
1753 | |||
1754 | return 0; | ||
1755 | } | ||
1756 | EXPORT_SYMBOL(input_mt_create_slots); | ||
1757 | |||
1758 | /** | ||
1759 | * input_mt_destroy_slots() - frees the MT slots of the input device | ||
1760 | * @dev: input device with allocated MT slots | ||
1761 | * | ||
1762 | * This function is only needed in error path as the input core will | ||
1763 | * automatically free the MT slots when the device is destroyed. | ||
1764 | */ | ||
1765 | void input_mt_destroy_slots(struct input_dev *dev) | ||
1766 | { | ||
1767 | kfree(dev->mt); | ||
1768 | dev->mt = NULL; | ||
1769 | dev->mtsize = 0; | ||
1770 | } | ||
1771 | EXPORT_SYMBOL(input_mt_destroy_slots); | ||
1772 | |||
1773 | /** | ||
1774 | * input_set_capability - mark device as capable of a certain event | 1691 | * input_set_capability - mark device as capable of a certain event |
1775 | * @dev: device that is capable of emitting or accepting event | 1692 | * @dev: device that is capable of emitting or accepting event |
1776 | * @type: type of the event (EV_KEY, EV_REL, etc...) | 1693 | * @type: type of the event (EV_KEY, EV_REL, etc...) |
@@ -1819,9 +1736,8 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
1819 | break; | 1736 | break; |
1820 | 1737 | ||
1821 | default: | 1738 | default: |
1822 | printk(KERN_ERR | 1739 | pr_err("input_set_capability: unknown type %u (code %u)\n", |
1823 | "input_set_capability: unknown type %u (code %u)\n", | 1740 | type, code); |
1824 | type, code); | ||
1825 | dump_stack(); | 1741 | dump_stack(); |
1826 | return; | 1742 | return; |
1827 | } | 1743 | } |
@@ -1830,6 +1746,42 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
1830 | } | 1746 | } |
1831 | EXPORT_SYMBOL(input_set_capability); | 1747 | EXPORT_SYMBOL(input_set_capability); |
1832 | 1748 | ||
1749 | static unsigned int input_estimate_events_per_packet(struct input_dev *dev) | ||
1750 | { | ||
1751 | int mt_slots; | ||
1752 | int i; | ||
1753 | unsigned int events; | ||
1754 | |||
1755 | if (dev->mtsize) { | ||
1756 | mt_slots = dev->mtsize; | ||
1757 | } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { | ||
1758 | mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - | ||
1759 | dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, | ||
1760 | clamp(mt_slots, 2, 32); | ||
1761 | } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { | ||
1762 | mt_slots = 2; | ||
1763 | } else { | ||
1764 | mt_slots = 0; | ||
1765 | } | ||
1766 | |||
1767 | events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */ | ||
1768 | |||
1769 | for (i = 0; i < ABS_CNT; i++) { | ||
1770 | if (test_bit(i, dev->absbit)) { | ||
1771 | if (input_is_mt_axis(i)) | ||
1772 | events += mt_slots; | ||
1773 | else | ||
1774 | events++; | ||
1775 | } | ||
1776 | } | ||
1777 | |||
1778 | for (i = 0; i < REL_CNT; i++) | ||
1779 | if (test_bit(i, dev->relbit)) | ||
1780 | events++; | ||
1781 | |||
1782 | return events; | ||
1783 | } | ||
1784 | |||
1833 | #define INPUT_CLEANSE_BITMASK(dev, type, bits) \ | 1785 | #define INPUT_CLEANSE_BITMASK(dev, type, bits) \ |
1834 | do { \ | 1786 | do { \ |
1835 | if (!test_bit(EV_##type, dev->evbit)) \ | 1787 | if (!test_bit(EV_##type, dev->evbit)) \ |
@@ -1877,6 +1829,10 @@ int input_register_device(struct input_dev *dev) | |||
1877 | /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ | 1829 | /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ |
1878 | input_cleanse_bitmasks(dev); | 1830 | input_cleanse_bitmasks(dev); |
1879 | 1831 | ||
1832 | if (!dev->hint_events_per_packet) | ||
1833 | dev->hint_events_per_packet = | ||
1834 | input_estimate_events_per_packet(dev); | ||
1835 | |||
1880 | /* | 1836 | /* |
1881 | * If delay and period are pre-set by the driver, then autorepeating | 1837 | * If delay and period are pre-set by the driver, then autorepeating |
1882 | * is handled by the driver itself and we don't do it in input.c. | 1838 | * is handled by the driver itself and we don't do it in input.c. |
@@ -1889,11 +1845,11 @@ int input_register_device(struct input_dev *dev) | |||
1889 | dev->rep[REP_PERIOD] = 33; | 1845 | dev->rep[REP_PERIOD] = 33; |
1890 | } | 1846 | } |
1891 | 1847 | ||
1892 | if (!dev->getkeycode && !dev->getkeycode_new) | 1848 | if (!dev->getkeycode) |
1893 | dev->getkeycode_new = input_default_getkeycode; | 1849 | dev->getkeycode = input_default_getkeycode; |
1894 | 1850 | ||
1895 | if (!dev->setkeycode && !dev->setkeycode_new) | 1851 | if (!dev->setkeycode) |
1896 | dev->setkeycode_new = input_default_setkeycode; | 1852 | dev->setkeycode = input_default_setkeycode; |
1897 | 1853 | ||
1898 | dev_set_name(&dev->dev, "input%ld", | 1854 | dev_set_name(&dev->dev, "input%ld", |
1899 | (unsigned long) atomic_inc_return(&input_no) - 1); | 1855 | (unsigned long) atomic_inc_return(&input_no) - 1); |
@@ -1903,8 +1859,9 @@ int input_register_device(struct input_dev *dev) | |||
1903 | return error; | 1859 | return error; |
1904 | 1860 | ||
1905 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); | 1861 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
1906 | printk(KERN_INFO "input: %s as %s\n", | 1862 | pr_info("%s as %s\n", |
1907 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); | 1863 | dev->name ? dev->name : "Unspecified device", |
1864 | path ? path : "N/A"); | ||
1908 | kfree(path); | 1865 | kfree(path); |
1909 | 1866 | ||
1910 | error = mutex_lock_interruptible(&input_mutex); | 1867 | error = mutex_lock_interruptible(&input_mutex); |
@@ -2186,7 +2143,7 @@ static int __init input_init(void) | |||
2186 | 2143 | ||
2187 | err = class_register(&input_class); | 2144 | err = class_register(&input_class); |
2188 | if (err) { | 2145 | if (err) { |
2189 | printk(KERN_ERR "input: unable to register input_dev class\n"); | 2146 | pr_err("unable to register input_dev class\n"); |
2190 | return err; | 2147 | return err; |
2191 | } | 2148 | } |
2192 | 2149 | ||
@@ -2196,7 +2153,7 @@ static int __init input_init(void) | |||
2196 | 2153 | ||
2197 | err = register_chrdev(INPUT_MAJOR, "input", &input_fops); | 2154 | err = register_chrdev(INPUT_MAJOR, "input", &input_fops); |
2198 | if (err) { | 2155 | if (err) { |
2199 | printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); | 2156 | pr_err("unable to register char major %d", INPUT_MAJOR); |
2200 | goto fail2; | 2157 | goto fail2; |
2201 | } | 2158 | } |
2202 | 2159 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9d424cebfd2c..5688b5c88f24 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
13 | #include <asm/io.h> | 15 | #include <asm/io.h> |
14 | #include <asm/system.h> | 16 | #include <asm/system.h> |
15 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
@@ -756,7 +758,7 @@ static void joydev_remove_chrdev(struct joydev *joydev) | |||
756 | } | 758 | } |
757 | 759 | ||
758 | /* | 760 | /* |
759 | * Mark device non-existant. This disables writes, ioctls and | 761 | * Mark device non-existent. This disables writes, ioctls and |
760 | * prevents new users from opening the device. Already posted | 762 | * prevents new users from opening the device. Already posted |
761 | * blocking reads will stay, however new ones will fail. | 763 | * blocking reads will stay, however new ones will fail. |
762 | */ | 764 | */ |
@@ -775,7 +777,7 @@ static void joydev_cleanup(struct joydev *joydev) | |||
775 | joydev_hangup(joydev); | 777 | joydev_hangup(joydev); |
776 | joydev_remove_chrdev(joydev); | 778 | joydev_remove_chrdev(joydev); |
777 | 779 | ||
778 | /* joydev is marked dead so noone else accesses joydev->open */ | 780 | /* joydev is marked dead so no one else accesses joydev->open */ |
779 | if (joydev->open) | 781 | if (joydev->open) |
780 | input_close_device(handle); | 782 | input_close_device(handle); |
781 | } | 783 | } |
@@ -806,7 +808,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
806 | break; | 808 | break; |
807 | 809 | ||
808 | if (minor == JOYDEV_MINORS) { | 810 | if (minor == JOYDEV_MINORS) { |
809 | printk(KERN_ERR "joydev: no more free joydev devices\n"); | 811 | pr_err("no more free joydev devices\n"); |
810 | return -ENFILE; | 812 | return -ENFILE; |
811 | } | 813 | } |
812 | 814 | ||
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 5b596165b571..56eb471b5576 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
@@ -255,6 +255,16 @@ config JOYSTICK_AMIGA | |||
255 | To compile this driver as a module, choose M here: the | 255 | To compile this driver as a module, choose M here: the |
256 | module will be called amijoy. | 256 | module will be called amijoy. |
257 | 257 | ||
258 | config JOYSTICK_AS5011 | ||
259 | tristate "Austria Microsystem AS5011 joystick" | ||
260 | depends on I2C | ||
261 | help | ||
262 | Say Y here if you have an AS5011 digital joystick connected to your | ||
263 | system. | ||
264 | |||
265 | To compile this driver as a module, choose M here: the | ||
266 | module will be called as5011. | ||
267 | |||
258 | config JOYSTICK_JOYDUMP | 268 | config JOYSTICK_JOYDUMP |
259 | tristate "Gameport data dumper" | 269 | tristate "Gameport data dumper" |
260 | select GAMEPORT | 270 | select GAMEPORT |
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index f3a8cbe2abb6..92dc0de9dfed 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile | |||
@@ -7,6 +7,7 @@ | |||
7 | obj-$(CONFIG_JOYSTICK_A3D) += a3d.o | 7 | obj-$(CONFIG_JOYSTICK_A3D) += a3d.o |
8 | obj-$(CONFIG_JOYSTICK_ADI) += adi.o | 8 | obj-$(CONFIG_JOYSTICK_ADI) += adi.o |
9 | obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o | 9 | obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o |
10 | obj-$(CONFIG_JOYSTICK_AS5011) += as5011.o | ||
10 | obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o | 11 | obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o |
11 | obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o | 12 | obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o |
12 | obj-$(CONFIG_JOYSTICK_DB9) += db9.o | 13 | obj-$(CONFIG_JOYSTICK_DB9) += db9.o |
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index d259b41354b8..1639ab2b94b7 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -3,7 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * FP-Gaming Assasin 3D joystick driver for Linux | 6 | * FP-Gaming Assassin 3D joystick driver for Linux |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/input.h> | 34 | #include <linux/input.h> |
35 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
36 | 36 | ||
37 | #define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver" | 37 | #define DRIVER_DESC "FP-Gaming Assassin 3D joystick driver" |
38 | 38 | ||
39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
40 | MODULE_DESCRIPTION(DRIVER_DESC); | 40 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c new file mode 100644 index 000000000000..f6732b57ca07 --- /dev/null +++ b/drivers/input/joystick/as5011.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@armadeus.com> | ||
3 | * Sponsored by ARMadeus Systems | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * Driver for Austria Microsystems joysticks AS5011 | ||
20 | * | ||
21 | * TODO: | ||
22 | * - Power on the chip when open() and power down when close() | ||
23 | * - Manage power mode | ||
24 | */ | ||
25 | |||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/input/as5011.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | #define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick" | ||
35 | #define MODULE_DEVICE_ALIAS "as5011" | ||
36 | |||
37 | MODULE_AUTHOR("Fabien Marteau <fabien.marteau@armadeus.com>"); | ||
38 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | /* registers */ | ||
42 | #define AS5011_CTRL1 0x76 | ||
43 | #define AS5011_CTRL2 0x75 | ||
44 | #define AS5011_XP 0x43 | ||
45 | #define AS5011_XN 0x44 | ||
46 | #define AS5011_YP 0x53 | ||
47 | #define AS5011_YN 0x54 | ||
48 | #define AS5011_X_REG 0x41 | ||
49 | #define AS5011_Y_REG 0x42 | ||
50 | #define AS5011_X_RES_INT 0x51 | ||
51 | #define AS5011_Y_RES_INT 0x52 | ||
52 | |||
53 | /* CTRL1 bits */ | ||
54 | #define AS5011_CTRL1_LP_PULSED 0x80 | ||
55 | #define AS5011_CTRL1_LP_ACTIVE 0x40 | ||
56 | #define AS5011_CTRL1_LP_CONTINUE 0x20 | ||
57 | #define AS5011_CTRL1_INT_WUP_EN 0x10 | ||
58 | #define AS5011_CTRL1_INT_ACT_EN 0x08 | ||
59 | #define AS5011_CTRL1_EXT_CLK_EN 0x04 | ||
60 | #define AS5011_CTRL1_SOFT_RST 0x02 | ||
61 | #define AS5011_CTRL1_DATA_VALID 0x01 | ||
62 | |||
63 | /* CTRL2 bits */ | ||
64 | #define AS5011_CTRL2_EXT_SAMPLE_EN 0x08 | ||
65 | #define AS5011_CTRL2_RC_BIAS_ON 0x04 | ||
66 | #define AS5011_CTRL2_INV_SPINNING 0x02 | ||
67 | |||
68 | #define AS5011_MAX_AXIS 80 | ||
69 | #define AS5011_MIN_AXIS (-80) | ||
70 | #define AS5011_FUZZ 8 | ||
71 | #define AS5011_FLAT 40 | ||
72 | |||
73 | struct as5011_device { | ||
74 | struct input_dev *input_dev; | ||
75 | struct i2c_client *i2c_client; | ||
76 | unsigned int button_gpio; | ||
77 | unsigned int button_irq; | ||
78 | unsigned int axis_irq; | ||
79 | }; | ||
80 | |||
81 | static int as5011_i2c_write(struct i2c_client *client, | ||
82 | uint8_t aregaddr, | ||
83 | uint8_t avalue) | ||
84 | { | ||
85 | uint8_t data[2] = { aregaddr, avalue }; | ||
86 | struct i2c_msg msg = { | ||
87 | client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data | ||
88 | }; | ||
89 | int error; | ||
90 | |||
91 | error = i2c_transfer(client->adapter, &msg, 1); | ||
92 | return error < 0 ? error : 0; | ||
93 | } | ||
94 | |||
95 | static int as5011_i2c_read(struct i2c_client *client, | ||
96 | uint8_t aregaddr, signed char *value) | ||
97 | { | ||
98 | uint8_t data[2] = { aregaddr }; | ||
99 | struct i2c_msg msg_set[2] = { | ||
100 | { client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data }, | ||
101 | { client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data } | ||
102 | }; | ||
103 | int error; | ||
104 | |||
105 | error = i2c_transfer(client->adapter, msg_set, 2); | ||
106 | if (error < 0) | ||
107 | return error; | ||
108 | |||
109 | *value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0]; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static irqreturn_t as5011_button_interrupt(int irq, void *dev_id) | ||
114 | { | ||
115 | struct as5011_device *as5011 = dev_id; | ||
116 | int val = gpio_get_value_cansleep(as5011->button_gpio); | ||
117 | |||
118 | input_report_key(as5011->input_dev, BTN_JOYSTICK, !val); | ||
119 | input_sync(as5011->input_dev); | ||
120 | |||
121 | return IRQ_HANDLED; | ||
122 | } | ||
123 | |||
124 | static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id) | ||
125 | { | ||
126 | struct as5011_device *as5011 = dev_id; | ||
127 | int error; | ||
128 | signed char x, y; | ||
129 | |||
130 | error = as5011_i2c_read(as5011->i2c_client, AS5011_X_RES_INT, &x); | ||
131 | if (error < 0) | ||
132 | goto out; | ||
133 | |||
134 | error = as5011_i2c_read(as5011->i2c_client, AS5011_Y_RES_INT, &y); | ||
135 | if (error < 0) | ||
136 | goto out; | ||
137 | |||
138 | input_report_abs(as5011->input_dev, ABS_X, x); | ||
139 | input_report_abs(as5011->input_dev, ABS_Y, y); | ||
140 | input_sync(as5011->input_dev); | ||
141 | |||
142 | out: | ||
143 | return IRQ_HANDLED; | ||
144 | } | ||
145 | |||
146 | static int __devinit as5011_configure_chip(struct as5011_device *as5011, | ||
147 | const struct as5011_platform_data *plat_dat) | ||
148 | { | ||
149 | struct i2c_client *client = as5011->i2c_client; | ||
150 | int error; | ||
151 | signed char value; | ||
152 | |||
153 | /* chip soft reset */ | ||
154 | error = as5011_i2c_write(client, AS5011_CTRL1, | ||
155 | AS5011_CTRL1_SOFT_RST); | ||
156 | if (error < 0) { | ||
157 | dev_err(&client->dev, "Soft reset failed\n"); | ||
158 | return error; | ||
159 | } | ||
160 | |||
161 | mdelay(10); | ||
162 | |||
163 | error = as5011_i2c_write(client, AS5011_CTRL1, | ||
164 | AS5011_CTRL1_LP_PULSED | | ||
165 | AS5011_CTRL1_LP_ACTIVE | | ||
166 | AS5011_CTRL1_INT_ACT_EN); | ||
167 | if (error < 0) { | ||
168 | dev_err(&client->dev, "Power config failed\n"); | ||
169 | return error; | ||
170 | } | ||
171 | |||
172 | error = as5011_i2c_write(client, AS5011_CTRL2, | ||
173 | AS5011_CTRL2_INV_SPINNING); | ||
174 | if (error < 0) { | ||
175 | dev_err(&client->dev, "Can't invert spinning\n"); | ||
176 | return error; | ||
177 | } | ||
178 | |||
179 | /* write threshold */ | ||
180 | error = as5011_i2c_write(client, AS5011_XP, plat_dat->xp); | ||
181 | if (error < 0) { | ||
182 | dev_err(&client->dev, "Can't write threshold\n"); | ||
183 | return error; | ||
184 | } | ||
185 | |||
186 | error = as5011_i2c_write(client, AS5011_XN, plat_dat->xn); | ||
187 | if (error < 0) { | ||
188 | dev_err(&client->dev, "Can't write threshold\n"); | ||
189 | return error; | ||
190 | } | ||
191 | |||
192 | error = as5011_i2c_write(client, AS5011_YP, plat_dat->yp); | ||
193 | if (error < 0) { | ||
194 | dev_err(&client->dev, "Can't write threshold\n"); | ||
195 | return error; | ||
196 | } | ||
197 | |||
198 | error = as5011_i2c_write(client, AS5011_YN, plat_dat->yn); | ||
199 | if (error < 0) { | ||
200 | dev_err(&client->dev, "Can't write threshold\n"); | ||
201 | return error; | ||
202 | } | ||
203 | |||
204 | /* to free irq gpio in chip */ | ||
205 | error = as5011_i2c_read(client, AS5011_X_RES_INT, &value); | ||
206 | if (error < 0) { | ||
207 | dev_err(&client->dev, "Can't read i2c X resolution value\n"); | ||
208 | return error; | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int __devinit as5011_probe(struct i2c_client *client, | ||
215 | const struct i2c_device_id *id) | ||
216 | { | ||
217 | const struct as5011_platform_data *plat_data; | ||
218 | struct as5011_device *as5011; | ||
219 | struct input_dev *input_dev; | ||
220 | int irq; | ||
221 | int error; | ||
222 | |||
223 | plat_data = client->dev.platform_data; | ||
224 | if (!plat_data) | ||
225 | return -EINVAL; | ||
226 | |||
227 | if (!plat_data->axis_irq) { | ||
228 | dev_err(&client->dev, "No axis IRQ?\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | if (!i2c_check_functionality(client->adapter, | ||
233 | I2C_FUNC_PROTOCOL_MANGLING)) { | ||
234 | dev_err(&client->dev, | ||
235 | "need i2c bus that supports protocol mangling\n"); | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | |||
239 | as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL); | ||
240 | input_dev = input_allocate_device(); | ||
241 | if (!as5011 || !input_dev) { | ||
242 | dev_err(&client->dev, | ||
243 | "Can't allocate memory for device structure\n"); | ||
244 | error = -ENOMEM; | ||
245 | goto err_free_mem; | ||
246 | } | ||
247 | |||
248 | as5011->i2c_client = client; | ||
249 | as5011->input_dev = input_dev; | ||
250 | as5011->button_gpio = plat_data->button_gpio; | ||
251 | as5011->axis_irq = plat_data->axis_irq; | ||
252 | |||
253 | input_dev->name = "Austria Microsystem as5011 joystick"; | ||
254 | input_dev->id.bustype = BUS_I2C; | ||
255 | input_dev->dev.parent = &client->dev; | ||
256 | |||
257 | __set_bit(EV_KEY, input_dev->evbit); | ||
258 | __set_bit(EV_ABS, input_dev->evbit); | ||
259 | __set_bit(BTN_JOYSTICK, input_dev->keybit); | ||
260 | |||
261 | input_set_abs_params(input_dev, ABS_X, | ||
262 | AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT); | ||
263 | input_set_abs_params(as5011->input_dev, ABS_Y, | ||
264 | AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT); | ||
265 | |||
266 | error = gpio_request(as5011->button_gpio, "AS5011 button"); | ||
267 | if (error < 0) { | ||
268 | dev_err(&client->dev, "Failed to request button gpio\n"); | ||
269 | goto err_free_mem; | ||
270 | } | ||
271 | |||
272 | irq = gpio_to_irq(as5011->button_gpio); | ||
273 | if (irq < 0) { | ||
274 | dev_err(&client->dev, | ||
275 | "Failed to get irq number for button gpio\n"); | ||
276 | goto err_free_button_gpio; | ||
277 | } | ||
278 | |||
279 | as5011->button_irq = irq; | ||
280 | |||
281 | error = request_threaded_irq(as5011->button_irq, | ||
282 | NULL, as5011_button_interrupt, | ||
283 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
284 | "as5011_button", as5011); | ||
285 | if (error < 0) { | ||
286 | dev_err(&client->dev, | ||
287 | "Can't allocate button irq %d\n", as5011->button_irq); | ||
288 | goto err_free_button_gpio; | ||
289 | } | ||
290 | |||
291 | error = as5011_configure_chip(as5011, plat_data); | ||
292 | if (error) | ||
293 | goto err_free_button_irq; | ||
294 | |||
295 | error = request_threaded_irq(as5011->axis_irq, NULL, | ||
296 | as5011_axis_interrupt, | ||
297 | plat_data->axis_irqflags, | ||
298 | "as5011_joystick", as5011); | ||
299 | if (error) { | ||
300 | dev_err(&client->dev, | ||
301 | "Can't allocate axis irq %d\n", plat_data->axis_irq); | ||
302 | goto err_free_button_irq; | ||
303 | } | ||
304 | |||
305 | error = input_register_device(as5011->input_dev); | ||
306 | if (error) { | ||
307 | dev_err(&client->dev, "Failed to register input device\n"); | ||
308 | goto err_free_axis_irq; | ||
309 | } | ||
310 | |||
311 | i2c_set_clientdata(client, as5011); | ||
312 | |||
313 | return 0; | ||
314 | |||
315 | err_free_axis_irq: | ||
316 | free_irq(as5011->axis_irq, as5011); | ||
317 | err_free_button_irq: | ||
318 | free_irq(as5011->button_irq, as5011); | ||
319 | err_free_button_gpio: | ||
320 | gpio_free(as5011->button_gpio); | ||
321 | err_free_mem: | ||
322 | input_free_device(input_dev); | ||
323 | kfree(as5011); | ||
324 | |||
325 | return error; | ||
326 | } | ||
327 | |||
328 | static int __devexit as5011_remove(struct i2c_client *client) | ||
329 | { | ||
330 | struct as5011_device *as5011 = i2c_get_clientdata(client); | ||
331 | |||
332 | free_irq(as5011->axis_irq, as5011); | ||
333 | free_irq(as5011->button_irq, as5011); | ||
334 | gpio_free(as5011->button_gpio); | ||
335 | |||
336 | input_unregister_device(as5011->input_dev); | ||
337 | kfree(as5011); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static const struct i2c_device_id as5011_id[] = { | ||
343 | { MODULE_DEVICE_ALIAS, 0 }, | ||
344 | { } | ||
345 | }; | ||
346 | MODULE_DEVICE_TABLE(i2c, as5011_id); | ||
347 | |||
348 | static struct i2c_driver as5011_driver = { | ||
349 | .driver = { | ||
350 | .name = "as5011", | ||
351 | }, | ||
352 | .probe = as5011_probe, | ||
353 | .remove = __devexit_p(as5011_remove), | ||
354 | .id_table = as5011_id, | ||
355 | }; | ||
356 | |||
357 | static int __init as5011_init(void) | ||
358 | { | ||
359 | return i2c_add_driver(&as5011_driver); | ||
360 | } | ||
361 | module_init(as5011_init); | ||
362 | |||
363 | static void __exit as5011_exit(void) | ||
364 | { | ||
365 | i2c_del_driver(&as5011_driver); | ||
366 | } | ||
367 | module_exit(as5011_exit); | ||
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile index 74daff49ab6e..bc5bda22f15e 100644 --- a/drivers/input/joystick/iforce/Makefile +++ b/drivers/input/joystick/iforce/Makefile | |||
@@ -4,17 +4,8 @@ | |||
4 | # By Johann Deneux <johann.deneux@gmail.com> | 4 | # By Johann Deneux <johann.deneux@gmail.com> |
5 | # | 5 | # |
6 | 6 | ||
7 | # Goal definition | ||
8 | iforce-objs := iforce-ff.o iforce-main.o iforce-packets.o | ||
9 | |||
10 | obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o | 7 | obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o |
11 | 8 | ||
12 | ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y) | 9 | iforce-y := iforce-ff.o iforce-main.o iforce-packets.o |
13 | iforce-objs += iforce-serio.o | 10 | iforce-$(CONFIG_JOYSTICK_IFORCE_232) += iforce-serio.o |
14 | endif | 11 | iforce-$(CONFIG_JOYSTICK_IFORCE_USB) += iforce-usb.o |
15 | |||
16 | ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y) | ||
17 | iforce-objs += iforce-usb.o | ||
18 | endif | ||
19 | |||
20 | EXTRA_CFLAGS = -Werror-implicit-function-declaration | ||
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index d53b9e900234..27b6a3ce18ca 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -245,6 +245,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) | |||
245 | goto err_free_tgfx; | 245 | goto err_free_tgfx; |
246 | } | 246 | } |
247 | 247 | ||
248 | parport_put_port(pp); | ||
248 | return tgfx; | 249 | return tgfx; |
249 | 250 | ||
250 | err_free_dev: | 251 | err_free_dev: |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f9fb7fa10af3..56abf3d0e911 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -543,21 +543,25 @@ exit: | |||
543 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | 543 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) |
544 | { | 544 | { |
545 | struct usb_endpoint_descriptor *ep_irq_out; | 545 | struct usb_endpoint_descriptor *ep_irq_out; |
546 | int error = -ENOMEM; | 546 | int error; |
547 | 547 | ||
548 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) | 548 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) |
549 | return 0; | 549 | return 0; |
550 | 550 | ||
551 | xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, | 551 | xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, |
552 | GFP_KERNEL, &xpad->odata_dma); | 552 | GFP_KERNEL, &xpad->odata_dma); |
553 | if (!xpad->odata) | 553 | if (!xpad->odata) { |
554 | error = -ENOMEM; | ||
554 | goto fail1; | 555 | goto fail1; |
556 | } | ||
555 | 557 | ||
556 | mutex_init(&xpad->odata_mutex); | 558 | mutex_init(&xpad->odata_mutex); |
557 | 559 | ||
558 | xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); | 560 | xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); |
559 | if (!xpad->irq_out) | 561 | if (!xpad->irq_out) { |
562 | error = -ENOMEM; | ||
560 | goto fail2; | 563 | goto fail2; |
564 | } | ||
561 | 565 | ||
562 | ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; | 566 | ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; |
563 | usb_fill_int_urb(xpad->irq_out, xpad->udev, | 567 | usb_fill_int_urb(xpad->irq_out, xpad->udev, |
@@ -728,7 +732,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) | |||
728 | 732 | ||
729 | if (xpad_led) { | 733 | if (xpad_led) { |
730 | led_classdev_unregister(&xpad_led->led_cdev); | 734 | led_classdev_unregister(&xpad_led->led_cdev); |
731 | kfree(xpad_led->name); | 735 | kfree(xpad_led); |
732 | } | 736 | } |
733 | } | 737 | } |
734 | #else | 738 | #else |
@@ -756,8 +760,9 @@ static void xpad_close(struct input_dev *dev) | |||
756 | { | 760 | { |
757 | struct usb_xpad *xpad = input_get_drvdata(dev); | 761 | struct usb_xpad *xpad = input_get_drvdata(dev); |
758 | 762 | ||
759 | if(xpad->xtype != XTYPE_XBOX360W) | 763 | if (xpad->xtype != XTYPE_XBOX360W) |
760 | usb_kill_urb(xpad->irq_in); | 764 | usb_kill_urb(xpad->irq_in); |
765 | |||
761 | xpad_stop_output(xpad); | 766 | xpad_stop_output(xpad); |
762 | } | 767 | } |
763 | 768 | ||
@@ -789,8 +794,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
789 | struct usb_xpad *xpad; | 794 | struct usb_xpad *xpad; |
790 | struct input_dev *input_dev; | 795 | struct input_dev *input_dev; |
791 | struct usb_endpoint_descriptor *ep_irq_in; | 796 | struct usb_endpoint_descriptor *ep_irq_in; |
792 | int i; | 797 | int i, error; |
793 | int error = -ENOMEM; | ||
794 | 798 | ||
795 | for (i = 0; xpad_device[i].idVendor; i++) { | 799 | for (i = 0; xpad_device[i].idVendor; i++) { |
796 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | 800 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
@@ -800,17 +804,23 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
800 | 804 | ||
801 | xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); | 805 | xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); |
802 | input_dev = input_allocate_device(); | 806 | input_dev = input_allocate_device(); |
803 | if (!xpad || !input_dev) | 807 | if (!xpad || !input_dev) { |
808 | error = -ENOMEM; | ||
804 | goto fail1; | 809 | goto fail1; |
810 | } | ||
805 | 811 | ||
806 | xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, | 812 | xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, |
807 | GFP_KERNEL, &xpad->idata_dma); | 813 | GFP_KERNEL, &xpad->idata_dma); |
808 | if (!xpad->idata) | 814 | if (!xpad->idata) { |
815 | error = -ENOMEM; | ||
809 | goto fail1; | 816 | goto fail1; |
817 | } | ||
810 | 818 | ||
811 | xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); | 819 | xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); |
812 | if (!xpad->irq_in) | 820 | if (!xpad->irq_in) { |
821 | error = -ENOMEM; | ||
813 | goto fail2; | 822 | goto fail2; |
823 | } | ||
814 | 824 | ||
815 | xpad->udev = udev; | 825 | xpad->udev = udev; |
816 | xpad->mapping = xpad_device[i].mapping; | 826 | xpad->mapping = xpad_device[i].mapping; |
@@ -887,15 +897,15 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
887 | 897 | ||
888 | error = xpad_init_output(intf, xpad); | 898 | error = xpad_init_output(intf, xpad); |
889 | if (error) | 899 | if (error) |
890 | goto fail2; | 900 | goto fail3; |
891 | 901 | ||
892 | error = xpad_init_ff(xpad); | 902 | error = xpad_init_ff(xpad); |
893 | if (error) | 903 | if (error) |
894 | goto fail3; | 904 | goto fail4; |
895 | 905 | ||
896 | error = xpad_led_probe(xpad); | 906 | error = xpad_led_probe(xpad); |
897 | if (error) | 907 | if (error) |
898 | goto fail3; | 908 | goto fail5; |
899 | 909 | ||
900 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 910 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
901 | usb_fill_int_urb(xpad->irq_in, udev, | 911 | usb_fill_int_urb(xpad->irq_in, udev, |
@@ -907,34 +917,26 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
907 | 917 | ||
908 | error = input_register_device(xpad->dev); | 918 | error = input_register_device(xpad->dev); |
909 | if (error) | 919 | if (error) |
910 | goto fail4; | 920 | goto fail6; |
911 | 921 | ||
912 | usb_set_intfdata(intf, xpad); | 922 | usb_set_intfdata(intf, xpad); |
913 | 923 | ||
914 | /* | ||
915 | * Submit the int URB immediatly rather than waiting for open | ||
916 | * because we get status messages from the device whether | ||
917 | * or not any controllers are attached. In fact, it's | ||
918 | * exactly the message that a controller has arrived that | ||
919 | * we're waiting for. | ||
920 | */ | ||
921 | if (xpad->xtype == XTYPE_XBOX360W) { | 924 | if (xpad->xtype == XTYPE_XBOX360W) { |
922 | xpad->irq_in->dev = xpad->udev; | ||
923 | error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); | ||
924 | if (error) | ||
925 | goto fail4; | ||
926 | |||
927 | /* | 925 | /* |
928 | * Setup the message to set the LEDs on the | 926 | * Setup the message to set the LEDs on the |
929 | * controller when it shows up | 927 | * controller when it shows up |
930 | */ | 928 | */ |
931 | xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); | 929 | xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); |
932 | if(!xpad->bulk_out) | 930 | if (!xpad->bulk_out) { |
933 | goto fail5; | 931 | error = -ENOMEM; |
932 | goto fail7; | ||
933 | } | ||
934 | 934 | ||
935 | xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); | 935 | xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); |
936 | if(!xpad->bdata) | 936 | if (!xpad->bdata) { |
937 | goto fail6; | 937 | error = -ENOMEM; |
938 | goto fail8; | ||
939 | } | ||
938 | 940 | ||
939 | xpad->bdata[2] = 0x08; | 941 | xpad->bdata[2] = 0x08; |
940 | switch (intf->cur_altsetting->desc.bInterfaceNumber) { | 942 | switch (intf->cur_altsetting->desc.bInterfaceNumber) { |
@@ -955,14 +957,31 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
955 | usb_fill_bulk_urb(xpad->bulk_out, udev, | 957 | usb_fill_bulk_urb(xpad->bulk_out, udev, |
956 | usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), | 958 | usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), |
957 | xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); | 959 | xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); |
960 | |||
961 | /* | ||
962 | * Submit the int URB immediately rather than waiting for open | ||
963 | * because we get status messages from the device whether | ||
964 | * or not any controllers are attached. In fact, it's | ||
965 | * exactly the message that a controller has arrived that | ||
966 | * we're waiting for. | ||
967 | */ | ||
968 | xpad->irq_in->dev = xpad->udev; | ||
969 | error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); | ||
970 | if (error) | ||
971 | goto fail9; | ||
958 | } | 972 | } |
959 | 973 | ||
960 | return 0; | 974 | return 0; |
961 | 975 | ||
962 | fail6: usb_free_urb(xpad->bulk_out); | 976 | fail9: kfree(xpad->bdata); |
963 | fail5: usb_kill_urb(xpad->irq_in); | 977 | fail8: usb_free_urb(xpad->bulk_out); |
964 | fail4: usb_free_urb(xpad->irq_in); | 978 | fail7: input_unregister_device(input_dev); |
965 | fail3: xpad_deinit_output(xpad); | 979 | input_dev = NULL; |
980 | fail6: xpad_led_disconnect(xpad); | ||
981 | fail5: if (input_dev) | ||
982 | input_ff_destroy(input_dev); | ||
983 | fail4: xpad_deinit_output(xpad); | ||
984 | fail3: usb_free_urb(xpad->irq_in); | ||
966 | fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | 985 | fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); |
967 | fail1: input_free_device(input_dev); | 986 | fail1: input_free_device(input_dev); |
968 | kfree(xpad); | 987 | kfree(xpad); |
@@ -974,21 +993,24 @@ static void xpad_disconnect(struct usb_interface *intf) | |||
974 | { | 993 | { |
975 | struct usb_xpad *xpad = usb_get_intfdata (intf); | 994 | struct usb_xpad *xpad = usb_get_intfdata (intf); |
976 | 995 | ||
977 | usb_set_intfdata(intf, NULL); | 996 | xpad_led_disconnect(xpad); |
978 | if (xpad) { | 997 | input_unregister_device(xpad->dev); |
979 | xpad_led_disconnect(xpad); | 998 | xpad_deinit_output(xpad); |
980 | input_unregister_device(xpad->dev); | 999 | |
981 | xpad_deinit_output(xpad); | 1000 | if (xpad->xtype == XTYPE_XBOX360W) { |
982 | if (xpad->xtype == XTYPE_XBOX360W) { | 1001 | usb_kill_urb(xpad->bulk_out); |
983 | usb_kill_urb(xpad->bulk_out); | 1002 | usb_free_urb(xpad->bulk_out); |
984 | usb_free_urb(xpad->bulk_out); | 1003 | usb_kill_urb(xpad->irq_in); |
985 | usb_kill_urb(xpad->irq_in); | ||
986 | } | ||
987 | usb_free_urb(xpad->irq_in); | ||
988 | usb_free_coherent(xpad->udev, XPAD_PKT_LEN, | ||
989 | xpad->idata, xpad->idata_dma); | ||
990 | kfree(xpad); | ||
991 | } | 1004 | } |
1005 | |||
1006 | usb_free_urb(xpad->irq_in); | ||
1007 | usb_free_coherent(xpad->udev, XPAD_PKT_LEN, | ||
1008 | xpad->idata, xpad->idata_dma); | ||
1009 | |||
1010 | kfree(xpad->bdata); | ||
1011 | kfree(xpad); | ||
1012 | |||
1013 | usb_set_intfdata(intf, NULL); | ||
992 | } | 1014 | } |
993 | 1015 | ||
994 | static struct usb_driver xpad_driver = { | 1016 | static struct usb_driver xpad_driver = { |
@@ -1000,10 +1022,7 @@ static struct usb_driver xpad_driver = { | |||
1000 | 1022 | ||
1001 | static int __init usb_xpad_init(void) | 1023 | static int __init usb_xpad_init(void) |
1002 | { | 1024 | { |
1003 | int result = usb_register(&xpad_driver); | 1025 | return usb_register(&xpad_driver); |
1004 | if (result == 0) | ||
1005 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); | ||
1006 | return result; | ||
1007 | } | 1026 | } |
1008 | 1027 | ||
1009 | static void __exit usb_xpad_exit(void) | 1028 | static void __exit usb_xpad_exit(void) |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b8c51b9781db..b16bed038f72 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Input core configuration | 2 | # Input core configuration |
3 | # | 3 | # |
4 | menuconfig INPUT_KEYBOARD | 4 | menuconfig INPUT_KEYBOARD |
5 | bool "Keyboards" if EMBEDDED || !X86 | 5 | bool "Keyboards" if EXPERT || !X86 |
6 | default y | 6 | default y |
7 | help | 7 | help |
8 | Say Y here, and a list of supported keyboards will be displayed. | 8 | Say Y here, and a list of supported keyboards will be displayed. |
@@ -12,18 +12,6 @@ menuconfig INPUT_KEYBOARD | |||
12 | 12 | ||
13 | if INPUT_KEYBOARD | 13 | if INPUT_KEYBOARD |
14 | 14 | ||
15 | config KEYBOARD_AAED2000 | ||
16 | tristate "AAED-2000 keyboard" | ||
17 | depends on MACH_AAED2000 | ||
18 | select INPUT_POLLDEV | ||
19 | default y | ||
20 | help | ||
21 | Say Y here to enable the keyboard on the Agilent AAED-2000 | ||
22 | development board. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called aaed2000_kbd. | ||
26 | |||
27 | config KEYBOARD_ADP5520 | 15 | config KEYBOARD_ADP5520 |
28 | tristate "Keypad Support for ADP5520 PMIC" | 16 | tristate "Keypad Support for ADP5520 PMIC" |
29 | depends on PMIC_ADP5520 | 17 | depends on PMIC_ADP5520 |
@@ -69,7 +57,7 @@ config KEYBOARD_ATARI | |||
69 | module will be called atakbd. | 57 | module will be called atakbd. |
70 | 58 | ||
71 | config KEYBOARD_ATKBD | 59 | config KEYBOARD_ATKBD |
72 | tristate "AT keyboard" if EMBEDDED || !X86 | 60 | tristate "AT keyboard" if EXPERT || !X86 |
73 | default y | 61 | default y |
74 | select SERIO | 62 | select SERIO |
75 | select SERIO_LIBPS2 | 63 | select SERIO_LIBPS2 |
@@ -124,6 +112,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES | |||
124 | right-hand column will be interpreted as the key shown in the | 112 | right-hand column will be interpreted as the key shown in the |
125 | left-hand column. | 113 | left-hand column. |
126 | 114 | ||
115 | config KEYBOARD_QT1070 | ||
116 | tristate "Atmel AT42QT1070 Touch Sensor Chip" | ||
117 | depends on I2C | ||
118 | help | ||
119 | Say Y here if you want to use Atmel AT42QT1070 QTouch | ||
120 | Sensor chip as input device. | ||
121 | |||
122 | To compile this driver as a module, choose M here: | ||
123 | the module will be called qt1070 | ||
124 | |||
127 | config KEYBOARD_QT2160 | 125 | config KEYBOARD_QT2160 |
128 | tristate "Atmel AT42QT2160 Touch Sensor Chip" | 126 | tristate "Atmel AT42QT2160 Touch Sensor Chip" |
129 | depends on I2C && EXPERIMENTAL | 127 | depends on I2C && EXPERIMENTAL |
@@ -179,21 +177,39 @@ config KEYBOARD_GPIO | |||
179 | To compile this driver as a module, choose M here: the | 177 | To compile this driver as a module, choose M here: the |
180 | module will be called gpio_keys. | 178 | module will be called gpio_keys. |
181 | 179 | ||
180 | config KEYBOARD_GPIO_POLLED | ||
181 | tristate "Polled GPIO buttons" | ||
182 | depends on GENERIC_GPIO | ||
183 | select INPUT_POLLDEV | ||
184 | help | ||
185 | This driver implements support for buttons connected | ||
186 | to GPIO pins that are not capable of generating interrupts. | ||
187 | |||
188 | Say Y here if your device has buttons connected | ||
189 | directly to such GPIO pins. Your board-specific | ||
190 | setup logic must also provide a platform device, | ||
191 | with configuration data saying which GPIOs are used. | ||
192 | |||
193 | To compile this driver as a module, choose M here: the | ||
194 | module will be called gpio_keys_polled. | ||
195 | |||
182 | config KEYBOARD_TCA6416 | 196 | config KEYBOARD_TCA6416 |
183 | tristate "TCA6416 Keypad Support" | 197 | tristate "TCA6416/TCA6408A Keypad Support" |
184 | depends on I2C | 198 | depends on I2C |
185 | help | 199 | help |
186 | This driver implements basic keypad functionality | 200 | This driver implements basic keypad functionality |
187 | for keys connected through TCA6416 IO expander | 201 | for keys connected through TCA6416/TCA6408A IO expanders. |
188 | 202 | ||
189 | Say Y here if your device has keys connected to | 203 | Say Y here if your device has keys connected to |
190 | TCA6416 IO expander. Your board-specific setup logic | 204 | TCA6416/TCA6408A IO expander. Your board-specific setup logic |
191 | must also provide pin-mask details(of which TCA6416 pins | 205 | must also provide pin-mask details(of which TCA6416 pins |
192 | are used for keypad). | 206 | are used for keypad). |
193 | 207 | ||
194 | If enabled the complete TCA6416 device will be managed through | 208 | If enabled the entire TCA6416 device will be managed through |
195 | this driver. | 209 | this driver. |
196 | 210 | ||
211 | To compile this driver as a module, choose M here: the | ||
212 | module will be called tca6416_keypad. | ||
197 | 213 | ||
198 | config KEYBOARD_MATRIX | 214 | config KEYBOARD_MATRIX |
199 | tristate "GPIO driven matrix keypad support" | 215 | tristate "GPIO driven matrix keypad support" |
@@ -337,6 +353,16 @@ config KEYBOARD_NOMADIK | |||
337 | To compile this driver as a module, choose M here: the | 353 | To compile this driver as a module, choose M here: the |
338 | module will be called nmk-ske-keypad. | 354 | module will be called nmk-ske-keypad. |
339 | 355 | ||
356 | config KEYBOARD_TEGRA | ||
357 | tristate "NVIDIA Tegra internal matrix keyboard controller support" | ||
358 | depends on ARCH_TEGRA | ||
359 | help | ||
360 | Say Y here if you want to use a matrix keyboard connected directly | ||
361 | to the internal keyboard controller on Tegra SoCs. | ||
362 | |||
363 | To compile this driver as a module, choose M here: the | ||
364 | module will be called tegra-kbc. | ||
365 | |||
340 | config KEYBOARD_OPENCORES | 366 | config KEYBOARD_OPENCORES |
341 | tristate "OpenCores Keyboard Controller" | 367 | tristate "OpenCores Keyboard Controller" |
342 | help | 368 | help |
@@ -443,6 +469,25 @@ config KEYBOARD_OMAP4 | |||
443 | To compile this driver as a module, choose M here: the | 469 | To compile this driver as a module, choose M here: the |
444 | module will be called omap4-keypad. | 470 | module will be called omap4-keypad. |
445 | 471 | ||
472 | config KEYBOARD_SPEAR | ||
473 | tristate "ST SPEAR keyboard support" | ||
474 | depends on PLAT_SPEAR | ||
475 | help | ||
476 | Say Y here if you want to use the SPEAR keyboard. | ||
477 | |||
478 | To compile this driver as a module, choose M here: the | ||
479 | module will be called spear-keboard. | ||
480 | |||
481 | config KEYBOARD_TC3589X | ||
482 | tristate "TC3589X Keypad support" | ||
483 | depends on MFD_TC3589X | ||
484 | help | ||
485 | Say Y here if you want to use the keypad controller on | ||
486 | TC35892/3 I/O expander. | ||
487 | |||
488 | To compile this driver as a module, choose M here: the | ||
489 | module will be called tc3589x-keypad. | ||
490 | |||
446 | config KEYBOARD_TNETV107X | 491 | config KEYBOARD_TNETV107X |
447 | tristate "TI TNETV107X keypad support" | 492 | tristate "TI TNETV107X keypad support" |
448 | depends on ARCH_DAVINCI_TNETV107X | 493 | depends on ARCH_DAVINCI_TNETV107X |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index a34452e8ebe2..878e6c20deb0 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | ||
8 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o | 7 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o |
9 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | 8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o |
10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
@@ -14,6 +13,7 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | |||
14 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 13 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
15 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 14 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
16 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 15 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
16 | obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o | ||
17 | obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o | 17 | obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o |
18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
@@ -34,12 +34,16 @@ obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o | |||
34 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | 34 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o |
35 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 35 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
36 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 36 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
37 | obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o | ||
37 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 38 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
38 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o | 39 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o |
39 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 40 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
41 | obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o | ||
40 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | 42 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o |
41 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 43 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
42 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 44 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
45 | obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o | ||
46 | obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o | ||
43 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o | 47 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o |
44 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 48 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
45 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 49 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c deleted file mode 100644 index 18222a689a03..000000000000 --- a/drivers/input/keyboard/aaed2000_kbd.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * Keyboard driver for the AAED-2000 dev board | ||
3 | * | ||
4 | * Copyright (c) 2006 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * Based on corgikbd.c | ||
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 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/input-polldev.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <mach/hardware.h> | ||
24 | #include <mach/aaed2000.h> | ||
25 | |||
26 | #define KB_ROWS 12 | ||
27 | #define KB_COLS 8 | ||
28 | #define KB_ROWMASK(r) (1 << (r)) | ||
29 | #define SCANCODE(r,c) (((c) * KB_ROWS) + (r)) | ||
30 | #define NR_SCANCODES (KB_COLS * KB_ROWS) | ||
31 | |||
32 | #define SCAN_INTERVAL (50) /* ms */ | ||
33 | #define KB_ACTIVATE_DELAY (20) /* us */ | ||
34 | |||
35 | static unsigned char aaedkbd_keycode[NR_SCANCODES] = { | ||
36 | KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0, | ||
37 | KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0, | ||
38 | KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0, | ||
39 | KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, | ||
40 | KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK, | ||
41 | KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB, | ||
42 | KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE, | ||
43 | 0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL | ||
44 | }; | ||
45 | |||
46 | struct aaedkbd { | ||
47 | unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; | ||
48 | struct input_polled_dev *poll_dev; | ||
49 | int kbdscan_state[KB_COLS]; | ||
50 | int kbdscan_count[KB_COLS]; | ||
51 | }; | ||
52 | |||
53 | #define KBDSCAN_STABLE_COUNT 2 | ||
54 | |||
55 | static void aaedkbd_report_col(struct aaedkbd *aaedkbd, | ||
56 | unsigned int col, unsigned int rowd) | ||
57 | { | ||
58 | unsigned int scancode, pressed; | ||
59 | unsigned int row; | ||
60 | |||
61 | for (row = 0; row < KB_ROWS; row++) { | ||
62 | scancode = SCANCODE(row, col); | ||
63 | pressed = rowd & KB_ROWMASK(row); | ||
64 | |||
65 | input_report_key(aaedkbd->poll_dev->input, | ||
66 | aaedkbd->keycode[scancode], pressed); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
71 | static void aaedkbd_poll(struct input_polled_dev *dev) | ||
72 | { | ||
73 | struct aaedkbd *aaedkbd = dev->private; | ||
74 | unsigned int col, rowd; | ||
75 | |||
76 | col = 0; | ||
77 | do { | ||
78 | AAEC_GPIO_KSCAN = col + 8; | ||
79 | udelay(KB_ACTIVATE_DELAY); | ||
80 | rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN; | ||
81 | |||
82 | if (rowd != aaedkbd->kbdscan_state[col]) { | ||
83 | aaedkbd->kbdscan_count[col] = 0; | ||
84 | aaedkbd->kbdscan_state[col] = rowd; | ||
85 | } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) { | ||
86 | aaedkbd_report_col(aaedkbd, col, rowd); | ||
87 | col++; | ||
88 | } | ||
89 | } while (col < KB_COLS); | ||
90 | |||
91 | AAEC_GPIO_KSCAN = 0x07; | ||
92 | input_sync(dev->input); | ||
93 | } | ||
94 | |||
95 | static int __devinit aaedkbd_probe(struct platform_device *pdev) | ||
96 | { | ||
97 | struct aaedkbd *aaedkbd; | ||
98 | struct input_polled_dev *poll_dev; | ||
99 | struct input_dev *input_dev; | ||
100 | int i; | ||
101 | int error; | ||
102 | |||
103 | aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); | ||
104 | poll_dev = input_allocate_polled_device(); | ||
105 | if (!aaedkbd || !poll_dev) { | ||
106 | error = -ENOMEM; | ||
107 | goto fail; | ||
108 | } | ||
109 | |||
110 | platform_set_drvdata(pdev, aaedkbd); | ||
111 | |||
112 | aaedkbd->poll_dev = poll_dev; | ||
113 | memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); | ||
114 | |||
115 | poll_dev->private = aaedkbd; | ||
116 | poll_dev->poll = aaedkbd_poll; | ||
117 | poll_dev->poll_interval = SCAN_INTERVAL; | ||
118 | |||
119 | input_dev = poll_dev->input; | ||
120 | input_dev->name = "AAED-2000 Keyboard"; | ||
121 | input_dev->phys = "aaedkbd/input0"; | ||
122 | input_dev->id.bustype = BUS_HOST; | ||
123 | input_dev->id.vendor = 0x0001; | ||
124 | input_dev->id.product = 0x0001; | ||
125 | input_dev->id.version = 0x0100; | ||
126 | input_dev->dev.parent = &pdev->dev; | ||
127 | |||
128 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
129 | input_dev->keycode = aaedkbd->keycode; | ||
130 | input_dev->keycodesize = sizeof(unsigned char); | ||
131 | input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode); | ||
132 | |||
133 | for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++) | ||
134 | set_bit(aaedkbd->keycode[i], input_dev->keybit); | ||
135 | clear_bit(0, input_dev->keybit); | ||
136 | |||
137 | error = input_register_polled_device(aaedkbd->poll_dev); | ||
138 | if (error) | ||
139 | goto fail; | ||
140 | |||
141 | return 0; | ||
142 | |||
143 | fail: kfree(aaedkbd); | ||
144 | input_free_polled_device(poll_dev); | ||
145 | return error; | ||
146 | } | ||
147 | |||
148 | static int __devexit aaedkbd_remove(struct platform_device *pdev) | ||
149 | { | ||
150 | struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); | ||
151 | |||
152 | input_unregister_polled_device(aaedkbd->poll_dev); | ||
153 | input_free_polled_device(aaedkbd->poll_dev); | ||
154 | kfree(aaedkbd); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* work with hotplug and coldplug */ | ||
160 | MODULE_ALIAS("platform:aaed2000-keyboard"); | ||
161 | |||
162 | static struct platform_driver aaedkbd_driver = { | ||
163 | .probe = aaedkbd_probe, | ||
164 | .remove = __devexit_p(aaedkbd_remove), | ||
165 | .driver = { | ||
166 | .name = "aaed2000-keyboard", | ||
167 | .owner = THIS_MODULE, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | static int __init aaedkbd_init(void) | ||
172 | { | ||
173 | return platform_driver_register(&aaedkbd_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit aaedkbd_exit(void) | ||
177 | { | ||
178 | platform_driver_unregister(&aaedkbd_driver); | ||
179 | } | ||
180 | |||
181 | module_init(aaedkbd_init); | ||
182 | module_exit(aaedkbd_exit); | ||
183 | |||
184 | MODULE_AUTHOR("Nicolas Bellido Y Ortega"); | ||
185 | MODULE_DESCRIPTION("AAED-2000 Keyboard Driver"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index a91ee941b5c1..cd89d17162a3 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | 6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> |
7 | * | 7 | * |
8 | * Intial Code: Sandeep Paulraj <s-paulraj@ti.com> | 8 | * Initial Code: Sandeep Paulraj <s-paulraj@ti.com> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6069abe31e42..eb3006361ee4 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -322,7 +322,7 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) | |||
322 | struct gpio_keys_button *button = bdata->button; | 322 | struct gpio_keys_button *button = bdata->button; |
323 | struct input_dev *input = bdata->input; | 323 | struct input_dev *input = bdata->input; |
324 | unsigned int type = button->type ?: EV_KEY; | 324 | unsigned int type = button->type ?: EV_KEY; |
325 | int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; | 325 | int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; |
326 | 326 | ||
327 | input_event(input, type, button->code, !!state); | 327 | input_event(input, type, button->code, !!state); |
328 | input_sync(input); | 328 | input_sync(input); |
@@ -410,8 +410,8 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, | |||
410 | if (!button->can_disable) | 410 | if (!button->can_disable) |
411 | irqflags |= IRQF_SHARED; | 411 | irqflags |= IRQF_SHARED; |
412 | 412 | ||
413 | error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata); | 413 | error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); |
414 | if (error) { | 414 | if (error < 0) { |
415 | dev_err(dev, "Unable to claim irq %d; error %d\n", | 415 | dev_err(dev, "Unable to claim irq %d; error %d\n", |
416 | irq, error); | 416 | irq, error); |
417 | goto fail3; | 417 | goto fail3; |
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c new file mode 100644 index 000000000000..4c17aff20657 --- /dev/null +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * Driver for buttons on GPIO lines not capable of generating interrupts | ||
3 | * | ||
4 | * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org> | ||
5 | * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com> | ||
6 | * | ||
7 | * This file was based on: /drivers/input/misc/cobalt_btns.c | ||
8 | * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
9 | * | ||
10 | * also was based on: /drivers/input/keyboard/gpio_keys.c | ||
11 | * Copyright 2005 Phil Blundell | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/input.h> | ||
23 | #include <linux/input-polldev.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/gpio_keys.h> | ||
28 | |||
29 | #define DRV_NAME "gpio-keys-polled" | ||
30 | |||
31 | struct gpio_keys_button_data { | ||
32 | int last_state; | ||
33 | int count; | ||
34 | int threshold; | ||
35 | int can_sleep; | ||
36 | }; | ||
37 | |||
38 | struct gpio_keys_polled_dev { | ||
39 | struct input_polled_dev *poll_dev; | ||
40 | struct device *dev; | ||
41 | struct gpio_keys_platform_data *pdata; | ||
42 | struct gpio_keys_button_data data[0]; | ||
43 | }; | ||
44 | |||
45 | static void gpio_keys_polled_check_state(struct input_dev *input, | ||
46 | struct gpio_keys_button *button, | ||
47 | struct gpio_keys_button_data *bdata) | ||
48 | { | ||
49 | int state; | ||
50 | |||
51 | if (bdata->can_sleep) | ||
52 | state = !!gpio_get_value_cansleep(button->gpio); | ||
53 | else | ||
54 | state = !!gpio_get_value(button->gpio); | ||
55 | |||
56 | if (state != bdata->last_state) { | ||
57 | unsigned int type = button->type ?: EV_KEY; | ||
58 | |||
59 | input_event(input, type, button->code, | ||
60 | !!(state ^ button->active_low)); | ||
61 | input_sync(input); | ||
62 | bdata->count = 0; | ||
63 | bdata->last_state = state; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static void gpio_keys_polled_poll(struct input_polled_dev *dev) | ||
68 | { | ||
69 | struct gpio_keys_polled_dev *bdev = dev->private; | ||
70 | struct gpio_keys_platform_data *pdata = bdev->pdata; | ||
71 | struct input_dev *input = dev->input; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < bdev->pdata->nbuttons; i++) { | ||
75 | struct gpio_keys_button_data *bdata = &bdev->data[i]; | ||
76 | |||
77 | if (bdata->count < bdata->threshold) | ||
78 | bdata->count++; | ||
79 | else | ||
80 | gpio_keys_polled_check_state(input, &pdata->buttons[i], | ||
81 | bdata); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | static void gpio_keys_polled_open(struct input_polled_dev *dev) | ||
86 | { | ||
87 | struct gpio_keys_polled_dev *bdev = dev->private; | ||
88 | struct gpio_keys_platform_data *pdata = bdev->pdata; | ||
89 | |||
90 | if (pdata->enable) | ||
91 | pdata->enable(bdev->dev); | ||
92 | } | ||
93 | |||
94 | static void gpio_keys_polled_close(struct input_polled_dev *dev) | ||
95 | { | ||
96 | struct gpio_keys_polled_dev *bdev = dev->private; | ||
97 | struct gpio_keys_platform_data *pdata = bdev->pdata; | ||
98 | |||
99 | if (pdata->disable) | ||
100 | pdata->disable(bdev->dev); | ||
101 | } | ||
102 | |||
103 | static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) | ||
104 | { | ||
105 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
106 | struct device *dev = &pdev->dev; | ||
107 | struct gpio_keys_polled_dev *bdev; | ||
108 | struct input_polled_dev *poll_dev; | ||
109 | struct input_dev *input; | ||
110 | int error; | ||
111 | int i; | ||
112 | |||
113 | if (!pdata || !pdata->poll_interval) | ||
114 | return -EINVAL; | ||
115 | |||
116 | bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + | ||
117 | pdata->nbuttons * sizeof(struct gpio_keys_button_data), | ||
118 | GFP_KERNEL); | ||
119 | if (!bdev) { | ||
120 | dev_err(dev, "no memory for private data\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | poll_dev = input_allocate_polled_device(); | ||
125 | if (!poll_dev) { | ||
126 | dev_err(dev, "no memory for polled device\n"); | ||
127 | error = -ENOMEM; | ||
128 | goto err_free_bdev; | ||
129 | } | ||
130 | |||
131 | poll_dev->private = bdev; | ||
132 | poll_dev->poll = gpio_keys_polled_poll; | ||
133 | poll_dev->poll_interval = pdata->poll_interval; | ||
134 | poll_dev->open = gpio_keys_polled_open; | ||
135 | poll_dev->close = gpio_keys_polled_close; | ||
136 | |||
137 | input = poll_dev->input; | ||
138 | |||
139 | input->evbit[0] = BIT(EV_KEY); | ||
140 | input->name = pdev->name; | ||
141 | input->phys = DRV_NAME"/input0"; | ||
142 | input->dev.parent = &pdev->dev; | ||
143 | |||
144 | input->id.bustype = BUS_HOST; | ||
145 | input->id.vendor = 0x0001; | ||
146 | input->id.product = 0x0001; | ||
147 | input->id.version = 0x0100; | ||
148 | |||
149 | for (i = 0; i < pdata->nbuttons; i++) { | ||
150 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
151 | struct gpio_keys_button_data *bdata = &bdev->data[i]; | ||
152 | unsigned int gpio = button->gpio; | ||
153 | unsigned int type = button->type ?: EV_KEY; | ||
154 | |||
155 | if (button->wakeup) { | ||
156 | dev_err(dev, DRV_NAME " does not support wakeup\n"); | ||
157 | error = -EINVAL; | ||
158 | goto err_free_gpio; | ||
159 | } | ||
160 | |||
161 | error = gpio_request(gpio, | ||
162 | button->desc ? button->desc : DRV_NAME); | ||
163 | if (error) { | ||
164 | dev_err(dev, "unable to claim gpio %u, err=%d\n", | ||
165 | gpio, error); | ||
166 | goto err_free_gpio; | ||
167 | } | ||
168 | |||
169 | error = gpio_direction_input(gpio); | ||
170 | if (error) { | ||
171 | dev_err(dev, | ||
172 | "unable to set direction on gpio %u, err=%d\n", | ||
173 | gpio, error); | ||
174 | goto err_free_gpio; | ||
175 | } | ||
176 | |||
177 | bdata->can_sleep = gpio_cansleep(gpio); | ||
178 | bdata->last_state = -1; | ||
179 | bdata->threshold = DIV_ROUND_UP(button->debounce_interval, | ||
180 | pdata->poll_interval); | ||
181 | |||
182 | input_set_capability(input, type, button->code); | ||
183 | } | ||
184 | |||
185 | bdev->poll_dev = poll_dev; | ||
186 | bdev->dev = dev; | ||
187 | bdev->pdata = pdata; | ||
188 | platform_set_drvdata(pdev, bdev); | ||
189 | |||
190 | error = input_register_polled_device(poll_dev); | ||
191 | if (error) { | ||
192 | dev_err(dev, "unable to register polled device, err=%d\n", | ||
193 | error); | ||
194 | goto err_free_gpio; | ||
195 | } | ||
196 | |||
197 | /* report initial state of the buttons */ | ||
198 | for (i = 0; i < pdata->nbuttons; i++) | ||
199 | gpio_keys_polled_check_state(input, &pdata->buttons[i], | ||
200 | &bdev->data[i]); | ||
201 | |||
202 | return 0; | ||
203 | |||
204 | err_free_gpio: | ||
205 | while (--i >= 0) | ||
206 | gpio_free(pdata->buttons[i].gpio); | ||
207 | |||
208 | input_free_polled_device(poll_dev); | ||
209 | |||
210 | err_free_bdev: | ||
211 | kfree(bdev); | ||
212 | |||
213 | platform_set_drvdata(pdev, NULL); | ||
214 | return error; | ||
215 | } | ||
216 | |||
217 | static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) | ||
218 | { | ||
219 | struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); | ||
220 | struct gpio_keys_platform_data *pdata = bdev->pdata; | ||
221 | int i; | ||
222 | |||
223 | input_unregister_polled_device(bdev->poll_dev); | ||
224 | |||
225 | for (i = 0; i < pdata->nbuttons; i++) | ||
226 | gpio_free(pdata->buttons[i].gpio); | ||
227 | |||
228 | input_free_polled_device(bdev->poll_dev); | ||
229 | |||
230 | kfree(bdev); | ||
231 | platform_set_drvdata(pdev, NULL); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct platform_driver gpio_keys_polled_driver = { | ||
237 | .probe = gpio_keys_polled_probe, | ||
238 | .remove = __devexit_p(gpio_keys_polled_remove), | ||
239 | .driver = { | ||
240 | .name = DRV_NAME, | ||
241 | .owner = THIS_MODULE, | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | static int __init gpio_keys_polled_init(void) | ||
246 | { | ||
247 | return platform_driver_register(&gpio_keys_polled_driver); | ||
248 | } | ||
249 | |||
250 | static void __exit gpio_keys_polled_exit(void) | ||
251 | { | ||
252 | platform_driver_unregister(&gpio_keys_polled_driver); | ||
253 | } | ||
254 | |||
255 | module_init(gpio_keys_polled_init); | ||
256 | module_exit(gpio_keys_polled_exit); | ||
257 | |||
258 | MODULE_LICENSE("GPL v2"); | ||
259 | MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); | ||
260 | MODULE_DESCRIPTION("Polled GPIO Buttons driver"); | ||
261 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index f7c2a166576b..71f744a8e686 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/leds.h> | 32 | #include <linux/leds.h> |
33 | #include <linux/pm.h> | ||
33 | #include <linux/i2c/lm8323.h> | 34 | #include <linux/i2c/lm8323.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
35 | 36 | ||
@@ -802,12 +803,13 @@ static int __devexit lm8323_remove(struct i2c_client *client) | |||
802 | * We don't need to explicitly suspend the chip, as it already switches off | 803 | * We don't need to explicitly suspend the chip, as it already switches off |
803 | * when there's no activity. | 804 | * when there's no activity. |
804 | */ | 805 | */ |
805 | static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg) | 806 | static int lm8323_suspend(struct device *dev) |
806 | { | 807 | { |
808 | struct i2c_client *client = to_i2c_client(dev); | ||
807 | struct lm8323_chip *lm = i2c_get_clientdata(client); | 809 | struct lm8323_chip *lm = i2c_get_clientdata(client); |
808 | int i; | 810 | int i; |
809 | 811 | ||
810 | set_irq_wake(client->irq, 0); | 812 | irq_set_irq_wake(client->irq, 0); |
811 | disable_irq(client->irq); | 813 | disable_irq(client->irq); |
812 | 814 | ||
813 | mutex_lock(&lm->lock); | 815 | mutex_lock(&lm->lock); |
@@ -821,8 +823,9 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg) | |||
821 | return 0; | 823 | return 0; |
822 | } | 824 | } |
823 | 825 | ||
824 | static int lm8323_resume(struct i2c_client *client) | 826 | static int lm8323_resume(struct device *dev) |
825 | { | 827 | { |
828 | struct i2c_client *client = to_i2c_client(dev); | ||
826 | struct lm8323_chip *lm = i2c_get_clientdata(client); | 829 | struct lm8323_chip *lm = i2c_get_clientdata(client); |
827 | int i; | 830 | int i; |
828 | 831 | ||
@@ -835,15 +838,14 @@ static int lm8323_resume(struct i2c_client *client) | |||
835 | led_classdev_resume(&lm->pwm[i].cdev); | 838 | led_classdev_resume(&lm->pwm[i].cdev); |
836 | 839 | ||
837 | enable_irq(client->irq); | 840 | enable_irq(client->irq); |
838 | set_irq_wake(client->irq, 1); | 841 | irq_set_irq_wake(client->irq, 1); |
839 | 842 | ||
840 | return 0; | 843 | return 0; |
841 | } | 844 | } |
842 | #else | ||
843 | #define lm8323_suspend NULL | ||
844 | #define lm8323_resume NULL | ||
845 | #endif | 845 | #endif |
846 | 846 | ||
847 | static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume); | ||
848 | |||
847 | static const struct i2c_device_id lm8323_id[] = { | 849 | static const struct i2c_device_id lm8323_id[] = { |
848 | { "lm8323", 0 }, | 850 | { "lm8323", 0 }, |
849 | { } | 851 | { } |
@@ -852,11 +854,10 @@ static const struct i2c_device_id lm8323_id[] = { | |||
852 | static struct i2c_driver lm8323_i2c_driver = { | 854 | static struct i2c_driver lm8323_i2c_driver = { |
853 | .driver = { | 855 | .driver = { |
854 | .name = "lm8323", | 856 | .name = "lm8323", |
857 | .pm = &lm8323_pm_ops, | ||
855 | }, | 858 | }, |
856 | .probe = lm8323_probe, | 859 | .probe = lm8323_probe, |
857 | .remove = __devexit_p(lm8323_remove), | 860 | .remove = __devexit_p(lm8323_remove), |
858 | .suspend = lm8323_suspend, | ||
859 | .resume = lm8323_resume, | ||
860 | .id_table = lm8323_id, | 861 | .id_table = lm8323_id, |
861 | }; | 862 | }; |
862 | MODULE_DEVICE_TABLE(i2c, lm8323_id); | 863 | MODULE_DEVICE_TABLE(i2c, lm8323_id); |
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 9091ff5ea808..5afe35ad24d3 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/pm.h> | ||
20 | #include <linux/input.h> | 21 | #include <linux/input.h> |
21 | #include <linux/input/matrix_keypad.h> | 22 | #include <linux/input/matrix_keypad.h> |
22 | 23 | ||
@@ -271,8 +272,10 @@ static int __devexit max7359_remove(struct i2c_client *client) | |||
271 | } | 272 | } |
272 | 273 | ||
273 | #ifdef CONFIG_PM | 274 | #ifdef CONFIG_PM |
274 | static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) | 275 | static int max7359_suspend(struct device *dev) |
275 | { | 276 | { |
277 | struct i2c_client *client = to_i2c_client(dev); | ||
278 | |||
276 | max7359_fall_deepsleep(client); | 279 | max7359_fall_deepsleep(client); |
277 | 280 | ||
278 | if (device_may_wakeup(&client->dev)) | 281 | if (device_may_wakeup(&client->dev)) |
@@ -281,8 +284,10 @@ static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) | |||
281 | return 0; | 284 | return 0; |
282 | } | 285 | } |
283 | 286 | ||
284 | static int max7359_resume(struct i2c_client *client) | 287 | static int max7359_resume(struct device *dev) |
285 | { | 288 | { |
289 | struct i2c_client *client = to_i2c_client(dev); | ||
290 | |||
286 | if (device_may_wakeup(&client->dev)) | 291 | if (device_may_wakeup(&client->dev)) |
287 | disable_irq_wake(client->irq); | 292 | disable_irq_wake(client->irq); |
288 | 293 | ||
@@ -291,11 +296,10 @@ static int max7359_resume(struct i2c_client *client) | |||
291 | 296 | ||
292 | return 0; | 297 | return 0; |
293 | } | 298 | } |
294 | #else | ||
295 | #define max7359_suspend NULL | ||
296 | #define max7359_resume NULL | ||
297 | #endif | 299 | #endif |
298 | 300 | ||
301 | static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume); | ||
302 | |||
299 | static const struct i2c_device_id max7359_ids[] = { | 303 | static const struct i2c_device_id max7359_ids[] = { |
300 | { "max7359", 0 }, | 304 | { "max7359", 0 }, |
301 | { } | 305 | { } |
@@ -305,11 +309,10 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids); | |||
305 | static struct i2c_driver max7359_i2c_driver = { | 309 | static struct i2c_driver max7359_i2c_driver = { |
306 | .driver = { | 310 | .driver = { |
307 | .name = "max7359", | 311 | .name = "max7359", |
312 | .pm = &max7359_pm, | ||
308 | }, | 313 | }, |
309 | .probe = max7359_probe, | 314 | .probe = max7359_probe, |
310 | .remove = __devexit_p(max7359_remove), | 315 | .remove = __devexit_p(max7359_remove), |
311 | .suspend = max7359_suspend, | ||
312 | .resume = max7359_resume, | ||
313 | .id_table = max7359_ids, | 316 | .id_table = max7359_ids, |
314 | }; | 317 | }; |
315 | 318 | ||
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 63b849d7e90b..af1aab324a4c 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller | 2 | * Touchkey driver for MELFAS MCS5000/5080 controller |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | 4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd |
5 | * Author: HeungJun Kim <riverful.kim@samsung.com> | 5 | * Author: HeungJun Kim <riverful.kim@samsung.com> |
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/input.h> | 19 | #include <linux/input.h> |
20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/pm.h> | ||
22 | 23 | ||
23 | /* MCS5000 Touchkey */ | 24 | /* MCS5000 Touchkey */ |
24 | #define MCS5000_TOUCHKEY_STATUS 0x04 | 25 | #define MCS5000_TOUCHKEY_STATUS 0x04 |
@@ -45,6 +46,8 @@ struct mcs_touchkey_chip { | |||
45 | }; | 46 | }; |
46 | 47 | ||
47 | struct mcs_touchkey_data { | 48 | struct mcs_touchkey_data { |
49 | void (*poweron)(bool); | ||
50 | |||
48 | struct i2c_client *client; | 51 | struct i2c_client *client; |
49 | struct input_dev *input_dev; | 52 | struct input_dev *input_dev; |
50 | struct mcs_touchkey_chip chip; | 53 | struct mcs_touchkey_chip chip; |
@@ -169,6 +172,11 @@ static int __devinit mcs_touchkey_probe(struct i2c_client *client, | |||
169 | if (pdata->cfg_pin) | 172 | if (pdata->cfg_pin) |
170 | pdata->cfg_pin(); | 173 | pdata->cfg_pin(); |
171 | 174 | ||
175 | if (pdata->poweron) { | ||
176 | data->poweron = pdata->poweron; | ||
177 | data->poweron(true); | ||
178 | } | ||
179 | |||
172 | error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, | 180 | error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, |
173 | IRQF_TRIGGER_FALLING, client->dev.driver->name, data); | 181 | IRQF_TRIGGER_FALLING, client->dev.driver->name, data); |
174 | if (error) { | 182 | if (error) { |
@@ -196,12 +204,57 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client) | |||
196 | struct mcs_touchkey_data *data = i2c_get_clientdata(client); | 204 | struct mcs_touchkey_data *data = i2c_get_clientdata(client); |
197 | 205 | ||
198 | free_irq(client->irq, data); | 206 | free_irq(client->irq, data); |
207 | if (data->poweron) | ||
208 | data->poweron(false); | ||
199 | input_unregister_device(data->input_dev); | 209 | input_unregister_device(data->input_dev); |
200 | kfree(data); | 210 | kfree(data); |
201 | 211 | ||
202 | return 0; | 212 | return 0; |
203 | } | 213 | } |
204 | 214 | ||
215 | static void mcs_touchkey_shutdown(struct i2c_client *client) | ||
216 | { | ||
217 | struct mcs_touchkey_data *data = i2c_get_clientdata(client); | ||
218 | |||
219 | if (data->poweron) | ||
220 | data->poweron(false); | ||
221 | } | ||
222 | |||
223 | #ifdef CONFIG_PM_SLEEP | ||
224 | static int mcs_touchkey_suspend(struct device *dev) | ||
225 | { | ||
226 | struct mcs_touchkey_data *data = dev_get_drvdata(dev); | ||
227 | struct i2c_client *client = data->client; | ||
228 | |||
229 | /* Disable the work */ | ||
230 | disable_irq(client->irq); | ||
231 | |||
232 | /* Finally turn off the power */ | ||
233 | if (data->poweron) | ||
234 | data->poweron(false); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int mcs_touchkey_resume(struct device *dev) | ||
240 | { | ||
241 | struct mcs_touchkey_data *data = dev_get_drvdata(dev); | ||
242 | struct i2c_client *client = data->client; | ||
243 | |||
244 | /* Enable the device first */ | ||
245 | if (data->poweron) | ||
246 | data->poweron(true); | ||
247 | |||
248 | /* Enable irq again */ | ||
249 | enable_irq(client->irq); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | #endif | ||
254 | |||
255 | static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, | ||
256 | mcs_touchkey_suspend, mcs_touchkey_resume); | ||
257 | |||
205 | static const struct i2c_device_id mcs_touchkey_id[] = { | 258 | static const struct i2c_device_id mcs_touchkey_id[] = { |
206 | { "mcs5000_touchkey", MCS5000_TOUCHKEY }, | 259 | { "mcs5000_touchkey", MCS5000_TOUCHKEY }, |
207 | { "mcs5080_touchkey", MCS5080_TOUCHKEY }, | 260 | { "mcs5080_touchkey", MCS5080_TOUCHKEY }, |
@@ -213,9 +266,11 @@ static struct i2c_driver mcs_touchkey_driver = { | |||
213 | .driver = { | 266 | .driver = { |
214 | .name = "mcs_touchkey", | 267 | .name = "mcs_touchkey", |
215 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
269 | .pm = &mcs_touchkey_pm_ops, | ||
216 | }, | 270 | }, |
217 | .probe = mcs_touchkey_probe, | 271 | .probe = mcs_touchkey_probe, |
218 | .remove = __devexit_p(mcs_touchkey_remove), | 272 | .remove = __devexit_p(mcs_touchkey_remove), |
273 | .shutdown = mcs_touchkey_shutdown, | ||
219 | .id_table = mcs_touchkey_id, | 274 | .id_table = mcs_touchkey_id, |
220 | }; | 275 | }; |
221 | 276 | ||
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index a72e61ddca91..0e2a19cb43d8 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -65,7 +65,6 @@ struct omap_kp { | |||
65 | 65 | ||
66 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); | 66 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); |
67 | 67 | ||
68 | static int *keymap; | ||
69 | static unsigned int *row_gpios; | 68 | static unsigned int *row_gpios; |
70 | static unsigned int *col_gpios; | 69 | static unsigned int *col_gpios; |
71 | 70 | ||
@@ -162,20 +161,11 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state) | |||
162 | } | 161 | } |
163 | } | 162 | } |
164 | 163 | ||
165 | static inline int omap_kp_find_key(int col, int row) | ||
166 | { | ||
167 | int i, key; | ||
168 | |||
169 | key = KEY(col, row, 0); | ||
170 | for (i = 0; keymap[i] != 0; i++) | ||
171 | if ((keymap[i] & 0xff000000) == key) | ||
172 | return keymap[i] & 0x00ffffff; | ||
173 | return -1; | ||
174 | } | ||
175 | |||
176 | static void omap_kp_tasklet(unsigned long data) | 164 | static void omap_kp_tasklet(unsigned long data) |
177 | { | 165 | { |
178 | struct omap_kp *omap_kp_data = (struct omap_kp *) data; | 166 | struct omap_kp *omap_kp_data = (struct omap_kp *) data; |
167 | unsigned short *keycodes = omap_kp_data->input->keycode; | ||
168 | unsigned int row_shift = get_count_order(omap_kp_data->cols); | ||
179 | unsigned char new_state[8], changed, key_down = 0; | 169 | unsigned char new_state[8], changed, key_down = 0; |
180 | int col, row; | 170 | int col, row; |
181 | int spurious = 0; | 171 | int spurious = 0; |
@@ -199,7 +189,7 @@ static void omap_kp_tasklet(unsigned long data) | |||
199 | row, (new_state[col] & (1 << row)) ? | 189 | row, (new_state[col] & (1 << row)) ? |
200 | "pressed" : "released"); | 190 | "pressed" : "released"); |
201 | #else | 191 | #else |
202 | key = omap_kp_find_key(col, row); | 192 | key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)]; |
203 | if (key < 0) { | 193 | if (key < 0) { |
204 | printk(KERN_WARNING | 194 | printk(KERN_WARNING |
205 | "omap-keypad: Spurious key event %d-%d\n", | 195 | "omap-keypad: Spurious key event %d-%d\n", |
@@ -298,13 +288,18 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
298 | struct input_dev *input_dev; | 288 | struct input_dev *input_dev; |
299 | struct omap_kp_platform_data *pdata = pdev->dev.platform_data; | 289 | struct omap_kp_platform_data *pdata = pdev->dev.platform_data; |
300 | int i, col_idx, row_idx, irq_idx, ret; | 290 | int i, col_idx, row_idx, irq_idx, ret; |
291 | unsigned int row_shift, keycodemax; | ||
301 | 292 | ||
302 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | 293 | if (!pdata->rows || !pdata->cols || !pdata->keymap_data) { |
303 | printk(KERN_ERR "No rows, cols or keymap from pdata\n"); | 294 | printk(KERN_ERR "No rows, cols or keymap_data from pdata\n"); |
304 | return -EINVAL; | 295 | return -EINVAL; |
305 | } | 296 | } |
306 | 297 | ||
307 | omap_kp = kzalloc(sizeof(struct omap_kp), GFP_KERNEL); | 298 | row_shift = get_count_order(pdata->cols); |
299 | keycodemax = pdata->rows << row_shift; | ||
300 | |||
301 | omap_kp = kzalloc(sizeof(struct omap_kp) + | ||
302 | keycodemax * sizeof(unsigned short), GFP_KERNEL); | ||
308 | input_dev = input_allocate_device(); | 303 | input_dev = input_allocate_device(); |
309 | if (!omap_kp || !input_dev) { | 304 | if (!omap_kp || !input_dev) { |
310 | kfree(omap_kp); | 305 | kfree(omap_kp); |
@@ -320,7 +315,9 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
320 | if (!cpu_is_omap24xx()) | 315 | if (!cpu_is_omap24xx()) |
321 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 316 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
322 | 317 | ||
323 | keymap = pdata->keymap; | 318 | input_dev->keycode = &omap_kp[1]; |
319 | input_dev->keycodesize = sizeof(unsigned short); | ||
320 | input_dev->keycodemax = keycodemax; | ||
324 | 321 | ||
325 | if (pdata->rep) | 322 | if (pdata->rep) |
326 | __set_bit(EV_REP, input_dev->evbit); | 323 | __set_bit(EV_REP, input_dev->evbit); |
@@ -374,8 +371,8 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
374 | 371 | ||
375 | /* setup input device */ | 372 | /* setup input device */ |
376 | __set_bit(EV_KEY, input_dev->evbit); | 373 | __set_bit(EV_KEY, input_dev->evbit); |
377 | for (i = 0; keymap[i] != 0; i++) | 374 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, |
378 | __set_bit(keymap[i] & KEY_MAX, input_dev->keybit); | 375 | input_dev->keycode, input_dev->keybit); |
379 | input_dev->name = "omap-keypad"; | 376 | input_dev->name = "omap-keypad"; |
380 | input_dev->phys = "omap-keypad/input0"; | 377 | input_dev->phys = "omap-keypad/input0"; |
381 | input_dev->dev.parent = &pdev->dev; | 378 | input_dev->dev.parent = &pdev->dev; |
@@ -416,7 +413,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
416 | return 0; | 413 | return 0; |
417 | err5: | 414 | err5: |
418 | for (i = irq_idx - 1; i >=0; i--) | 415 | for (i = irq_idx - 1; i >=0; i--) |
419 | free_irq(row_gpios[i], 0); | 416 | free_irq(row_gpios[i], NULL); |
420 | err4: | 417 | err4: |
421 | input_unregister_device(omap_kp->input); | 418 | input_unregister_device(omap_kp->input); |
422 | input_dev = NULL; | 419 | input_dev = NULL; |
@@ -447,11 +444,11 @@ static int __devexit omap_kp_remove(struct platform_device *pdev) | |||
447 | gpio_free(col_gpios[i]); | 444 | gpio_free(col_gpios[i]); |
448 | for (i = 0; i < omap_kp->rows; i++) { | 445 | for (i = 0; i < omap_kp->rows; i++) { |
449 | gpio_free(row_gpios[i]); | 446 | gpio_free(row_gpios[i]); |
450 | free_irq(gpio_to_irq(row_gpios[i]), 0); | 447 | free_irq(gpio_to_irq(row_gpios[i]), NULL); |
451 | } | 448 | } |
452 | } else { | 449 | } else { |
453 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 450 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
454 | free_irq(omap_kp->irq, 0); | 451 | free_irq(omap_kp->irq, NULL); |
455 | } | 452 | } |
456 | 453 | ||
457 | del_timer_sync(&omap_kp->timer); | 454 | del_timer_sync(&omap_kp->timer); |
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 45bd0977d006..c51a3c4a7feb 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/input.h> | 30 | #include <linux/input.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/pm_runtime.h> | ||
32 | 33 | ||
33 | #include <plat/omap4-keypad.h> | 34 | #include <plat/omap4-keypad.h> |
34 | 35 | ||
@@ -80,20 +81,6 @@ struct omap4_keypad { | |||
80 | unsigned short keymap[]; | 81 | unsigned short keymap[]; |
81 | }; | 82 | }; |
82 | 83 | ||
83 | static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data) | ||
84 | { | ||
85 | __raw_writel(OMAP4_VAL_FUNCTIONALCFG, | ||
86 | keypad_data->base + OMAP4_KBD_CTRL); | ||
87 | __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, | ||
88 | keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); | ||
89 | __raw_writel(OMAP4_VAL_IRQDISABLE, | ||
90 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | ||
91 | __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, | ||
92 | keypad_data->base + OMAP4_KBD_IRQENABLE); | ||
93 | __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, | ||
94 | keypad_data->base + OMAP4_KBD_WAKEUPENABLE); | ||
95 | } | ||
96 | |||
97 | /* Interrupt handler */ | 84 | /* Interrupt handler */ |
98 | static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) | 85 | static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) |
99 | { | 86 | { |
@@ -144,6 +131,49 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) | |||
144 | return IRQ_HANDLED; | 131 | return IRQ_HANDLED; |
145 | } | 132 | } |
146 | 133 | ||
134 | static int omap4_keypad_open(struct input_dev *input) | ||
135 | { | ||
136 | struct omap4_keypad *keypad_data = input_get_drvdata(input); | ||
137 | |||
138 | pm_runtime_get_sync(input->dev.parent); | ||
139 | |||
140 | disable_irq(keypad_data->irq); | ||
141 | |||
142 | __raw_writel(OMAP4_VAL_FUNCTIONALCFG, | ||
143 | keypad_data->base + OMAP4_KBD_CTRL); | ||
144 | __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, | ||
145 | keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); | ||
146 | __raw_writel(OMAP4_VAL_IRQDISABLE, | ||
147 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | ||
148 | __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, | ||
149 | keypad_data->base + OMAP4_KBD_IRQENABLE); | ||
150 | __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, | ||
151 | keypad_data->base + OMAP4_KBD_WAKEUPENABLE); | ||
152 | |||
153 | enable_irq(keypad_data->irq); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static void omap4_keypad_close(struct input_dev *input) | ||
159 | { | ||
160 | struct omap4_keypad *keypad_data = input_get_drvdata(input); | ||
161 | |||
162 | disable_irq(keypad_data->irq); | ||
163 | |||
164 | /* Disable interrupts */ | ||
165 | __raw_writel(OMAP4_VAL_IRQDISABLE, | ||
166 | keypad_data->base + OMAP4_KBD_IRQENABLE); | ||
167 | |||
168 | /* clear pending interrupts */ | ||
169 | __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), | ||
170 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | ||
171 | |||
172 | enable_irq(keypad_data->irq); | ||
173 | |||
174 | pm_runtime_put_sync(input->dev.parent); | ||
175 | } | ||
176 | |||
147 | static int __devinit omap4_keypad_probe(struct platform_device *pdev) | 177 | static int __devinit omap4_keypad_probe(struct platform_device *pdev) |
148 | { | 178 | { |
149 | const struct omap4_keypad_platform_data *pdata; | 179 | const struct omap4_keypad_platform_data *pdata; |
@@ -225,6 +255,9 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
225 | input_dev->id.product = 0x0001; | 255 | input_dev->id.product = 0x0001; |
226 | input_dev->id.version = 0x0001; | 256 | input_dev->id.version = 0x0001; |
227 | 257 | ||
258 | input_dev->open = omap4_keypad_open; | ||
259 | input_dev->close = omap4_keypad_close; | ||
260 | |||
228 | input_dev->keycode = keypad_data->keymap; | 261 | input_dev->keycode = keypad_data->keymap; |
229 | input_dev->keycodesize = sizeof(keypad_data->keymap[0]); | 262 | input_dev->keycodesize = sizeof(keypad_data->keymap[0]); |
230 | input_dev->keycodemax = max_keys; | 263 | input_dev->keycodemax = max_keys; |
@@ -239,8 +272,6 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
239 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, | 272 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, |
240 | input_dev->keycode, input_dev->keybit); | 273 | input_dev->keycode, input_dev->keybit); |
241 | 274 | ||
242 | omap4_keypad_config(keypad_data); | ||
243 | |||
244 | error = request_irq(keypad_data->irq, omap4_keypad_interrupt, | 275 | error = request_irq(keypad_data->irq, omap4_keypad_interrupt, |
245 | IRQF_TRIGGER_RISING, | 276 | IRQF_TRIGGER_RISING, |
246 | "omap4-keypad", keypad_data); | 277 | "omap4-keypad", keypad_data); |
@@ -249,17 +280,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
249 | goto err_free_input; | 280 | goto err_free_input; |
250 | } | 281 | } |
251 | 282 | ||
283 | pm_runtime_enable(&pdev->dev); | ||
284 | |||
252 | error = input_register_device(keypad_data->input); | 285 | error = input_register_device(keypad_data->input); |
253 | if (error < 0) { | 286 | if (error < 0) { |
254 | dev_err(&pdev->dev, "failed to register input device\n"); | 287 | dev_err(&pdev->dev, "failed to register input device\n"); |
255 | goto err_free_irq; | 288 | goto err_pm_disable; |
256 | } | 289 | } |
257 | 290 | ||
258 | |||
259 | platform_set_drvdata(pdev, keypad_data); | 291 | platform_set_drvdata(pdev, keypad_data); |
260 | return 0; | 292 | return 0; |
261 | 293 | ||
262 | err_free_irq: | 294 | err_pm_disable: |
295 | pm_runtime_disable(&pdev->dev); | ||
263 | free_irq(keypad_data->irq, keypad_data); | 296 | free_irq(keypad_data->irq, keypad_data); |
264 | err_free_input: | 297 | err_free_input: |
265 | input_free_device(input_dev); | 298 | input_free_device(input_dev); |
@@ -278,6 +311,9 @@ static int __devexit omap4_keypad_remove(struct platform_device *pdev) | |||
278 | struct resource *res; | 311 | struct resource *res; |
279 | 312 | ||
280 | free_irq(keypad_data->irq, keypad_data); | 313 | free_irq(keypad_data->irq, keypad_data); |
314 | |||
315 | pm_runtime_disable(&pdev->dev); | ||
316 | |||
281 | input_unregister_device(keypad_data->input); | 317 | input_unregister_device(keypad_data->input); |
282 | 318 | ||
283 | iounmap(keypad_data->base); | 319 | iounmap(keypad_data->base); |
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c new file mode 100644 index 000000000000..fba8404c7297 --- /dev/null +++ b/drivers/input/keyboard/qt1070.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * Atmel AT42QT1070 QTouch Sensor Controller | ||
3 | * | ||
4 | * Copyright (C) 2011 Atmel | ||
5 | * | ||
6 | * Authors: Bo Shen <voice.shen@atmel.com> | ||
7 | * | ||
8 | * Base on AT42QT2160 driver by: | ||
9 | * Raphael Derosso Pereira <raphaelpereira@gmail.com> | ||
10 | * Copyright (C) 2009 | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program 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 | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/irq.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/jiffies.h> | ||
35 | #include <linux/delay.h> | ||
36 | |||
37 | /* Address for each register */ | ||
38 | #define CHIP_ID 0x00 | ||
39 | #define QT1070_CHIP_ID 0x2E | ||
40 | |||
41 | #define FW_VERSION 0x01 | ||
42 | #define QT1070_FW_VERSION 0x15 | ||
43 | |||
44 | #define DET_STATUS 0x02 | ||
45 | |||
46 | #define KEY_STATUS 0x03 | ||
47 | |||
48 | /* Calibrate */ | ||
49 | #define CALIBRATE_CMD 0x38 | ||
50 | #define QT1070_CAL_TIME 200 | ||
51 | |||
52 | /* Reset */ | ||
53 | #define RESET 0x39 | ||
54 | #define QT1070_RESET_TIME 255 | ||
55 | |||
56 | /* AT42QT1070 support up to 7 keys */ | ||
57 | static const unsigned short qt1070_key2code[] = { | ||
58 | KEY_0, KEY_1, KEY_2, KEY_3, | ||
59 | KEY_4, KEY_5, KEY_6, | ||
60 | }; | ||
61 | |||
62 | struct qt1070_data { | ||
63 | struct i2c_client *client; | ||
64 | struct input_dev *input; | ||
65 | unsigned int irq; | ||
66 | unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)]; | ||
67 | u8 last_keys; | ||
68 | }; | ||
69 | |||
70 | static int qt1070_read(struct i2c_client *client, u8 reg) | ||
71 | { | ||
72 | int ret; | ||
73 | |||
74 | ret = i2c_smbus_read_byte_data(client, reg); | ||
75 | if (ret < 0) | ||
76 | dev_err(&client->dev, | ||
77 | "can not read register, returned %d\n", ret); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static int qt1070_write(struct i2c_client *client, u8 reg, u8 data) | ||
83 | { | ||
84 | int ret; | ||
85 | |||
86 | ret = i2c_smbus_write_byte_data(client, reg, data); | ||
87 | if (ret < 0) | ||
88 | dev_err(&client->dev, | ||
89 | "can not write register, returned %d\n", ret); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static bool __devinit qt1070_identify(struct i2c_client *client) | ||
95 | { | ||
96 | int id, ver; | ||
97 | |||
98 | /* Read Chip ID */ | ||
99 | id = qt1070_read(client, CHIP_ID); | ||
100 | if (id != QT1070_CHIP_ID) { | ||
101 | dev_err(&client->dev, "ID %d not supported\n", id); | ||
102 | return false; | ||
103 | } | ||
104 | |||
105 | /* Read firmware version */ | ||
106 | ver = qt1070_read(client, FW_VERSION); | ||
107 | if (ver < 0) { | ||
108 | dev_err(&client->dev, "could not read the firmware version\n"); | ||
109 | return false; | ||
110 | } | ||
111 | |||
112 | dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver); | ||
113 | |||
114 | return true; | ||
115 | } | ||
116 | |||
117 | static irqreturn_t qt1070_interrupt(int irq, void *dev_id) | ||
118 | { | ||
119 | struct qt1070_data *data = dev_id; | ||
120 | struct i2c_client *client = data->client; | ||
121 | struct input_dev *input = data->input; | ||
122 | int i; | ||
123 | u8 new_keys, keyval, mask = 0x01; | ||
124 | |||
125 | /* Read the detected status register, thus clearing interrupt */ | ||
126 | qt1070_read(client, DET_STATUS); | ||
127 | |||
128 | /* Read which key changed */ | ||
129 | new_keys = qt1070_read(client, KEY_STATUS); | ||
130 | |||
131 | for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { | ||
132 | keyval = new_keys & mask; | ||
133 | if ((data->last_keys & mask) != keyval) | ||
134 | input_report_key(input, data->keycodes[i], keyval); | ||
135 | mask <<= 1; | ||
136 | } | ||
137 | input_sync(input); | ||
138 | |||
139 | data->last_keys = new_keys; | ||
140 | return IRQ_HANDLED; | ||
141 | } | ||
142 | |||
143 | static int __devinit qt1070_probe(struct i2c_client *client, | ||
144 | const struct i2c_device_id *id) | ||
145 | { | ||
146 | struct qt1070_data *data; | ||
147 | struct input_dev *input; | ||
148 | int i; | ||
149 | int err; | ||
150 | |||
151 | err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE); | ||
152 | if (!err) { | ||
153 | dev_err(&client->dev, "%s adapter not supported\n", | ||
154 | dev_driver_string(&client->adapter->dev)); | ||
155 | return -ENODEV; | ||
156 | } | ||
157 | |||
158 | if (!client->irq) { | ||
159 | dev_err(&client->dev, "please assign the irq to this device\n"); | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | |||
163 | /* Identify the qt1070 chip */ | ||
164 | if (!qt1070_identify(client)) | ||
165 | return -ENODEV; | ||
166 | |||
167 | data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL); | ||
168 | input = input_allocate_device(); | ||
169 | if (!data || !input) { | ||
170 | dev_err(&client->dev, "insufficient memory\n"); | ||
171 | err = -ENOMEM; | ||
172 | goto err_free_mem; | ||
173 | } | ||
174 | |||
175 | data->client = client; | ||
176 | data->input = input; | ||
177 | data->irq = client->irq; | ||
178 | |||
179 | input->name = "AT42QT1070 QTouch Sensor"; | ||
180 | input->dev.parent = &client->dev; | ||
181 | input->id.bustype = BUS_I2C; | ||
182 | |||
183 | /* Add the keycode */ | ||
184 | input->keycode = data->keycodes; | ||
185 | input->keycodesize = sizeof(data->keycodes[0]); | ||
186 | input->keycodemax = ARRAY_SIZE(qt1070_key2code); | ||
187 | |||
188 | __set_bit(EV_KEY, input->evbit); | ||
189 | |||
190 | for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { | ||
191 | data->keycodes[i] = qt1070_key2code[i]; | ||
192 | __set_bit(qt1070_key2code[i], input->keybit); | ||
193 | } | ||
194 | |||
195 | /* Calibrate device */ | ||
196 | qt1070_write(client, CALIBRATE_CMD, 1); | ||
197 | msleep(QT1070_CAL_TIME); | ||
198 | |||
199 | /* Soft reset */ | ||
200 | qt1070_write(client, RESET, 1); | ||
201 | msleep(QT1070_RESET_TIME); | ||
202 | |||
203 | err = request_threaded_irq(client->irq, NULL, qt1070_interrupt, | ||
204 | IRQF_TRIGGER_NONE, client->dev.driver->name, data); | ||
205 | if (err) { | ||
206 | dev_err(&client->dev, "fail to request irq\n"); | ||
207 | goto err_free_mem; | ||
208 | } | ||
209 | |||
210 | /* Register the input device */ | ||
211 | err = input_register_device(data->input); | ||
212 | if (err) { | ||
213 | dev_err(&client->dev, "Failed to register input device\n"); | ||
214 | goto err_free_irq; | ||
215 | } | ||
216 | |||
217 | i2c_set_clientdata(client, data); | ||
218 | |||
219 | /* Read to clear the chang line */ | ||
220 | qt1070_read(client, DET_STATUS); | ||
221 | |||
222 | return 0; | ||
223 | |||
224 | err_free_irq: | ||
225 | free_irq(client->irq, data); | ||
226 | err_free_mem: | ||
227 | input_free_device(input); | ||
228 | kfree(data); | ||
229 | return err; | ||
230 | } | ||
231 | |||
232 | static int __devexit qt1070_remove(struct i2c_client *client) | ||
233 | { | ||
234 | struct qt1070_data *data = i2c_get_clientdata(client); | ||
235 | |||
236 | /* Release IRQ */ | ||
237 | free_irq(client->irq, data); | ||
238 | |||
239 | input_unregister_device(data->input); | ||
240 | kfree(data); | ||
241 | |||
242 | i2c_set_clientdata(client, NULL); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static const struct i2c_device_id qt1070_id[] = { | ||
248 | { "qt1070", 0 }, | ||
249 | { }, | ||
250 | }; | ||
251 | |||
252 | static struct i2c_driver qt1070_driver = { | ||
253 | .driver = { | ||
254 | .name = "qt1070", | ||
255 | .owner = THIS_MODULE, | ||
256 | }, | ||
257 | .id_table = qt1070_id, | ||
258 | .probe = qt1070_probe, | ||
259 | .remove = __devexit_p(qt1070_remove), | ||
260 | }; | ||
261 | |||
262 | static int __init qt1070_init(void) | ||
263 | { | ||
264 | return i2c_add_driver(&qt1070_driver); | ||
265 | } | ||
266 | module_init(qt1070_init); | ||
267 | |||
268 | static void __exit qt1070_exit(void) | ||
269 | { | ||
270 | i2c_del_driver(&qt1070_driver); | ||
271 | } | ||
272 | module_exit(qt1070_exit); | ||
273 | |||
274 | MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>"); | ||
275 | MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor"); | ||
276 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c new file mode 100644 index 000000000000..d712dffd2157 --- /dev/null +++ b/drivers/input/keyboard/spear-keyboard.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * SPEAr Keyboard Driver | ||
3 | * Based on omap-keypad driver | ||
4 | * | ||
5 | * Copyright (C) 2010 ST Microelectronics | ||
6 | * Rajeev Kumar<rajeev-dlh.kumar@st.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/pm_wakeup.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <plat/keyboard.h> | ||
27 | |||
28 | /* Keyboard Registers */ | ||
29 | #define MODE_REG 0x00 /* 16 bit reg */ | ||
30 | #define STATUS_REG 0x0C /* 2 bit reg */ | ||
31 | #define DATA_REG 0x10 /* 8 bit reg */ | ||
32 | #define INTR_MASK 0x54 | ||
33 | |||
34 | /* Register Values */ | ||
35 | /* | ||
36 | * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode | ||
37 | * control register as 1010010(82MHZ) | ||
38 | */ | ||
39 | #define PCLK_FREQ_MSK 0xA400 /* 82 MHz */ | ||
40 | #define START_SCAN 0x0100 | ||
41 | #define SCAN_RATE_10 0x0000 | ||
42 | #define SCAN_RATE_20 0x0004 | ||
43 | #define SCAN_RATE_40 0x0008 | ||
44 | #define SCAN_RATE_80 0x000C | ||
45 | #define MODE_KEYBOARD 0x0002 | ||
46 | #define DATA_AVAIL 0x2 | ||
47 | |||
48 | #define KEY_MASK 0xFF000000 | ||
49 | #define KEY_VALUE 0x00FFFFFF | ||
50 | #define ROW_MASK 0xF0 | ||
51 | #define COLUMN_MASK 0x0F | ||
52 | #define ROW_SHIFT 4 | ||
53 | |||
54 | struct spear_kbd { | ||
55 | struct input_dev *input; | ||
56 | struct resource *res; | ||
57 | void __iomem *io_base; | ||
58 | struct clk *clk; | ||
59 | unsigned int irq; | ||
60 | unsigned short last_key; | ||
61 | unsigned short keycodes[256]; | ||
62 | }; | ||
63 | |||
64 | static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) | ||
65 | { | ||
66 | struct spear_kbd *kbd = dev_id; | ||
67 | struct input_dev *input = kbd->input; | ||
68 | unsigned int key; | ||
69 | u8 sts, val; | ||
70 | |||
71 | sts = readb(kbd->io_base + STATUS_REG); | ||
72 | if (!(sts & DATA_AVAIL)) | ||
73 | return IRQ_NONE; | ||
74 | |||
75 | if (kbd->last_key != KEY_RESERVED) { | ||
76 | input_report_key(input, kbd->last_key, 0); | ||
77 | kbd->last_key = KEY_RESERVED; | ||
78 | } | ||
79 | |||
80 | /* following reads active (row, col) pair */ | ||
81 | val = readb(kbd->io_base + DATA_REG); | ||
82 | key = kbd->keycodes[val]; | ||
83 | |||
84 | input_event(input, EV_MSC, MSC_SCAN, val); | ||
85 | input_report_key(input, key, 1); | ||
86 | input_sync(input); | ||
87 | |||
88 | kbd->last_key = key; | ||
89 | |||
90 | /* clear interrupt */ | ||
91 | writeb(0, kbd->io_base + STATUS_REG); | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | } | ||
95 | |||
96 | static int spear_kbd_open(struct input_dev *dev) | ||
97 | { | ||
98 | struct spear_kbd *kbd = input_get_drvdata(dev); | ||
99 | int error; | ||
100 | u16 val; | ||
101 | |||
102 | kbd->last_key = KEY_RESERVED; | ||
103 | |||
104 | error = clk_enable(kbd->clk); | ||
105 | if (error) | ||
106 | return error; | ||
107 | |||
108 | /* program keyboard */ | ||
109 | val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK; | ||
110 | writew(val, kbd->io_base + MODE_REG); | ||
111 | writeb(1, kbd->io_base + STATUS_REG); | ||
112 | |||
113 | /* start key scan */ | ||
114 | val = readw(kbd->io_base + MODE_REG); | ||
115 | val |= START_SCAN; | ||
116 | writew(val, kbd->io_base + MODE_REG); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static void spear_kbd_close(struct input_dev *dev) | ||
122 | { | ||
123 | struct spear_kbd *kbd = input_get_drvdata(dev); | ||
124 | u16 val; | ||
125 | |||
126 | /* stop key scan */ | ||
127 | val = readw(kbd->io_base + MODE_REG); | ||
128 | val &= ~START_SCAN; | ||
129 | writew(val, kbd->io_base + MODE_REG); | ||
130 | |||
131 | clk_disable(kbd->clk); | ||
132 | |||
133 | kbd->last_key = KEY_RESERVED; | ||
134 | } | ||
135 | |||
136 | static int __devinit spear_kbd_probe(struct platform_device *pdev) | ||
137 | { | ||
138 | const struct kbd_platform_data *pdata = pdev->dev.platform_data; | ||
139 | const struct matrix_keymap_data *keymap; | ||
140 | struct spear_kbd *kbd; | ||
141 | struct input_dev *input_dev; | ||
142 | struct resource *res; | ||
143 | int irq; | ||
144 | int error; | ||
145 | |||
146 | if (!pdata) { | ||
147 | dev_err(&pdev->dev, "Invalid platform data\n"); | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | |||
151 | keymap = pdata->keymap; | ||
152 | if (!keymap) { | ||
153 | dev_err(&pdev->dev, "no keymap defined\n"); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
158 | if (!res) { | ||
159 | dev_err(&pdev->dev, "no keyboard resource defined\n"); | ||
160 | return -EBUSY; | ||
161 | } | ||
162 | |||
163 | irq = platform_get_irq(pdev, 0); | ||
164 | if (irq < 0) { | ||
165 | dev_err(&pdev->dev, "not able to get irq for the device\n"); | ||
166 | return irq; | ||
167 | } | ||
168 | |||
169 | kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); | ||
170 | input_dev = input_allocate_device(); | ||
171 | if (!kbd || !input_dev) { | ||
172 | dev_err(&pdev->dev, "out of memory\n"); | ||
173 | error = -ENOMEM; | ||
174 | goto err_free_mem; | ||
175 | } | ||
176 | |||
177 | kbd->input = input_dev; | ||
178 | kbd->irq = irq; | ||
179 | kbd->res = request_mem_region(res->start, resource_size(res), | ||
180 | pdev->name); | ||
181 | if (!kbd->res) { | ||
182 | dev_err(&pdev->dev, "keyboard region already claimed\n"); | ||
183 | error = -EBUSY; | ||
184 | goto err_free_mem; | ||
185 | } | ||
186 | |||
187 | kbd->io_base = ioremap(res->start, resource_size(res)); | ||
188 | if (!kbd->io_base) { | ||
189 | dev_err(&pdev->dev, "ioremap failed for kbd_region\n"); | ||
190 | error = -ENOMEM; | ||
191 | goto err_release_mem_region; | ||
192 | } | ||
193 | |||
194 | kbd->clk = clk_get(&pdev->dev, NULL); | ||
195 | if (IS_ERR(kbd->clk)) { | ||
196 | error = PTR_ERR(kbd->clk); | ||
197 | goto err_iounmap; | ||
198 | } | ||
199 | |||
200 | input_dev->name = "Spear Keyboard"; | ||
201 | input_dev->phys = "keyboard/input0"; | ||
202 | input_dev->dev.parent = &pdev->dev; | ||
203 | input_dev->id.bustype = BUS_HOST; | ||
204 | input_dev->id.vendor = 0x0001; | ||
205 | input_dev->id.product = 0x0001; | ||
206 | input_dev->id.version = 0x0100; | ||
207 | input_dev->open = spear_kbd_open; | ||
208 | input_dev->close = spear_kbd_close; | ||
209 | |||
210 | __set_bit(EV_KEY, input_dev->evbit); | ||
211 | if (pdata->rep) | ||
212 | __set_bit(EV_REP, input_dev->evbit); | ||
213 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
214 | |||
215 | input_dev->keycode = kbd->keycodes; | ||
216 | input_dev->keycodesize = sizeof(kbd->keycodes[0]); | ||
217 | input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes); | ||
218 | |||
219 | matrix_keypad_build_keymap(keymap, ROW_SHIFT, | ||
220 | input_dev->keycode, input_dev->keybit); | ||
221 | |||
222 | input_set_drvdata(input_dev, kbd); | ||
223 | |||
224 | error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); | ||
225 | if (error) { | ||
226 | dev_err(&pdev->dev, "request_irq fail\n"); | ||
227 | goto err_put_clk; | ||
228 | } | ||
229 | |||
230 | error = input_register_device(input_dev); | ||
231 | if (error) { | ||
232 | dev_err(&pdev->dev, "Unable to register keyboard device\n"); | ||
233 | goto err_free_irq; | ||
234 | } | ||
235 | |||
236 | device_init_wakeup(&pdev->dev, 1); | ||
237 | platform_set_drvdata(pdev, kbd); | ||
238 | |||
239 | return 0; | ||
240 | |||
241 | err_free_irq: | ||
242 | free_irq(kbd->irq, kbd); | ||
243 | err_put_clk: | ||
244 | clk_put(kbd->clk); | ||
245 | err_iounmap: | ||
246 | iounmap(kbd->io_base); | ||
247 | err_release_mem_region: | ||
248 | release_mem_region(res->start, resource_size(res)); | ||
249 | err_free_mem: | ||
250 | input_free_device(input_dev); | ||
251 | kfree(kbd); | ||
252 | |||
253 | return error; | ||
254 | } | ||
255 | |||
256 | static int __devexit spear_kbd_remove(struct platform_device *pdev) | ||
257 | { | ||
258 | struct spear_kbd *kbd = platform_get_drvdata(pdev); | ||
259 | |||
260 | free_irq(kbd->irq, kbd); | ||
261 | input_unregister_device(kbd->input); | ||
262 | clk_put(kbd->clk); | ||
263 | iounmap(kbd->io_base); | ||
264 | release_mem_region(kbd->res->start, resource_size(kbd->res)); | ||
265 | kfree(kbd); | ||
266 | |||
267 | device_init_wakeup(&pdev->dev, 1); | ||
268 | platform_set_drvdata(pdev, NULL); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | #ifdef CONFIG_PM | ||
274 | static int spear_kbd_suspend(struct device *dev) | ||
275 | { | ||
276 | struct platform_device *pdev = to_platform_device(dev); | ||
277 | struct spear_kbd *kbd = platform_get_drvdata(pdev); | ||
278 | struct input_dev *input_dev = kbd->input; | ||
279 | |||
280 | mutex_lock(&input_dev->mutex); | ||
281 | |||
282 | if (input_dev->users) | ||
283 | clk_enable(kbd->clk); | ||
284 | |||
285 | if (device_may_wakeup(&pdev->dev)) | ||
286 | enable_irq_wake(kbd->irq); | ||
287 | |||
288 | mutex_unlock(&input_dev->mutex); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int spear_kbd_resume(struct device *dev) | ||
294 | { | ||
295 | struct platform_device *pdev = to_platform_device(dev); | ||
296 | struct spear_kbd *kbd = platform_get_drvdata(pdev); | ||
297 | struct input_dev *input_dev = kbd->input; | ||
298 | |||
299 | mutex_lock(&input_dev->mutex); | ||
300 | |||
301 | if (device_may_wakeup(&pdev->dev)) | ||
302 | disable_irq_wake(kbd->irq); | ||
303 | |||
304 | if (input_dev->users) | ||
305 | clk_enable(kbd->clk); | ||
306 | |||
307 | mutex_unlock(&input_dev->mutex); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static const struct dev_pm_ops spear_kbd_pm_ops = { | ||
313 | .suspend = spear_kbd_suspend, | ||
314 | .resume = spear_kbd_resume, | ||
315 | }; | ||
316 | #endif | ||
317 | |||
318 | static struct platform_driver spear_kbd_driver = { | ||
319 | .probe = spear_kbd_probe, | ||
320 | .remove = __devexit_p(spear_kbd_remove), | ||
321 | .driver = { | ||
322 | .name = "keyboard", | ||
323 | .owner = THIS_MODULE, | ||
324 | #ifdef CONFIG_PM | ||
325 | .pm = &spear_kbd_pm_ops, | ||
326 | #endif | ||
327 | }, | ||
328 | }; | ||
329 | |||
330 | static int __init spear_kbd_init(void) | ||
331 | { | ||
332 | return platform_driver_register(&spear_kbd_driver); | ||
333 | } | ||
334 | module_init(spear_kbd_init); | ||
335 | |||
336 | static void __exit spear_kbd_exit(void) | ||
337 | { | ||
338 | platform_driver_unregister(&spear_kbd_driver); | ||
339 | } | ||
340 | module_exit(spear_kbd_exit); | ||
341 | |||
342 | MODULE_AUTHOR("Rajeev Kumar"); | ||
343 | MODULE_DESCRIPTION("SPEAr Keyboard Driver"); | ||
344 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c new file mode 100644 index 000000000000..99122f59e988 --- /dev/null +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com> | ||
5 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
6 | * | ||
7 | * License Terms: GNU General Public License, version 2 | ||
8 | * | ||
9 | * TC35893 MFD Keypad Controller driver | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/input/matrix_keypad.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mfd/tc3589x.h> | ||
21 | |||
22 | /* Maximum supported keypad matrix row/columns size */ | ||
23 | #define TC3589x_MAX_KPROW 8 | ||
24 | #define TC3589x_MAX_KPCOL 12 | ||
25 | |||
26 | /* keypad related Constants */ | ||
27 | #define TC3589x_MAX_DEBOUNCE_SETTLE 0xFF | ||
28 | #define DEDICATED_KEY_VAL 0xFF | ||
29 | |||
30 | /* Pull up/down masks */ | ||
31 | #define TC3589x_NO_PULL_MASK 0x0 | ||
32 | #define TC3589x_PULL_DOWN_MASK 0x1 | ||
33 | #define TC3589x_PULL_UP_MASK 0x2 | ||
34 | #define TC3589x_PULLUP_ALL_MASK 0xAA | ||
35 | #define TC3589x_IO_PULL_VAL(index, mask) ((mask)<<((index)%4)*2)) | ||
36 | |||
37 | /* Bit masks for IOCFG register */ | ||
38 | #define IOCFG_BALLCFG 0x01 | ||
39 | #define IOCFG_IG 0x08 | ||
40 | |||
41 | #define KP_EVCODE_COL_MASK 0x0F | ||
42 | #define KP_EVCODE_ROW_MASK 0x70 | ||
43 | #define KP_RELEASE_EVT_MASK 0x80 | ||
44 | |||
45 | #define KP_ROW_SHIFT 4 | ||
46 | |||
47 | #define KP_NO_VALID_KEY_MASK 0x7F | ||
48 | |||
49 | /* bit masks for RESTCTRL register */ | ||
50 | #define TC3589x_KBDRST 0x2 | ||
51 | #define TC3589x_IRQRST 0x10 | ||
52 | #define TC3589x_RESET_ALL 0x1B | ||
53 | |||
54 | /* KBDMFS register bit mask */ | ||
55 | #define TC3589x_KBDMFS_EN 0x1 | ||
56 | |||
57 | /* CLKEN register bitmask */ | ||
58 | #define KPD_CLK_EN 0x1 | ||
59 | |||
60 | /* RSTINTCLR register bit mask */ | ||
61 | #define IRQ_CLEAR 0x1 | ||
62 | |||
63 | /* bit masks for keyboard interrupts*/ | ||
64 | #define TC3589x_EVT_LOSS_INT 0x8 | ||
65 | #define TC3589x_EVT_INT 0x4 | ||
66 | #define TC3589x_KBD_LOSS_INT 0x2 | ||
67 | #define TC3589x_KBD_INT 0x1 | ||
68 | |||
69 | /* bit masks for keyboard interrupt clear*/ | ||
70 | #define TC3589x_EVT_INT_CLR 0x2 | ||
71 | #define TC3589x_KBD_INT_CLR 0x1 | ||
72 | |||
73 | #define TC3589x_KBD_KEYMAP_SIZE 64 | ||
74 | |||
75 | /** | ||
76 | * struct tc_keypad - data structure used by keypad driver | ||
77 | * @input: pointer to input device object | ||
78 | * @board: keypad platform device | ||
79 | * @krow: number of rows | ||
80 | * @kcol: number of coloumns | ||
81 | * @keymap: matrix scan code table for keycodes | ||
82 | */ | ||
83 | struct tc_keypad { | ||
84 | struct tc3589x *tc3589x; | ||
85 | struct input_dev *input; | ||
86 | const struct tc3589x_keypad_platform_data *board; | ||
87 | unsigned int krow; | ||
88 | unsigned int kcol; | ||
89 | unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; | ||
90 | bool keypad_stopped; | ||
91 | }; | ||
92 | |||
93 | static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) | ||
94 | { | ||
95 | int ret; | ||
96 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
97 | u8 settle_time = keypad->board->settle_time; | ||
98 | u8 dbounce_period = keypad->board->debounce_period; | ||
99 | u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */ | ||
100 | u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */ | ||
101 | |||
102 | /* validate platform configurations */ | ||
103 | if (keypad->board->kcol > TC3589x_MAX_KPCOL || | ||
104 | keypad->board->krow > TC3589x_MAX_KPROW || | ||
105 | keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE || | ||
106 | keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE) | ||
107 | return -EINVAL; | ||
108 | |||
109 | /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ | ||
110 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, | ||
111 | (rows << KP_ROW_SHIFT) | column); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | /* configure dedicated key config, no dedicated key selected */ | ||
116 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL); | ||
121 | if (ret < 0) | ||
122 | return ret; | ||
123 | |||
124 | /* Configure settle time */ | ||
125 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time); | ||
126 | if (ret < 0) | ||
127 | return ret; | ||
128 | |||
129 | /* Configure debounce time */ | ||
130 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | /* Start of initialise keypad GPIOs */ | ||
135 | ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* Configure pull-up resistors for all row GPIOs */ | ||
140 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB, | ||
141 | TC3589x_PULLUP_ALL_MASK); | ||
142 | if (ret < 0) | ||
143 | return ret; | ||
144 | |||
145 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB, | ||
146 | TC3589x_PULLUP_ALL_MASK); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | /* Configure pull-up resistors for all column GPIOs */ | ||
151 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB, | ||
152 | TC3589x_PULLUP_ALL_MASK); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB, | ||
157 | TC3589x_PULLUP_ALL_MASK); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB, | ||
162 | TC3589x_PULLUP_ALL_MASK); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | #define TC35893_DATA_REGS 4 | ||
168 | #define TC35893_KEYCODE_FIFO_EMPTY 0x7f | ||
169 | #define TC35893_KEYCODE_FIFO_CLEAR 0xff | ||
170 | #define TC35893_KEYPAD_ROW_SHIFT 0x3 | ||
171 | |||
172 | static irqreturn_t tc3589x_keypad_irq(int irq, void *dev) | ||
173 | { | ||
174 | struct tc_keypad *keypad = dev; | ||
175 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
176 | u8 i, row_index, col_index, kbd_code, up; | ||
177 | u8 code; | ||
178 | |||
179 | for (i = 0; i < TC35893_DATA_REGS * 2; i++) { | ||
180 | kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO); | ||
181 | |||
182 | /* loop till fifo is empty and no more keys are pressed */ | ||
183 | if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY || | ||
184 | kbd_code == TC35893_KEYCODE_FIFO_CLEAR) | ||
185 | continue; | ||
186 | |||
187 | /* valid key is found */ | ||
188 | col_index = kbd_code & KP_EVCODE_COL_MASK; | ||
189 | row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT; | ||
190 | code = MATRIX_SCAN_CODE(row_index, col_index, | ||
191 | TC35893_KEYPAD_ROW_SHIFT); | ||
192 | up = kbd_code & KP_RELEASE_EVT_MASK; | ||
193 | |||
194 | input_event(keypad->input, EV_MSC, MSC_SCAN, code); | ||
195 | input_report_key(keypad->input, keypad->keymap[code], !up); | ||
196 | input_sync(keypad->input); | ||
197 | } | ||
198 | |||
199 | /* clear IRQ */ | ||
200 | tc3589x_set_bits(tc3589x, TC3589x_KBDIC, | ||
201 | 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); | ||
202 | /* enable IRQ */ | ||
203 | tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, | ||
204 | 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); | ||
205 | |||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | static int tc3589x_keypad_enable(struct tc_keypad *keypad) | ||
210 | { | ||
211 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
212 | int ret; | ||
213 | |||
214 | /* pull the keypad module out of reset */ | ||
215 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0); | ||
216 | if (ret < 0) | ||
217 | return ret; | ||
218 | |||
219 | /* configure KBDMFS */ | ||
220 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | |||
224 | /* enable the keypad clock */ | ||
225 | ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
229 | /* clear pending IRQs */ | ||
230 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
233 | |||
234 | /* enable the IRQs */ | ||
235 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0, | ||
236 | TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); | ||
237 | if (ret < 0) | ||
238 | return ret; | ||
239 | |||
240 | keypad->keypad_stopped = false; | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static int tc3589x_keypad_disable(struct tc_keypad *keypad) | ||
246 | { | ||
247 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
248 | int ret; | ||
249 | |||
250 | /* clear IRQ */ | ||
251 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC, | ||
252 | 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); | ||
253 | if (ret < 0) | ||
254 | return ret; | ||
255 | |||
256 | /* disable all interrupts */ | ||
257 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, | ||
258 | ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | |||
262 | /* disable the keypad module */ | ||
263 | ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | /* put the keypad module into reset */ | ||
268 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1); | ||
269 | |||
270 | keypad->keypad_stopped = true; | ||
271 | |||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static int tc3589x_keypad_open(struct input_dev *input) | ||
276 | { | ||
277 | int error; | ||
278 | struct tc_keypad *keypad = input_get_drvdata(input); | ||
279 | |||
280 | /* enable the keypad module */ | ||
281 | error = tc3589x_keypad_enable(keypad); | ||
282 | if (error < 0) { | ||
283 | dev_err(&input->dev, "failed to enable keypad module\n"); | ||
284 | return error; | ||
285 | } | ||
286 | |||
287 | error = tc3589x_keypad_init_key_hardware(keypad); | ||
288 | if (error < 0) { | ||
289 | dev_err(&input->dev, "failed to configure keypad module\n"); | ||
290 | return error; | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static void tc3589x_keypad_close(struct input_dev *input) | ||
297 | { | ||
298 | struct tc_keypad *keypad = input_get_drvdata(input); | ||
299 | |||
300 | /* disable the keypad module */ | ||
301 | tc3589x_keypad_disable(keypad); | ||
302 | } | ||
303 | |||
304 | static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) | ||
305 | { | ||
306 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); | ||
307 | struct tc_keypad *keypad; | ||
308 | struct input_dev *input; | ||
309 | const struct tc3589x_keypad_platform_data *plat; | ||
310 | int error, irq; | ||
311 | |||
312 | plat = tc3589x->pdata->keypad; | ||
313 | if (!plat) { | ||
314 | dev_err(&pdev->dev, "invalid keypad platform data\n"); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | irq = platform_get_irq(pdev, 0); | ||
319 | if (irq < 0) | ||
320 | return irq; | ||
321 | |||
322 | keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL); | ||
323 | input = input_allocate_device(); | ||
324 | if (!keypad || !input) { | ||
325 | dev_err(&pdev->dev, "failed to allocate keypad memory\n"); | ||
326 | error = -ENOMEM; | ||
327 | goto err_free_mem; | ||
328 | } | ||
329 | |||
330 | keypad->board = plat; | ||
331 | keypad->input = input; | ||
332 | keypad->tc3589x = tc3589x; | ||
333 | |||
334 | input->id.bustype = BUS_I2C; | ||
335 | input->name = pdev->name; | ||
336 | input->dev.parent = &pdev->dev; | ||
337 | |||
338 | input->keycode = keypad->keymap; | ||
339 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
340 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
341 | |||
342 | input->open = tc3589x_keypad_open; | ||
343 | input->close = tc3589x_keypad_close; | ||
344 | |||
345 | input_set_drvdata(input, keypad); | ||
346 | |||
347 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
348 | |||
349 | __set_bit(EV_KEY, input->evbit); | ||
350 | if (!plat->no_autorepeat) | ||
351 | __set_bit(EV_REP, input->evbit); | ||
352 | |||
353 | matrix_keypad_build_keymap(plat->keymap_data, 0x3, | ||
354 | input->keycode, input->keybit); | ||
355 | |||
356 | error = request_threaded_irq(irq, NULL, | ||
357 | tc3589x_keypad_irq, plat->irqtype, | ||
358 | "tc3589x-keypad", keypad); | ||
359 | if (error < 0) { | ||
360 | dev_err(&pdev->dev, | ||
361 | "Could not allocate irq %d,error %d\n", | ||
362 | irq, error); | ||
363 | goto err_free_mem; | ||
364 | } | ||
365 | |||
366 | error = input_register_device(input); | ||
367 | if (error) { | ||
368 | dev_err(&pdev->dev, "Could not register input device\n"); | ||
369 | goto err_free_irq; | ||
370 | } | ||
371 | |||
372 | /* let platform decide if keypad is a wakeup source or not */ | ||
373 | device_init_wakeup(&pdev->dev, plat->enable_wakeup); | ||
374 | device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup); | ||
375 | |||
376 | platform_set_drvdata(pdev, keypad); | ||
377 | |||
378 | return 0; | ||
379 | |||
380 | err_free_irq: | ||
381 | free_irq(irq, keypad); | ||
382 | err_free_mem: | ||
383 | input_free_device(input); | ||
384 | kfree(keypad); | ||
385 | return error; | ||
386 | } | ||
387 | |||
388 | static int __devexit tc3589x_keypad_remove(struct platform_device *pdev) | ||
389 | { | ||
390 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
391 | int irq = platform_get_irq(pdev, 0); | ||
392 | |||
393 | if (!keypad->keypad_stopped) | ||
394 | tc3589x_keypad_disable(keypad); | ||
395 | |||
396 | free_irq(irq, keypad); | ||
397 | |||
398 | input_unregister_device(keypad->input); | ||
399 | |||
400 | kfree(keypad); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | #ifdef CONFIG_PM_SLEEP | ||
406 | static int tc3589x_keypad_suspend(struct device *dev) | ||
407 | { | ||
408 | struct platform_device *pdev = to_platform_device(dev); | ||
409 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
410 | int irq = platform_get_irq(pdev, 0); | ||
411 | |||
412 | /* keypad is already off; we do nothing */ | ||
413 | if (keypad->keypad_stopped) | ||
414 | return 0; | ||
415 | |||
416 | /* if device is not a wakeup source, disable it for powersave */ | ||
417 | if (!device_may_wakeup(&pdev->dev)) | ||
418 | tc3589x_keypad_disable(keypad); | ||
419 | else | ||
420 | enable_irq_wake(irq); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int tc3589x_keypad_resume(struct device *dev) | ||
426 | { | ||
427 | struct platform_device *pdev = to_platform_device(dev); | ||
428 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
429 | int irq = platform_get_irq(pdev, 0); | ||
430 | |||
431 | if (!keypad->keypad_stopped) | ||
432 | return 0; | ||
433 | |||
434 | /* enable the device to resume normal operations */ | ||
435 | if (!device_may_wakeup(&pdev->dev)) | ||
436 | tc3589x_keypad_enable(keypad); | ||
437 | else | ||
438 | disable_irq_wake(irq); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | #endif | ||
443 | |||
444 | static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, | ||
445 | tc3589x_keypad_suspend, tc3589x_keypad_resume); | ||
446 | |||
447 | static struct platform_driver tc3589x_keypad_driver = { | ||
448 | .driver = { | ||
449 | .name = "tc3589x-keypad", | ||
450 | .owner = THIS_MODULE, | ||
451 | .pm = &tc3589x_keypad_dev_pm_ops, | ||
452 | }, | ||
453 | .probe = tc3589x_keypad_probe, | ||
454 | .remove = __devexit_p(tc3589x_keypad_remove), | ||
455 | }; | ||
456 | |||
457 | static int __init tc3589x_keypad_init(void) | ||
458 | { | ||
459 | return platform_driver_register(&tc3589x_keypad_driver); | ||
460 | } | ||
461 | module_init(tc3589x_keypad_init); | ||
462 | |||
463 | static void __exit tc3589x_keypad_exit(void) | ||
464 | { | ||
465 | return platform_driver_unregister(&tc3589x_keypad_driver); | ||
466 | } | ||
467 | module_exit(tc3589x_keypad_exit); | ||
468 | |||
469 | MODULE_LICENSE("GPL v2"); | ||
470 | MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer"); | ||
471 | MODULE_DESCRIPTION("TC35893 Keypad Driver"); | ||
472 | MODULE_ALIAS("platform:tc3589x-keypad"); | ||
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 00137bebcf97..3afea3f89718 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | static const struct i2c_device_id tca6416_id[] = { | 30 | static const struct i2c_device_id tca6416_id[] = { |
31 | { "tca6416-keys", 16, }, | 31 | { "tca6416-keys", 16, }, |
32 | { "tca6408-keys", 8, }, | ||
32 | { } | 33 | { } |
33 | }; | 34 | }; |
34 | MODULE_DEVICE_TABLE(i2c, tca6416_id); | 35 | MODULE_DEVICE_TABLE(i2c, tca6416_id); |
@@ -46,8 +47,9 @@ struct tca6416_keypad_chip { | |||
46 | struct i2c_client *client; | 47 | struct i2c_client *client; |
47 | struct input_dev *input; | 48 | struct input_dev *input; |
48 | struct delayed_work dwork; | 49 | struct delayed_work dwork; |
49 | u16 pinmask; | 50 | int io_size; |
50 | int irqnum; | 51 | int irqnum; |
52 | u16 pinmask; | ||
51 | bool use_polling; | 53 | bool use_polling; |
52 | struct tca6416_button buttons[0]; | 54 | struct tca6416_button buttons[0]; |
53 | }; | 55 | }; |
@@ -56,7 +58,9 @@ static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val) | |||
56 | { | 58 | { |
57 | int error; | 59 | int error; |
58 | 60 | ||
59 | error = i2c_smbus_write_word_data(chip->client, reg << 1, val); | 61 | error = chip->io_size > 8 ? |
62 | i2c_smbus_write_word_data(chip->client, reg << 1, val) : | ||
63 | i2c_smbus_write_byte_data(chip->client, reg, val); | ||
60 | if (error < 0) { | 64 | if (error < 0) { |
61 | dev_err(&chip->client->dev, | 65 | dev_err(&chip->client->dev, |
62 | "%s failed, reg: %d, val: %d, error: %d\n", | 66 | "%s failed, reg: %d, val: %d, error: %d\n", |
@@ -71,7 +75,9 @@ static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val) | |||
71 | { | 75 | { |
72 | int retval; | 76 | int retval; |
73 | 77 | ||
74 | retval = i2c_smbus_read_word_data(chip->client, reg << 1); | 78 | retval = chip->io_size > 8 ? |
79 | i2c_smbus_read_word_data(chip->client, reg << 1) : | ||
80 | i2c_smbus_read_byte_data(chip->client, reg); | ||
75 | if (retval < 0) { | 81 | if (retval < 0) { |
76 | dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n", | 82 | dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n", |
77 | __func__, reg, retval); | 83 | __func__, reg, retval); |
@@ -224,6 +230,7 @@ static int __devinit tca6416_keypad_probe(struct i2c_client *client, | |||
224 | 230 | ||
225 | chip->client = client; | 231 | chip->client = client; |
226 | chip->input = input; | 232 | chip->input = input; |
233 | chip->io_size = id->driver_data; | ||
227 | chip->pinmask = pdata->pinmask; | 234 | chip->pinmask = pdata->pinmask; |
228 | chip->use_polling = pdata->use_polling; | 235 | chip->use_polling = pdata->use_polling; |
229 | 236 | ||
@@ -290,6 +297,7 @@ static int __devinit tca6416_keypad_probe(struct i2c_client *client, | |||
290 | } | 297 | } |
291 | 298 | ||
292 | i2c_set_clientdata(client, chip); | 299 | i2c_set_clientdata(client, chip); |
300 | device_init_wakeup(&client->dev, 1); | ||
293 | 301 | ||
294 | return 0; | 302 | return 0; |
295 | 303 | ||
@@ -319,10 +327,37 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client) | |||
319 | return 0; | 327 | return 0; |
320 | } | 328 | } |
321 | 329 | ||
330 | #ifdef CONFIG_PM_SLEEP | ||
331 | static int tca6416_keypad_suspend(struct device *dev) | ||
332 | { | ||
333 | struct i2c_client *client = to_i2c_client(dev); | ||
334 | struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); | ||
335 | |||
336 | if (device_may_wakeup(dev)) | ||
337 | enable_irq_wake(chip->irqnum); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int tca6416_keypad_resume(struct device *dev) | ||
343 | { | ||
344 | struct i2c_client *client = to_i2c_client(dev); | ||
345 | struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); | ||
346 | |||
347 | if (device_may_wakeup(dev)) | ||
348 | disable_irq_wake(chip->irqnum); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | #endif | ||
353 | |||
354 | static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops, | ||
355 | tca6416_keypad_suspend, tca6416_keypad_resume); | ||
322 | 356 | ||
323 | static struct i2c_driver tca6416_keypad_driver = { | 357 | static struct i2c_driver tca6416_keypad_driver = { |
324 | .driver = { | 358 | .driver = { |
325 | .name = "tca6416-keypad", | 359 | .name = "tca6416-keypad", |
360 | .pm = &tca6416_keypad_dev_pm_ops, | ||
326 | }, | 361 | }, |
327 | .probe = tca6416_keypad_probe, | 362 | .probe = tca6416_keypad_probe, |
328 | .remove = __devexit_p(tca6416_keypad_remove), | 363 | .remove = __devexit_p(tca6416_keypad_remove), |
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c new file mode 100644 index 000000000000..99ce9032d08c --- /dev/null +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -0,0 +1,783 @@ | |||
1 | /* | ||
2 | * Keyboard class input driver for the NVIDIA Tegra SoC internal matrix | ||
3 | * keyboard controller | ||
4 | * | ||
5 | * Copyright (c) 2009-2011, NVIDIA Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/clk.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <mach/clk.h> | ||
31 | #include <mach/kbc.h> | ||
32 | |||
33 | #define KBC_MAX_DEBOUNCE_CNT 0x3ffu | ||
34 | |||
35 | /* KBC row scan time and delay for beginning the row scan. */ | ||
36 | #define KBC_ROW_SCAN_TIME 16 | ||
37 | #define KBC_ROW_SCAN_DLY 5 | ||
38 | |||
39 | /* KBC uses a 32KHz clock so a cycle = 1/32Khz */ | ||
40 | #define KBC_CYCLE_USEC 32 | ||
41 | |||
42 | /* KBC Registers */ | ||
43 | |||
44 | /* KBC Control Register */ | ||
45 | #define KBC_CONTROL_0 0x0 | ||
46 | #define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14) | ||
47 | #define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4) | ||
48 | #define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3) | ||
49 | #define KBC_CONTROL_KBC_EN (1 << 0) | ||
50 | |||
51 | /* KBC Interrupt Register */ | ||
52 | #define KBC_INT_0 0x4 | ||
53 | #define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) | ||
54 | |||
55 | #define KBC_ROW_CFG0_0 0x8 | ||
56 | #define KBC_COL_CFG0_0 0x18 | ||
57 | #define KBC_INIT_DLY_0 0x28 | ||
58 | #define KBC_RPT_DLY_0 0x2c | ||
59 | #define KBC_KP_ENT0_0 0x30 | ||
60 | #define KBC_KP_ENT1_0 0x34 | ||
61 | #define KBC_ROW0_MASK_0 0x38 | ||
62 | |||
63 | #define KBC_ROW_SHIFT 3 | ||
64 | |||
65 | struct tegra_kbc { | ||
66 | void __iomem *mmio; | ||
67 | struct input_dev *idev; | ||
68 | unsigned int irq; | ||
69 | unsigned int wake_enable_rows; | ||
70 | unsigned int wake_enable_cols; | ||
71 | spinlock_t lock; | ||
72 | unsigned int repoll_dly; | ||
73 | unsigned long cp_dly_jiffies; | ||
74 | bool use_fn_map; | ||
75 | const struct tegra_kbc_platform_data *pdata; | ||
76 | unsigned short keycode[KBC_MAX_KEY * 2]; | ||
77 | unsigned short current_keys[KBC_MAX_KPENT]; | ||
78 | unsigned int num_pressed_keys; | ||
79 | struct timer_list timer; | ||
80 | struct clk *clk; | ||
81 | }; | ||
82 | |||
83 | static const u32 tegra_kbc_default_keymap[] = { | ||
84 | KEY(0, 2, KEY_W), | ||
85 | KEY(0, 3, KEY_S), | ||
86 | KEY(0, 4, KEY_A), | ||
87 | KEY(0, 5, KEY_Z), | ||
88 | KEY(0, 7, KEY_FN), | ||
89 | |||
90 | KEY(1, 7, KEY_LEFTMETA), | ||
91 | |||
92 | KEY(2, 6, KEY_RIGHTALT), | ||
93 | KEY(2, 7, KEY_LEFTALT), | ||
94 | |||
95 | KEY(3, 0, KEY_5), | ||
96 | KEY(3, 1, KEY_4), | ||
97 | KEY(3, 2, KEY_R), | ||
98 | KEY(3, 3, KEY_E), | ||
99 | KEY(3, 4, KEY_F), | ||
100 | KEY(3, 5, KEY_D), | ||
101 | KEY(3, 6, KEY_X), | ||
102 | |||
103 | KEY(4, 0, KEY_7), | ||
104 | KEY(4, 1, KEY_6), | ||
105 | KEY(4, 2, KEY_T), | ||
106 | KEY(4, 3, KEY_H), | ||
107 | KEY(4, 4, KEY_G), | ||
108 | KEY(4, 5, KEY_V), | ||
109 | KEY(4, 6, KEY_C), | ||
110 | KEY(4, 7, KEY_SPACE), | ||
111 | |||
112 | KEY(5, 0, KEY_9), | ||
113 | KEY(5, 1, KEY_8), | ||
114 | KEY(5, 2, KEY_U), | ||
115 | KEY(5, 3, KEY_Y), | ||
116 | KEY(5, 4, KEY_J), | ||
117 | KEY(5, 5, KEY_N), | ||
118 | KEY(5, 6, KEY_B), | ||
119 | KEY(5, 7, KEY_BACKSLASH), | ||
120 | |||
121 | KEY(6, 0, KEY_MINUS), | ||
122 | KEY(6, 1, KEY_0), | ||
123 | KEY(6, 2, KEY_O), | ||
124 | KEY(6, 3, KEY_I), | ||
125 | KEY(6, 4, KEY_L), | ||
126 | KEY(6, 5, KEY_K), | ||
127 | KEY(6, 6, KEY_COMMA), | ||
128 | KEY(6, 7, KEY_M), | ||
129 | |||
130 | KEY(7, 1, KEY_EQUAL), | ||
131 | KEY(7, 2, KEY_RIGHTBRACE), | ||
132 | KEY(7, 3, KEY_ENTER), | ||
133 | KEY(7, 7, KEY_MENU), | ||
134 | |||
135 | KEY(8, 4, KEY_RIGHTSHIFT), | ||
136 | KEY(8, 5, KEY_LEFTSHIFT), | ||
137 | |||
138 | KEY(9, 5, KEY_RIGHTCTRL), | ||
139 | KEY(9, 7, KEY_LEFTCTRL), | ||
140 | |||
141 | KEY(11, 0, KEY_LEFTBRACE), | ||
142 | KEY(11, 1, KEY_P), | ||
143 | KEY(11, 2, KEY_APOSTROPHE), | ||
144 | KEY(11, 3, KEY_SEMICOLON), | ||
145 | KEY(11, 4, KEY_SLASH), | ||
146 | KEY(11, 5, KEY_DOT), | ||
147 | |||
148 | KEY(12, 0, KEY_F10), | ||
149 | KEY(12, 1, KEY_F9), | ||
150 | KEY(12, 2, KEY_BACKSPACE), | ||
151 | KEY(12, 3, KEY_3), | ||
152 | KEY(12, 4, KEY_2), | ||
153 | KEY(12, 5, KEY_UP), | ||
154 | KEY(12, 6, KEY_PRINT), | ||
155 | KEY(12, 7, KEY_PAUSE), | ||
156 | |||
157 | KEY(13, 0, KEY_INSERT), | ||
158 | KEY(13, 1, KEY_DELETE), | ||
159 | KEY(13, 3, KEY_PAGEUP), | ||
160 | KEY(13, 4, KEY_PAGEDOWN), | ||
161 | KEY(13, 5, KEY_RIGHT), | ||
162 | KEY(13, 6, KEY_DOWN), | ||
163 | KEY(13, 7, KEY_LEFT), | ||
164 | |||
165 | KEY(14, 0, KEY_F11), | ||
166 | KEY(14, 1, KEY_F12), | ||
167 | KEY(14, 2, KEY_F8), | ||
168 | KEY(14, 3, KEY_Q), | ||
169 | KEY(14, 4, KEY_F4), | ||
170 | KEY(14, 5, KEY_F3), | ||
171 | KEY(14, 6, KEY_1), | ||
172 | KEY(14, 7, KEY_F7), | ||
173 | |||
174 | KEY(15, 0, KEY_ESC), | ||
175 | KEY(15, 1, KEY_GRAVE), | ||
176 | KEY(15, 2, KEY_F5), | ||
177 | KEY(15, 3, KEY_TAB), | ||
178 | KEY(15, 4, KEY_F1), | ||
179 | KEY(15, 5, KEY_F2), | ||
180 | KEY(15, 6, KEY_CAPSLOCK), | ||
181 | KEY(15, 7, KEY_F6), | ||
182 | |||
183 | /* Software Handled Function Keys */ | ||
184 | KEY(20, 0, KEY_KP7), | ||
185 | |||
186 | KEY(21, 0, KEY_KP9), | ||
187 | KEY(21, 1, KEY_KP8), | ||
188 | KEY(21, 2, KEY_KP4), | ||
189 | KEY(21, 4, KEY_KP1), | ||
190 | |||
191 | KEY(22, 1, KEY_KPSLASH), | ||
192 | KEY(22, 2, KEY_KP6), | ||
193 | KEY(22, 3, KEY_KP5), | ||
194 | KEY(22, 4, KEY_KP3), | ||
195 | KEY(22, 5, KEY_KP2), | ||
196 | KEY(22, 7, KEY_KP0), | ||
197 | |||
198 | KEY(27, 1, KEY_KPASTERISK), | ||
199 | KEY(27, 3, KEY_KPMINUS), | ||
200 | KEY(27, 4, KEY_KPPLUS), | ||
201 | KEY(27, 5, KEY_KPDOT), | ||
202 | |||
203 | KEY(28, 5, KEY_VOLUMEUP), | ||
204 | |||
205 | KEY(29, 3, KEY_HOME), | ||
206 | KEY(29, 4, KEY_END), | ||
207 | KEY(29, 5, KEY_BRIGHTNESSDOWN), | ||
208 | KEY(29, 6, KEY_VOLUMEDOWN), | ||
209 | KEY(29, 7, KEY_BRIGHTNESSUP), | ||
210 | |||
211 | KEY(30, 0, KEY_NUMLOCK), | ||
212 | KEY(30, 1, KEY_SCROLLLOCK), | ||
213 | KEY(30, 2, KEY_MUTE), | ||
214 | |||
215 | KEY(31, 4, KEY_HELP), | ||
216 | }; | ||
217 | |||
218 | static const struct matrix_keymap_data tegra_kbc_default_keymap_data = { | ||
219 | .keymap = tegra_kbc_default_keymap, | ||
220 | .keymap_size = ARRAY_SIZE(tegra_kbc_default_keymap), | ||
221 | }; | ||
222 | |||
223 | static void tegra_kbc_report_released_keys(struct input_dev *input, | ||
224 | unsigned short old_keycodes[], | ||
225 | unsigned int old_num_keys, | ||
226 | unsigned short new_keycodes[], | ||
227 | unsigned int new_num_keys) | ||
228 | { | ||
229 | unsigned int i, j; | ||
230 | |||
231 | for (i = 0; i < old_num_keys; i++) { | ||
232 | for (j = 0; j < new_num_keys; j++) | ||
233 | if (old_keycodes[i] == new_keycodes[j]) | ||
234 | break; | ||
235 | |||
236 | if (j == new_num_keys) | ||
237 | input_report_key(input, old_keycodes[i], 0); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | static void tegra_kbc_report_pressed_keys(struct input_dev *input, | ||
242 | unsigned char scancodes[], | ||
243 | unsigned short keycodes[], | ||
244 | unsigned int num_pressed_keys) | ||
245 | { | ||
246 | unsigned int i; | ||
247 | |||
248 | for (i = 0; i < num_pressed_keys; i++) { | ||
249 | input_event(input, EV_MSC, MSC_SCAN, scancodes[i]); | ||
250 | input_report_key(input, keycodes[i], 1); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | ||
255 | { | ||
256 | unsigned char scancodes[KBC_MAX_KPENT]; | ||
257 | unsigned short keycodes[KBC_MAX_KPENT]; | ||
258 | u32 val = 0; | ||
259 | unsigned int i; | ||
260 | unsigned int num_down = 0; | ||
261 | unsigned long flags; | ||
262 | bool fn_keypress = false; | ||
263 | |||
264 | spin_lock_irqsave(&kbc->lock, flags); | ||
265 | for (i = 0; i < KBC_MAX_KPENT; i++) { | ||
266 | if ((i % 4) == 0) | ||
267 | val = readl(kbc->mmio + KBC_KP_ENT0_0 + i); | ||
268 | |||
269 | if (val & 0x80) { | ||
270 | unsigned int col = val & 0x07; | ||
271 | unsigned int row = (val >> 3) & 0x0f; | ||
272 | unsigned char scancode = | ||
273 | MATRIX_SCAN_CODE(row, col, KBC_ROW_SHIFT); | ||
274 | |||
275 | scancodes[num_down] = scancode; | ||
276 | keycodes[num_down] = kbc->keycode[scancode]; | ||
277 | /* If driver uses Fn map, do not report the Fn key. */ | ||
278 | if ((keycodes[num_down] == KEY_FN) && kbc->use_fn_map) | ||
279 | fn_keypress = true; | ||
280 | else | ||
281 | num_down++; | ||
282 | } | ||
283 | |||
284 | val >>= 8; | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * If the platform uses Fn keymaps, translate keys on a Fn keypress. | ||
289 | * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. | ||
290 | */ | ||
291 | if (fn_keypress) { | ||
292 | for (i = 0; i < num_down; i++) { | ||
293 | scancodes[i] += KBC_MAX_KEY; | ||
294 | keycodes[i] = kbc->keycode[scancodes[i]]; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
299 | |||
300 | tegra_kbc_report_released_keys(kbc->idev, | ||
301 | kbc->current_keys, kbc->num_pressed_keys, | ||
302 | keycodes, num_down); | ||
303 | tegra_kbc_report_pressed_keys(kbc->idev, scancodes, keycodes, num_down); | ||
304 | input_sync(kbc->idev); | ||
305 | |||
306 | memcpy(kbc->current_keys, keycodes, sizeof(kbc->current_keys)); | ||
307 | kbc->num_pressed_keys = num_down; | ||
308 | } | ||
309 | |||
310 | static void tegra_kbc_keypress_timer(unsigned long data) | ||
311 | { | ||
312 | struct tegra_kbc *kbc = (struct tegra_kbc *)data; | ||
313 | unsigned long flags; | ||
314 | u32 val; | ||
315 | unsigned int i; | ||
316 | |||
317 | val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf; | ||
318 | if (val) { | ||
319 | unsigned long dly; | ||
320 | |||
321 | tegra_kbc_report_keys(kbc); | ||
322 | |||
323 | /* | ||
324 | * If more than one keys are pressed we need not wait | ||
325 | * for the repoll delay. | ||
326 | */ | ||
327 | dly = (val == 1) ? kbc->repoll_dly : 1; | ||
328 | mod_timer(&kbc->timer, jiffies + msecs_to_jiffies(dly)); | ||
329 | } else { | ||
330 | /* Release any pressed keys and exit the polling loop */ | ||
331 | for (i = 0; i < kbc->num_pressed_keys; i++) | ||
332 | input_report_key(kbc->idev, kbc->current_keys[i], 0); | ||
333 | input_sync(kbc->idev); | ||
334 | |||
335 | kbc->num_pressed_keys = 0; | ||
336 | |||
337 | /* All keys are released so enable the keypress interrupt */ | ||
338 | spin_lock_irqsave(&kbc->lock, flags); | ||
339 | val = readl(kbc->mmio + KBC_CONTROL_0); | ||
340 | val |= KBC_CONTROL_FIFO_CNT_INT_EN; | ||
341 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
342 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | static irqreturn_t tegra_kbc_isr(int irq, void *args) | ||
347 | { | ||
348 | struct tegra_kbc *kbc = args; | ||
349 | u32 val, ctl; | ||
350 | |||
351 | /* | ||
352 | * Until all keys are released, defer further processing to | ||
353 | * the polling loop in tegra_kbc_keypress_timer | ||
354 | */ | ||
355 | ctl = readl(kbc->mmio + KBC_CONTROL_0); | ||
356 | ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN; | ||
357 | writel(ctl, kbc->mmio + KBC_CONTROL_0); | ||
358 | |||
359 | /* | ||
360 | * Quickly bail out & reenable interrupts if the fifo threshold | ||
361 | * count interrupt wasn't the interrupt source | ||
362 | */ | ||
363 | val = readl(kbc->mmio + KBC_INT_0); | ||
364 | writel(val, kbc->mmio + KBC_INT_0); | ||
365 | |||
366 | if (val & KBC_INT_FIFO_CNT_INT_STATUS) { | ||
367 | /* | ||
368 | * Schedule timer to run when hardware is in continuous | ||
369 | * polling mode. | ||
370 | */ | ||
371 | mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); | ||
372 | } else { | ||
373 | ctl |= KBC_CONTROL_FIFO_CNT_INT_EN; | ||
374 | writel(ctl, kbc->mmio + KBC_CONTROL_0); | ||
375 | } | ||
376 | |||
377 | return IRQ_HANDLED; | ||
378 | } | ||
379 | |||
380 | static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) | ||
381 | { | ||
382 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | ||
383 | int i; | ||
384 | unsigned int rst_val; | ||
385 | |||
386 | BUG_ON(pdata->wake_cnt > KBC_MAX_KEY); | ||
387 | rst_val = (filter && pdata->wake_cnt) ? ~0 : 0; | ||
388 | |||
389 | for (i = 0; i < KBC_MAX_ROW; i++) | ||
390 | writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); | ||
391 | |||
392 | if (filter) { | ||
393 | for (i = 0; i < pdata->wake_cnt; i++) { | ||
394 | u32 val, addr; | ||
395 | addr = pdata->wake_cfg[i].row * 4 + KBC_ROW0_MASK_0; | ||
396 | val = readl(kbc->mmio + addr); | ||
397 | val &= ~(1 << pdata->wake_cfg[i].col); | ||
398 | writel(val, kbc->mmio + addr); | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static void tegra_kbc_config_pins(struct tegra_kbc *kbc) | ||
404 | { | ||
405 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | ||
406 | int i; | ||
407 | |||
408 | for (i = 0; i < KBC_MAX_GPIO; i++) { | ||
409 | u32 r_shft = 5 * (i % 6); | ||
410 | u32 c_shft = 4 * (i % 8); | ||
411 | u32 r_mask = 0x1f << r_shft; | ||
412 | u32 c_mask = 0x0f << c_shft; | ||
413 | u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; | ||
414 | u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; | ||
415 | u32 row_cfg = readl(kbc->mmio + r_offs); | ||
416 | u32 col_cfg = readl(kbc->mmio + c_offs); | ||
417 | |||
418 | row_cfg &= ~r_mask; | ||
419 | col_cfg &= ~c_mask; | ||
420 | |||
421 | if (pdata->pin_cfg[i].is_row) | ||
422 | row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; | ||
423 | else | ||
424 | col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; | ||
425 | |||
426 | writel(row_cfg, kbc->mmio + r_offs); | ||
427 | writel(col_cfg, kbc->mmio + c_offs); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | static int tegra_kbc_start(struct tegra_kbc *kbc) | ||
432 | { | ||
433 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | ||
434 | unsigned long flags; | ||
435 | unsigned int debounce_cnt; | ||
436 | u32 val = 0; | ||
437 | |||
438 | clk_enable(kbc->clk); | ||
439 | |||
440 | /* Reset the KBC controller to clear all previous status.*/ | ||
441 | tegra_periph_reset_assert(kbc->clk); | ||
442 | udelay(100); | ||
443 | tegra_periph_reset_deassert(kbc->clk); | ||
444 | udelay(100); | ||
445 | |||
446 | tegra_kbc_config_pins(kbc); | ||
447 | tegra_kbc_setup_wakekeys(kbc, false); | ||
448 | |||
449 | writel(pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); | ||
450 | |||
451 | /* Keyboard debounce count is maximum of 12 bits. */ | ||
452 | debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); | ||
453 | val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt); | ||
454 | val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */ | ||
455 | val |= KBC_CONTROL_FIFO_CNT_INT_EN; /* interrupt on FIFO threshold */ | ||
456 | val |= KBC_CONTROL_KBC_EN; /* enable */ | ||
457 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
458 | |||
459 | /* | ||
460 | * Compute the delay(ns) from interrupt mode to continuous polling | ||
461 | * mode so the timer routine is scheduled appropriately. | ||
462 | */ | ||
463 | val = readl(kbc->mmio + KBC_INIT_DLY_0); | ||
464 | kbc->cp_dly_jiffies = usecs_to_jiffies((val & 0xfffff) * 32); | ||
465 | |||
466 | kbc->num_pressed_keys = 0; | ||
467 | |||
468 | /* | ||
469 | * Atomically clear out any remaining entries in the key FIFO | ||
470 | * and enable keyboard interrupts. | ||
471 | */ | ||
472 | spin_lock_irqsave(&kbc->lock, flags); | ||
473 | while (1) { | ||
474 | val = readl(kbc->mmio + KBC_INT_0); | ||
475 | val >>= 4; | ||
476 | if (!val) | ||
477 | break; | ||
478 | |||
479 | val = readl(kbc->mmio + KBC_KP_ENT0_0); | ||
480 | val = readl(kbc->mmio + KBC_KP_ENT1_0); | ||
481 | } | ||
482 | writel(0x7, kbc->mmio + KBC_INT_0); | ||
483 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
484 | |||
485 | enable_irq(kbc->irq); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static void tegra_kbc_stop(struct tegra_kbc *kbc) | ||
491 | { | ||
492 | unsigned long flags; | ||
493 | u32 val; | ||
494 | |||
495 | spin_lock_irqsave(&kbc->lock, flags); | ||
496 | val = readl(kbc->mmio + KBC_CONTROL_0); | ||
497 | val &= ~1; | ||
498 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
499 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
500 | |||
501 | disable_irq(kbc->irq); | ||
502 | del_timer_sync(&kbc->timer); | ||
503 | |||
504 | clk_disable(kbc->clk); | ||
505 | } | ||
506 | |||
507 | static int tegra_kbc_open(struct input_dev *dev) | ||
508 | { | ||
509 | struct tegra_kbc *kbc = input_get_drvdata(dev); | ||
510 | |||
511 | return tegra_kbc_start(kbc); | ||
512 | } | ||
513 | |||
514 | static void tegra_kbc_close(struct input_dev *dev) | ||
515 | { | ||
516 | struct tegra_kbc *kbc = input_get_drvdata(dev); | ||
517 | |||
518 | return tegra_kbc_stop(kbc); | ||
519 | } | ||
520 | |||
521 | static bool __devinit | ||
522 | tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, | ||
523 | struct device *dev, unsigned int *num_rows) | ||
524 | { | ||
525 | int i; | ||
526 | |||
527 | *num_rows = 0; | ||
528 | |||
529 | for (i = 0; i < KBC_MAX_GPIO; i++) { | ||
530 | const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; | ||
531 | |||
532 | if (pin_cfg->is_row) { | ||
533 | if (pin_cfg->num >= KBC_MAX_ROW) { | ||
534 | dev_err(dev, | ||
535 | "pin_cfg[%d]: invalid row number %d\n", | ||
536 | i, pin_cfg->num); | ||
537 | return false; | ||
538 | } | ||
539 | (*num_rows)++; | ||
540 | } else { | ||
541 | if (pin_cfg->num >= KBC_MAX_COL) { | ||
542 | dev_err(dev, | ||
543 | "pin_cfg[%d]: invalid column number %d\n", | ||
544 | i, pin_cfg->num); | ||
545 | return false; | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | |||
550 | return true; | ||
551 | } | ||
552 | |||
553 | static int __devinit tegra_kbc_probe(struct platform_device *pdev) | ||
554 | { | ||
555 | const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; | ||
556 | const struct matrix_keymap_data *keymap_data; | ||
557 | struct tegra_kbc *kbc; | ||
558 | struct input_dev *input_dev; | ||
559 | struct resource *res; | ||
560 | int irq; | ||
561 | int err; | ||
562 | int i; | ||
563 | int num_rows = 0; | ||
564 | unsigned int debounce_cnt; | ||
565 | unsigned int scan_time_rows; | ||
566 | |||
567 | if (!pdata) | ||
568 | return -EINVAL; | ||
569 | |||
570 | if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) | ||
571 | return -EINVAL; | ||
572 | |||
573 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
574 | if (!res) { | ||
575 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
576 | return -ENXIO; | ||
577 | } | ||
578 | |||
579 | irq = platform_get_irq(pdev, 0); | ||
580 | if (irq < 0) { | ||
581 | dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); | ||
582 | return -ENXIO; | ||
583 | } | ||
584 | |||
585 | kbc = kzalloc(sizeof(*kbc), GFP_KERNEL); | ||
586 | input_dev = input_allocate_device(); | ||
587 | if (!kbc || !input_dev) { | ||
588 | err = -ENOMEM; | ||
589 | goto err_free_mem; | ||
590 | } | ||
591 | |||
592 | kbc->pdata = pdata; | ||
593 | kbc->idev = input_dev; | ||
594 | kbc->irq = irq; | ||
595 | spin_lock_init(&kbc->lock); | ||
596 | setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); | ||
597 | |||
598 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
599 | if (!res) { | ||
600 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
601 | err = -EBUSY; | ||
602 | goto err_free_mem; | ||
603 | } | ||
604 | |||
605 | kbc->mmio = ioremap(res->start, resource_size(res)); | ||
606 | if (!kbc->mmio) { | ||
607 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
608 | err = -ENXIO; | ||
609 | goto err_free_mem_region; | ||
610 | } | ||
611 | |||
612 | kbc->clk = clk_get(&pdev->dev, NULL); | ||
613 | if (IS_ERR(kbc->clk)) { | ||
614 | dev_err(&pdev->dev, "failed to get keyboard clock\n"); | ||
615 | err = PTR_ERR(kbc->clk); | ||
616 | goto err_iounmap; | ||
617 | } | ||
618 | |||
619 | kbc->wake_enable_rows = 0; | ||
620 | kbc->wake_enable_cols = 0; | ||
621 | for (i = 0; i < pdata->wake_cnt; i++) { | ||
622 | kbc->wake_enable_rows |= (1 << pdata->wake_cfg[i].row); | ||
623 | kbc->wake_enable_cols |= (1 << pdata->wake_cfg[i].col); | ||
624 | } | ||
625 | |||
626 | /* | ||
627 | * The time delay between two consecutive reads of the FIFO is | ||
628 | * the sum of the repeat time and the time taken for scanning | ||
629 | * the rows. There is an additional delay before the row scanning | ||
630 | * starts. The repoll delay is computed in milliseconds. | ||
631 | */ | ||
632 | debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); | ||
633 | scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows; | ||
634 | kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; | ||
635 | kbc->repoll_dly = ((kbc->repoll_dly * KBC_CYCLE_USEC) + 999) / 1000; | ||
636 | |||
637 | input_dev->name = pdev->name; | ||
638 | input_dev->id.bustype = BUS_HOST; | ||
639 | input_dev->dev.parent = &pdev->dev; | ||
640 | input_dev->open = tegra_kbc_open; | ||
641 | input_dev->close = tegra_kbc_close; | ||
642 | |||
643 | input_set_drvdata(input_dev, kbc); | ||
644 | |||
645 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
646 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
647 | |||
648 | input_dev->keycode = kbc->keycode; | ||
649 | input_dev->keycodesize = sizeof(kbc->keycode[0]); | ||
650 | input_dev->keycodemax = KBC_MAX_KEY; | ||
651 | if (pdata->use_fn_map) | ||
652 | input_dev->keycodemax *= 2; | ||
653 | |||
654 | kbc->use_fn_map = pdata->use_fn_map; | ||
655 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | ||
656 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, | ||
657 | input_dev->keycode, input_dev->keybit); | ||
658 | |||
659 | err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH, | ||
660 | pdev->name, kbc); | ||
661 | if (err) { | ||
662 | dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); | ||
663 | goto err_put_clk; | ||
664 | } | ||
665 | |||
666 | disable_irq(kbc->irq); | ||
667 | |||
668 | err = input_register_device(kbc->idev); | ||
669 | if (err) { | ||
670 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
671 | goto err_free_irq; | ||
672 | } | ||
673 | |||
674 | platform_set_drvdata(pdev, kbc); | ||
675 | device_init_wakeup(&pdev->dev, pdata->wakeup); | ||
676 | |||
677 | return 0; | ||
678 | |||
679 | err_free_irq: | ||
680 | free_irq(kbc->irq, pdev); | ||
681 | err_put_clk: | ||
682 | clk_put(kbc->clk); | ||
683 | err_iounmap: | ||
684 | iounmap(kbc->mmio); | ||
685 | err_free_mem_region: | ||
686 | release_mem_region(res->start, resource_size(res)); | ||
687 | err_free_mem: | ||
688 | input_free_device(kbc->idev); | ||
689 | kfree(kbc); | ||
690 | |||
691 | return err; | ||
692 | } | ||
693 | |||
694 | static int __devexit tegra_kbc_remove(struct platform_device *pdev) | ||
695 | { | ||
696 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); | ||
697 | struct resource *res; | ||
698 | |||
699 | free_irq(kbc->irq, pdev); | ||
700 | clk_put(kbc->clk); | ||
701 | |||
702 | input_unregister_device(kbc->idev); | ||
703 | iounmap(kbc->mmio); | ||
704 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
705 | release_mem_region(res->start, resource_size(res)); | ||
706 | |||
707 | kfree(kbc); | ||
708 | |||
709 | platform_set_drvdata(pdev, NULL); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | #ifdef CONFIG_PM_SLEEP | ||
715 | static int tegra_kbc_suspend(struct device *dev) | ||
716 | { | ||
717 | struct platform_device *pdev = to_platform_device(dev); | ||
718 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); | ||
719 | |||
720 | if (device_may_wakeup(&pdev->dev)) { | ||
721 | tegra_kbc_setup_wakekeys(kbc, true); | ||
722 | enable_irq_wake(kbc->irq); | ||
723 | /* Forcefully clear the interrupt status */ | ||
724 | writel(0x7, kbc->mmio + KBC_INT_0); | ||
725 | msleep(30); | ||
726 | } else { | ||
727 | mutex_lock(&kbc->idev->mutex); | ||
728 | if (kbc->idev->users) | ||
729 | tegra_kbc_stop(kbc); | ||
730 | mutex_unlock(&kbc->idev->mutex); | ||
731 | } | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int tegra_kbc_resume(struct device *dev) | ||
737 | { | ||
738 | struct platform_device *pdev = to_platform_device(dev); | ||
739 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); | ||
740 | int err = 0; | ||
741 | |||
742 | if (device_may_wakeup(&pdev->dev)) { | ||
743 | disable_irq_wake(kbc->irq); | ||
744 | tegra_kbc_setup_wakekeys(kbc, false); | ||
745 | } else { | ||
746 | mutex_lock(&kbc->idev->mutex); | ||
747 | if (kbc->idev->users) | ||
748 | err = tegra_kbc_start(kbc); | ||
749 | mutex_unlock(&kbc->idev->mutex); | ||
750 | } | ||
751 | |||
752 | return err; | ||
753 | } | ||
754 | #endif | ||
755 | |||
756 | static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume); | ||
757 | |||
758 | static struct platform_driver tegra_kbc_driver = { | ||
759 | .probe = tegra_kbc_probe, | ||
760 | .remove = __devexit_p(tegra_kbc_remove), | ||
761 | .driver = { | ||
762 | .name = "tegra-kbc", | ||
763 | .owner = THIS_MODULE, | ||
764 | .pm = &tegra_kbc_pm_ops, | ||
765 | }, | ||
766 | }; | ||
767 | |||
768 | static void __exit tegra_kbc_exit(void) | ||
769 | { | ||
770 | platform_driver_unregister(&tegra_kbc_driver); | ||
771 | } | ||
772 | module_exit(tegra_kbc_exit); | ||
773 | |||
774 | static int __init tegra_kbc_init(void) | ||
775 | { | ||
776 | return platform_driver_register(&tegra_kbc_driver); | ||
777 | } | ||
778 | module_init(tegra_kbc_init); | ||
779 | |||
780 | MODULE_LICENSE("GPL"); | ||
781 | MODULE_AUTHOR("Rakesh Iyer <riyer@nvidia.com>"); | ||
782 | MODULE_DESCRIPTION("Tegra matrix keyboard controller driver"); | ||
783 | MODULE_ALIAS("platform:tegra-kbc"); | ||
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index b4a81ebfab92..c8f097a15d89 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/err.h> | ||
17 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
18 | #include <linux/input.h> | 19 | #include <linux/input.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -219,9 +220,9 @@ static int __devinit keypad_probe(struct platform_device *pdev) | |||
219 | } | 220 | } |
220 | 221 | ||
221 | kp->clk = clk_get(dev, NULL); | 222 | kp->clk = clk_get(dev, NULL); |
222 | if (!kp->clk) { | 223 | if (IS_ERR(kp->clk)) { |
223 | dev_err(dev, "cannot claim device clock\n"); | 224 | dev_err(dev, "cannot claim device clock\n"); |
224 | error = -EINVAL; | 225 | error = PTR_ERR(kp->clk); |
225 | goto error_clk; | 226 | goto error_clk; |
226 | } | 227 | } |
227 | 228 | ||
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 09bef79d9da1..a26922cf0e84 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -332,18 +332,20 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) | |||
332 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) | 332 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) |
333 | { | 333 | { |
334 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; | 334 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; |
335 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | 335 | const struct matrix_keymap_data *keymap_data; |
336 | struct twl4030_keypad *kp; | 336 | struct twl4030_keypad *kp; |
337 | struct input_dev *input; | 337 | struct input_dev *input; |
338 | u8 reg; | 338 | u8 reg; |
339 | int error; | 339 | int error; |
340 | 340 | ||
341 | if (!pdata || !pdata->rows || !pdata->cols || | 341 | if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data || |
342 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { | 342 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { |
343 | dev_err(&pdev->dev, "Invalid platform_data\n"); | 343 | dev_err(&pdev->dev, "Invalid platform_data\n"); |
344 | return -EINVAL; | 344 | return -EINVAL; |
345 | } | 345 | } |
346 | 346 | ||
347 | keymap_data = pdata->keymap_data; | ||
348 | |||
347 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | 349 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); |
348 | input = input_allocate_device(); | 350 | input = input_allocate_device(); |
349 | if (!kp || !input) { | 351 | if (!kp || !input) { |
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index 4cc82826ea6b..3dca3c14510e 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c | |||
@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) | |||
74 | info->chip = chip; | 74 | info->chip = chip; |
75 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 75 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
76 | info->dev = &pdev->dev; | 76 | info->dev = &pdev->dev; |
77 | info->irq = irq + chip->irq_base; | 77 | info->irq = irq; |
78 | 78 | ||
79 | info->idev = input_allocate_device(); | 79 | info->idev = input_allocate_device(); |
80 | if (!info->idev) { | 80 | if (!info->idev) { |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index b99b8cbde02f..f9cf0881b0e3 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -294,24 +294,6 @@ config INPUT_SGI_BTNS | |||
294 | To compile this driver as a module, choose M here: the | 294 | To compile this driver as a module, choose M here: the |
295 | module will be called sgi_btns. | 295 | module will be called sgi_btns. |
296 | 296 | ||
297 | config INPUT_WINBOND_CIR | ||
298 | tristate "Winbond IR remote control" | ||
299 | depends on X86 && PNP | ||
300 | select NEW_LEDS | ||
301 | select LEDS_CLASS | ||
302 | select LEDS_TRIGGERS | ||
303 | select BITREVERSE | ||
304 | help | ||
305 | Say Y here if you want to use the IR remote functionality found | ||
306 | in some Winbond SuperI/O chips. Currently only the WPCD376I | ||
307 | chip is supported (included in some Intel Media series motherboards). | ||
308 | |||
309 | IR Receive and wake-on-IR from suspend and power-off is currently | ||
310 | supported. | ||
311 | |||
312 | To compile this driver as a module, choose M here: the module will be | ||
313 | called winbond_cir. | ||
314 | |||
315 | config HP_SDC_RTC | 297 | config HP_SDC_RTC |
316 | tristate "HP SDC Real Time Clock" | 298 | tristate "HP SDC Real Time Clock" |
317 | depends on (GSC || HP300) && SERIO | 299 | depends on (GSC || HP300) && SERIO |
@@ -448,4 +430,41 @@ config INPUT_ADXL34X_SPI | |||
448 | To compile this driver as a module, choose M here: the | 430 | To compile this driver as a module, choose M here: the |
449 | module will be called adxl34x-spi. | 431 | module will be called adxl34x-spi. |
450 | 432 | ||
433 | config INPUT_CMA3000 | ||
434 | tristate "VTI CMA3000 Tri-axis accelerometer" | ||
435 | help | ||
436 | Say Y here if you want to use VTI CMA3000_D0x Accelerometer | ||
437 | driver | ||
438 | |||
439 | This driver currently only supports I2C interface to the | ||
440 | controller. Also select the I2C method. | ||
441 | |||
442 | If unsure, say N | ||
443 | |||
444 | To compile this driver as a module, choose M here: the | ||
445 | module will be called cma3000_d0x. | ||
446 | |||
447 | config INPUT_CMA3000_I2C | ||
448 | tristate "Support I2C bus connection" | ||
449 | depends on INPUT_CMA3000 && I2C | ||
450 | help | ||
451 | Say Y here if you want to use VTI CMA3000_D0x Accelerometer | ||
452 | through I2C interface. | ||
453 | |||
454 | To compile this driver as a module, choose M here: the | ||
455 | module will be called cma3000_d0x_i2c. | ||
456 | |||
457 | config INPUT_XEN_KBDDEV_FRONTEND | ||
458 | tristate "Xen virtual keyboard and mouse support" | ||
459 | depends on XEN_FBDEV_FRONTEND | ||
460 | default y | ||
461 | select XEN_XENBUS_FRONTEND | ||
462 | help | ||
463 | This driver implements the front-end of the Xen virtual | ||
464 | keyboard and mouse device driver. It communicates with a back-end | ||
465 | in another domain. | ||
466 | |||
467 | To compile this driver as a module, choose M here: the | ||
468 | module will be called xen-kbdfront. | ||
469 | |||
451 | endif | 470 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1fe1f6c8b737..e3f7984e6274 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -18,6 +18,8 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | |||
18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | 19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o |
20 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 20 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
21 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o | ||
22 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o | ||
21 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 23 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
22 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 24 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
23 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 25 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
@@ -38,8 +40,8 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | |||
38 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 40 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
39 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | 41 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o |
40 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 42 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
41 | obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o | ||
42 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 43 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
43 | obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o | 44 | obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o |
45 | obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o | ||
44 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 46 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
45 | 47 | ||
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 2bef8fa56c94..e21deb1baa8a 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c | |||
@@ -10,23 +10,23 @@ | |||
10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/pm.h> | ||
13 | #include "ad714x.h" | 14 | #include "ad714x.h" |
14 | 15 | ||
15 | #ifdef CONFIG_PM | 16 | #ifdef CONFIG_PM |
16 | static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message) | 17 | static int ad714x_i2c_suspend(struct device *dev) |
17 | { | 18 | { |
18 | return ad714x_disable(i2c_get_clientdata(client)); | 19 | return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev))); |
19 | } | 20 | } |
20 | 21 | ||
21 | static int ad714x_i2c_resume(struct i2c_client *client) | 22 | static int ad714x_i2c_resume(struct device *dev) |
22 | { | 23 | { |
23 | return ad714x_enable(i2c_get_clientdata(client)); | 24 | return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev))); |
24 | } | 25 | } |
25 | #else | ||
26 | # define ad714x_i2c_suspend NULL | ||
27 | # define ad714x_i2c_resume NULL | ||
28 | #endif | 26 | #endif |
29 | 27 | ||
28 | static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume); | ||
29 | |||
30 | static int ad714x_i2c_write(struct device *dev, unsigned short reg, | 30 | static int ad714x_i2c_write(struct device *dev, unsigned short reg, |
31 | unsigned short data) | 31 | unsigned short data) |
32 | { | 32 | { |
@@ -114,11 +114,10 @@ MODULE_DEVICE_TABLE(i2c, ad714x_id); | |||
114 | static struct i2c_driver ad714x_i2c_driver = { | 114 | static struct i2c_driver ad714x_i2c_driver = { |
115 | .driver = { | 115 | .driver = { |
116 | .name = "ad714x_captouch", | 116 | .name = "ad714x_captouch", |
117 | .pm = &ad714x_i2c_pm, | ||
117 | }, | 118 | }, |
118 | .probe = ad714x_i2c_probe, | 119 | .probe = ad714x_i2c_probe, |
119 | .remove = __devexit_p(ad714x_i2c_remove), | 120 | .remove = __devexit_p(ad714x_i2c_remove), |
120 | .suspend = ad714x_i2c_suspend, | ||
121 | .resume = ad714x_i2c_resume, | ||
122 | .id_table = ad714x_id, | 121 | .id_table = ad714x_id, |
123 | }; | 122 | }; |
124 | 123 | ||
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 7f8dedfd1bfe..4120dd549305 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/input.h> /* BUS_I2C */ | 9 | #include <linux/input.h> /* BUS_I2C */ |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
12 | #include <linux/pm.h> | ||
12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
13 | #include "ad714x.h" | 14 | #include "ad714x.h" |
14 | 15 | ||
@@ -16,20 +17,19 @@ | |||
16 | #define AD714x_SPI_READ BIT(10) | 17 | #define AD714x_SPI_READ BIT(10) |
17 | 18 | ||
18 | #ifdef CONFIG_PM | 19 | #ifdef CONFIG_PM |
19 | static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message) | 20 | static int ad714x_spi_suspend(struct device *dev) |
20 | { | 21 | { |
21 | return ad714x_disable(spi_get_drvdata(spi)); | 22 | return ad714x_disable(spi_get_drvdata(to_spi_device(dev))); |
22 | } | 23 | } |
23 | 24 | ||
24 | static int ad714x_spi_resume(struct spi_device *spi) | 25 | static int ad714x_spi_resume(struct device *dev) |
25 | { | 26 | { |
26 | return ad714x_enable(spi_get_drvdata(spi)); | 27 | return ad714x_enable(spi_get_drvdata(to_spi_device(dev))); |
27 | } | 28 | } |
28 | #else | ||
29 | # define ad714x_spi_suspend NULL | ||
30 | # define ad714x_spi_resume NULL | ||
31 | #endif | 29 | #endif |
32 | 30 | ||
31 | static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume); | ||
32 | |||
33 | static int ad714x_spi_read(struct device *dev, unsigned short reg, | 33 | static int ad714x_spi_read(struct device *dev, unsigned short reg, |
34 | unsigned short *data) | 34 | unsigned short *data) |
35 | { | 35 | { |
@@ -79,11 +79,10 @@ static struct spi_driver ad714x_spi_driver = { | |||
79 | .driver = { | 79 | .driver = { |
80 | .name = "ad714x_captouch", | 80 | .name = "ad714x_captouch", |
81 | .owner = THIS_MODULE, | 81 | .owner = THIS_MODULE, |
82 | .pm = &ad714x_spi_pm, | ||
82 | }, | 83 | }, |
83 | .probe = ad714x_spi_probe, | 84 | .probe = ad714x_spi_probe, |
84 | .remove = __devexit_p(ad714x_spi_remove), | 85 | .remove = __devexit_p(ad714x_spi_remove), |
85 | .suspend = ad714x_spi_suspend, | ||
86 | .resume = ad714x_spi_resume, | ||
87 | }; | 86 | }; |
88 | 87 | ||
89 | static __init int ad714x_spi_init(void) | 88 | static __init int ad714x_spi_init(void) |
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 0779724af7e7..ccacf2bb06a4 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/i2c.h> | 11 | #include <linux/i2c.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/pm.h> | ||
14 | #include "adxl34x.h" | 15 | #include "adxl34x.h" |
15 | 16 | ||
16 | static int adxl34x_smbus_read(struct device *dev, unsigned char reg) | 17 | static int adxl34x_smbus_read(struct device *dev, unsigned char reg) |
@@ -105,8 +106,9 @@ static int __devexit adxl34x_i2c_remove(struct i2c_client *client) | |||
105 | } | 106 | } |
106 | 107 | ||
107 | #ifdef CONFIG_PM | 108 | #ifdef CONFIG_PM |
108 | static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message) | 109 | static int adxl34x_i2c_suspend(struct device *dev) |
109 | { | 110 | { |
111 | struct i2c_client *client = to_i2c_client(dev); | ||
110 | struct adxl34x *ac = i2c_get_clientdata(client); | 112 | struct adxl34x *ac = i2c_get_clientdata(client); |
111 | 113 | ||
112 | adxl34x_suspend(ac); | 114 | adxl34x_suspend(ac); |
@@ -114,19 +116,20 @@ static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message) | |||
114 | return 0; | 116 | return 0; |
115 | } | 117 | } |
116 | 118 | ||
117 | static int adxl34x_i2c_resume(struct i2c_client *client) | 119 | static int adxl34x_i2c_resume(struct device *dev) |
118 | { | 120 | { |
121 | struct i2c_client *client = to_i2c_client(dev); | ||
119 | struct adxl34x *ac = i2c_get_clientdata(client); | 122 | struct adxl34x *ac = i2c_get_clientdata(client); |
120 | 123 | ||
121 | adxl34x_resume(ac); | 124 | adxl34x_resume(ac); |
122 | 125 | ||
123 | return 0; | 126 | return 0; |
124 | } | 127 | } |
125 | #else | ||
126 | # define adxl34x_i2c_suspend NULL | ||
127 | # define adxl34x_i2c_resume NULL | ||
128 | #endif | 128 | #endif |
129 | 129 | ||
130 | static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend, | ||
131 | adxl34x_i2c_resume); | ||
132 | |||
130 | static const struct i2c_device_id adxl34x_id[] = { | 133 | static const struct i2c_device_id adxl34x_id[] = { |
131 | { "adxl34x", 0 }, | 134 | { "adxl34x", 0 }, |
132 | { } | 135 | { } |
@@ -138,11 +141,10 @@ static struct i2c_driver adxl34x_driver = { | |||
138 | .driver = { | 141 | .driver = { |
139 | .name = "adxl34x", | 142 | .name = "adxl34x", |
140 | .owner = THIS_MODULE, | 143 | .owner = THIS_MODULE, |
144 | .pm = &adxl34x_i2c_pm, | ||
141 | }, | 145 | }, |
142 | .probe = adxl34x_i2c_probe, | 146 | .probe = adxl34x_i2c_probe, |
143 | .remove = __devexit_p(adxl34x_i2c_remove), | 147 | .remove = __devexit_p(adxl34x_i2c_remove), |
144 | .suspend = adxl34x_i2c_suspend, | ||
145 | .resume = adxl34x_i2c_resume, | ||
146 | .id_table = adxl34x_id, | 148 | .id_table = adxl34x_id, |
147 | }; | 149 | }; |
148 | 150 | ||
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 782de9e89828..f29de22fdda0 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/input.h> /* BUS_SPI */ | 10 | #include <linux/input.h> /* BUS_SPI */ |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/spi/spi.h> | 12 | #include <linux/spi/spi.h> |
13 | #include <linux/pm.h> | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include "adxl34x.h" | 15 | #include "adxl34x.h" |
15 | 16 | ||
@@ -57,7 +58,7 @@ static int adxl34x_spi_read_block(struct device *dev, | |||
57 | return (status < 0) ? status : 0; | 58 | return (status < 0) ? status : 0; |
58 | } | 59 | } |
59 | 60 | ||
60 | static const struct adxl34x_bus_ops adx134x_spi_bops = { | 61 | static const struct adxl34x_bus_ops adxl34x_spi_bops = { |
61 | .bustype = BUS_SPI, | 62 | .bustype = BUS_SPI, |
62 | .write = adxl34x_spi_write, | 63 | .write = adxl34x_spi_write, |
63 | .read = adxl34x_spi_read, | 64 | .read = adxl34x_spi_read, |
@@ -76,7 +77,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi) | |||
76 | 77 | ||
77 | ac = adxl34x_probe(&spi->dev, spi->irq, | 78 | ac = adxl34x_probe(&spi->dev, spi->irq, |
78 | spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY, | 79 | spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY, |
79 | &adx134x_spi_bops); | 80 | &adxl34x_spi_bops); |
80 | 81 | ||
81 | if (IS_ERR(ac)) | 82 | if (IS_ERR(ac)) |
82 | return PTR_ERR(ac); | 83 | return PTR_ERR(ac); |
@@ -94,8 +95,9 @@ static int __devexit adxl34x_spi_remove(struct spi_device *spi) | |||
94 | } | 95 | } |
95 | 96 | ||
96 | #ifdef CONFIG_PM | 97 | #ifdef CONFIG_PM |
97 | static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message) | 98 | static int adxl34x_spi_suspend(struct device *dev) |
98 | { | 99 | { |
100 | struct spi_device *spi = to_spi_device(dev); | ||
99 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); | 101 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); |
100 | 102 | ||
101 | adxl34x_suspend(ac); | 103 | adxl34x_suspend(ac); |
@@ -103,29 +105,29 @@ static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message) | |||
103 | return 0; | 105 | return 0; |
104 | } | 106 | } |
105 | 107 | ||
106 | static int adxl34x_spi_resume(struct spi_device *spi) | 108 | static int adxl34x_spi_resume(struct device *dev) |
107 | { | 109 | { |
110 | struct spi_device *spi = to_spi_device(dev); | ||
108 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); | 111 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); |
109 | 112 | ||
110 | adxl34x_resume(ac); | 113 | adxl34x_resume(ac); |
111 | 114 | ||
112 | return 0; | 115 | return 0; |
113 | } | 116 | } |
114 | #else | ||
115 | # define adxl34x_spi_suspend NULL | ||
116 | # define adxl34x_spi_resume NULL | ||
117 | #endif | 117 | #endif |
118 | 118 | ||
119 | static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend, | ||
120 | adxl34x_spi_resume); | ||
121 | |||
119 | static struct spi_driver adxl34x_driver = { | 122 | static struct spi_driver adxl34x_driver = { |
120 | .driver = { | 123 | .driver = { |
121 | .name = "adxl34x", | 124 | .name = "adxl34x", |
122 | .bus = &spi_bus_type, | 125 | .bus = &spi_bus_type, |
123 | .owner = THIS_MODULE, | 126 | .owner = THIS_MODULE, |
127 | .pm = &adxl34x_spi_pm, | ||
124 | }, | 128 | }, |
125 | .probe = adxl34x_spi_probe, | 129 | .probe = adxl34x_spi_probe, |
126 | .remove = __devexit_p(adxl34x_spi_remove), | 130 | .remove = __devexit_p(adxl34x_spi_remove), |
127 | .suspend = adxl34x_spi_suspend, | ||
128 | .resume = adxl34x_spi_resume, | ||
129 | }; | 131 | }; |
130 | 132 | ||
131 | static int __init adxl34x_spi_init(void) | 133 | static int __init adxl34x_spi_init(void) |
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index de5900d50788..144ddbdeb9b3 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c | |||
@@ -716,7 +716,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, | |||
716 | pdata = dev->platform_data; | 716 | pdata = dev->platform_data; |
717 | if (!pdata) { | 717 | if (!pdata) { |
718 | dev_dbg(dev, | 718 | dev_dbg(dev, |
719 | "No platfrom data: Using default initialization\n"); | 719 | "No platform data: Using default initialization\n"); |
720 | pdata = &adxl34x_default_init; | 720 | pdata = &adxl34x_default_init; |
721 | } | 721 | } |
722 | 722 | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0b0e9be63542..9ccdb82d869a 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -612,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
612 | idev->open = ati_remote2_open; | 612 | idev->open = ati_remote2_open; |
613 | idev->close = ati_remote2_close; | 613 | idev->close = ati_remote2_close; |
614 | 614 | ||
615 | idev->getkeycode_new = ati_remote2_getkeycode; | 615 | idev->getkeycode = ati_remote2_getkeycode; |
616 | idev->setkeycode_new = ati_remote2_setkeycode; | 616 | idev->setkeycode = ati_remote2_setkeycode; |
617 | 617 | ||
618 | idev->name = ar2->name; | 618 | idev->name = ar2->name; |
619 | idev->phys = ar2->phys; | 619 | idev->phys = ar2->phys; |
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c new file mode 100644 index 000000000000..1633b6342267 --- /dev/null +++ b/drivers/input/misc/cma3000_d0x.c | |||
@@ -0,0 +1,398 @@ | |||
1 | /* | ||
2 | * VTI CMA3000_D0x Accelerometer driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * Author: Hemanth V <hemanthv@ti.com> | ||
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 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/input/cma3000.h> | ||
26 | |||
27 | #include "cma3000_d0x.h" | ||
28 | |||
29 | #define CMA3000_WHOAMI 0x00 | ||
30 | #define CMA3000_REVID 0x01 | ||
31 | #define CMA3000_CTRL 0x02 | ||
32 | #define CMA3000_STATUS 0x03 | ||
33 | #define CMA3000_RSTR 0x04 | ||
34 | #define CMA3000_INTSTATUS 0x05 | ||
35 | #define CMA3000_DOUTX 0x06 | ||
36 | #define CMA3000_DOUTY 0x07 | ||
37 | #define CMA3000_DOUTZ 0x08 | ||
38 | #define CMA3000_MDTHR 0x09 | ||
39 | #define CMA3000_MDFFTMR 0x0A | ||
40 | #define CMA3000_FFTHR 0x0B | ||
41 | |||
42 | #define CMA3000_RANGE2G (1 << 7) | ||
43 | #define CMA3000_RANGE8G (0 << 7) | ||
44 | #define CMA3000_BUSI2C (0 << 4) | ||
45 | #define CMA3000_MODEMASK (7 << 1) | ||
46 | #define CMA3000_GRANGEMASK (1 << 7) | ||
47 | |||
48 | #define CMA3000_STATUS_PERR 1 | ||
49 | #define CMA3000_INTSTATUS_FFDET (1 << 2) | ||
50 | |||
51 | /* Settling time delay in ms */ | ||
52 | #define CMA3000_SETDELAY 30 | ||
53 | |||
54 | /* Delay for clearing interrupt in us */ | ||
55 | #define CMA3000_INTDELAY 44 | ||
56 | |||
57 | |||
58 | /* | ||
59 | * Bit weights in mg for bit 0, other bits need | ||
60 | * multipy factor 2^n. Eight bit is the sign bit. | ||
61 | */ | ||
62 | #define BIT_TO_2G 18 | ||
63 | #define BIT_TO_8G 71 | ||
64 | |||
65 | struct cma3000_accl_data { | ||
66 | const struct cma3000_bus_ops *bus_ops; | ||
67 | const struct cma3000_platform_data *pdata; | ||
68 | |||
69 | struct device *dev; | ||
70 | struct input_dev *input_dev; | ||
71 | |||
72 | int bit_to_mg; | ||
73 | int irq; | ||
74 | |||
75 | int g_range; | ||
76 | u8 mode; | ||
77 | |||
78 | struct mutex mutex; | ||
79 | bool opened; | ||
80 | bool suspended; | ||
81 | }; | ||
82 | |||
83 | #define CMA3000_READ(data, reg, msg) \ | ||
84 | (data->bus_ops->read(data->dev, reg, msg)) | ||
85 | #define CMA3000_SET(data, reg, val, msg) \ | ||
86 | ((data)->bus_ops->write(data->dev, reg, val, msg)) | ||
87 | |||
88 | /* | ||
89 | * Conversion for each of the eight modes to g, depending | ||
90 | * on G range i.e 2G or 8G. Some modes always operate in | ||
91 | * 8G. | ||
92 | */ | ||
93 | |||
94 | static int mode_to_mg[8][2] = { | ||
95 | { 0, 0 }, | ||
96 | { BIT_TO_8G, BIT_TO_2G }, | ||
97 | { BIT_TO_8G, BIT_TO_2G }, | ||
98 | { BIT_TO_8G, BIT_TO_8G }, | ||
99 | { BIT_TO_8G, BIT_TO_8G }, | ||
100 | { BIT_TO_8G, BIT_TO_2G }, | ||
101 | { BIT_TO_8G, BIT_TO_2G }, | ||
102 | { 0, 0}, | ||
103 | }; | ||
104 | |||
105 | static void decode_mg(struct cma3000_accl_data *data, int *datax, | ||
106 | int *datay, int *dataz) | ||
107 | { | ||
108 | /* Data in 2's complement, convert to mg */ | ||
109 | *datax = ((s8)*datax) * data->bit_to_mg; | ||
110 | *datay = ((s8)*datay) * data->bit_to_mg; | ||
111 | *dataz = ((s8)*dataz) * data->bit_to_mg; | ||
112 | } | ||
113 | |||
114 | static irqreturn_t cma3000_thread_irq(int irq, void *dev_id) | ||
115 | { | ||
116 | struct cma3000_accl_data *data = dev_id; | ||
117 | int datax, datay, dataz; | ||
118 | u8 ctrl, mode, range, intr_status; | ||
119 | |||
120 | intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status"); | ||
121 | if (intr_status < 0) | ||
122 | return IRQ_NONE; | ||
123 | |||
124 | /* Check if free fall is detected, report immediately */ | ||
125 | if (intr_status & CMA3000_INTSTATUS_FFDET) { | ||
126 | input_report_abs(data->input_dev, ABS_MISC, 1); | ||
127 | input_sync(data->input_dev); | ||
128 | } else { | ||
129 | input_report_abs(data->input_dev, ABS_MISC, 0); | ||
130 | } | ||
131 | |||
132 | datax = CMA3000_READ(data, CMA3000_DOUTX, "X"); | ||
133 | datay = CMA3000_READ(data, CMA3000_DOUTY, "Y"); | ||
134 | dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z"); | ||
135 | |||
136 | ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl"); | ||
137 | mode = (ctrl & CMA3000_MODEMASK) >> 1; | ||
138 | range = (ctrl & CMA3000_GRANGEMASK) >> 7; | ||
139 | |||
140 | data->bit_to_mg = mode_to_mg[mode][range]; | ||
141 | |||
142 | /* Interrupt not for this device */ | ||
143 | if (data->bit_to_mg == 0) | ||
144 | return IRQ_NONE; | ||
145 | |||
146 | /* Decode register values to milli g */ | ||
147 | decode_mg(data, &datax, &datay, &dataz); | ||
148 | |||
149 | input_report_abs(data->input_dev, ABS_X, datax); | ||
150 | input_report_abs(data->input_dev, ABS_Y, datay); | ||
151 | input_report_abs(data->input_dev, ABS_Z, dataz); | ||
152 | input_sync(data->input_dev); | ||
153 | |||
154 | return IRQ_HANDLED; | ||
155 | } | ||
156 | |||
157 | static int cma3000_reset(struct cma3000_accl_data *data) | ||
158 | { | ||
159 | int val; | ||
160 | |||
161 | /* Reset sequence */ | ||
162 | CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset"); | ||
163 | CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset"); | ||
164 | CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset"); | ||
165 | |||
166 | /* Settling time delay */ | ||
167 | mdelay(10); | ||
168 | |||
169 | val = CMA3000_READ(data, CMA3000_STATUS, "Status"); | ||
170 | if (val < 0) { | ||
171 | dev_err(data->dev, "Reset failed\n"); | ||
172 | return val; | ||
173 | } | ||
174 | |||
175 | if (val & CMA3000_STATUS_PERR) { | ||
176 | dev_err(data->dev, "Parity Error\n"); | ||
177 | return -EIO; | ||
178 | } | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int cma3000_poweron(struct cma3000_accl_data *data) | ||
184 | { | ||
185 | const struct cma3000_platform_data *pdata = data->pdata; | ||
186 | u8 ctrl = 0; | ||
187 | int ret; | ||
188 | |||
189 | if (data->g_range == CMARANGE_2G) { | ||
190 | ctrl = (data->mode << 1) | CMA3000_RANGE2G; | ||
191 | } else if (data->g_range == CMARANGE_8G) { | ||
192 | ctrl = (data->mode << 1) | CMA3000_RANGE8G; | ||
193 | } else { | ||
194 | dev_info(data->dev, | ||
195 | "Invalid G range specified, assuming 8G\n"); | ||
196 | ctrl = (data->mode << 1) | CMA3000_RANGE8G; | ||
197 | } | ||
198 | |||
199 | ctrl |= data->bus_ops->ctrl_mod; | ||
200 | |||
201 | CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr, | ||
202 | "Motion Detect Threshold"); | ||
203 | CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr, | ||
204 | "Time register"); | ||
205 | CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr, | ||
206 | "Free fall threshold"); | ||
207 | ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting"); | ||
208 | if (ret < 0) | ||
209 | return -EIO; | ||
210 | |||
211 | msleep(CMA3000_SETDELAY); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int cma3000_poweroff(struct cma3000_accl_data *data) | ||
217 | { | ||
218 | int ret; | ||
219 | |||
220 | ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting"); | ||
221 | msleep(CMA3000_SETDELAY); | ||
222 | |||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int cma3000_open(struct input_dev *input_dev) | ||
227 | { | ||
228 | struct cma3000_accl_data *data = input_get_drvdata(input_dev); | ||
229 | |||
230 | mutex_lock(&data->mutex); | ||
231 | |||
232 | if (!data->suspended) | ||
233 | cma3000_poweron(data); | ||
234 | |||
235 | data->opened = true; | ||
236 | |||
237 | mutex_unlock(&data->mutex); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static void cma3000_close(struct input_dev *input_dev) | ||
243 | { | ||
244 | struct cma3000_accl_data *data = input_get_drvdata(input_dev); | ||
245 | |||
246 | mutex_lock(&data->mutex); | ||
247 | |||
248 | if (!data->suspended) | ||
249 | cma3000_poweroff(data); | ||
250 | |||
251 | data->opened = false; | ||
252 | |||
253 | mutex_unlock(&data->mutex); | ||
254 | } | ||
255 | |||
256 | void cma3000_suspend(struct cma3000_accl_data *data) | ||
257 | { | ||
258 | mutex_lock(&data->mutex); | ||
259 | |||
260 | if (!data->suspended && data->opened) | ||
261 | cma3000_poweroff(data); | ||
262 | |||
263 | data->suspended = true; | ||
264 | |||
265 | mutex_unlock(&data->mutex); | ||
266 | } | ||
267 | EXPORT_SYMBOL(cma3000_suspend); | ||
268 | |||
269 | |||
270 | void cma3000_resume(struct cma3000_accl_data *data) | ||
271 | { | ||
272 | mutex_lock(&data->mutex); | ||
273 | |||
274 | if (data->suspended && data->opened) | ||
275 | cma3000_poweron(data); | ||
276 | |||
277 | data->suspended = false; | ||
278 | |||
279 | mutex_unlock(&data->mutex); | ||
280 | } | ||
281 | EXPORT_SYMBOL(cma3000_resume); | ||
282 | |||
283 | struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, | ||
284 | const struct cma3000_bus_ops *bops) | ||
285 | { | ||
286 | const struct cma3000_platform_data *pdata = dev->platform_data; | ||
287 | struct cma3000_accl_data *data; | ||
288 | struct input_dev *input_dev; | ||
289 | int rev; | ||
290 | int error; | ||
291 | |||
292 | if (!pdata) { | ||
293 | dev_err(dev, "platform data not found\n"); | ||
294 | error = -EINVAL; | ||
295 | goto err_out; | ||
296 | } | ||
297 | |||
298 | |||
299 | /* if no IRQ return error */ | ||
300 | if (irq == 0) { | ||
301 | error = -EINVAL; | ||
302 | goto err_out; | ||
303 | } | ||
304 | |||
305 | data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL); | ||
306 | input_dev = input_allocate_device(); | ||
307 | if (!data || !input_dev) { | ||
308 | error = -ENOMEM; | ||
309 | goto err_free_mem; | ||
310 | } | ||
311 | |||
312 | data->dev = dev; | ||
313 | data->input_dev = input_dev; | ||
314 | data->bus_ops = bops; | ||
315 | data->pdata = pdata; | ||
316 | data->irq = irq; | ||
317 | mutex_init(&data->mutex); | ||
318 | |||
319 | data->mode = pdata->mode; | ||
320 | if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) { | ||
321 | data->mode = CMAMODE_MOTDET; | ||
322 | dev_warn(dev, | ||
323 | "Invalid mode specified, assuming Motion Detect\n"); | ||
324 | } | ||
325 | |||
326 | data->g_range = pdata->g_range; | ||
327 | if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) { | ||
328 | dev_info(dev, | ||
329 | "Invalid G range specified, assuming 8G\n"); | ||
330 | data->g_range = CMARANGE_8G; | ||
331 | } | ||
332 | |||
333 | input_dev->name = "cma3000-accelerometer"; | ||
334 | input_dev->id.bustype = bops->bustype; | ||
335 | input_dev->open = cma3000_open; | ||
336 | input_dev->close = cma3000_close; | ||
337 | |||
338 | __set_bit(EV_ABS, input_dev->evbit); | ||
339 | |||
340 | input_set_abs_params(input_dev, ABS_X, | ||
341 | -data->g_range, data->g_range, pdata->fuzz_x, 0); | ||
342 | input_set_abs_params(input_dev, ABS_Y, | ||
343 | -data->g_range, data->g_range, pdata->fuzz_y, 0); | ||
344 | input_set_abs_params(input_dev, ABS_Z, | ||
345 | -data->g_range, data->g_range, pdata->fuzz_z, 0); | ||
346 | input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0); | ||
347 | |||
348 | input_set_drvdata(input_dev, data); | ||
349 | |||
350 | error = cma3000_reset(data); | ||
351 | if (error) | ||
352 | goto err_free_mem; | ||
353 | |||
354 | rev = CMA3000_READ(data, CMA3000_REVID, "Revid"); | ||
355 | if (rev < 0) { | ||
356 | error = rev; | ||
357 | goto err_free_mem; | ||
358 | } | ||
359 | |||
360 | pr_info("CMA3000 Accelerometer: Revision %x\n", rev); | ||
361 | |||
362 | error = request_threaded_irq(irq, NULL, cma3000_thread_irq, | ||
363 | pdata->irqflags | IRQF_ONESHOT, | ||
364 | "cma3000_d0x", data); | ||
365 | if (error) { | ||
366 | dev_err(dev, "request_threaded_irq failed\n"); | ||
367 | goto err_free_mem; | ||
368 | } | ||
369 | |||
370 | error = input_register_device(data->input_dev); | ||
371 | if (error) { | ||
372 | dev_err(dev, "Unable to register input device\n"); | ||
373 | goto err_free_irq; | ||
374 | } | ||
375 | |||
376 | return data; | ||
377 | |||
378 | err_free_irq: | ||
379 | free_irq(irq, data); | ||
380 | err_free_mem: | ||
381 | input_free_device(input_dev); | ||
382 | kfree(data); | ||
383 | err_out: | ||
384 | return ERR_PTR(error); | ||
385 | } | ||
386 | EXPORT_SYMBOL(cma3000_init); | ||
387 | |||
388 | void cma3000_exit(struct cma3000_accl_data *data) | ||
389 | { | ||
390 | free_irq(data->irq, data); | ||
391 | input_unregister_device(data->input_dev); | ||
392 | kfree(data); | ||
393 | } | ||
394 | EXPORT_SYMBOL(cma3000_exit); | ||
395 | |||
396 | MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver"); | ||
397 | MODULE_LICENSE("GPL"); | ||
398 | MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>"); | ||
diff --git a/drivers/input/misc/cma3000_d0x.h b/drivers/input/misc/cma3000_d0x.h new file mode 100644 index 000000000000..2304ce306e1c --- /dev/null +++ b/drivers/input/misc/cma3000_d0x.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * VTI CMA3000_D0x Accelerometer driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * Author: Hemanth V <hemanthv@ti.com> | ||
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 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #ifndef _INPUT_CMA3000_H | ||
21 | #define _INPUT_CMA3000_H | ||
22 | |||
23 | #include <linux/types.h> | ||
24 | #include <linux/input.h> | ||
25 | |||
26 | struct device; | ||
27 | struct cma3000_accl_data; | ||
28 | |||
29 | struct cma3000_bus_ops { | ||
30 | u16 bustype; | ||
31 | u8 ctrl_mod; | ||
32 | int (*read)(struct device *, u8, char *); | ||
33 | int (*write)(struct device *, u8, u8, char *); | ||
34 | }; | ||
35 | |||
36 | struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, | ||
37 | const struct cma3000_bus_ops *bops); | ||
38 | void cma3000_exit(struct cma3000_accl_data *); | ||
39 | void cma3000_suspend(struct cma3000_accl_data *); | ||
40 | void cma3000_resume(struct cma3000_accl_data *); | ||
41 | |||
42 | #endif | ||
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c new file mode 100644 index 000000000000..d100cc5c5783 --- /dev/null +++ b/drivers/input/misc/cma3000_d0x_i2c.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Implements I2C interface for VTI CMA300_D0x Accelerometer driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * Author: Hemanth V <hemanthv@ti.com> | ||
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 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/input/cma3000.h> | ||
23 | #include "cma3000_d0x.h" | ||
24 | |||
25 | static int cma3000_i2c_set(struct device *dev, | ||
26 | u8 reg, u8 val, char *msg) | ||
27 | { | ||
28 | struct i2c_client *client = to_i2c_client(dev); | ||
29 | int ret; | ||
30 | |||
31 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
32 | if (ret < 0) | ||
33 | dev_err(&client->dev, | ||
34 | "%s failed (%s, %d)\n", __func__, msg, ret); | ||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | static int cma3000_i2c_read(struct device *dev, u8 reg, char *msg) | ||
39 | { | ||
40 | struct i2c_client *client = to_i2c_client(dev); | ||
41 | int ret; | ||
42 | |||
43 | ret = i2c_smbus_read_byte_data(client, reg); | ||
44 | if (ret < 0) | ||
45 | dev_err(&client->dev, | ||
46 | "%s failed (%s, %d)\n", __func__, msg, ret); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static const struct cma3000_bus_ops cma3000_i2c_bops = { | ||
51 | .bustype = BUS_I2C, | ||
52 | #define CMA3000_BUSI2C (0 << 4) | ||
53 | .ctrl_mod = CMA3000_BUSI2C, | ||
54 | .read = cma3000_i2c_read, | ||
55 | .write = cma3000_i2c_set, | ||
56 | }; | ||
57 | |||
58 | static int __devinit cma3000_i2c_probe(struct i2c_client *client, | ||
59 | const struct i2c_device_id *id) | ||
60 | { | ||
61 | struct cma3000_accl_data *data; | ||
62 | |||
63 | data = cma3000_init(&client->dev, client->irq, &cma3000_i2c_bops); | ||
64 | if (IS_ERR(data)) | ||
65 | return PTR_ERR(data); | ||
66 | |||
67 | i2c_set_clientdata(client, data); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int __devexit cma3000_i2c_remove(struct i2c_client *client) | ||
73 | { | ||
74 | struct cma3000_accl_data *data = i2c_get_clientdata(client); | ||
75 | |||
76 | cma3000_exit(data); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | #ifdef CONFIG_PM | ||
82 | static int cma3000_i2c_suspend(struct device *dev) | ||
83 | { | ||
84 | struct i2c_client *client = to_i2c_client(dev); | ||
85 | struct cma3000_accl_data *data = i2c_get_clientdata(client); | ||
86 | |||
87 | cma3000_suspend(data); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int cma3000_i2c_resume(struct device *dev) | ||
93 | { | ||
94 | struct i2c_client *client = to_i2c_client(dev); | ||
95 | struct cma3000_accl_data *data = i2c_get_clientdata(client); | ||
96 | |||
97 | cma3000_resume(data); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static const struct dev_pm_ops cma3000_i2c_pm_ops = { | ||
103 | .suspend = cma3000_i2c_suspend, | ||
104 | .resume = cma3000_i2c_resume, | ||
105 | }; | ||
106 | #endif | ||
107 | |||
108 | static const struct i2c_device_id cma3000_i2c_id[] = { | ||
109 | { "cma3000_d01", 0 }, | ||
110 | { }, | ||
111 | }; | ||
112 | |||
113 | MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id); | ||
114 | |||
115 | static struct i2c_driver cma3000_i2c_driver = { | ||
116 | .probe = cma3000_i2c_probe, | ||
117 | .remove = __devexit_p(cma3000_i2c_remove), | ||
118 | .id_table = cma3000_i2c_id, | ||
119 | .driver = { | ||
120 | .name = "cma3000_i2c_accl", | ||
121 | .owner = THIS_MODULE, | ||
122 | #ifdef CONFIG_PM | ||
123 | .pm = &cma3000_i2c_pm_ops, | ||
124 | #endif | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | static int __init cma3000_i2c_init(void) | ||
129 | { | ||
130 | return i2c_add_driver(&cma3000_i2c_driver); | ||
131 | } | ||
132 | |||
133 | static void __exit cma3000_i2c_exit(void) | ||
134 | { | ||
135 | i2c_del_driver(&cma3000_i2c_driver); | ||
136 | } | ||
137 | |||
138 | module_init(cma3000_i2c_init); | ||
139 | module_exit(cma3000_i2c_exit); | ||
140 | |||
141 | MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver"); | ||
142 | MODULE_LICENSE("GPL"); | ||
143 | MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>"); | ||
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 9dfd6e5f786f..1f38302a5951 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c | |||
@@ -69,11 +69,7 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned | |||
69 | } | 69 | } |
70 | 70 | ||
71 | if (value > 20 && value < 32767) | 71 | if (value > 20 && value < 32767) |
72 | #ifndef FREQ | 72 | count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1; |
73 | count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1; | ||
74 | #else | ||
75 | count = (FREQ / (value * 4)) - 1; | ||
76 | #endif | ||
77 | 73 | ||
78 | ixp4xx_spkr_control(pin, count); | 74 | ixp4xx_spkr_control(pin, count); |
79 | 75 | ||
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index a93c525475c6..fc62256c963f 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c | |||
@@ -312,7 +312,7 @@ static void keyspan_check_data(struct usb_keyspan *remote) | |||
312 | remote->data.tester = remote->data.tester >> 5; | 312 | remote->data.tester = remote->data.tester >> 5; |
313 | remote->data.bits_left -= 5; | 313 | remote->data.bits_left -= 5; |
314 | } else { | 314 | } else { |
315 | err("Bad message recieved, no stop bit found.\n"); | 315 | err("Bad message received, no stop bit found.\n"); |
316 | } | 316 | } |
317 | 317 | ||
318 | dev_dbg(&remote->udev->dev, | 318 | dev_dbg(&remote->udev->dev, |
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index d1583aea1721..08be1a355956 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c | |||
@@ -169,19 +169,29 @@ static int __devexit pcf8574_kp_remove(struct i2c_client *client) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
172 | static int pcf8574_kp_resume(struct i2c_client *client) | 172 | static int pcf8574_kp_resume(struct device *dev) |
173 | { | 173 | { |
174 | struct i2c_client *client = to_i2c_client(dev); | ||
175 | |||
174 | enable_irq(client->irq); | 176 | enable_irq(client->irq); |
175 | 177 | ||
176 | return 0; | 178 | return 0; |
177 | } | 179 | } |
178 | 180 | ||
179 | static int pcf8574_kp_suspend(struct i2c_client *client, pm_message_t mesg) | 181 | static int pcf8574_kp_suspend(struct device *dev) |
180 | { | 182 | { |
183 | struct i2c_client *client = to_i2c_client(dev); | ||
184 | |||
181 | disable_irq(client->irq); | 185 | disable_irq(client->irq); |
182 | 186 | ||
183 | return 0; | 187 | return 0; |
184 | } | 188 | } |
189 | |||
190 | static const struct dev_pm_ops pcf8574_kp_pm_ops = { | ||
191 | .suspend = pcf8574_kp_suspend, | ||
192 | .resume = pcf8574_kp_resume, | ||
193 | }; | ||
194 | |||
185 | #else | 195 | #else |
186 | # define pcf8574_kp_resume NULL | 196 | # define pcf8574_kp_resume NULL |
187 | # define pcf8574_kp_suspend NULL | 197 | # define pcf8574_kp_suspend NULL |
@@ -197,11 +207,12 @@ static struct i2c_driver pcf8574_kp_driver = { | |||
197 | .driver = { | 207 | .driver = { |
198 | .name = DRV_NAME, | 208 | .name = DRV_NAME, |
199 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
210 | #ifdef CONFIG_PM | ||
211 | .pm = &pcf8574_kp_pm_ops, | ||
212 | #endif | ||
200 | }, | 213 | }, |
201 | .probe = pcf8574_kp_probe, | 214 | .probe = pcf8574_kp_probe, |
202 | .remove = __devexit_p(pcf8574_kp_remove), | 215 | .remove = __devexit_p(pcf8574_kp_remove), |
203 | .suspend = pcf8574_kp_suspend, | ||
204 | .resume = pcf8574_kp_resume, | ||
205 | .id_table = pcf8574_kp_id, | 216 | .id_table = pcf8574_kp_id, |
206 | }; | 217 | }; |
207 | 218 | ||
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 1f8e0108962e..7e64d01da2be 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -176,7 +176,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
176 | 176 | ||
177 | /* request the IRQs */ | 177 | /* request the IRQs */ |
178 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, | 178 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, |
179 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, | 179 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
180 | DRV_NAME, encoder); | 180 | DRV_NAME, encoder); |
181 | if (err) { | 181 | if (err) { |
182 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | 182 | dev_err(&pdev->dev, "unable to request IRQ %d\n", |
@@ -185,7 +185,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
185 | } | 185 | } |
186 | 186 | ||
187 | err = request_irq(encoder->irq_b, &rotary_encoder_irq, | 187 | err = request_irq(encoder->irq_b, &rotary_encoder_irq, |
188 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, | 188 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
189 | DRV_NAME, encoder); | 189 | DRV_NAME, encoder); |
190 | if (err) { | 190 | if (err) { |
191 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | 191 | dev_err(&pdev->dev, "unable to request IRQ %d\n", |
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 8e130bf7d32b..0122f5351577 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
@@ -173,18 +173,16 @@ static int __devinit sparcspkr_probe(struct device *dev) | |||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | static int sparcspkr_shutdown(struct platform_device *dev) | 176 | static void sparcspkr_shutdown(struct platform_device *dev) |
177 | { | 177 | { |
178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); | 178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); |
179 | struct input_dev *input_dev = state->input_dev; | 179 | struct input_dev *input_dev = state->input_dev; |
180 | 180 | ||
181 | /* turn off the speaker */ | 181 | /* turn off the speaker */ |
182 | state->event(input_dev, EV_SND, SND_BELL, 0); | 182 | state->event(input_dev, EV_SND, SND_BELL, 0); |
183 | |||
184 | return 0; | ||
185 | } | 183 | } |
186 | 184 | ||
187 | static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) | 185 | static int __devinit bbc_beep_probe(struct platform_device *op) |
188 | { | 186 | { |
189 | struct sparcspkr_state *state; | 187 | struct sparcspkr_state *state; |
190 | struct bbc_beep_info *info; | 188 | struct bbc_beep_info *info; |
@@ -258,7 +256,7 @@ static const struct of_device_id bbc_beep_match[] = { | |||
258 | {}, | 256 | {}, |
259 | }; | 257 | }; |
260 | 258 | ||
261 | static struct of_platform_driver bbc_beep_driver = { | 259 | static struct platform_driver bbc_beep_driver = { |
262 | .driver = { | 260 | .driver = { |
263 | .name = "bbcbeep", | 261 | .name = "bbcbeep", |
264 | .owner = THIS_MODULE, | 262 | .owner = THIS_MODULE, |
@@ -269,7 +267,7 @@ static struct of_platform_driver bbc_beep_driver = { | |||
269 | .shutdown = sparcspkr_shutdown, | 267 | .shutdown = sparcspkr_shutdown, |
270 | }; | 268 | }; |
271 | 269 | ||
272 | static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) | 270 | static int __devinit grover_beep_probe(struct platform_device *op) |
273 | { | 271 | { |
274 | struct sparcspkr_state *state; | 272 | struct sparcspkr_state *state; |
275 | struct grover_beep_info *info; | 273 | struct grover_beep_info *info; |
@@ -340,7 +338,7 @@ static const struct of_device_id grover_beep_match[] = { | |||
340 | {}, | 338 | {}, |
341 | }; | 339 | }; |
342 | 340 | ||
343 | static struct of_platform_driver grover_beep_driver = { | 341 | static struct platform_driver grover_beep_driver = { |
344 | .driver = { | 342 | .driver = { |
345 | .name = "groverbeep", | 343 | .name = "groverbeep", |
346 | .owner = THIS_MODULE, | 344 | .owner = THIS_MODULE, |
@@ -353,12 +351,12 @@ static struct of_platform_driver grover_beep_driver = { | |||
353 | 351 | ||
354 | static int __init sparcspkr_init(void) | 352 | static int __init sparcspkr_init(void) |
355 | { | 353 | { |
356 | int err = of_register_platform_driver(&bbc_beep_driver); | 354 | int err = platform_driver_register(&bbc_beep_driver); |
357 | 355 | ||
358 | if (!err) { | 356 | if (!err) { |
359 | err = of_register_platform_driver(&grover_beep_driver); | 357 | err = platform_driver_register(&grover_beep_driver); |
360 | if (err) | 358 | if (err) |
361 | of_unregister_platform_driver(&bbc_beep_driver); | 359 | platform_driver_unregister(&bbc_beep_driver); |
362 | } | 360 | } |
363 | 361 | ||
364 | return err; | 362 | return err; |
@@ -366,8 +364,8 @@ static int __init sparcspkr_init(void) | |||
366 | 364 | ||
367 | static void __exit sparcspkr_exit(void) | 365 | static void __exit sparcspkr_exit(void) |
368 | { | 366 | { |
369 | of_unregister_platform_driver(&bbc_beep_driver); | 367 | platform_driver_unregister(&bbc_beep_driver); |
370 | of_unregister_platform_driver(&grover_beep_driver); | 368 | platform_driver_unregister(&grover_beep_driver); |
371 | } | 369 | } |
372 | 370 | ||
373 | module_init(sparcspkr_init); | 371 | module_init(sparcspkr_init); |
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 014dd4ad0d4f..6a11694e3fc7 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
30 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
31 | #include <linux/mfd/twl4030-codec.h> | 31 | #include <linux/mfd/twl4030-codec.h> |
32 | #include <linux/mfd/core.h> | ||
32 | #include <linux/input.h> | 33 | #include <linux/input.h> |
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
34 | 35 | ||
@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, | |||
196 | 197 | ||
197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) | 198 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) |
198 | { | 199 | { |
199 | struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; | 200 | struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev); |
200 | struct vibra_info *info; | 201 | struct vibra_info *info; |
201 | int ret; | 202 | int ret; |
202 | 203 | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index b9410784e6a1..736056897e50 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <linux/uinput.h> | 39 | #include <linux/uinput.h> |
40 | #include <linux/input/mt.h> | ||
40 | #include "../input-compat.h" | 41 | #include "../input-compat.h" |
41 | 42 | ||
42 | static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 43 | static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
@@ -301,10 +302,14 @@ static int uinput_validate_absbits(struct input_dev *dev) | |||
301 | int retval = 0; | 302 | int retval = 0; |
302 | 303 | ||
303 | for (cnt = 0; cnt < ABS_CNT; cnt++) { | 304 | for (cnt = 0; cnt < ABS_CNT; cnt++) { |
305 | int min, max; | ||
304 | if (!test_bit(cnt, dev->absbit)) | 306 | if (!test_bit(cnt, dev->absbit)) |
305 | continue; | 307 | continue; |
306 | 308 | ||
307 | if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) { | 309 | min = input_abs_get_min(dev, cnt); |
310 | max = input_abs_get_max(dev, cnt); | ||
311 | |||
312 | if ((min != 0 || max != 0) && max <= min) { | ||
308 | printk(KERN_DEBUG | 313 | printk(KERN_DEBUG |
309 | "%s: invalid abs[%02x] min:%d max:%d\n", | 314 | "%s: invalid abs[%02x] min:%d max:%d\n", |
310 | UINPUT_NAME, cnt, | 315 | UINPUT_NAME, cnt, |
@@ -346,8 +351,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
346 | { | 351 | { |
347 | struct uinput_user_dev *user_dev; | 352 | struct uinput_user_dev *user_dev; |
348 | struct input_dev *dev; | 353 | struct input_dev *dev; |
349 | char *name; | 354 | int i; |
350 | int i, size; | ||
351 | int retval; | 355 | int retval; |
352 | 356 | ||
353 | if (count != sizeof(struct uinput_user_dev)) | 357 | if (count != sizeof(struct uinput_user_dev)) |
@@ -361,30 +365,25 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
361 | 365 | ||
362 | dev = udev->dev; | 366 | dev = udev->dev; |
363 | 367 | ||
364 | user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); | 368 | user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev)); |
365 | if (!user_dev) | 369 | if (IS_ERR(user_dev)) |
366 | return -ENOMEM; | 370 | return PTR_ERR(user_dev); |
367 | |||
368 | if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) { | ||
369 | retval = -EFAULT; | ||
370 | goto exit; | ||
371 | } | ||
372 | 371 | ||
373 | udev->ff_effects_max = user_dev->ff_effects_max; | 372 | udev->ff_effects_max = user_dev->ff_effects_max; |
374 | 373 | ||
375 | size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; | 374 | /* Ensure name is filled in */ |
376 | if (!size) { | 375 | if (!user_dev->name[0]) { |
377 | retval = -EINVAL; | 376 | retval = -EINVAL; |
378 | goto exit; | 377 | goto exit; |
379 | } | 378 | } |
380 | 379 | ||
381 | kfree(dev->name); | 380 | kfree(dev->name); |
382 | dev->name = name = kmalloc(size, GFP_KERNEL); | 381 | dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE, |
383 | if (!name) { | 382 | GFP_KERNEL); |
383 | if (!dev->name) { | ||
384 | retval = -ENOMEM; | 384 | retval = -ENOMEM; |
385 | goto exit; | 385 | goto exit; |
386 | } | 386 | } |
387 | strlcpy(name, user_dev->name, size); | ||
388 | 387 | ||
389 | dev->id.bustype = user_dev->id.bustype; | 388 | dev->id.bustype = user_dev->id.bustype; |
390 | dev->id.vendor = user_dev->id.vendor; | 389 | dev->id.vendor = user_dev->id.vendor; |
@@ -406,8 +405,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
406 | goto exit; | 405 | goto exit; |
407 | if (test_bit(ABS_MT_SLOT, dev->absbit)) { | 406 | if (test_bit(ABS_MT_SLOT, dev->absbit)) { |
408 | int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; | 407 | int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; |
409 | input_mt_create_slots(dev, nslot); | 408 | input_mt_init_slots(dev, nslot); |
410 | input_set_events_per_packet(dev, 6 * nslot); | ||
411 | } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { | 409 | } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { |
412 | input_set_events_per_packet(dev, 60); | 410 | input_set_events_per_packet(dev, 60); |
413 | } | 411 | } |
@@ -622,7 +620,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
622 | struct uinput_ff_upload ff_up; | 620 | struct uinput_ff_upload ff_up; |
623 | struct uinput_ff_erase ff_erase; | 621 | struct uinput_ff_erase ff_erase; |
624 | struct uinput_request *req; | 622 | struct uinput_request *req; |
625 | int length; | ||
626 | char *phys; | 623 | char *phys; |
627 | 624 | ||
628 | retval = mutex_lock_interruptible(&udev->mutex); | 625 | retval = mutex_lock_interruptible(&udev->mutex); |
@@ -680,29 +677,24 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
680 | retval = uinput_set_bit(arg, swbit, SW_MAX); | 677 | retval = uinput_set_bit(arg, swbit, SW_MAX); |
681 | break; | 678 | break; |
682 | 679 | ||
680 | case UI_SET_PROPBIT: | ||
681 | retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); | ||
682 | break; | ||
683 | |||
683 | case UI_SET_PHYS: | 684 | case UI_SET_PHYS: |
684 | if (udev->state == UIST_CREATED) { | 685 | if (udev->state == UIST_CREATED) { |
685 | retval = -EINVAL; | 686 | retval = -EINVAL; |
686 | goto out; | 687 | goto out; |
687 | } | 688 | } |
688 | length = strnlen_user(p, 1024); | 689 | |
689 | if (length <= 0) { | 690 | phys = strndup_user(p, 1024); |
690 | retval = -EFAULT; | 691 | if (IS_ERR(phys)) { |
691 | break; | 692 | retval = PTR_ERR(phys); |
693 | goto out; | ||
692 | } | 694 | } |
695 | |||
693 | kfree(udev->dev->phys); | 696 | kfree(udev->dev->phys); |
694 | udev->dev->phys = phys = kmalloc(length, GFP_KERNEL); | 697 | udev->dev->phys = phys; |
695 | if (!phys) { | ||
696 | retval = -ENOMEM; | ||
697 | break; | ||
698 | } | ||
699 | if (copy_from_user(phys, p, length)) { | ||
700 | udev->dev->phys = NULL; | ||
701 | kfree(phys); | ||
702 | retval = -EFAULT; | ||
703 | break; | ||
704 | } | ||
705 | phys[length - 1] = '\0'; | ||
706 | break; | 698 | break; |
707 | 699 | ||
708 | case UI_BEGIN_FF_UPLOAD: | 700 | case UI_BEGIN_FF_UPLOAD: |
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c deleted file mode 100644 index 64f1de7960c6..000000000000 --- a/drivers/input/misc/winbond-cir.c +++ /dev/null | |||
@@ -1,1608 +0,0 @@ | |||
1 | /* | ||
2 | * winbond-cir.c - Driver for the Consumer IR functionality of Winbond | ||
3 | * SuperI/O chips. | ||
4 | * | ||
5 | * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but | ||
6 | * could probably support others (Winbond WEC102X, NatSemi, etc) | ||
7 | * with minor modifications. | ||
8 | * | ||
9 | * Original Author: David Härdeman <david@hardeman.nu> | ||
10 | * Copyright (C) 2009 David Härdeman <david@hardeman.nu> | ||
11 | * | ||
12 | * Dedicated to Matilda, my newborn daughter, without whose loving attention | ||
13 | * this driver would have been finished in half the time and with a fraction | ||
14 | * of the bugs. | ||
15 | * | ||
16 | * Written using: | ||
17 | * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel | ||
18 | * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff) | ||
19 | * o DSDT dumps | ||
20 | * | ||
21 | * Supported features: | ||
22 | * o RC6 | ||
23 | * o Wake-On-CIR functionality | ||
24 | * | ||
25 | * To do: | ||
26 | * o Test NEC and RC5 | ||
27 | * | ||
28 | * Left as an exercise for the reader: | ||
29 | * o Learning (I have neither the hardware, nor the need) | ||
30 | * o IR Transmit (ibid) | ||
31 | * | ||
32 | * This program is free software; you can redistribute it and/or modify | ||
33 | * it under the terms of the GNU General Public License as published by | ||
34 | * the Free Software Foundation; either version 2 of the License, or | ||
35 | * (at your option) any later version. | ||
36 | * | ||
37 | * This program is distributed in the hope that it will be useful, | ||
38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
40 | * GNU General Public License for more details. | ||
41 | * | ||
42 | * You should have received a copy of the GNU General Public License | ||
43 | * along with this program; if not, write to the Free Software | ||
44 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
45 | */ | ||
46 | |||
47 | #include <linux/module.h> | ||
48 | #include <linux/pnp.h> | ||
49 | #include <linux/interrupt.h> | ||
50 | #include <linux/timer.h> | ||
51 | #include <linux/input.h> | ||
52 | #include <linux/leds.h> | ||
53 | #include <linux/list.h> | ||
54 | #include <linux/spinlock.h> | ||
55 | #include <linux/pci_ids.h> | ||
56 | #include <linux/io.h> | ||
57 | #include <linux/bitrev.h> | ||
58 | #include <linux/bitops.h> | ||
59 | #include <linux/slab.h> | ||
60 | |||
61 | #define DRVNAME "winbond-cir" | ||
62 | |||
63 | /* CEIR Wake-Up Registers, relative to data->wbase */ | ||
64 | #define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */ | ||
65 | #define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */ | ||
66 | #define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */ | ||
67 | #define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */ | ||
68 | #define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */ | ||
69 | #define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */ | ||
70 | #define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */ | ||
71 | #define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */ | ||
72 | #define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */ | ||
73 | #define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */ | ||
74 | |||
75 | /* CEIR Enhanced Functionality Registers, relative to data->ebase */ | ||
76 | #define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */ | ||
77 | #define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */ | ||
78 | #define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */ | ||
79 | #define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */ | ||
80 | #define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */ | ||
81 | |||
82 | /* SP3 Banked Registers, relative to data->sbase */ | ||
83 | #define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */ | ||
84 | /* Bank 0 */ | ||
85 | #define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */ | ||
86 | #define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */ | ||
87 | #define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */ | ||
88 | #define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */ | ||
89 | #define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */ | ||
90 | #define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */ | ||
91 | #define WBCIR_REG_SP3_LSR 0x05 /* Link Status */ | ||
92 | #define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */ | ||
93 | #define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */ | ||
94 | /* Bank 2 */ | ||
95 | #define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */ | ||
96 | #define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */ | ||
97 | #define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */ | ||
98 | #define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */ | ||
99 | #define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */ | ||
100 | #define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */ | ||
101 | /* Bank 3 */ | ||
102 | #define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */ | ||
103 | #define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */ | ||
104 | #define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */ | ||
105 | /* Bank 4 */ | ||
106 | #define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */ | ||
107 | /* Bank 5 */ | ||
108 | #define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */ | ||
109 | /* Bank 6 */ | ||
110 | #define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */ | ||
111 | #define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */ | ||
112 | /* Bank 7 */ | ||
113 | #define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */ | ||
114 | #define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */ | ||
115 | #define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */ | ||
116 | #define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */ | ||
117 | #define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ | ||
118 | |||
119 | /* | ||
120 | * Magic values follow | ||
121 | */ | ||
122 | |||
123 | /* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
124 | #define WBCIR_IRQ_NONE 0x00 | ||
125 | /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
126 | #define WBCIR_IRQ_RX 0x01 | ||
127 | /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
128 | #define WBCIR_IRQ_ERR 0x04 | ||
129 | /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ | ||
130 | #define WBCIR_LED_ENABLE 0x80 | ||
131 | /* RX data available bit for WBCIR_REG_SP3_LSR */ | ||
132 | #define WBCIR_RX_AVAIL 0x01 | ||
133 | /* RX disable bit for WBCIR_REG_SP3_ASCR */ | ||
134 | #define WBCIR_RX_DISABLE 0x20 | ||
135 | /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ | ||
136 | #define WBCIR_EXT_ENABLE 0x01 | ||
137 | /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ | ||
138 | #define WBCIR_REGSEL_COMPARE 0x10 | ||
139 | /* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ | ||
140 | #define WBCIR_REGSEL_MASK 0x20 | ||
141 | /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */ | ||
142 | #define WBCIR_REG_ADDR0 0x00 | ||
143 | |||
144 | /* Valid banks for the SP3 UART */ | ||
145 | enum wbcir_bank { | ||
146 | WBCIR_BANK_0 = 0x00, | ||
147 | WBCIR_BANK_1 = 0x80, | ||
148 | WBCIR_BANK_2 = 0xE0, | ||
149 | WBCIR_BANK_3 = 0xE4, | ||
150 | WBCIR_BANK_4 = 0xE8, | ||
151 | WBCIR_BANK_5 = 0xEC, | ||
152 | WBCIR_BANK_6 = 0xF0, | ||
153 | WBCIR_BANK_7 = 0xF4, | ||
154 | }; | ||
155 | |||
156 | /* Supported IR Protocols */ | ||
157 | enum wbcir_protocol { | ||
158 | IR_PROTOCOL_RC5 = 0x0, | ||
159 | IR_PROTOCOL_NEC = 0x1, | ||
160 | IR_PROTOCOL_RC6 = 0x2, | ||
161 | }; | ||
162 | |||
163 | /* Misc */ | ||
164 | #define WBCIR_NAME "Winbond CIR" | ||
165 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ | ||
166 | #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ | ||
167 | #define IR_KEYPRESS_TIMEOUT 250 /* FIXME: should be per-protocol? */ | ||
168 | #define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ | ||
169 | #define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ | ||
170 | #define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ | ||
171 | #define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ | ||
172 | #define WBCIR_MAX_IDLE_BYTES 10 | ||
173 | |||
174 | static DEFINE_SPINLOCK(wbcir_lock); | ||
175 | static DEFINE_RWLOCK(keytable_lock); | ||
176 | |||
177 | struct wbcir_key { | ||
178 | u32 scancode; | ||
179 | unsigned int keycode; | ||
180 | }; | ||
181 | |||
182 | struct wbcir_keyentry { | ||
183 | struct wbcir_key key; | ||
184 | struct list_head list; | ||
185 | }; | ||
186 | |||
187 | static struct wbcir_key rc6_def_keymap[] = { | ||
188 | { 0x800F0400, KEY_NUMERIC_0 }, | ||
189 | { 0x800F0401, KEY_NUMERIC_1 }, | ||
190 | { 0x800F0402, KEY_NUMERIC_2 }, | ||
191 | { 0x800F0403, KEY_NUMERIC_3 }, | ||
192 | { 0x800F0404, KEY_NUMERIC_4 }, | ||
193 | { 0x800F0405, KEY_NUMERIC_5 }, | ||
194 | { 0x800F0406, KEY_NUMERIC_6 }, | ||
195 | { 0x800F0407, KEY_NUMERIC_7 }, | ||
196 | { 0x800F0408, KEY_NUMERIC_8 }, | ||
197 | { 0x800F0409, KEY_NUMERIC_9 }, | ||
198 | { 0x800F041D, KEY_NUMERIC_STAR }, | ||
199 | { 0x800F041C, KEY_NUMERIC_POUND }, | ||
200 | { 0x800F0410, KEY_VOLUMEUP }, | ||
201 | { 0x800F0411, KEY_VOLUMEDOWN }, | ||
202 | { 0x800F0412, KEY_CHANNELUP }, | ||
203 | { 0x800F0413, KEY_CHANNELDOWN }, | ||
204 | { 0x800F040E, KEY_MUTE }, | ||
205 | { 0x800F040D, KEY_VENDOR }, /* Vista Logo Key */ | ||
206 | { 0x800F041E, KEY_UP }, | ||
207 | { 0x800F041F, KEY_DOWN }, | ||
208 | { 0x800F0420, KEY_LEFT }, | ||
209 | { 0x800F0421, KEY_RIGHT }, | ||
210 | { 0x800F0422, KEY_OK }, | ||
211 | { 0x800F0423, KEY_ESC }, | ||
212 | { 0x800F040F, KEY_INFO }, | ||
213 | { 0x800F040A, KEY_CLEAR }, | ||
214 | { 0x800F040B, KEY_ENTER }, | ||
215 | { 0x800F045B, KEY_RED }, | ||
216 | { 0x800F045C, KEY_GREEN }, | ||
217 | { 0x800F045D, KEY_YELLOW }, | ||
218 | { 0x800F045E, KEY_BLUE }, | ||
219 | { 0x800F045A, KEY_TEXT }, | ||
220 | { 0x800F0427, KEY_SWITCHVIDEOMODE }, | ||
221 | { 0x800F040C, KEY_POWER }, | ||
222 | { 0x800F0450, KEY_RADIO }, | ||
223 | { 0x800F0448, KEY_PVR }, | ||
224 | { 0x800F0447, KEY_AUDIO }, | ||
225 | { 0x800F0426, KEY_EPG }, | ||
226 | { 0x800F0449, KEY_CAMERA }, | ||
227 | { 0x800F0425, KEY_TV }, | ||
228 | { 0x800F044A, KEY_VIDEO }, | ||
229 | { 0x800F0424, KEY_DVD }, | ||
230 | { 0x800F0416, KEY_PLAY }, | ||
231 | { 0x800F0418, KEY_PAUSE }, | ||
232 | { 0x800F0419, KEY_STOP }, | ||
233 | { 0x800F0414, KEY_FASTFORWARD }, | ||
234 | { 0x800F041A, KEY_NEXT }, | ||
235 | { 0x800F041B, KEY_PREVIOUS }, | ||
236 | { 0x800F0415, KEY_REWIND }, | ||
237 | { 0x800F0417, KEY_RECORD }, | ||
238 | }; | ||
239 | |||
240 | /* Registers and other state is protected by wbcir_lock */ | ||
241 | struct wbcir_data { | ||
242 | unsigned long wbase; /* Wake-Up Baseaddr */ | ||
243 | unsigned long ebase; /* Enhanced Func. Baseaddr */ | ||
244 | unsigned long sbase; /* Serial Port Baseaddr */ | ||
245 | unsigned int irq; /* Serial Port IRQ */ | ||
246 | |||
247 | struct input_dev *input_dev; | ||
248 | struct timer_list timer_keyup; | ||
249 | struct led_trigger *rxtrigger; | ||
250 | struct led_trigger *txtrigger; | ||
251 | struct led_classdev led; | ||
252 | |||
253 | u32 last_scancode; | ||
254 | unsigned int last_keycode; | ||
255 | u8 last_toggle; | ||
256 | u8 keypressed; | ||
257 | unsigned long keyup_jiffies; | ||
258 | unsigned int idle_count; | ||
259 | |||
260 | /* RX irdata and parsing state */ | ||
261 | unsigned long irdata[30]; | ||
262 | unsigned int irdata_count; | ||
263 | unsigned int irdata_idle; | ||
264 | unsigned int irdata_off; | ||
265 | unsigned int irdata_error; | ||
266 | |||
267 | /* Protected by keytable_lock */ | ||
268 | struct list_head keytable; | ||
269 | }; | ||
270 | |||
271 | static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; | ||
272 | module_param(protocol, uint, 0444); | ||
273 | MODULE_PARM_DESC(protocol, "IR protocol to use " | ||
274 | "(0 = RC5, 1 = NEC, 2 = RC6A, default)"); | ||
275 | |||
276 | static int invert; /* default = 0 */ | ||
277 | module_param(invert, bool, 0444); | ||
278 | MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); | ||
279 | |||
280 | static unsigned int wake_sc = 0x800F040C; | ||
281 | module_param(wake_sc, uint, 0644); | ||
282 | MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); | ||
283 | |||
284 | static unsigned int wake_rc6mode = 6; | ||
285 | module_param(wake_rc6mode, uint, 0644); | ||
286 | MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command " | ||
287 | "(0 = 0, 6 = 6A, default)"); | ||
288 | |||
289 | |||
290 | |||
291 | /***************************************************************************** | ||
292 | * | ||
293 | * UTILITY FUNCTIONS | ||
294 | * | ||
295 | *****************************************************************************/ | ||
296 | |||
297 | /* Caller needs to hold wbcir_lock */ | ||
298 | static void | ||
299 | wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) | ||
300 | { | ||
301 | u8 val; | ||
302 | |||
303 | val = inb(addr); | ||
304 | val = ((val & ~mask) | (bits & mask)); | ||
305 | outb(val, addr); | ||
306 | } | ||
307 | |||
308 | /* Selects the register bank for the serial port */ | ||
309 | static inline void | ||
310 | wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) | ||
311 | { | ||
312 | outb(bank, data->sbase + WBCIR_REG_SP3_BSR); | ||
313 | } | ||
314 | |||
315 | static enum led_brightness | ||
316 | wbcir_led_brightness_get(struct led_classdev *led_cdev) | ||
317 | { | ||
318 | struct wbcir_data *data = container_of(led_cdev, | ||
319 | struct wbcir_data, | ||
320 | led); | ||
321 | |||
322 | if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE) | ||
323 | return LED_FULL; | ||
324 | else | ||
325 | return LED_OFF; | ||
326 | } | ||
327 | |||
328 | static void | ||
329 | wbcir_led_brightness_set(struct led_classdev *led_cdev, | ||
330 | enum led_brightness brightness) | ||
331 | { | ||
332 | struct wbcir_data *data = container_of(led_cdev, | ||
333 | struct wbcir_data, | ||
334 | led); | ||
335 | |||
336 | wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, | ||
337 | brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE, | ||
338 | WBCIR_LED_ENABLE); | ||
339 | } | ||
340 | |||
341 | /* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */ | ||
342 | static u8 | ||
343 | wbcir_to_rc6cells(u8 val) | ||
344 | { | ||
345 | u8 coded = 0x00; | ||
346 | int i; | ||
347 | |||
348 | val &= 0x0F; | ||
349 | for (i = 0; i < 4; i++) { | ||
350 | if (val & 0x01) | ||
351 | coded |= 0x02 << (i * 2); | ||
352 | else | ||
353 | coded |= 0x01 << (i * 2); | ||
354 | val >>= 1; | ||
355 | } | ||
356 | |||
357 | return coded; | ||
358 | } | ||
359 | |||
360 | |||
361 | |||
362 | /***************************************************************************** | ||
363 | * | ||
364 | * INPUT FUNCTIONS | ||
365 | * | ||
366 | *****************************************************************************/ | ||
367 | |||
368 | static unsigned int | ||
369 | wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) | ||
370 | { | ||
371 | struct wbcir_keyentry *keyentry; | ||
372 | unsigned int keycode = KEY_RESERVED; | ||
373 | unsigned long flags; | ||
374 | |||
375 | read_lock_irqsave(&keytable_lock, flags); | ||
376 | |||
377 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
378 | if (keyentry->key.scancode == scancode) { | ||
379 | keycode = keyentry->key.keycode; | ||
380 | break; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | read_unlock_irqrestore(&keytable_lock, flags); | ||
385 | return keycode; | ||
386 | } | ||
387 | |||
388 | static int | ||
389 | wbcir_getkeycode(struct input_dev *dev, | ||
390 | unsigned int scancode, unsigned int *keycode) | ||
391 | { | ||
392 | struct wbcir_data *data = input_get_drvdata(dev); | ||
393 | |||
394 | *keycode = wbcir_do_getkeycode(data, scancode); | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int | ||
399 | wbcir_setkeycode(struct input_dev *dev, | ||
400 | unsigned int scancode, unsigned int keycode) | ||
401 | { | ||
402 | struct wbcir_data *data = input_get_drvdata(dev); | ||
403 | struct wbcir_keyentry *keyentry; | ||
404 | struct wbcir_keyentry *new_keyentry; | ||
405 | unsigned long flags; | ||
406 | unsigned int old_keycode = KEY_RESERVED; | ||
407 | |||
408 | new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); | ||
409 | if (!new_keyentry) | ||
410 | return -ENOMEM; | ||
411 | |||
412 | write_lock_irqsave(&keytable_lock, flags); | ||
413 | |||
414 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
415 | if (keyentry->key.scancode != scancode) | ||
416 | continue; | ||
417 | |||
418 | old_keycode = keyentry->key.keycode; | ||
419 | keyentry->key.keycode = keycode; | ||
420 | |||
421 | if (keyentry->key.keycode == KEY_RESERVED) { | ||
422 | list_del(&keyentry->list); | ||
423 | kfree(keyentry); | ||
424 | } | ||
425 | |||
426 | break; | ||
427 | } | ||
428 | |||
429 | set_bit(keycode, dev->keybit); | ||
430 | |||
431 | if (old_keycode == KEY_RESERVED) { | ||
432 | new_keyentry->key.scancode = scancode; | ||
433 | new_keyentry->key.keycode = keycode; | ||
434 | list_add(&new_keyentry->list, &data->keytable); | ||
435 | } else { | ||
436 | kfree(new_keyentry); | ||
437 | clear_bit(old_keycode, dev->keybit); | ||
438 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
439 | if (keyentry->key.keycode == old_keycode) { | ||
440 | set_bit(old_keycode, dev->keybit); | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | write_unlock_irqrestore(&keytable_lock, flags); | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Timer function to report keyup event some time after keydown is | ||
452 | * reported by the ISR. | ||
453 | */ | ||
454 | static void | ||
455 | wbcir_keyup(unsigned long cookie) | ||
456 | { | ||
457 | struct wbcir_data *data = (struct wbcir_data *)cookie; | ||
458 | unsigned long flags; | ||
459 | |||
460 | /* | ||
461 | * data->keyup_jiffies is used to prevent a race condition if a | ||
462 | * hardware interrupt occurs at this point and the keyup timer | ||
463 | * event is moved further into the future as a result. | ||
464 | * | ||
465 | * The timer will then be reactivated and this function called | ||
466 | * again in the future. We need to exit gracefully in that case | ||
467 | * to allow the input subsystem to do its auto-repeat magic or | ||
468 | * a keyup event might follow immediately after the keydown. | ||
469 | */ | ||
470 | |||
471 | spin_lock_irqsave(&wbcir_lock, flags); | ||
472 | |||
473 | if (time_is_after_eq_jiffies(data->keyup_jiffies) && data->keypressed) { | ||
474 | data->keypressed = 0; | ||
475 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
476 | input_report_key(data->input_dev, data->last_keycode, 0); | ||
477 | input_sync(data->input_dev); | ||
478 | } | ||
479 | |||
480 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
481 | } | ||
482 | |||
483 | static void | ||
484 | wbcir_keydown(struct wbcir_data *data, u32 scancode, u8 toggle) | ||
485 | { | ||
486 | unsigned int keycode; | ||
487 | |||
488 | /* Repeat? */ | ||
489 | if (data->last_scancode == scancode && | ||
490 | data->last_toggle == toggle && | ||
491 | data->keypressed) | ||
492 | goto set_timer; | ||
493 | data->last_scancode = scancode; | ||
494 | |||
495 | /* Do we need to release an old keypress? */ | ||
496 | if (data->keypressed) { | ||
497 | input_report_key(data->input_dev, data->last_keycode, 0); | ||
498 | input_sync(data->input_dev); | ||
499 | data->keypressed = 0; | ||
500 | } | ||
501 | |||
502 | /* Report scancode */ | ||
503 | input_event(data->input_dev, EV_MSC, MSC_SCAN, (int)scancode); | ||
504 | |||
505 | /* Do we know this scancode? */ | ||
506 | keycode = wbcir_do_getkeycode(data, scancode); | ||
507 | if (keycode == KEY_RESERVED) | ||
508 | goto set_timer; | ||
509 | |||
510 | /* Register a keypress */ | ||
511 | input_report_key(data->input_dev, keycode, 1); | ||
512 | data->keypressed = 1; | ||
513 | data->last_keycode = keycode; | ||
514 | data->last_toggle = toggle; | ||
515 | |||
516 | set_timer: | ||
517 | input_sync(data->input_dev); | ||
518 | led_trigger_event(data->rxtrigger, | ||
519 | data->keypressed ? LED_FULL : LED_OFF); | ||
520 | data->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); | ||
521 | mod_timer(&data->timer_keyup, data->keyup_jiffies); | ||
522 | } | ||
523 | |||
524 | |||
525 | |||
526 | /***************************************************************************** | ||
527 | * | ||
528 | * IR PARSING FUNCTIONS | ||
529 | * | ||
530 | *****************************************************************************/ | ||
531 | |||
532 | /* Resets all irdata */ | ||
533 | static void | ||
534 | wbcir_reset_irdata(struct wbcir_data *data) | ||
535 | { | ||
536 | memset(data->irdata, 0, sizeof(data->irdata)); | ||
537 | data->irdata_count = 0; | ||
538 | data->irdata_off = 0; | ||
539 | data->irdata_error = 0; | ||
540 | data->idle_count = 0; | ||
541 | } | ||
542 | |||
543 | /* Adds one bit of irdata */ | ||
544 | static void | ||
545 | add_irdata_bit(struct wbcir_data *data, int set) | ||
546 | { | ||
547 | if (data->irdata_count >= sizeof(data->irdata) * 8) { | ||
548 | data->irdata_error = 1; | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | if (set) | ||
553 | __set_bit(data->irdata_count, data->irdata); | ||
554 | data->irdata_count++; | ||
555 | } | ||
556 | |||
557 | /* Gets count bits of irdata */ | ||
558 | static u16 | ||
559 | get_bits(struct wbcir_data *data, int count) | ||
560 | { | ||
561 | u16 val = 0x0; | ||
562 | |||
563 | if (data->irdata_count - data->irdata_off < count) { | ||
564 | data->irdata_error = 1; | ||
565 | return 0x0; | ||
566 | } | ||
567 | |||
568 | while (count > 0) { | ||
569 | val <<= 1; | ||
570 | if (test_bit(data->irdata_off, data->irdata)) | ||
571 | val |= 0x1; | ||
572 | count--; | ||
573 | data->irdata_off++; | ||
574 | } | ||
575 | |||
576 | return val; | ||
577 | } | ||
578 | |||
579 | /* Reads 16 cells and converts them to a byte */ | ||
580 | static u8 | ||
581 | wbcir_rc6cells_to_byte(struct wbcir_data *data) | ||
582 | { | ||
583 | u16 raw = get_bits(data, 16); | ||
584 | u8 val = 0x00; | ||
585 | int bit; | ||
586 | |||
587 | for (bit = 0; bit < 8; bit++) { | ||
588 | switch (raw & 0x03) { | ||
589 | case 0x01: | ||
590 | break; | ||
591 | case 0x02: | ||
592 | val |= (0x01 << bit); | ||
593 | break; | ||
594 | default: | ||
595 | data->irdata_error = 1; | ||
596 | break; | ||
597 | } | ||
598 | raw >>= 2; | ||
599 | } | ||
600 | |||
601 | return val; | ||
602 | } | ||
603 | |||
604 | /* Decodes a number of bits from raw RC5 data */ | ||
605 | static u8 | ||
606 | wbcir_get_rc5bits(struct wbcir_data *data, unsigned int count) | ||
607 | { | ||
608 | u16 raw = get_bits(data, count * 2); | ||
609 | u8 val = 0x00; | ||
610 | int bit; | ||
611 | |||
612 | for (bit = 0; bit < count; bit++) { | ||
613 | switch (raw & 0x03) { | ||
614 | case 0x01: | ||
615 | val |= (0x01 << bit); | ||
616 | break; | ||
617 | case 0x02: | ||
618 | break; | ||
619 | default: | ||
620 | data->irdata_error = 1; | ||
621 | break; | ||
622 | } | ||
623 | raw >>= 2; | ||
624 | } | ||
625 | |||
626 | return val; | ||
627 | } | ||
628 | |||
629 | static void | ||
630 | wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) | ||
631 | { | ||
632 | /* | ||
633 | * Normal bits are manchester coded as follows: | ||
634 | * cell0 + cell1 = logic "0" | ||
635 | * cell1 + cell0 = logic "1" | ||
636 | * | ||
637 | * The IR pulse has the following components: | ||
638 | * | ||
639 | * Leader - 6 * cell1 - discarded | ||
640 | * Gap - 2 * cell0 - discarded | ||
641 | * Start bit - Normal Coding - always "1" | ||
642 | * Mode Bit 2 - 0 - Normal Coding | ||
643 | * Toggle bit - Normal Coding with double bit time, | ||
644 | * e.g. cell0 + cell0 + cell1 + cell1 | ||
645 | * means logic "0". | ||
646 | * | ||
647 | * The rest depends on the mode, the following modes are known: | ||
648 | * | ||
649 | * MODE 0: | ||
650 | * Address Bit 7 - 0 - Normal Coding | ||
651 | * Command Bit 7 - 0 - Normal Coding | ||
652 | * | ||
653 | * MODE 6: | ||
654 | * The above Toggle Bit is used as a submode bit, 0 = A, 1 = B. | ||
655 | * Submode B is for pointing devices, only remotes using submode A | ||
656 | * are supported. | ||
657 | * | ||
658 | * Customer range bit - 0 => Customer = 7 bits, 0...127 | ||
659 | * 1 => Customer = 15 bits, 32768...65535 | ||
660 | * Customer Bits - Normal Coding | ||
661 | * | ||
662 | * Customer codes are allocated by Philips. The rest of the bits | ||
663 | * are customer dependent. The following is commonly used (and the | ||
664 | * only supported config): | ||
665 | * | ||
666 | * Toggle Bit - Normal Coding | ||
667 | * Address Bit 6 - 0 - Normal Coding | ||
668 | * Command Bit 7 - 0 - Normal Coding | ||
669 | * | ||
670 | * All modes are followed by at least 6 * cell0. | ||
671 | * | ||
672 | * MODE 0 msglen: | ||
673 | * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (toggle) + | ||
674 | * 8 * 2 (address) + 8 * 2 (command) = | ||
675 | * 44 cells | ||
676 | * | ||
677 | * MODE 6A msglen: | ||
678 | * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (submode) + | ||
679 | * 1 * 2 (customer range bit) + 7/15 * 2 (customer bits) + | ||
680 | * 1 * 2 (toggle bit) + 7 * 2 (address) + 8 * 2 (command) = | ||
681 | * 60 - 76 cells | ||
682 | */ | ||
683 | u8 mode; | ||
684 | u8 toggle; | ||
685 | u16 customer = 0x0; | ||
686 | u8 address; | ||
687 | u8 command; | ||
688 | u32 scancode; | ||
689 | |||
690 | /* Leader mark */ | ||
691 | while (get_bits(data, 1) && !data->irdata_error) | ||
692 | /* Do nothing */; | ||
693 | |||
694 | /* Leader space */ | ||
695 | if (get_bits(data, 1)) { | ||
696 | dev_dbg(dev, "RC6 - Invalid leader space\n"); | ||
697 | return; | ||
698 | } | ||
699 | |||
700 | /* Start bit */ | ||
701 | if (get_bits(data, 2) != 0x02) { | ||
702 | dev_dbg(dev, "RC6 - Invalid start bit\n"); | ||
703 | return; | ||
704 | } | ||
705 | |||
706 | /* Mode */ | ||
707 | mode = get_bits(data, 6); | ||
708 | switch (mode) { | ||
709 | case 0x15: /* 010101 = b000 */ | ||
710 | mode = 0; | ||
711 | break; | ||
712 | case 0x29: /* 101001 = b110 */ | ||
713 | mode = 6; | ||
714 | break; | ||
715 | default: | ||
716 | dev_dbg(dev, "RC6 - Invalid mode\n"); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | /* Toggle bit / Submode bit */ | ||
721 | toggle = get_bits(data, 4); | ||
722 | switch (toggle) { | ||
723 | case 0x03: | ||
724 | toggle = 0; | ||
725 | break; | ||
726 | case 0x0C: | ||
727 | toggle = 1; | ||
728 | break; | ||
729 | default: | ||
730 | dev_dbg(dev, "RC6 - Toggle bit error\n"); | ||
731 | break; | ||
732 | } | ||
733 | |||
734 | /* Customer */ | ||
735 | if (mode == 6) { | ||
736 | if (toggle != 0) { | ||
737 | dev_dbg(dev, "RC6B - Not Supported\n"); | ||
738 | return; | ||
739 | } | ||
740 | |||
741 | customer = wbcir_rc6cells_to_byte(data); | ||
742 | |||
743 | if (customer & 0x80) { | ||
744 | /* 15 bit customer value */ | ||
745 | customer <<= 8; | ||
746 | customer |= wbcir_rc6cells_to_byte(data); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | /* Address */ | ||
751 | address = wbcir_rc6cells_to_byte(data); | ||
752 | if (mode == 6) { | ||
753 | toggle = address >> 7; | ||
754 | address &= 0x7F; | ||
755 | } | ||
756 | |||
757 | /* Command */ | ||
758 | command = wbcir_rc6cells_to_byte(data); | ||
759 | |||
760 | /* Create scancode */ | ||
761 | scancode = command; | ||
762 | scancode |= address << 8; | ||
763 | scancode |= customer << 16; | ||
764 | |||
765 | /* Last sanity check */ | ||
766 | if (data->irdata_error) { | ||
767 | dev_dbg(dev, "RC6 - Cell error(s)\n"); | ||
768 | return; | ||
769 | } | ||
770 | |||
771 | dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " | ||
772 | "toggle %u mode %u scan 0x%08X\n", | ||
773 | address, | ||
774 | command, | ||
775 | customer, | ||
776 | (unsigned int)toggle, | ||
777 | (unsigned int)mode, | ||
778 | scancode); | ||
779 | |||
780 | wbcir_keydown(data, scancode, toggle); | ||
781 | } | ||
782 | |||
783 | static void | ||
784 | wbcir_parse_rc5(struct device *dev, struct wbcir_data *data) | ||
785 | { | ||
786 | /* | ||
787 | * Bits are manchester coded as follows: | ||
788 | * cell1 + cell0 = logic "0" | ||
789 | * cell0 + cell1 = logic "1" | ||
790 | * (i.e. the reverse of RC6) | ||
791 | * | ||
792 | * Start bit 1 - "1" - discarded | ||
793 | * Start bit 2 - Must be inverted to get command bit 6 | ||
794 | * Toggle bit | ||
795 | * Address Bit 4 - 0 | ||
796 | * Command Bit 5 - 0 | ||
797 | */ | ||
798 | u8 toggle; | ||
799 | u8 address; | ||
800 | u8 command; | ||
801 | u32 scancode; | ||
802 | |||
803 | /* Start bit 1 */ | ||
804 | if (!get_bits(data, 1)) { | ||
805 | dev_dbg(dev, "RC5 - Invalid start bit\n"); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | /* Start bit 2 */ | ||
810 | if (!wbcir_get_rc5bits(data, 1)) | ||
811 | command = 0x40; | ||
812 | else | ||
813 | command = 0x00; | ||
814 | |||
815 | toggle = wbcir_get_rc5bits(data, 1); | ||
816 | address = wbcir_get_rc5bits(data, 5); | ||
817 | command |= wbcir_get_rc5bits(data, 6); | ||
818 | scancode = address << 7 | command; | ||
819 | |||
820 | /* Last sanity check */ | ||
821 | if (data->irdata_error) { | ||
822 | dev_dbg(dev, "RC5 - Invalid message\n"); | ||
823 | return; | ||
824 | } | ||
825 | |||
826 | dev_dbg(dev, "IR-RC5 ad %u cm %u t %u s %u\n", | ||
827 | (unsigned int)address, | ||
828 | (unsigned int)command, | ||
829 | (unsigned int)toggle, | ||
830 | (unsigned int)scancode); | ||
831 | |||
832 | wbcir_keydown(data, scancode, toggle); | ||
833 | } | ||
834 | |||
835 | static void | ||
836 | wbcir_parse_nec(struct device *dev, struct wbcir_data *data) | ||
837 | { | ||
838 | /* | ||
839 | * Each bit represents 560 us. | ||
840 | * | ||
841 | * Leader - 9 ms burst | ||
842 | * Gap - 4.5 ms silence | ||
843 | * Address1 bit 0 - 7 - Address 1 | ||
844 | * Address2 bit 0 - 7 - Address 2 | ||
845 | * Command1 bit 0 - 7 - Command 1 | ||
846 | * Command2 bit 0 - 7 - Command 2 | ||
847 | * | ||
848 | * Note the bit order! | ||
849 | * | ||
850 | * With the old NEC protocol, Address2 was the inverse of Address1 | ||
851 | * and Command2 was the inverse of Command1 and were used as | ||
852 | * an error check. | ||
853 | * | ||
854 | * With NEC extended, Address1 is the LSB of the Address and | ||
855 | * Address2 is the MSB, Command parsing remains unchanged. | ||
856 | * | ||
857 | * A repeat message is coded as: | ||
858 | * Leader - 9 ms burst | ||
859 | * Gap - 2.25 ms silence | ||
860 | * Repeat - 560 us active | ||
861 | */ | ||
862 | u8 address1; | ||
863 | u8 address2; | ||
864 | u8 command1; | ||
865 | u8 command2; | ||
866 | u16 address; | ||
867 | u32 scancode; | ||
868 | |||
869 | /* Leader mark */ | ||
870 | while (get_bits(data, 1) && !data->irdata_error) | ||
871 | /* Do nothing */; | ||
872 | |||
873 | /* Leader space */ | ||
874 | if (get_bits(data, 4)) { | ||
875 | dev_dbg(dev, "NEC - Invalid leader space\n"); | ||
876 | return; | ||
877 | } | ||
878 | |||
879 | /* Repeat? */ | ||
880 | if (get_bits(data, 1)) { | ||
881 | if (!data->keypressed) { | ||
882 | dev_dbg(dev, "NEC - Stray repeat message\n"); | ||
883 | return; | ||
884 | } | ||
885 | |||
886 | dev_dbg(dev, "IR-NEC repeat s %u\n", | ||
887 | (unsigned int)data->last_scancode); | ||
888 | |||
889 | wbcir_keydown(data, data->last_scancode, data->last_toggle); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | /* Remaining leader space */ | ||
894 | if (get_bits(data, 3)) { | ||
895 | dev_dbg(dev, "NEC - Invalid leader space\n"); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | address1 = bitrev8(get_bits(data, 8)); | ||
900 | address2 = bitrev8(get_bits(data, 8)); | ||
901 | command1 = bitrev8(get_bits(data, 8)); | ||
902 | command2 = bitrev8(get_bits(data, 8)); | ||
903 | |||
904 | /* Sanity check */ | ||
905 | if (data->irdata_error) { | ||
906 | dev_dbg(dev, "NEC - Invalid message\n"); | ||
907 | return; | ||
908 | } | ||
909 | |||
910 | /* Check command validity */ | ||
911 | if (command1 != ~command2) { | ||
912 | dev_dbg(dev, "NEC - Command bytes mismatch\n"); | ||
913 | return; | ||
914 | } | ||
915 | |||
916 | /* Check for extended NEC protocol */ | ||
917 | address = address1; | ||
918 | if (address1 != ~address2) | ||
919 | address |= address2 << 8; | ||
920 | |||
921 | scancode = address << 8 | command1; | ||
922 | |||
923 | dev_dbg(dev, "IR-NEC ad %u cm %u s %u\n", | ||
924 | (unsigned int)address, | ||
925 | (unsigned int)command1, | ||
926 | (unsigned int)scancode); | ||
927 | |||
928 | wbcir_keydown(data, scancode, !data->last_toggle); | ||
929 | } | ||
930 | |||
931 | |||
932 | |||
933 | /***************************************************************************** | ||
934 | * | ||
935 | * INTERRUPT FUNCTIONS | ||
936 | * | ||
937 | *****************************************************************************/ | ||
938 | |||
939 | static irqreturn_t | ||
940 | wbcir_irq_handler(int irqno, void *cookie) | ||
941 | { | ||
942 | struct pnp_dev *device = cookie; | ||
943 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
944 | struct device *dev = &device->dev; | ||
945 | u8 status; | ||
946 | unsigned long flags; | ||
947 | u8 irdata[8]; | ||
948 | int i; | ||
949 | unsigned int hw; | ||
950 | |||
951 | spin_lock_irqsave(&wbcir_lock, flags); | ||
952 | |||
953 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
954 | |||
955 | status = inb(data->sbase + WBCIR_REG_SP3_EIR); | ||
956 | |||
957 | if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { | ||
958 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
959 | return IRQ_NONE; | ||
960 | } | ||
961 | |||
962 | if (status & WBCIR_IRQ_ERR) | ||
963 | data->irdata_error = 1; | ||
964 | |||
965 | if (!(status & WBCIR_IRQ_RX)) | ||
966 | goto out; | ||
967 | |||
968 | /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | ||
969 | insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); | ||
970 | |||
971 | for (i = 0; i < sizeof(irdata); i++) { | ||
972 | hw = hweight8(irdata[i]); | ||
973 | if (hw > 4) | ||
974 | add_irdata_bit(data, 0); | ||
975 | else | ||
976 | add_irdata_bit(data, 1); | ||
977 | |||
978 | if (hw == 8) | ||
979 | data->idle_count++; | ||
980 | else | ||
981 | data->idle_count = 0; | ||
982 | } | ||
983 | |||
984 | if (data->idle_count > WBCIR_MAX_IDLE_BYTES) { | ||
985 | /* Set RXINACTIVE... */ | ||
986 | outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | ||
987 | |||
988 | /* ...and drain the FIFO */ | ||
989 | while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) | ||
990 | inb(data->sbase + WBCIR_REG_SP3_RXDATA); | ||
991 | |||
992 | dev_dbg(dev, "IRDATA:\n"); | ||
993 | for (i = 0; i < data->irdata_count; i += BITS_PER_LONG) | ||
994 | dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]); | ||
995 | |||
996 | switch (protocol) { | ||
997 | case IR_PROTOCOL_RC5: | ||
998 | wbcir_parse_rc5(dev, data); | ||
999 | break; | ||
1000 | case IR_PROTOCOL_RC6: | ||
1001 | wbcir_parse_rc6(dev, data); | ||
1002 | break; | ||
1003 | case IR_PROTOCOL_NEC: | ||
1004 | wbcir_parse_nec(dev, data); | ||
1005 | break; | ||
1006 | } | ||
1007 | |||
1008 | wbcir_reset_irdata(data); | ||
1009 | } | ||
1010 | |||
1011 | out: | ||
1012 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
1013 | return IRQ_HANDLED; | ||
1014 | } | ||
1015 | |||
1016 | |||
1017 | |||
1018 | /***************************************************************************** | ||
1019 | * | ||
1020 | * SETUP/INIT/SUSPEND/RESUME FUNCTIONS | ||
1021 | * | ||
1022 | *****************************************************************************/ | ||
1023 | |||
1024 | static void | ||
1025 | wbcir_shutdown(struct pnp_dev *device) | ||
1026 | { | ||
1027 | struct device *dev = &device->dev; | ||
1028 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1029 | int do_wake = 1; | ||
1030 | u8 match[11]; | ||
1031 | u8 mask[11]; | ||
1032 | u8 rc6_csl = 0; | ||
1033 | int i; | ||
1034 | |||
1035 | memset(match, 0, sizeof(match)); | ||
1036 | memset(mask, 0, sizeof(mask)); | ||
1037 | |||
1038 | if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { | ||
1039 | do_wake = 0; | ||
1040 | goto finish; | ||
1041 | } | ||
1042 | |||
1043 | switch (protocol) { | ||
1044 | case IR_PROTOCOL_RC5: | ||
1045 | if (wake_sc > 0xFFF) { | ||
1046 | do_wake = 0; | ||
1047 | dev_err(dev, "RC5 - Invalid wake scancode\n"); | ||
1048 | break; | ||
1049 | } | ||
1050 | |||
1051 | /* Mask = 13 bits, ex toggle */ | ||
1052 | mask[0] = 0xFF; | ||
1053 | mask[1] = 0x17; | ||
1054 | |||
1055 | match[0] = (wake_sc & 0x003F); /* 6 command bits */ | ||
1056 | match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ | ||
1057 | match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ | ||
1058 | if (!(wake_sc & 0x0040)) /* 2nd start bit */ | ||
1059 | match[1] |= 0x10; | ||
1060 | |||
1061 | break; | ||
1062 | |||
1063 | case IR_PROTOCOL_NEC: | ||
1064 | if (wake_sc > 0xFFFFFF) { | ||
1065 | do_wake = 0; | ||
1066 | dev_err(dev, "NEC - Invalid wake scancode\n"); | ||
1067 | break; | ||
1068 | } | ||
1069 | |||
1070 | mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; | ||
1071 | |||
1072 | match[1] = bitrev8((wake_sc & 0xFF)); | ||
1073 | match[0] = ~match[1]; | ||
1074 | |||
1075 | match[3] = bitrev8((wake_sc & 0xFF00) >> 8); | ||
1076 | if (wake_sc > 0xFFFF) | ||
1077 | match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); | ||
1078 | else | ||
1079 | match[2] = ~match[3]; | ||
1080 | |||
1081 | break; | ||
1082 | |||
1083 | case IR_PROTOCOL_RC6: | ||
1084 | |||
1085 | if (wake_rc6mode == 0) { | ||
1086 | if (wake_sc > 0xFFFF) { | ||
1087 | do_wake = 0; | ||
1088 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | ||
1089 | break; | ||
1090 | } | ||
1091 | |||
1092 | /* Command */ | ||
1093 | match[0] = wbcir_to_rc6cells(wake_sc >> 0); | ||
1094 | mask[0] = 0xFF; | ||
1095 | match[1] = wbcir_to_rc6cells(wake_sc >> 4); | ||
1096 | mask[1] = 0xFF; | ||
1097 | |||
1098 | /* Address */ | ||
1099 | match[2] = wbcir_to_rc6cells(wake_sc >> 8); | ||
1100 | mask[2] = 0xFF; | ||
1101 | match[3] = wbcir_to_rc6cells(wake_sc >> 12); | ||
1102 | mask[3] = 0xFF; | ||
1103 | |||
1104 | /* Header */ | ||
1105 | match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ | ||
1106 | mask[4] = 0xF0; | ||
1107 | match[5] = 0x09; /* start bit = 1, mode2 = 0 */ | ||
1108 | mask[5] = 0x0F; | ||
1109 | |||
1110 | rc6_csl = 44; | ||
1111 | |||
1112 | } else if (wake_rc6mode == 6) { | ||
1113 | i = 0; | ||
1114 | |||
1115 | /* Command */ | ||
1116 | match[i] = wbcir_to_rc6cells(wake_sc >> 0); | ||
1117 | mask[i++] = 0xFF; | ||
1118 | match[i] = wbcir_to_rc6cells(wake_sc >> 4); | ||
1119 | mask[i++] = 0xFF; | ||
1120 | |||
1121 | /* Address + Toggle */ | ||
1122 | match[i] = wbcir_to_rc6cells(wake_sc >> 8); | ||
1123 | mask[i++] = 0xFF; | ||
1124 | match[i] = wbcir_to_rc6cells(wake_sc >> 12); | ||
1125 | mask[i++] = 0x3F; | ||
1126 | |||
1127 | /* Customer bits 7 - 0 */ | ||
1128 | match[i] = wbcir_to_rc6cells(wake_sc >> 16); | ||
1129 | mask[i++] = 0xFF; | ||
1130 | match[i] = wbcir_to_rc6cells(wake_sc >> 20); | ||
1131 | mask[i++] = 0xFF; | ||
1132 | |||
1133 | if (wake_sc & 0x80000000) { | ||
1134 | /* Customer range bit and bits 15 - 8 */ | ||
1135 | match[i] = wbcir_to_rc6cells(wake_sc >> 24); | ||
1136 | mask[i++] = 0xFF; | ||
1137 | match[i] = wbcir_to_rc6cells(wake_sc >> 28); | ||
1138 | mask[i++] = 0xFF; | ||
1139 | rc6_csl = 76; | ||
1140 | } else if (wake_sc <= 0x007FFFFF) { | ||
1141 | rc6_csl = 60; | ||
1142 | } else { | ||
1143 | do_wake = 0; | ||
1144 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | ||
1145 | break; | ||
1146 | } | ||
1147 | |||
1148 | /* Header */ | ||
1149 | match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */ | ||
1150 | mask[i++] = 0xFF; | ||
1151 | match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ | ||
1152 | mask[i++] = 0x0F; | ||
1153 | |||
1154 | } else { | ||
1155 | do_wake = 0; | ||
1156 | dev_err(dev, "RC6 - Invalid wake mode\n"); | ||
1157 | } | ||
1158 | |||
1159 | break; | ||
1160 | |||
1161 | default: | ||
1162 | do_wake = 0; | ||
1163 | break; | ||
1164 | } | ||
1165 | |||
1166 | finish: | ||
1167 | if (do_wake) { | ||
1168 | /* Set compare and compare mask */ | ||
1169 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, | ||
1170 | WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0, | ||
1171 | 0x3F); | ||
1172 | outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11); | ||
1173 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, | ||
1174 | WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0, | ||
1175 | 0x3F); | ||
1176 | outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11); | ||
1177 | |||
1178 | /* RC6 Compare String Len */ | ||
1179 | outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL); | ||
1180 | |||
1181 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1182 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1183 | |||
1184 | /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */ | ||
1185 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); | ||
1186 | |||
1187 | /* Set CEIR_EN */ | ||
1188 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); | ||
1189 | |||
1190 | } else { | ||
1191 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
1192 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1193 | |||
1194 | /* Clear CEIR_EN */ | ||
1195 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
1196 | } | ||
1197 | |||
1198 | /* Disable interrupts */ | ||
1199 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1200 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1201 | |||
1202 | /* | ||
1203 | * ACPI will set the HW disable bit for SP3 which means that the | ||
1204 | * output signals are left in an undefined state which may cause | ||
1205 | * spurious interrupts which we need to ignore until the hardware | ||
1206 | * is reinitialized. | ||
1207 | */ | ||
1208 | disable_irq(data->irq); | ||
1209 | } | ||
1210 | |||
1211 | static int | ||
1212 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) | ||
1213 | { | ||
1214 | wbcir_shutdown(device); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | static void | ||
1219 | wbcir_init_hw(struct wbcir_data *data) | ||
1220 | { | ||
1221 | u8 tmp; | ||
1222 | |||
1223 | /* Disable interrupts */ | ||
1224 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1225 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1226 | |||
1227 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ | ||
1228 | tmp = protocol << 4; | ||
1229 | if (invert) | ||
1230 | tmp |= 0x08; | ||
1231 | outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL); | ||
1232 | |||
1233 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1234 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1235 | |||
1236 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
1237 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1238 | |||
1239 | /* Set RC5 cell time to correspond to 36 kHz */ | ||
1240 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F); | ||
1241 | |||
1242 | /* Set IRTX_INV */ | ||
1243 | if (invert) | ||
1244 | outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL); | ||
1245 | else | ||
1246 | outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); | ||
1247 | |||
1248 | /* | ||
1249 | * Clear IR LED, set SP3 clock to 24Mhz | ||
1250 | * set SP3_IRRX_SW to binary 01, helpfully not documented | ||
1251 | */ | ||
1252 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); | ||
1253 | |||
1254 | /* Enable extended mode */ | ||
1255 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
1256 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
1257 | |||
1258 | /* | ||
1259 | * Configure baud generator, IR data will be sampled at | ||
1260 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
1261 | * | ||
1262 | * The ECIR registers include a flag to change the | ||
1263 | * 24Mhz clock freq to 48Mhz. | ||
1264 | * | ||
1265 | * It's not documented in the specs, but fifo levels | ||
1266 | * other than 16 seems to be unsupported. | ||
1267 | */ | ||
1268 | |||
1269 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
1270 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
1271 | |||
1272 | /* Set baud divisor to generate one byte per bit/cell */ | ||
1273 | switch (protocol) { | ||
1274 | case IR_PROTOCOL_RC5: | ||
1275 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1276 | break; | ||
1277 | case IR_PROTOCOL_RC6: | ||
1278 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1279 | break; | ||
1280 | case IR_PROTOCOL_NEC: | ||
1281 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1282 | break; | ||
1283 | } | ||
1284 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
1285 | |||
1286 | /* Set CEIR mode */ | ||
1287 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1288 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
1289 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
1290 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
1291 | |||
1292 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
1293 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
1294 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
1295 | |||
1296 | /* Disable timer */ | ||
1297 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
1298 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
1299 | |||
1300 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
1301 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
1302 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
1303 | |||
1304 | /* Disable CRC */ | ||
1305 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
1306 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
1307 | |||
1308 | /* Set RX/TX (de)modulation freq, not really used */ | ||
1309 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
1310 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
1311 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
1312 | |||
1313 | /* Set invert and pin direction */ | ||
1314 | if (invert) | ||
1315 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
1316 | else | ||
1317 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
1318 | |||
1319 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
1320 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1321 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
1322 | |||
1323 | /* Clear AUX status bits */ | ||
1324 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
1325 | |||
1326 | /* Enable interrupts */ | ||
1327 | wbcir_reset_irdata(data); | ||
1328 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
1329 | } | ||
1330 | |||
1331 | static int | ||
1332 | wbcir_resume(struct pnp_dev *device) | ||
1333 | { | ||
1334 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1335 | |||
1336 | wbcir_init_hw(data); | ||
1337 | enable_irq(data->irq); | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | static int __devinit | ||
1343 | wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | ||
1344 | { | ||
1345 | struct device *dev = &device->dev; | ||
1346 | struct wbcir_data *data; | ||
1347 | int err; | ||
1348 | |||
1349 | if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN && | ||
1350 | pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN && | ||
1351 | pnp_port_len(device, 2) == SP_IOMEM_LEN)) { | ||
1352 | dev_err(dev, "Invalid resources\n"); | ||
1353 | return -ENODEV; | ||
1354 | } | ||
1355 | |||
1356 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
1357 | if (!data) { | ||
1358 | err = -ENOMEM; | ||
1359 | goto exit; | ||
1360 | } | ||
1361 | |||
1362 | pnp_set_drvdata(device, data); | ||
1363 | |||
1364 | data->ebase = pnp_port_start(device, 0); | ||
1365 | data->wbase = pnp_port_start(device, 1); | ||
1366 | data->sbase = pnp_port_start(device, 2); | ||
1367 | data->irq = pnp_irq(device, 0); | ||
1368 | |||
1369 | if (data->wbase == 0 || data->ebase == 0 || | ||
1370 | data->sbase == 0 || data->irq == 0) { | ||
1371 | err = -ENODEV; | ||
1372 | dev_err(dev, "Invalid resources\n"); | ||
1373 | goto exit_free_data; | ||
1374 | } | ||
1375 | |||
1376 | dev_dbg(&device->dev, "Found device " | ||
1377 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", | ||
1378 | data->wbase, data->ebase, data->sbase, data->irq); | ||
1379 | |||
1380 | if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { | ||
1381 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1382 | data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); | ||
1383 | err = -EBUSY; | ||
1384 | goto exit_free_data; | ||
1385 | } | ||
1386 | |||
1387 | if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { | ||
1388 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1389 | data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); | ||
1390 | err = -EBUSY; | ||
1391 | goto exit_release_wbase; | ||
1392 | } | ||
1393 | |||
1394 | if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { | ||
1395 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1396 | data->sbase, data->sbase + SP_IOMEM_LEN - 1); | ||
1397 | err = -EBUSY; | ||
1398 | goto exit_release_ebase; | ||
1399 | } | ||
1400 | |||
1401 | err = request_irq(data->irq, wbcir_irq_handler, | ||
1402 | IRQF_DISABLED, DRVNAME, device); | ||
1403 | if (err) { | ||
1404 | dev_err(dev, "Failed to claim IRQ %u\n", data->irq); | ||
1405 | err = -EBUSY; | ||
1406 | goto exit_release_sbase; | ||
1407 | } | ||
1408 | |||
1409 | led_trigger_register_simple("cir-tx", &data->txtrigger); | ||
1410 | if (!data->txtrigger) { | ||
1411 | err = -ENOMEM; | ||
1412 | goto exit_free_irq; | ||
1413 | } | ||
1414 | |||
1415 | led_trigger_register_simple("cir-rx", &data->rxtrigger); | ||
1416 | if (!data->rxtrigger) { | ||
1417 | err = -ENOMEM; | ||
1418 | goto exit_unregister_txtrigger; | ||
1419 | } | ||
1420 | |||
1421 | data->led.name = "cir::activity"; | ||
1422 | data->led.default_trigger = "cir-rx"; | ||
1423 | data->led.brightness_set = wbcir_led_brightness_set; | ||
1424 | data->led.brightness_get = wbcir_led_brightness_get; | ||
1425 | err = led_classdev_register(&device->dev, &data->led); | ||
1426 | if (err) | ||
1427 | goto exit_unregister_rxtrigger; | ||
1428 | |||
1429 | data->input_dev = input_allocate_device(); | ||
1430 | if (!data->input_dev) { | ||
1431 | err = -ENOMEM; | ||
1432 | goto exit_unregister_led; | ||
1433 | } | ||
1434 | |||
1435 | data->input_dev->evbit[0] = BIT(EV_KEY); | ||
1436 | data->input_dev->name = WBCIR_NAME; | ||
1437 | data->input_dev->phys = "wbcir/cir0"; | ||
1438 | data->input_dev->id.bustype = BUS_HOST; | ||
1439 | data->input_dev->id.vendor = PCI_VENDOR_ID_WINBOND; | ||
1440 | data->input_dev->id.product = WBCIR_ID_FAMILY; | ||
1441 | data->input_dev->id.version = WBCIR_ID_CHIP; | ||
1442 | data->input_dev->getkeycode = wbcir_getkeycode; | ||
1443 | data->input_dev->setkeycode = wbcir_setkeycode; | ||
1444 | input_set_capability(data->input_dev, EV_MSC, MSC_SCAN); | ||
1445 | input_set_drvdata(data->input_dev, data); | ||
1446 | |||
1447 | err = input_register_device(data->input_dev); | ||
1448 | if (err) | ||
1449 | goto exit_free_input; | ||
1450 | |||
1451 | data->last_scancode = INVALID_SCANCODE; | ||
1452 | INIT_LIST_HEAD(&data->keytable); | ||
1453 | setup_timer(&data->timer_keyup, wbcir_keyup, (unsigned long)data); | ||
1454 | |||
1455 | /* Load default keymaps */ | ||
1456 | if (protocol == IR_PROTOCOL_RC6) { | ||
1457 | int i; | ||
1458 | for (i = 0; i < ARRAY_SIZE(rc6_def_keymap); i++) { | ||
1459 | err = wbcir_setkeycode(data->input_dev, | ||
1460 | (int)rc6_def_keymap[i].scancode, | ||
1461 | (int)rc6_def_keymap[i].keycode); | ||
1462 | if (err) | ||
1463 | goto exit_unregister_keys; | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | device_init_wakeup(&device->dev, 1); | ||
1468 | |||
1469 | wbcir_init_hw(data); | ||
1470 | |||
1471 | return 0; | ||
1472 | |||
1473 | exit_unregister_keys: | ||
1474 | if (!list_empty(&data->keytable)) { | ||
1475 | struct wbcir_keyentry *key; | ||
1476 | struct wbcir_keyentry *keytmp; | ||
1477 | |||
1478 | list_for_each_entry_safe(key, keytmp, &data->keytable, list) { | ||
1479 | list_del(&key->list); | ||
1480 | kfree(key); | ||
1481 | } | ||
1482 | } | ||
1483 | input_unregister_device(data->input_dev); | ||
1484 | /* Can't call input_free_device on an unregistered device */ | ||
1485 | data->input_dev = NULL; | ||
1486 | exit_free_input: | ||
1487 | input_free_device(data->input_dev); | ||
1488 | exit_unregister_led: | ||
1489 | led_classdev_unregister(&data->led); | ||
1490 | exit_unregister_rxtrigger: | ||
1491 | led_trigger_unregister_simple(data->rxtrigger); | ||
1492 | exit_unregister_txtrigger: | ||
1493 | led_trigger_unregister_simple(data->txtrigger); | ||
1494 | exit_free_irq: | ||
1495 | free_irq(data->irq, device); | ||
1496 | exit_release_sbase: | ||
1497 | release_region(data->sbase, SP_IOMEM_LEN); | ||
1498 | exit_release_ebase: | ||
1499 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | ||
1500 | exit_release_wbase: | ||
1501 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | ||
1502 | exit_free_data: | ||
1503 | kfree(data); | ||
1504 | pnp_set_drvdata(device, NULL); | ||
1505 | exit: | ||
1506 | return err; | ||
1507 | } | ||
1508 | |||
1509 | static void __devexit | ||
1510 | wbcir_remove(struct pnp_dev *device) | ||
1511 | { | ||
1512 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1513 | struct wbcir_keyentry *key; | ||
1514 | struct wbcir_keyentry *keytmp; | ||
1515 | |||
1516 | /* Disable interrupts */ | ||
1517 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1518 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1519 | |||
1520 | del_timer_sync(&data->timer_keyup); | ||
1521 | |||
1522 | free_irq(data->irq, device); | ||
1523 | |||
1524 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1525 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1526 | |||
1527 | /* Clear CEIR_EN */ | ||
1528 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
1529 | |||
1530 | /* Clear BUFF_EN, END_EN, MATCH_EN */ | ||
1531 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1532 | |||
1533 | /* This will generate a keyup event if necessary */ | ||
1534 | input_unregister_device(data->input_dev); | ||
1535 | |||
1536 | led_trigger_unregister_simple(data->rxtrigger); | ||
1537 | led_trigger_unregister_simple(data->txtrigger); | ||
1538 | led_classdev_unregister(&data->led); | ||
1539 | |||
1540 | /* This is ok since &data->led isn't actually used */ | ||
1541 | wbcir_led_brightness_set(&data->led, LED_OFF); | ||
1542 | |||
1543 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | ||
1544 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | ||
1545 | release_region(data->sbase, SP_IOMEM_LEN); | ||
1546 | |||
1547 | list_for_each_entry_safe(key, keytmp, &data->keytable, list) { | ||
1548 | list_del(&key->list); | ||
1549 | kfree(key); | ||
1550 | } | ||
1551 | |||
1552 | kfree(data); | ||
1553 | |||
1554 | pnp_set_drvdata(device, NULL); | ||
1555 | } | ||
1556 | |||
1557 | static const struct pnp_device_id wbcir_ids[] = { | ||
1558 | { "WEC1022", 0 }, | ||
1559 | { "", 0 } | ||
1560 | }; | ||
1561 | MODULE_DEVICE_TABLE(pnp, wbcir_ids); | ||
1562 | |||
1563 | static struct pnp_driver wbcir_driver = { | ||
1564 | .name = WBCIR_NAME, | ||
1565 | .id_table = wbcir_ids, | ||
1566 | .probe = wbcir_probe, | ||
1567 | .remove = __devexit_p(wbcir_remove), | ||
1568 | .suspend = wbcir_suspend, | ||
1569 | .resume = wbcir_resume, | ||
1570 | .shutdown = wbcir_shutdown | ||
1571 | }; | ||
1572 | |||
1573 | static int __init | ||
1574 | wbcir_init(void) | ||
1575 | { | ||
1576 | int ret; | ||
1577 | |||
1578 | switch (protocol) { | ||
1579 | case IR_PROTOCOL_RC5: | ||
1580 | case IR_PROTOCOL_NEC: | ||
1581 | case IR_PROTOCOL_RC6: | ||
1582 | break; | ||
1583 | default: | ||
1584 | printk(KERN_ERR DRVNAME ": Invalid protocol argument\n"); | ||
1585 | return -EINVAL; | ||
1586 | } | ||
1587 | |||
1588 | ret = pnp_register_driver(&wbcir_driver); | ||
1589 | if (ret) | ||
1590 | printk(KERN_ERR DRVNAME ": Unable to register driver\n"); | ||
1591 | |||
1592 | return ret; | ||
1593 | } | ||
1594 | |||
1595 | static void __exit | ||
1596 | wbcir_exit(void) | ||
1597 | { | ||
1598 | pnp_unregister_driver(&wbcir_driver); | ||
1599 | } | ||
1600 | |||
1601 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); | ||
1602 | MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); | ||
1603 | MODULE_LICENSE("GPL"); | ||
1604 | |||
1605 | module_init(wbcir_init); | ||
1606 | module_exit(wbcir_exit); | ||
1607 | |||
1608 | |||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 12501de0c5cd..52b419348983 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -274,7 +274,7 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { | |||
274 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ | 274 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ |
275 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ | 275 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ |
276 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ | 276 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ |
277 | { KE_WIFI, 0x78 }, /* satelite dish button */ | 277 | { KE_WIFI, 0x78 }, /* satellite dish button */ |
278 | { KE_END, 0 } | 278 | { KE_END, 0 } |
279 | }; | 279 | }; |
280 | 280 | ||
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index e0c024db2ca5..62bae99424e6 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c | |||
@@ -11,11 +11,7 @@ | |||
11 | * more details. | 11 | * more details. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
15 | * TODO: | ||
16 | * | ||
17 | * Switch to grant tables together with xen-fbfront.c. | ||
18 | */ | ||
19 | 15 | ||
20 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
21 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
@@ -28,6 +24,8 @@ | |||
28 | #include <xen/xen.h> | 24 | #include <xen/xen.h> |
29 | #include <xen/events.h> | 25 | #include <xen/events.h> |
30 | #include <xen/page.h> | 26 | #include <xen/page.h> |
27 | #include <xen/grant_table.h> | ||
28 | #include <xen/interface/grant_table.h> | ||
31 | #include <xen/interface/io/fbif.h> | 29 | #include <xen/interface/io/fbif.h> |
32 | #include <xen/interface/io/kbdif.h> | 30 | #include <xen/interface/io/kbdif.h> |
33 | #include <xen/xenbus.h> | 31 | #include <xen/xenbus.h> |
@@ -36,6 +34,7 @@ struct xenkbd_info { | |||
36 | struct input_dev *kbd; | 34 | struct input_dev *kbd; |
37 | struct input_dev *ptr; | 35 | struct input_dev *ptr; |
38 | struct xenkbd_page *page; | 36 | struct xenkbd_page *page; |
37 | int gref; | ||
39 | int irq; | 38 | int irq; |
40 | struct xenbus_device *xbdev; | 39 | struct xenbus_device *xbdev; |
41 | char phys[32]; | 40 | char phys[32]; |
@@ -84,9 +83,8 @@ static irqreturn_t input_handler(int rq, void *dev_id) | |||
84 | input_report_key(dev, event->key.keycode, | 83 | input_report_key(dev, event->key.keycode, |
85 | event->key.pressed); | 84 | event->key.pressed); |
86 | else | 85 | else |
87 | printk(KERN_WARNING | 86 | pr_warning("unhandled keycode 0x%x\n", |
88 | "xenkbd: unhandled keycode 0x%x\n", | 87 | event->key.keycode); |
89 | event->key.keycode); | ||
90 | break; | 88 | break; |
91 | case XENKBD_TYPE_POS: | 89 | case XENKBD_TYPE_POS: |
92 | input_report_abs(dev, ABS_X, event->pos.abs_x); | 90 | input_report_abs(dev, ABS_X, event->pos.abs_x); |
@@ -109,7 +107,7 @@ static irqreturn_t input_handler(int rq, void *dev_id) | |||
109 | static int __devinit xenkbd_probe(struct xenbus_device *dev, | 107 | static int __devinit xenkbd_probe(struct xenbus_device *dev, |
110 | const struct xenbus_device_id *id) | 108 | const struct xenbus_device_id *id) |
111 | { | 109 | { |
112 | int ret, i; | 110 | int ret, i, abs; |
113 | struct xenkbd_info *info; | 111 | struct xenkbd_info *info; |
114 | struct input_dev *kbd, *ptr; | 112 | struct input_dev *kbd, *ptr; |
115 | 113 | ||
@@ -121,12 +119,18 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, | |||
121 | dev_set_drvdata(&dev->dev, info); | 119 | dev_set_drvdata(&dev->dev, info); |
122 | info->xbdev = dev; | 120 | info->xbdev = dev; |
123 | info->irq = -1; | 121 | info->irq = -1; |
122 | info->gref = -1; | ||
124 | snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); | 123 | snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); |
125 | 124 | ||
126 | info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); | 125 | info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); |
127 | if (!info->page) | 126 | if (!info->page) |
128 | goto error_nomem; | 127 | goto error_nomem; |
129 | 128 | ||
129 | if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0) | ||
130 | abs = 0; | ||
131 | if (abs) | ||
132 | xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1"); | ||
133 | |||
130 | /* keyboard */ | 134 | /* keyboard */ |
131 | kbd = input_allocate_device(); | 135 | kbd = input_allocate_device(); |
132 | if (!kbd) | 136 | if (!kbd) |
@@ -136,11 +140,12 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, | |||
136 | kbd->id.bustype = BUS_PCI; | 140 | kbd->id.bustype = BUS_PCI; |
137 | kbd->id.vendor = 0x5853; | 141 | kbd->id.vendor = 0x5853; |
138 | kbd->id.product = 0xffff; | 142 | kbd->id.product = 0xffff; |
139 | kbd->evbit[0] = BIT(EV_KEY); | 143 | |
144 | __set_bit(EV_KEY, kbd->evbit); | ||
140 | for (i = KEY_ESC; i < KEY_UNKNOWN; i++) | 145 | for (i = KEY_ESC; i < KEY_UNKNOWN; i++) |
141 | set_bit(i, kbd->keybit); | 146 | __set_bit(i, kbd->keybit); |
142 | for (i = KEY_OK; i < KEY_MAX; i++) | 147 | for (i = KEY_OK; i < KEY_MAX; i++) |
143 | set_bit(i, kbd->keybit); | 148 | __set_bit(i, kbd->keybit); |
144 | 149 | ||
145 | ret = input_register_device(kbd); | 150 | ret = input_register_device(kbd); |
146 | if (ret) { | 151 | if (ret) { |
@@ -159,12 +164,20 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, | |||
159 | ptr->id.bustype = BUS_PCI; | 164 | ptr->id.bustype = BUS_PCI; |
160 | ptr->id.vendor = 0x5853; | 165 | ptr->id.vendor = 0x5853; |
161 | ptr->id.product = 0xfffe; | 166 | ptr->id.product = 0xfffe; |
162 | ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); | 167 | |
168 | if (abs) { | ||
169 | __set_bit(EV_ABS, ptr->evbit); | ||
170 | input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); | ||
171 | input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); | ||
172 | } else { | ||
173 | input_set_capability(ptr, EV_REL, REL_X); | ||
174 | input_set_capability(ptr, EV_REL, REL_Y); | ||
175 | } | ||
176 | input_set_capability(ptr, EV_REL, REL_WHEEL); | ||
177 | |||
178 | __set_bit(EV_KEY, ptr->evbit); | ||
163 | for (i = BTN_LEFT; i <= BTN_TASK; i++) | 179 | for (i = BTN_LEFT; i <= BTN_TASK; i++) |
164 | set_bit(i, ptr->keybit); | 180 | __set_bit(i, ptr->keybit); |
165 | ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
166 | input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); | ||
167 | input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); | ||
168 | 181 | ||
169 | ret = input_register_device(ptr); | 182 | ret = input_register_device(ptr); |
170 | if (ret) { | 183 | if (ret) { |
@@ -217,15 +230,20 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, | |||
217 | int ret, evtchn; | 230 | int ret, evtchn; |
218 | struct xenbus_transaction xbt; | 231 | struct xenbus_transaction xbt; |
219 | 232 | ||
233 | ret = gnttab_grant_foreign_access(dev->otherend_id, | ||
234 | virt_to_mfn(info->page), 0); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | info->gref = ret; | ||
238 | |||
220 | ret = xenbus_alloc_evtchn(dev, &evtchn); | 239 | ret = xenbus_alloc_evtchn(dev, &evtchn); |
221 | if (ret) | 240 | if (ret) |
222 | return ret; | 241 | goto error_grant; |
223 | ret = bind_evtchn_to_irqhandler(evtchn, input_handler, | 242 | ret = bind_evtchn_to_irqhandler(evtchn, input_handler, |
224 | 0, dev->devicetype, info); | 243 | 0, dev->devicetype, info); |
225 | if (ret < 0) { | 244 | if (ret < 0) { |
226 | xenbus_free_evtchn(dev, evtchn); | ||
227 | xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); | 245 | xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); |
228 | return ret; | 246 | goto error_evtchan; |
229 | } | 247 | } |
230 | info->irq = ret; | 248 | info->irq = ret; |
231 | 249 | ||
@@ -233,12 +251,15 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, | |||
233 | ret = xenbus_transaction_start(&xbt); | 251 | ret = xenbus_transaction_start(&xbt); |
234 | if (ret) { | 252 | if (ret) { |
235 | xenbus_dev_fatal(dev, ret, "starting transaction"); | 253 | xenbus_dev_fatal(dev, ret, "starting transaction"); |
236 | return ret; | 254 | goto error_irqh; |
237 | } | 255 | } |
238 | ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", | 256 | ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", |
239 | virt_to_mfn(info->page)); | 257 | virt_to_mfn(info->page)); |
240 | if (ret) | 258 | if (ret) |
241 | goto error_xenbus; | 259 | goto error_xenbus; |
260 | ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref); | ||
261 | if (ret) | ||
262 | goto error_xenbus; | ||
242 | ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", | 263 | ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", |
243 | evtchn); | 264 | evtchn); |
244 | if (ret) | 265 | if (ret) |
@@ -248,7 +269,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, | |||
248 | if (ret == -EAGAIN) | 269 | if (ret == -EAGAIN) |
249 | goto again; | 270 | goto again; |
250 | xenbus_dev_fatal(dev, ret, "completing transaction"); | 271 | xenbus_dev_fatal(dev, ret, "completing transaction"); |
251 | return ret; | 272 | goto error_irqh; |
252 | } | 273 | } |
253 | 274 | ||
254 | xenbus_switch_state(dev, XenbusStateInitialised); | 275 | xenbus_switch_state(dev, XenbusStateInitialised); |
@@ -257,6 +278,14 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, | |||
257 | error_xenbus: | 278 | error_xenbus: |
258 | xenbus_transaction_end(xbt, 1); | 279 | xenbus_transaction_end(xbt, 1); |
259 | xenbus_dev_fatal(dev, ret, "writing xenstore"); | 280 | xenbus_dev_fatal(dev, ret, "writing xenstore"); |
281 | error_irqh: | ||
282 | unbind_from_irqhandler(info->irq, info); | ||
283 | info->irq = -1; | ||
284 | error_evtchan: | ||
285 | xenbus_free_evtchn(dev, evtchn); | ||
286 | error_grant: | ||
287 | gnttab_end_foreign_access_ref(info->gref, 0); | ||
288 | info->gref = -1; | ||
260 | return ret; | 289 | return ret; |
261 | } | 290 | } |
262 | 291 | ||
@@ -265,6 +294,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *info) | |||
265 | if (info->irq >= 0) | 294 | if (info->irq >= 0) |
266 | unbind_from_irqhandler(info->irq, info); | 295 | unbind_from_irqhandler(info->irq, info); |
267 | info->irq = -1; | 296 | info->irq = -1; |
297 | if (info->gref >= 0) | ||
298 | gnttab_end_foreign_access_ref(info->gref, 0); | ||
299 | info->gref = -1; | ||
268 | } | 300 | } |
269 | 301 | ||
270 | static void xenkbd_backend_changed(struct xenbus_device *dev, | 302 | static void xenkbd_backend_changed(struct xenbus_device *dev, |
@@ -292,9 +324,9 @@ InitWait: | |||
292 | ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, | 324 | ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, |
293 | "request-abs-pointer", "1"); | 325 | "request-abs-pointer", "1"); |
294 | if (ret) | 326 | if (ret) |
295 | printk(KERN_WARNING | 327 | pr_warning("xenkbd: can't request abs-pointer"); |
296 | "xenkbd: can't request abs-pointer"); | ||
297 | } | 328 | } |
329 | |||
298 | xenbus_switch_state(dev, XenbusStateConnected); | 330 | xenbus_switch_state(dev, XenbusStateConnected); |
299 | break; | 331 | break; |
300 | 332 | ||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index bf5fd7f6a313..9c1e6ee83531 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -39,7 +39,7 @@ config MOUSE_PS2 | |||
39 | module will be called psmouse. | 39 | module will be called psmouse. |
40 | 40 | ||
41 | config MOUSE_PS2_ALPS | 41 | config MOUSE_PS2_ALPS |
42 | bool "ALPS PS/2 mouse protocol extension" if EMBEDDED | 42 | bool "ALPS PS/2 mouse protocol extension" if EXPERT |
43 | default y | 43 | default y |
44 | depends on MOUSE_PS2 | 44 | depends on MOUSE_PS2 |
45 | help | 45 | help |
@@ -49,7 +49,7 @@ config MOUSE_PS2_ALPS | |||
49 | If unsure, say Y. | 49 | If unsure, say Y. |
50 | 50 | ||
51 | config MOUSE_PS2_LOGIPS2PP | 51 | config MOUSE_PS2_LOGIPS2PP |
52 | bool "Logitech PS/2++ mouse protocol extension" if EMBEDDED | 52 | bool "Logitech PS/2++ mouse protocol extension" if EXPERT |
53 | default y | 53 | default y |
54 | depends on MOUSE_PS2 | 54 | depends on MOUSE_PS2 |
55 | help | 55 | help |
@@ -59,7 +59,7 @@ config MOUSE_PS2_LOGIPS2PP | |||
59 | If unsure, say Y. | 59 | If unsure, say Y. |
60 | 60 | ||
61 | config MOUSE_PS2_SYNAPTICS | 61 | config MOUSE_PS2_SYNAPTICS |
62 | bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED | 62 | bool "Synaptics PS/2 mouse protocol extension" if EXPERT |
63 | default y | 63 | default y |
64 | depends on MOUSE_PS2 | 64 | depends on MOUSE_PS2 |
65 | help | 65 | help |
@@ -69,7 +69,7 @@ config MOUSE_PS2_SYNAPTICS | |||
69 | If unsure, say Y. | 69 | If unsure, say Y. |
70 | 70 | ||
71 | config MOUSE_PS2_LIFEBOOK | 71 | config MOUSE_PS2_LIFEBOOK |
72 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 72 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT |
73 | default y | 73 | default y |
74 | depends on MOUSE_PS2 && X86 && DMI | 74 | depends on MOUSE_PS2 && X86 && DMI |
75 | help | 75 | help |
@@ -79,7 +79,7 @@ config MOUSE_PS2_LIFEBOOK | |||
79 | If unsure, say Y. | 79 | If unsure, say Y. |
80 | 80 | ||
81 | config MOUSE_PS2_TRACKPOINT | 81 | config MOUSE_PS2_TRACKPOINT |
82 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED | 82 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EXPERT |
83 | default y | 83 | default y |
84 | depends on MOUSE_PS2 | 84 | depends on MOUSE_PS2 |
85 | help | 85 | help |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b95231763911..3126983c004a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -55,6 +55,18 @@ | |||
55 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | 55 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 |
56 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | 56 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 |
57 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | 57 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 |
58 | /* MacbookAir3,2 (unibody), aka wellspring5 */ | ||
59 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f | ||
60 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 | ||
61 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 | ||
62 | /* MacbookAir3,1 (unibody), aka wellspring4 */ | ||
63 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 | ||
64 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 | ||
65 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 | ||
66 | /* Macbook8 (unibody, March 2011) */ | ||
67 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 | ||
68 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 | ||
69 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 | ||
58 | 70 | ||
59 | #define BCM5974_DEVICE(prod) { \ | 71 | #define BCM5974_DEVICE(prod) { \ |
60 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | 72 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ |
@@ -80,6 +92,18 @@ static const struct usb_device_id bcm5974_table[] = { | |||
80 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), | 92 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), |
81 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), | 93 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), |
82 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | 94 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), |
95 | /* MacbookAir3,2 */ | ||
96 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), | ||
97 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), | ||
98 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), | ||
99 | /* MacbookAir3,1 */ | ||
100 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), | ||
101 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), | ||
102 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), | ||
103 | /* MacbookPro8 */ | ||
104 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), | ||
105 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), | ||
106 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), | ||
83 | /* Terminating entry */ | 107 | /* Terminating entry */ |
84 | {} | 108 | {} |
85 | }; | 109 | }; |
@@ -234,6 +258,42 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
234 | { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, | 258 | { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, |
235 | { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } | 259 | { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } |
236 | }, | 260 | }, |
261 | { | ||
262 | USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, | ||
263 | USB_DEVICE_ID_APPLE_WELLSPRING4_ISO, | ||
264 | USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, | ||
265 | HAS_INTEGRATED_BUTTON, | ||
266 | 0x84, sizeof(struct bt_data), | ||
267 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
268 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
269 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
270 | { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, | ||
271 | { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } | ||
272 | }, | ||
273 | { | ||
274 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, | ||
275 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO, | ||
276 | USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, | ||
277 | HAS_INTEGRATED_BUTTON, | ||
278 | 0x84, sizeof(struct bt_data), | ||
279 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
280 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
281 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
282 | { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, | ||
283 | { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } | ||
284 | }, | ||
285 | { | ||
286 | USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, | ||
287 | USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, | ||
288 | USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, | ||
289 | HAS_INTEGRATED_BUTTON, | ||
290 | 0x84, sizeof(struct bt_data), | ||
291 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
292 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
293 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
294 | { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, | ||
295 | { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } | ||
296 | }, | ||
237 | {} | 297 | {} |
238 | }; | 298 | }; |
239 | 299 | ||
@@ -390,10 +450,6 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
390 | ptest = int2bound(&c->p, raw_p); | 450 | ptest = int2bound(&c->p, raw_p); |
391 | origin = raw2int(f->origin); | 451 | origin = raw2int(f->origin); |
392 | 452 | ||
393 | /* set the integrated button if applicable */ | ||
394 | if (c->tp_type == TYPE2) | ||
395 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | ||
396 | |||
397 | /* while tracking finger still valid, count all fingers */ | 453 | /* while tracking finger still valid, count all fingers */ |
398 | if (ptest > PRESSURE_LOW && origin) { | 454 | if (ptest > PRESSURE_LOW && origin) { |
399 | abs_p = ptest; | 455 | abs_p = ptest; |
@@ -412,6 +468,10 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
412 | } | 468 | } |
413 | } | 469 | } |
414 | 470 | ||
471 | /* set the integrated button if applicable */ | ||
472 | if (c->tp_type == TYPE2) | ||
473 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | ||
474 | |||
415 | if (dev->fingers < nmin) | 475 | if (dev->fingers < nmin) |
416 | dev->fingers = nmin; | 476 | dev->fingers = nmin; |
417 | if (dev->fingers > nmax) | 477 | if (dev->fingers > nmax) |
@@ -579,7 +639,7 @@ exit: | |||
579 | * device, resulting in trackpad malfunction under certain | 639 | * device, resulting in trackpad malfunction under certain |
580 | * circumstances. To get around this problem, there is at least one | 640 | * circumstances. To get around this problem, there is at least one |
581 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to | 641 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to |
582 | * recieve a reset_resume request rather than the normal resume. | 642 | * receive a reset_resume request rather than the normal resume. |
583 | * Since the implementation of reset_resume is equal to mode switch | 643 | * Since the implementation of reset_resume is equal to mode switch |
584 | * plus start_traffic, it seems easier to always do the switch when | 644 | * plus start_traffic, it seems easier to always do the switch when |
585 | * starting traffic on the device. | 645 | * starting traffic on the device. |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 1d2205b24800..95577c15ae56 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include "psmouse.h" | 40 | #include "psmouse.h" |
41 | #include "hgpk.h" | 41 | #include "hgpk.h" |
42 | 42 | ||
43 | #define ILLEGAL_XY 999999 | ||
44 | |||
43 | static bool tpdebug; | 45 | static bool tpdebug; |
44 | module_param(tpdebug, bool, 0644); | 46 | module_param(tpdebug, bool, 0644); |
45 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | 47 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); |
@@ -47,48 +49,150 @@ MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | |||
47 | static int recalib_delta = 100; | 49 | static int recalib_delta = 100; |
48 | module_param(recalib_delta, int, 0644); | 50 | module_param(recalib_delta, int, 0644); |
49 | MODULE_PARM_DESC(recalib_delta, | 51 | MODULE_PARM_DESC(recalib_delta, |
50 | "packets containing a delta this large will cause a recalibration."); | 52 | "packets containing a delta this large will be discarded, and a " |
53 | "recalibration may be scheduled."); | ||
51 | 54 | ||
52 | static int jumpy_delay = 1000; | 55 | static int jumpy_delay = 20; |
53 | module_param(jumpy_delay, int, 0644); | 56 | module_param(jumpy_delay, int, 0644); |
54 | MODULE_PARM_DESC(jumpy_delay, | 57 | MODULE_PARM_DESC(jumpy_delay, |
55 | "delay (ms) before recal after jumpiness detected"); | 58 | "delay (ms) before recal after jumpiness detected"); |
56 | 59 | ||
57 | static int spew_delay = 1000; | 60 | static int spew_delay = 1; |
58 | module_param(spew_delay, int, 0644); | 61 | module_param(spew_delay, int, 0644); |
59 | MODULE_PARM_DESC(spew_delay, | 62 | MODULE_PARM_DESC(spew_delay, |
60 | "delay (ms) before recal after packet spew detected"); | 63 | "delay (ms) before recal after packet spew detected"); |
61 | 64 | ||
62 | static int recal_guard_time = 2000; | 65 | static int recal_guard_time; |
63 | module_param(recal_guard_time, int, 0644); | 66 | module_param(recal_guard_time, int, 0644); |
64 | MODULE_PARM_DESC(recal_guard_time, | 67 | MODULE_PARM_DESC(recal_guard_time, |
65 | "interval (ms) during which recal will be restarted if packet received"); | 68 | "interval (ms) during which recal will be restarted if packet received"); |
66 | 69 | ||
67 | static int post_interrupt_delay = 1000; | 70 | static int post_interrupt_delay = 40; |
68 | module_param(post_interrupt_delay, int, 0644); | 71 | module_param(post_interrupt_delay, int, 0644); |
69 | MODULE_PARM_DESC(post_interrupt_delay, | 72 | MODULE_PARM_DESC(post_interrupt_delay, |
70 | "delay (ms) before recal after recal interrupt detected"); | 73 | "delay (ms) before recal after recal interrupt detected"); |
71 | 74 | ||
75 | static bool autorecal = true; | ||
76 | module_param(autorecal, bool, 0644); | ||
77 | MODULE_PARM_DESC(autorecal, "enable recalibration in the driver"); | ||
78 | |||
79 | static char hgpk_mode_name[16]; | ||
80 | module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644); | ||
81 | MODULE_PARM_DESC(hgpk_mode, | ||
82 | "default hgpk mode: mouse, glidesensor or pentablet"); | ||
83 | |||
84 | static int hgpk_default_mode = HGPK_MODE_MOUSE; | ||
85 | |||
86 | static const char * const hgpk_mode_names[] = { | ||
87 | [HGPK_MODE_MOUSE] = "Mouse", | ||
88 | [HGPK_MODE_GLIDESENSOR] = "GlideSensor", | ||
89 | [HGPK_MODE_PENTABLET] = "PenTablet", | ||
90 | }; | ||
91 | |||
92 | static int hgpk_mode_from_name(const char *buf, int len) | ||
93 | { | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) { | ||
97 | const char *name = hgpk_mode_names[i]; | ||
98 | if (strlen(name) == len && !strncasecmp(name, buf, len)) | ||
99 | return i; | ||
100 | } | ||
101 | |||
102 | return HGPK_MODE_INVALID; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * see if new value is within 20% of half of old value | ||
107 | */ | ||
108 | static int approx_half(int curr, int prev) | ||
109 | { | ||
110 | int belowhalf, abovehalf; | ||
111 | |||
112 | if (curr < 5 || prev < 5) | ||
113 | return 0; | ||
114 | |||
115 | belowhalf = (prev * 8) / 20; | ||
116 | abovehalf = (prev * 12) / 20; | ||
117 | |||
118 | return belowhalf < curr && curr <= abovehalf; | ||
119 | } | ||
120 | |||
72 | /* | 121 | /* |
73 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" | 122 | * Throw out oddly large delta packets, and any that immediately follow whose |
74 | * above the pad and still have it send packets. This causes a jump cursor | 123 | * values are each approximately half of the previous. It seems that the ALPS |
75 | * when one places their finger on the pad. We can probably detect the | 124 | * firmware emits errant packets, and they get averaged out slowly. |
76 | * jump as we see a large deltas (>= 100px). In mouse mode, I've been | ||
77 | * unable to even come close to 100px deltas during normal usage, so I think | ||
78 | * this threshold is safe. If a large delta occurs, trigger a recalibration. | ||
79 | */ | 125 | */ |
80 | static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) | 126 | static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) |
81 | { | 127 | { |
82 | struct hgpk_data *priv = psmouse->private; | 128 | struct hgpk_data *priv = psmouse->private; |
129 | int avx, avy; | ||
130 | bool do_recal = false; | ||
131 | |||
132 | avx = abs(x); | ||
133 | avy = abs(y); | ||
134 | |||
135 | /* discard if too big, or half that but > 4 times the prev delta */ | ||
136 | if (avx > recalib_delta || | ||
137 | (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) { | ||
138 | hgpk_err(psmouse, "detected %dpx jump in x\n", x); | ||
139 | priv->xbigj = avx; | ||
140 | } else if (approx_half(avx, priv->xbigj)) { | ||
141 | hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x); | ||
142 | priv->xbigj = avx; | ||
143 | priv->xsaw_secondary++; | ||
144 | } else { | ||
145 | if (priv->xbigj && priv->xsaw_secondary > 1) | ||
146 | do_recal = true; | ||
147 | priv->xbigj = 0; | ||
148 | priv->xsaw_secondary = 0; | ||
149 | } | ||
150 | |||
151 | if (avy > recalib_delta || | ||
152 | (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) { | ||
153 | hgpk_err(psmouse, "detected %dpx jump in y\n", y); | ||
154 | priv->ybigj = avy; | ||
155 | } else if (approx_half(avy, priv->ybigj)) { | ||
156 | hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y); | ||
157 | priv->ybigj = avy; | ||
158 | priv->ysaw_secondary++; | ||
159 | } else { | ||
160 | if (priv->ybigj && priv->ysaw_secondary > 1) | ||
161 | do_recal = true; | ||
162 | priv->ybigj = 0; | ||
163 | priv->ysaw_secondary = 0; | ||
164 | } | ||
83 | 165 | ||
84 | if (abs(x) > recalib_delta || abs(y) > recalib_delta) { | 166 | priv->xlast = avx; |
85 | hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n", | 167 | priv->ylast = avy; |
86 | recalib_delta, x, y); | 168 | |
87 | /* My car gets forty rods to the hogshead and that's the | 169 | if (do_recal && jumpy_delay) { |
88 | * way I likes it! */ | 170 | hgpk_err(psmouse, "scheduling recalibration\n"); |
89 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 171 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
90 | msecs_to_jiffies(jumpy_delay)); | 172 | msecs_to_jiffies(jumpy_delay)); |
91 | } | 173 | } |
174 | |||
175 | return priv->xbigj || priv->ybigj; | ||
176 | } | ||
177 | |||
178 | static void hgpk_reset_spew_detection(struct hgpk_data *priv) | ||
179 | { | ||
180 | priv->spew_count = 0; | ||
181 | priv->dupe_count = 0; | ||
182 | priv->x_tally = 0; | ||
183 | priv->y_tally = 0; | ||
184 | priv->spew_flag = NO_SPEW; | ||
185 | } | ||
186 | |||
187 | static void hgpk_reset_hack_state(struct psmouse *psmouse) | ||
188 | { | ||
189 | struct hgpk_data *priv = psmouse->private; | ||
190 | |||
191 | priv->abs_x = priv->abs_y = -1; | ||
192 | priv->xlast = priv->ylast = ILLEGAL_XY; | ||
193 | priv->xbigj = priv->ybigj = 0; | ||
194 | priv->xsaw_secondary = priv->ysaw_secondary = 0; | ||
195 | hgpk_reset_spew_detection(priv); | ||
92 | } | 196 | } |
93 | 197 | ||
94 | /* | 198 | /* |
@@ -116,20 +220,57 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, | |||
116 | if (l || r) | 220 | if (l || r) |
117 | return; | 221 | return; |
118 | 222 | ||
223 | /* don't track spew if the workaround feature has been turned off */ | ||
224 | if (!spew_delay) | ||
225 | return; | ||
226 | |||
227 | if (abs(x) > 3 || abs(y) > 3) { | ||
228 | /* no spew, or spew ended */ | ||
229 | hgpk_reset_spew_detection(priv); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | /* Keep a tally of the overall delta to the cursor position caused by | ||
234 | * the spew */ | ||
119 | priv->x_tally += x; | 235 | priv->x_tally += x; |
120 | priv->y_tally += y; | 236 | priv->y_tally += y; |
121 | 237 | ||
122 | if (++priv->count > 100) { | 238 | switch (priv->spew_flag) { |
239 | case NO_SPEW: | ||
240 | /* we're not spewing, but this packet might be the start */ | ||
241 | priv->spew_flag = MAYBE_SPEWING; | ||
242 | |||
243 | /* fall-through */ | ||
244 | |||
245 | case MAYBE_SPEWING: | ||
246 | priv->spew_count++; | ||
247 | |||
248 | if (priv->spew_count < SPEW_WATCH_COUNT) | ||
249 | break; | ||
250 | |||
251 | /* excessive spew detected, request recalibration */ | ||
252 | priv->spew_flag = SPEW_DETECTED; | ||
253 | |||
254 | /* fall-through */ | ||
255 | |||
256 | case SPEW_DETECTED: | ||
257 | /* only recalibrate when the overall delta to the cursor | ||
258 | * is really small. if the spew is causing significant cursor | ||
259 | * movement, it is probably a case of the user moving the | ||
260 | * cursor very slowly across the screen. */ | ||
123 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { | 261 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { |
124 | hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", | 262 | hgpk_err(psmouse, "packet spew detected (%d,%d)\n", |
125 | priv->x_tally, priv->y_tally); | 263 | priv->x_tally, priv->y_tally); |
264 | priv->spew_flag = RECALIBRATING; | ||
126 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 265 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
127 | msecs_to_jiffies(spew_delay)); | 266 | msecs_to_jiffies(spew_delay)); |
128 | } | 267 | } |
129 | /* reset every 100 packets */ | 268 | |
130 | priv->count = 0; | 269 | break; |
131 | priv->x_tally = 0; | 270 | case RECALIBRATING: |
132 | priv->y_tally = 0; | 271 | /* we already detected a spew and requested a recalibration, |
272 | * just wait for the queue to kick into action. */ | ||
273 | break; | ||
133 | } | 274 | } |
134 | } | 275 | } |
135 | 276 | ||
@@ -143,25 +284,168 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, | |||
143 | * swr/swl are the left/right buttons. | 284 | * swr/swl are the left/right buttons. |
144 | * x-neg/y-neg are the x and y delta negative bits | 285 | * x-neg/y-neg are the x and y delta negative bits |
145 | * x-over/y-over are the x and y overflow bits | 286 | * x-over/y-over are the x and y overflow bits |
287 | * | ||
288 | * --- | ||
289 | * | ||
290 | * HGPK Advanced Mode - single-mode format | ||
291 | * | ||
292 | * byte 0(PT): 1 1 0 0 1 1 1 1 | ||
293 | * byte 0(GS): 1 1 1 1 1 1 1 1 | ||
294 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | ||
295 | * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw 0 | ||
296 | * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw | ||
297 | * byte 3: 0 y9 y8 y7 1 0 swr swl | ||
298 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | ||
299 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | ||
300 | * | ||
301 | * ?'s are not defined in the protocol spec, may vary between models. | ||
302 | * | ||
303 | * swr/swl are the left/right buttons. | ||
304 | * | ||
305 | * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a | ||
306 | * pen/finger | ||
146 | */ | 307 | */ |
147 | static int hgpk_validate_byte(unsigned char *packet) | 308 | static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) |
148 | { | 309 | { |
149 | return (packet[0] & 0x0C) != 0x08; | 310 | struct hgpk_data *priv = psmouse->private; |
311 | int pktcnt = psmouse->pktcnt; | ||
312 | bool valid; | ||
313 | |||
314 | switch (priv->mode) { | ||
315 | case HGPK_MODE_MOUSE: | ||
316 | valid = (packet[0] & 0x0C) == 0x08; | ||
317 | break; | ||
318 | |||
319 | case HGPK_MODE_GLIDESENSOR: | ||
320 | valid = pktcnt == 1 ? | ||
321 | packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80); | ||
322 | break; | ||
323 | |||
324 | case HGPK_MODE_PENTABLET: | ||
325 | valid = pktcnt == 1 ? | ||
326 | packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80); | ||
327 | break; | ||
328 | |||
329 | default: | ||
330 | valid = false; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (!valid) | ||
335 | hgpk_dbg(psmouse, | ||
336 | "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", | ||
337 | priv->mode, pktcnt, | ||
338 | psmouse->packet[0], psmouse->packet[1], | ||
339 | psmouse->packet[2], psmouse->packet[3], | ||
340 | psmouse->packet[4], psmouse->packet[5]); | ||
341 | |||
342 | return valid; | ||
150 | } | 343 | } |
151 | 344 | ||
152 | static void hgpk_process_packet(struct psmouse *psmouse) | 345 | static void hgpk_process_advanced_packet(struct psmouse *psmouse) |
153 | { | 346 | { |
154 | struct input_dev *dev = psmouse->dev; | 347 | struct hgpk_data *priv = psmouse->private; |
348 | struct input_dev *idev = psmouse->dev; | ||
155 | unsigned char *packet = psmouse->packet; | 349 | unsigned char *packet = psmouse->packet; |
156 | int x, y, left, right; | 350 | int down = !!(packet[2] & 2); |
351 | int left = !!(packet[3] & 1); | ||
352 | int right = !!(packet[3] & 2); | ||
353 | int x = packet[1] | ((packet[2] & 0x78) << 4); | ||
354 | int y = packet[4] | ((packet[3] & 0x70) << 3); | ||
355 | |||
356 | if (priv->mode == HGPK_MODE_GLIDESENSOR) { | ||
357 | int pt_down = !!(packet[2] & 1); | ||
358 | int finger_down = !!(packet[2] & 2); | ||
359 | int z = packet[5]; | ||
360 | |||
361 | input_report_abs(idev, ABS_PRESSURE, z); | ||
362 | if (tpdebug) | ||
363 | hgpk_dbg(psmouse, "pd=%d fd=%d z=%d", | ||
364 | pt_down, finger_down, z); | ||
365 | } else { | ||
366 | /* | ||
367 | * PenTablet mode does not report pressure, so we don't | ||
368 | * report it here | ||
369 | */ | ||
370 | if (tpdebug) | ||
371 | hgpk_dbg(psmouse, "pd=%d ", down); | ||
372 | } | ||
373 | |||
374 | if (tpdebug) | ||
375 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | ||
376 | |||
377 | input_report_key(idev, BTN_TOUCH, down); | ||
378 | input_report_key(idev, BTN_LEFT, left); | ||
379 | input_report_key(idev, BTN_RIGHT, right); | ||
380 | |||
381 | /* | ||
382 | * If this packet says that the finger was removed, reset our position | ||
383 | * tracking so that we don't erroneously detect a jump on next press. | ||
384 | */ | ||
385 | if (!down) { | ||
386 | hgpk_reset_hack_state(psmouse); | ||
387 | goto done; | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * Weed out duplicate packets (we get quite a few, and they mess up | ||
392 | * our jump detection) | ||
393 | */ | ||
394 | if (x == priv->abs_x && y == priv->abs_y) { | ||
395 | if (++priv->dupe_count > SPEW_WATCH_COUNT) { | ||
396 | if (tpdebug) | ||
397 | hgpk_dbg(psmouse, "hard spew detected\n"); | ||
398 | priv->spew_flag = RECALIBRATING; | ||
399 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
400 | msecs_to_jiffies(spew_delay)); | ||
401 | } | ||
402 | goto done; | ||
403 | } | ||
157 | 404 | ||
158 | left = packet[0] & 1; | 405 | /* not a duplicate, continue with position reporting */ |
159 | right = (packet[0] >> 1) & 1; | 406 | priv->dupe_count = 0; |
407 | |||
408 | /* Don't apply hacks in PT mode, it seems reliable */ | ||
409 | if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) { | ||
410 | int x_diff = priv->abs_x - x; | ||
411 | int y_diff = priv->abs_y - y; | ||
412 | if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) { | ||
413 | if (tpdebug) | ||
414 | hgpk_dbg(psmouse, "discarding\n"); | ||
415 | goto done; | ||
416 | } | ||
417 | hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff); | ||
418 | } | ||
160 | 419 | ||
161 | x = packet[1] - ((packet[0] << 4) & 0x100); | 420 | input_report_abs(idev, ABS_X, x); |
162 | y = ((packet[0] << 3) & 0x100) - packet[2]; | 421 | input_report_abs(idev, ABS_Y, y); |
422 | priv->abs_x = x; | ||
423 | priv->abs_y = y; | ||
424 | |||
425 | done: | ||
426 | input_sync(idev); | ||
427 | } | ||
428 | |||
429 | static void hgpk_process_simple_packet(struct psmouse *psmouse) | ||
430 | { | ||
431 | struct input_dev *dev = psmouse->dev; | ||
432 | unsigned char *packet = psmouse->packet; | ||
433 | int left = packet[0] & 1; | ||
434 | int right = (packet[0] >> 1) & 1; | ||
435 | int x = packet[1] - ((packet[0] << 4) & 0x100); | ||
436 | int y = ((packet[0] << 3) & 0x100) - packet[2]; | ||
437 | |||
438 | if (packet[0] & 0xc0) | ||
439 | hgpk_dbg(psmouse, | ||
440 | "overflow -- 0x%02x 0x%02x 0x%02x\n", | ||
441 | packet[0], packet[1], packet[2]); | ||
442 | |||
443 | if (hgpk_discard_decay_hack(psmouse, x, y)) { | ||
444 | if (tpdebug) | ||
445 | hgpk_dbg(psmouse, "discarding\n"); | ||
446 | return; | ||
447 | } | ||
163 | 448 | ||
164 | hgpk_jumpy_hack(psmouse, x, y); | ||
165 | hgpk_spewing_hack(psmouse, left, right, x, y); | 449 | hgpk_spewing_hack(psmouse, left, right, x, y); |
166 | 450 | ||
167 | if (tpdebug) | 451 | if (tpdebug) |
@@ -180,15 +464,14 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | |||
180 | { | 464 | { |
181 | struct hgpk_data *priv = psmouse->private; | 465 | struct hgpk_data *priv = psmouse->private; |
182 | 466 | ||
183 | if (hgpk_validate_byte(psmouse->packet)) { | 467 | if (!hgpk_is_byte_valid(psmouse, psmouse->packet)) |
184 | hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n", | ||
185 | __func__, psmouse->pktcnt, psmouse->packet[0], | ||
186 | psmouse->packet[1], psmouse->packet[2]); | ||
187 | return PSMOUSE_BAD_DATA; | 468 | return PSMOUSE_BAD_DATA; |
188 | } | ||
189 | 469 | ||
190 | if (psmouse->pktcnt >= psmouse->pktsize) { | 470 | if (psmouse->pktcnt >= psmouse->pktsize) { |
191 | hgpk_process_packet(psmouse); | 471 | if (priv->mode == HGPK_MODE_MOUSE) |
472 | hgpk_process_simple_packet(psmouse); | ||
473 | else | ||
474 | hgpk_process_advanced_packet(psmouse); | ||
192 | return PSMOUSE_FULL_PACKET; | 475 | return PSMOUSE_FULL_PACKET; |
193 | } | 476 | } |
194 | 477 | ||
@@ -210,33 +493,176 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | |||
210 | return PSMOUSE_GOOD_DATA; | 493 | return PSMOUSE_GOOD_DATA; |
211 | } | 494 | } |
212 | 495 | ||
496 | static int hgpk_select_mode(struct psmouse *psmouse) | ||
497 | { | ||
498 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
499 | struct hgpk_data *priv = psmouse->private; | ||
500 | int i; | ||
501 | int cmd; | ||
502 | |||
503 | /* | ||
504 | * 4 disables to enable advanced mode | ||
505 | * then 3 0xf2 bytes as the preamble for GS/PT selection | ||
506 | */ | ||
507 | const int advanced_init[] = { | ||
508 | PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, | ||
509 | PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, | ||
510 | 0xf2, 0xf2, 0xf2, | ||
511 | }; | ||
512 | |||
513 | switch (priv->mode) { | ||
514 | case HGPK_MODE_MOUSE: | ||
515 | psmouse->pktsize = 3; | ||
516 | break; | ||
517 | |||
518 | case HGPK_MODE_GLIDESENSOR: | ||
519 | case HGPK_MODE_PENTABLET: | ||
520 | psmouse->pktsize = 6; | ||
521 | |||
522 | /* Switch to 'Advanced mode.', four disables in a row. */ | ||
523 | for (i = 0; i < ARRAY_SIZE(advanced_init); i++) | ||
524 | if (ps2_command(ps2dev, NULL, advanced_init[i])) | ||
525 | return -EIO; | ||
526 | |||
527 | /* select between GlideSensor (mouse) or PenTablet */ | ||
528 | cmd = priv->mode == HGPK_MODE_GLIDESENSOR ? | ||
529 | PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21; | ||
530 | |||
531 | if (ps2_command(ps2dev, NULL, cmd)) | ||
532 | return -EIO; | ||
533 | break; | ||
534 | |||
535 | default: | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static void hgpk_setup_input_device(struct input_dev *input, | ||
543 | struct input_dev *old_input, | ||
544 | enum hgpk_mode mode) | ||
545 | { | ||
546 | if (old_input) { | ||
547 | input->name = old_input->name; | ||
548 | input->phys = old_input->phys; | ||
549 | input->id = old_input->id; | ||
550 | input->dev.parent = old_input->dev.parent; | ||
551 | } | ||
552 | |||
553 | memset(input->evbit, 0, sizeof(input->evbit)); | ||
554 | memset(input->relbit, 0, sizeof(input->relbit)); | ||
555 | memset(input->keybit, 0, sizeof(input->keybit)); | ||
556 | |||
557 | /* All modes report left and right buttons */ | ||
558 | __set_bit(EV_KEY, input->evbit); | ||
559 | __set_bit(BTN_LEFT, input->keybit); | ||
560 | __set_bit(BTN_RIGHT, input->keybit); | ||
561 | |||
562 | switch (mode) { | ||
563 | case HGPK_MODE_MOUSE: | ||
564 | __set_bit(EV_REL, input->evbit); | ||
565 | __set_bit(REL_X, input->relbit); | ||
566 | __set_bit(REL_Y, input->relbit); | ||
567 | break; | ||
568 | |||
569 | case HGPK_MODE_GLIDESENSOR: | ||
570 | __set_bit(BTN_TOUCH, input->keybit); | ||
571 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
572 | |||
573 | __set_bit(EV_ABS, input->evbit); | ||
574 | |||
575 | /* GlideSensor has pressure sensor, PenTablet does not */ | ||
576 | input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0); | ||
577 | |||
578 | /* From device specs */ | ||
579 | input_set_abs_params(input, ABS_X, 0, 399, 0, 0); | ||
580 | input_set_abs_params(input, ABS_Y, 0, 290, 0, 0); | ||
581 | |||
582 | /* Calculated by hand based on usable size (52mm x 38mm) */ | ||
583 | input_abs_set_res(input, ABS_X, 8); | ||
584 | input_abs_set_res(input, ABS_Y, 8); | ||
585 | break; | ||
586 | |||
587 | case HGPK_MODE_PENTABLET: | ||
588 | __set_bit(BTN_TOUCH, input->keybit); | ||
589 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
590 | |||
591 | __set_bit(EV_ABS, input->evbit); | ||
592 | |||
593 | /* From device specs */ | ||
594 | input_set_abs_params(input, ABS_X, 0, 999, 0, 0); | ||
595 | input_set_abs_params(input, ABS_Y, 5, 239, 0, 0); | ||
596 | |||
597 | /* Calculated by hand based on usable size (156mm x 38mm) */ | ||
598 | input_abs_set_res(input, ABS_X, 6); | ||
599 | input_abs_set_res(input, ABS_Y, 8); | ||
600 | break; | ||
601 | |||
602 | default: | ||
603 | BUG(); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) | ||
608 | { | ||
609 | int err; | ||
610 | |||
611 | psmouse_reset(psmouse); | ||
612 | |||
613 | if (recalibrate) { | ||
614 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
615 | |||
616 | /* send the recalibrate request */ | ||
617 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
618 | ps2_command(ps2dev, NULL, 0xf5) || | ||
619 | ps2_command(ps2dev, NULL, 0xe6) || | ||
620 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
621 | return -1; | ||
622 | } | ||
623 | |||
624 | /* according to ALPS, 150mS is required for recalibration */ | ||
625 | msleep(150); | ||
626 | } | ||
627 | |||
628 | err = hgpk_select_mode(psmouse); | ||
629 | if (err) { | ||
630 | hgpk_err(psmouse, "failed to select mode\n"); | ||
631 | return err; | ||
632 | } | ||
633 | |||
634 | hgpk_reset_hack_state(psmouse); | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
213 | static int hgpk_force_recalibrate(struct psmouse *psmouse) | 639 | static int hgpk_force_recalibrate(struct psmouse *psmouse) |
214 | { | 640 | { |
215 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 641 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
216 | struct hgpk_data *priv = psmouse->private; | 642 | struct hgpk_data *priv = psmouse->private; |
643 | int err; | ||
217 | 644 | ||
218 | /* C-series touchpads added the recalibrate command */ | 645 | /* C-series touchpads added the recalibrate command */ |
219 | if (psmouse->model < HGPK_MODEL_C) | 646 | if (psmouse->model < HGPK_MODEL_C) |
220 | return 0; | 647 | return 0; |
221 | 648 | ||
649 | if (!autorecal) { | ||
650 | hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n"); | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
655 | |||
222 | /* we don't want to race with the irq handler, nor with resyncs */ | 656 | /* we don't want to race with the irq handler, nor with resyncs */ |
223 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 657 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
224 | 658 | ||
225 | /* start by resetting the device */ | 659 | /* start by resetting the device */ |
226 | psmouse_reset(psmouse); | 660 | err = hgpk_reset_device(psmouse, true); |
227 | 661 | if (err) | |
228 | /* send the recalibrate request */ | 662 | return err; |
229 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
230 | ps2_command(ps2dev, NULL, 0xf5) || | ||
231 | ps2_command(ps2dev, NULL, 0xe6) || | ||
232 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
233 | return -1; | ||
234 | } | ||
235 | |||
236 | /* according to ALPS, 150mS is required for recalibration */ | ||
237 | msleep(150); | ||
238 | 663 | ||
239 | /* XXX: If a finger is down during this delay, recalibration will | 664 | /* |
665 | * XXX: If a finger is down during this delay, recalibration will | ||
240 | * detect capacitance incorrectly. This is a hardware bug, and | 666 | * detect capacitance incorrectly. This is a hardware bug, and |
241 | * we don't have a good way to deal with it. The 2s window stuff | 667 | * we don't have a good way to deal with it. The 2s window stuff |
242 | * (below) is our best option for now. | 668 | * (below) is our best option for now. |
@@ -247,25 +673,35 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) | |||
247 | 673 | ||
248 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 674 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
249 | 675 | ||
250 | /* After we recalibrate, we shouldn't get any packets for 2s. If | 676 | if (tpdebug) |
251 | * we do, it's likely that someone's finger was on the touchpad. | 677 | hgpk_dbg(psmouse, "touchpad reactivated\n"); |
252 | * If someone's finger *was* on the touchpad, it's probably | 678 | |
253 | * miscalibrated. So, we should schedule another recalibration | 679 | /* |
680 | * If we get packets right away after recalibrating, it's likely | ||
681 | * that a finger was on the touchpad. If so, it's probably | ||
682 | * miscalibrated, so we optionally schedule another. | ||
254 | */ | 683 | */ |
255 | priv->recalib_window = jiffies + msecs_to_jiffies(recal_guard_time); | 684 | if (recal_guard_time) |
685 | priv->recalib_window = jiffies + | ||
686 | msecs_to_jiffies(recal_guard_time); | ||
256 | 687 | ||
257 | return 0; | 688 | return 0; |
258 | } | 689 | } |
259 | 690 | ||
260 | /* | 691 | /* |
261 | * This kills power to the touchpad; according to ALPS, current consumption | 692 | * This puts the touchpad in a power saving mode; according to ALPS, current |
262 | * goes down to 50uA after running this. To turn power back on, we drive | 693 | * consumption goes down to 50uA after running this. To turn power back on, |
263 | * MS-DAT low. | 694 | * we drive MS-DAT low. Measuring with a 1mA resolution ammeter says that |
695 | * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this. | ||
696 | * | ||
697 | * We have no formal spec that details this operation -- the low-power | ||
698 | * sequence came from a long-lost email trail. | ||
264 | */ | 699 | */ |
265 | static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | 700 | static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable) |
266 | { | 701 | { |
267 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 702 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
268 | int timeo; | 703 | int timeo; |
704 | int err; | ||
269 | 705 | ||
270 | /* Added on D-series touchpads */ | 706 | /* Added on D-series touchpads */ |
271 | if (psmouse->model < HGPK_MODEL_D) | 707 | if (psmouse->model < HGPK_MODEL_D) |
@@ -279,24 +715,27 @@ static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | |||
279 | * the controller. Once we get an ACK back from it, it | 715 | * the controller. Once we get an ACK back from it, it |
280 | * means we can continue with the touchpad re-init. ALPS | 716 | * means we can continue with the touchpad re-init. ALPS |
281 | * tells us that 1s should be long enough, so set that as | 717 | * tells us that 1s should be long enough, so set that as |
282 | * the upper bound. | 718 | * the upper bound. (in practice, it takes about 3 loops.) |
283 | */ | 719 | */ |
284 | for (timeo = 20; timeo > 0; timeo--) { | 720 | for (timeo = 20; timeo > 0; timeo--) { |
285 | if (!ps2_sendbyte(&psmouse->ps2dev, | 721 | if (!ps2_sendbyte(&psmouse->ps2dev, |
286 | PSMOUSE_CMD_DISABLE, 20)) | 722 | PSMOUSE_CMD_DISABLE, 20)) |
287 | break; | 723 | break; |
288 | msleep(50); | 724 | msleep(25); |
289 | } | 725 | } |
290 | 726 | ||
291 | psmouse_reset(psmouse); | 727 | err = hgpk_reset_device(psmouse, false); |
728 | if (err) { | ||
729 | hgpk_err(psmouse, "Failed to reset device!\n"); | ||
730 | return err; | ||
731 | } | ||
292 | 732 | ||
293 | /* should be all set, enable the touchpad */ | 733 | /* should be all set, enable the touchpad */ |
294 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 734 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
295 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 735 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
296 | 736 | hgpk_dbg(psmouse, "Touchpad powered up.\n"); | |
297 | } else { | 737 | } else { |
298 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); | 738 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); |
299 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
300 | 739 | ||
301 | if (ps2_command(ps2dev, NULL, 0xec) || | 740 | if (ps2_command(ps2dev, NULL, 0xec) || |
302 | ps2_command(ps2dev, NULL, 0xec) || | 741 | ps2_command(ps2dev, NULL, 0xec) || |
@@ -304,6 +743,8 @@ static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | |||
304 | return -1; | 743 | return -1; |
305 | } | 744 | } |
306 | 745 | ||
746 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
747 | |||
307 | /* probably won't see an ACK, the touchpad will be off */ | 748 | /* probably won't see an ACK, the touchpad will be off */ |
308 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); | 749 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); |
309 | } | 750 | } |
@@ -319,17 +760,20 @@ static int hgpk_poll(struct psmouse *psmouse) | |||
319 | 760 | ||
320 | static int hgpk_reconnect(struct psmouse *psmouse) | 761 | static int hgpk_reconnect(struct psmouse *psmouse) |
321 | { | 762 | { |
322 | /* During suspend/resume the ps2 rails remain powered. We don't want | 763 | struct hgpk_data *priv = psmouse->private; |
764 | |||
765 | /* | ||
766 | * During suspend/resume the ps2 rails remain powered. We don't want | ||
323 | * to do a reset because it's flush data out of buffers; however, | 767 | * to do a reset because it's flush data out of buffers; however, |
324 | * earlier prototypes (B1) had some brokenness that required a reset. */ | 768 | * earlier prototypes (B1) had some brokenness that required a reset. |
769 | */ | ||
325 | if (olpc_board_at_least(olpc_board(0xb2))) | 770 | if (olpc_board_at_least(olpc_board(0xb2))) |
326 | if (psmouse->ps2dev.serio->dev.power.power_state.event != | 771 | if (psmouse->ps2dev.serio->dev.power.power_state.event != |
327 | PM_EVENT_ON) | 772 | PM_EVENT_ON) |
328 | return 0; | 773 | return 0; |
329 | 774 | ||
330 | psmouse_reset(psmouse); | 775 | priv->powered = 1; |
331 | 776 | return hgpk_reset_device(psmouse, false); | |
332 | return 0; | ||
333 | } | 777 | } |
334 | 778 | ||
335 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) | 779 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) |
@@ -355,7 +799,7 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
355 | * hgpk_toggle_power will deal w/ state so | 799 | * hgpk_toggle_power will deal w/ state so |
356 | * we're not racing w/ irq | 800 | * we're not racing w/ irq |
357 | */ | 801 | */ |
358 | err = hgpk_toggle_power(psmouse, value); | 802 | err = hgpk_toggle_powersave(psmouse, value); |
359 | if (!err) | 803 | if (!err) |
360 | priv->powered = value; | 804 | priv->powered = value; |
361 | } | 805 | } |
@@ -366,6 +810,65 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
366 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 810 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
367 | hgpk_show_powered, hgpk_set_powered, false); | 811 | hgpk_show_powered, hgpk_set_powered, false); |
368 | 812 | ||
813 | static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf) | ||
814 | { | ||
815 | struct hgpk_data *priv = psmouse->private; | ||
816 | |||
817 | return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]); | ||
818 | } | ||
819 | |||
820 | static ssize_t attr_set_mode(struct psmouse *psmouse, void *data, | ||
821 | const char *buf, size_t len) | ||
822 | { | ||
823 | struct hgpk_data *priv = psmouse->private; | ||
824 | enum hgpk_mode old_mode = priv->mode; | ||
825 | enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len); | ||
826 | struct input_dev *old_dev = psmouse->dev; | ||
827 | struct input_dev *new_dev; | ||
828 | int err; | ||
829 | |||
830 | if (new_mode == HGPK_MODE_INVALID) | ||
831 | return -EINVAL; | ||
832 | |||
833 | if (old_mode == new_mode) | ||
834 | return len; | ||
835 | |||
836 | new_dev = input_allocate_device(); | ||
837 | if (!new_dev) | ||
838 | return -ENOMEM; | ||
839 | |||
840 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
841 | |||
842 | /* Switch device into the new mode */ | ||
843 | priv->mode = new_mode; | ||
844 | err = hgpk_reset_device(psmouse, false); | ||
845 | if (err) | ||
846 | goto err_try_restore; | ||
847 | |||
848 | hgpk_setup_input_device(new_dev, old_dev, new_mode); | ||
849 | |||
850 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
851 | |||
852 | err = input_register_device(new_dev); | ||
853 | if (err) | ||
854 | goto err_try_restore; | ||
855 | |||
856 | psmouse->dev = new_dev; | ||
857 | input_unregister_device(old_dev); | ||
858 | |||
859 | return len; | ||
860 | |||
861 | err_try_restore: | ||
862 | input_free_device(new_dev); | ||
863 | priv->mode = old_mode; | ||
864 | hgpk_reset_device(psmouse, false); | ||
865 | |||
866 | return err; | ||
867 | } | ||
868 | |||
869 | PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL, | ||
870 | attr_show_mode, attr_set_mode); | ||
871 | |||
369 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | 872 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, |
370 | void *data, char *buf) | 873 | void *data, char *buf) |
371 | { | 874 | { |
@@ -401,6 +904,8 @@ static void hgpk_disconnect(struct psmouse *psmouse) | |||
401 | 904 | ||
402 | device_remove_file(&psmouse->ps2dev.serio->dev, | 905 | device_remove_file(&psmouse->ps2dev.serio->dev, |
403 | &psmouse_attr_powered.dattr); | 906 | &psmouse_attr_powered.dattr); |
907 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
908 | &psmouse_attr_hgpk_mode.dattr); | ||
404 | 909 | ||
405 | if (psmouse->model >= HGPK_MODEL_C) | 910 | if (psmouse->model >= HGPK_MODEL_C) |
406 | device_remove_file(&psmouse->ps2dev.serio->dev, | 911 | device_remove_file(&psmouse->ps2dev.serio->dev, |
@@ -416,14 +921,13 @@ static void hgpk_recalib_work(struct work_struct *work) | |||
416 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); | 921 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); |
417 | struct psmouse *psmouse = priv->psmouse; | 922 | struct psmouse *psmouse = priv->psmouse; |
418 | 923 | ||
419 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
420 | |||
421 | if (hgpk_force_recalibrate(psmouse)) | 924 | if (hgpk_force_recalibrate(psmouse)) |
422 | hgpk_err(psmouse, "recalibration failed!\n"); | 925 | hgpk_err(psmouse, "recalibration failed!\n"); |
423 | } | 926 | } |
424 | 927 | ||
425 | static int hgpk_register(struct psmouse *psmouse) | 928 | static int hgpk_register(struct psmouse *psmouse) |
426 | { | 929 | { |
930 | struct hgpk_data *priv = psmouse->private; | ||
427 | int err; | 931 | int err; |
428 | 932 | ||
429 | /* register handlers */ | 933 | /* register handlers */ |
@@ -431,13 +935,14 @@ static int hgpk_register(struct psmouse *psmouse) | |||
431 | psmouse->poll = hgpk_poll; | 935 | psmouse->poll = hgpk_poll; |
432 | psmouse->disconnect = hgpk_disconnect; | 936 | psmouse->disconnect = hgpk_disconnect; |
433 | psmouse->reconnect = hgpk_reconnect; | 937 | psmouse->reconnect = hgpk_reconnect; |
434 | psmouse->pktsize = 3; | ||
435 | 938 | ||
436 | /* Disable the idle resync. */ | 939 | /* Disable the idle resync. */ |
437 | psmouse->resync_time = 0; | 940 | psmouse->resync_time = 0; |
438 | /* Reset after a lot of bad bytes. */ | 941 | /* Reset after a lot of bad bytes. */ |
439 | psmouse->resetafter = 1024; | 942 | psmouse->resetafter = 1024; |
440 | 943 | ||
944 | hgpk_setup_input_device(psmouse->dev, NULL, priv->mode); | ||
945 | |||
441 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 946 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
442 | &psmouse_attr_powered.dattr); | 947 | &psmouse_attr_powered.dattr); |
443 | if (err) { | 948 | if (err) { |
@@ -445,6 +950,13 @@ static int hgpk_register(struct psmouse *psmouse) | |||
445 | return err; | 950 | return err; |
446 | } | 951 | } |
447 | 952 | ||
953 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
954 | &psmouse_attr_hgpk_mode.dattr); | ||
955 | if (err) { | ||
956 | hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n"); | ||
957 | goto err_remove_powered; | ||
958 | } | ||
959 | |||
448 | /* C-series touchpads added the recalibrate command */ | 960 | /* C-series touchpads added the recalibrate command */ |
449 | if (psmouse->model >= HGPK_MODEL_C) { | 961 | if (psmouse->model >= HGPK_MODEL_C) { |
450 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 962 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
@@ -452,30 +964,40 @@ static int hgpk_register(struct psmouse *psmouse) | |||
452 | if (err) { | 964 | if (err) { |
453 | hgpk_err(psmouse, | 965 | hgpk_err(psmouse, |
454 | "Failed creating 'recalibrate' sysfs node\n"); | 966 | "Failed creating 'recalibrate' sysfs node\n"); |
455 | device_remove_file(&psmouse->ps2dev.serio->dev, | 967 | goto err_remove_mode; |
456 | &psmouse_attr_powered.dattr); | ||
457 | return err; | ||
458 | } | 968 | } |
459 | } | 969 | } |
460 | 970 | ||
461 | return 0; | 971 | return 0; |
972 | |||
973 | err_remove_mode: | ||
974 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
975 | &psmouse_attr_hgpk_mode.dattr); | ||
976 | err_remove_powered: | ||
977 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
978 | &psmouse_attr_powered.dattr); | ||
979 | return err; | ||
462 | } | 980 | } |
463 | 981 | ||
464 | int hgpk_init(struct psmouse *psmouse) | 982 | int hgpk_init(struct psmouse *psmouse) |
465 | { | 983 | { |
466 | struct hgpk_data *priv; | 984 | struct hgpk_data *priv; |
467 | int err = -ENOMEM; | 985 | int err; |
468 | 986 | ||
469 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); | 987 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); |
470 | if (!priv) | 988 | if (!priv) { |
989 | err = -ENOMEM; | ||
471 | goto alloc_fail; | 990 | goto alloc_fail; |
991 | } | ||
472 | 992 | ||
473 | psmouse->private = priv; | 993 | psmouse->private = priv; |
994 | |||
474 | priv->psmouse = psmouse; | 995 | priv->psmouse = psmouse; |
475 | priv->powered = true; | 996 | priv->powered = true; |
997 | priv->mode = hgpk_default_mode; | ||
476 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | 998 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); |
477 | 999 | ||
478 | err = psmouse_reset(psmouse); | 1000 | err = hgpk_reset_device(psmouse, false); |
479 | if (err) | 1001 | if (err) |
480 | goto init_fail; | 1002 | goto init_fail; |
481 | 1003 | ||
@@ -531,3 +1053,14 @@ int hgpk_detect(struct psmouse *psmouse, bool set_properties) | |||
531 | 1053 | ||
532 | return 0; | 1054 | return 0; |
533 | } | 1055 | } |
1056 | |||
1057 | void hgpk_module_init(void) | ||
1058 | { | ||
1059 | hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name, | ||
1060 | strlen(hgpk_mode_name)); | ||
1061 | if (hgpk_default_mode == HGPK_MODE_INVALID) { | ||
1062 | hgpk_default_mode = HGPK_MODE_MOUSE; | ||
1063 | strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE], | ||
1064 | sizeof(hgpk_mode_name)); | ||
1065 | } | ||
1066 | } | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index d61cfd3ee9cb..311c0e87fcbf 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
@@ -5,6 +5,9 @@ | |||
5 | #ifndef _HGPK_H | 5 | #ifndef _HGPK_H |
6 | #define _HGPK_H | 6 | #define _HGPK_H |
7 | 7 | ||
8 | #define HGPK_GS 0xff /* The GlideSensor */ | ||
9 | #define HGPK_PT 0xcf /* The PenTablet */ | ||
10 | |||
8 | enum hgpk_model_t { | 11 | enum hgpk_model_t { |
9 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ | 12 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ |
10 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ | 13 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ |
@@ -13,12 +16,34 @@ enum hgpk_model_t { | |||
13 | HGPK_MODEL_D = 0x50, /* C1, mass production */ | 16 | HGPK_MODEL_D = 0x50, /* C1, mass production */ |
14 | }; | 17 | }; |
15 | 18 | ||
19 | enum hgpk_spew_flag { | ||
20 | NO_SPEW, | ||
21 | MAYBE_SPEWING, | ||
22 | SPEW_DETECTED, | ||
23 | RECALIBRATING, | ||
24 | }; | ||
25 | |||
26 | #define SPEW_WATCH_COUNT 42 /* at 12ms/packet, this is 1/2 second */ | ||
27 | |||
28 | enum hgpk_mode { | ||
29 | HGPK_MODE_MOUSE, | ||
30 | HGPK_MODE_GLIDESENSOR, | ||
31 | HGPK_MODE_PENTABLET, | ||
32 | HGPK_MODE_INVALID | ||
33 | }; | ||
34 | |||
16 | struct hgpk_data { | 35 | struct hgpk_data { |
17 | struct psmouse *psmouse; | 36 | struct psmouse *psmouse; |
37 | enum hgpk_mode mode; | ||
18 | bool powered; | 38 | bool powered; |
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | 39 | enum hgpk_spew_flag spew_flag; |
40 | int spew_count, x_tally, y_tally; /* spew detection */ | ||
20 | unsigned long recalib_window; | 41 | unsigned long recalib_window; |
21 | struct delayed_work recalib_wq; | 42 | struct delayed_work recalib_wq; |
43 | int abs_x, abs_y; | ||
44 | int dupe_count; | ||
45 | int xbigj, ybigj, xlast, ylast; /* jumpiness detection */ | ||
46 | int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ | ||
22 | }; | 47 | }; |
23 | 48 | ||
24 | #define hgpk_dbg(psmouse, format, arg...) \ | 49 | #define hgpk_dbg(psmouse, format, arg...) \ |
@@ -33,9 +58,13 @@ struct hgpk_data { | |||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | 58 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) |
34 | 59 | ||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | 60 | #ifdef CONFIG_MOUSE_PS2_OLPC |
61 | void hgpk_module_init(void); | ||
36 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); | 62 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
37 | int hgpk_init(struct psmouse *psmouse); | 63 | int hgpk_init(struct psmouse *psmouse); |
38 | #else | 64 | #else |
65 | static inline void hgpk_module_init(void) | ||
66 | { | ||
67 | } | ||
39 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) | 68 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
40 | { | 69 | { |
41 | return -ENODEV; | 70 | return -ENODEV; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cd9d0c97e429..3f74baee102b 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -1711,6 +1711,7 @@ static int __init psmouse_init(void) | |||
1711 | 1711 | ||
1712 | lifebook_module_init(); | 1712 | lifebook_module_init(); |
1713 | synaptics_module_init(); | 1713 | synaptics_module_init(); |
1714 | hgpk_module_init(); | ||
1714 | 1715 | ||
1715 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | 1716 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); |
1716 | if (!kpsmoused_wq) { | 1717 | if (!kpsmoused_wq) { |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 2e300a460556..e06e045bf907 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/dmi.h> | 27 | #include <linux/dmi.h> |
28 | #include <linux/input.h> | 28 | #include <linux/input/mt.h> |
29 | #include <linux/serio.h> | 29 | #include <linux/serio.h> |
30 | #include <linux/libps2.h> | 30 | #include <linux/libps2.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -279,6 +279,25 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) | |||
279 | synaptics_mode_cmd(psmouse, priv->mode); | 279 | synaptics_mode_cmd(psmouse, priv->mode); |
280 | } | 280 | } |
281 | 281 | ||
282 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | ||
283 | { | ||
284 | static unsigned char param = 0xc8; | ||
285 | struct synaptics_data *priv = psmouse->private; | ||
286 | |||
287 | if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
288 | return 0; | ||
289 | |||
290 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | ||
291 | return -1; | ||
292 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | ||
293 | return -1; | ||
294 | |||
295 | /* Advanced gesture mode also sends multi finger data */ | ||
296 | priv->capabilities |= BIT(1); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
282 | /***************************************************************************** | 301 | /***************************************************************************** |
283 | * Synaptics pass-through PS/2 port support | 302 | * Synaptics pass-through PS/2 port support |
284 | ****************************************************************************/ | 303 | ****************************************************************************/ |
@@ -380,7 +399,9 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
380 | * Functions to interpret the absolute mode packets | 399 | * Functions to interpret the absolute mode packets |
381 | ****************************************************************************/ | 400 | ****************************************************************************/ |
382 | 401 | ||
383 | static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) | 402 | static int synaptics_parse_hw_state(const unsigned char buf[], |
403 | struct synaptics_data *priv, | ||
404 | struct synaptics_hw_state *hw) | ||
384 | { | 405 | { |
385 | memset(hw, 0, sizeof(struct synaptics_hw_state)); | 406 | memset(hw, 0, sizeof(struct synaptics_hw_state)); |
386 | 407 | ||
@@ -397,6 +418,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
397 | ((buf[0] & 0x04) >> 1) | | 418 | ((buf[0] & 0x04) >> 1) | |
398 | ((buf[3] & 0x04) >> 2)); | 419 | ((buf[3] & 0x04) >> 2)); |
399 | 420 | ||
421 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { | ||
422 | /* Gesture packet: (x, y, z) at half resolution */ | ||
423 | priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | ||
424 | priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | ||
425 | priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | ||
426 | return 1; | ||
427 | } | ||
428 | |||
400 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 429 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
401 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 430 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
402 | 431 | ||
@@ -452,6 +481,36 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
452 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 481 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
453 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 482 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
454 | } | 483 | } |
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y) | ||
489 | { | ||
490 | input_mt_slot(dev, slot); | ||
491 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
492 | if (active) { | ||
493 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
494 | input_report_abs(dev, ABS_MT_POSITION_Y, | ||
495 | YMAX_NOMINAL + YMIN_NOMINAL - y); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | static void synaptics_report_semi_mt_data(struct input_dev *dev, | ||
500 | const struct synaptics_hw_state *a, | ||
501 | const struct synaptics_hw_state *b, | ||
502 | int num_fingers) | ||
503 | { | ||
504 | if (num_fingers >= 2) { | ||
505 | set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y)); | ||
506 | set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y)); | ||
507 | } else if (num_fingers == 1) { | ||
508 | set_slot(dev, 0, true, a->x, a->y); | ||
509 | set_slot(dev, 1, false, 0, 0); | ||
510 | } else { | ||
511 | set_slot(dev, 0, false, 0, 0); | ||
512 | set_slot(dev, 1, false, 0, 0); | ||
513 | } | ||
455 | } | 514 | } |
456 | 515 | ||
457 | /* | 516 | /* |
@@ -466,7 +525,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
466 | int finger_width; | 525 | int finger_width; |
467 | int i; | 526 | int i; |
468 | 527 | ||
469 | synaptics_parse_hw_state(psmouse->packet, priv, &hw); | 528 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) |
529 | return; | ||
470 | 530 | ||
471 | if (hw.scroll) { | 531 | if (hw.scroll) { |
472 | priv->scroll += hw.scroll; | 532 | priv->scroll += hw.scroll; |
@@ -488,7 +548,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
488 | return; | 548 | return; |
489 | } | 549 | } |
490 | 550 | ||
491 | if (hw.z > 0) { | 551 | if (hw.z > 0 && hw.x > 1) { |
492 | num_fingers = 1; | 552 | num_fingers = 1; |
493 | finger_width = 5; | 553 | finger_width = 5; |
494 | if (SYN_CAP_EXTENDED(priv->capabilities)) { | 554 | if (SYN_CAP_EXTENDED(priv->capabilities)) { |
@@ -512,6 +572,9 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
512 | finger_width = 0; | 572 | finger_width = 0; |
513 | } | 573 | } |
514 | 574 | ||
575 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
576 | synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers); | ||
577 | |||
515 | /* Post events | 578 | /* Post events |
516 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 579 | * BTN_TOUCH has to be first as mousedev relies on it when doing |
517 | * absolute -> relative conversion | 580 | * absolute -> relative conversion |
@@ -519,7 +582,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
519 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | 582 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); |
520 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | 583 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); |
521 | 584 | ||
522 | if (hw.z > 0) { | 585 | if (num_fingers > 0) { |
523 | input_report_abs(dev, ABS_X, hw.x); | 586 | input_report_abs(dev, ABS_X, hw.x); |
524 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | 587 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); |
525 | } | 588 | } |
@@ -622,6 +685,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
622 | { | 685 | { |
623 | int i; | 686 | int i; |
624 | 687 | ||
688 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | ||
689 | |||
625 | __set_bit(EV_ABS, dev->evbit); | 690 | __set_bit(EV_ABS, dev->evbit); |
626 | input_set_abs_params(dev, ABS_X, | 691 | input_set_abs_params(dev, ABS_X, |
627 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); | 692 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); |
@@ -629,6 +694,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
629 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); | 694 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); |
630 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 695 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
631 | 696 | ||
697 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | ||
698 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
699 | input_mt_init_slots(dev, 2); | ||
700 | input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, | ||
701 | priv->x_max ?: XMAX_NOMINAL, 0, 0); | ||
702 | input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, | ||
703 | priv->y_max ?: YMAX_NOMINAL, 0, 0); | ||
704 | } | ||
705 | |||
632 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 706 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
633 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | 707 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); |
634 | 708 | ||
@@ -663,6 +737,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
663 | input_abs_set_res(dev, ABS_Y, priv->y_res); | 737 | input_abs_set_res(dev, ABS_Y, priv->y_res); |
664 | 738 | ||
665 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 739 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
740 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | ||
666 | /* Clickpads report only left button */ | 741 | /* Clickpads report only left button */ |
667 | __clear_bit(BTN_RIGHT, dev->keybit); | 742 | __clear_bit(BTN_RIGHT, dev->keybit); |
668 | __clear_bit(BTN_MIDDLE, dev->keybit); | 743 | __clear_bit(BTN_MIDDLE, dev->keybit); |
@@ -680,25 +755,46 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
680 | { | 755 | { |
681 | struct synaptics_data *priv = psmouse->private; | 756 | struct synaptics_data *priv = psmouse->private; |
682 | struct synaptics_data old_priv = *priv; | 757 | struct synaptics_data old_priv = *priv; |
758 | int retry = 0; | ||
759 | int error; | ||
683 | 760 | ||
684 | psmouse_reset(psmouse); | 761 | do { |
762 | psmouse_reset(psmouse); | ||
763 | error = synaptics_detect(psmouse, 0); | ||
764 | } while (error && ++retry < 3); | ||
685 | 765 | ||
686 | if (synaptics_detect(psmouse, 0)) | 766 | if (error) |
687 | return -1; | 767 | return -1; |
688 | 768 | ||
769 | if (retry > 1) | ||
770 | printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", | ||
771 | retry); | ||
772 | |||
689 | if (synaptics_query_hardware(psmouse)) { | 773 | if (synaptics_query_hardware(psmouse)) { |
690 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 774 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); |
691 | return -1; | 775 | return -1; |
692 | } | 776 | } |
693 | 777 | ||
778 | if (synaptics_set_absolute_mode(psmouse)) { | ||
779 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | ||
780 | return -1; | ||
781 | } | ||
782 | |||
783 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
784 | printk(KERN_ERR "Advanced gesture mode reconnect failed.\n"); | ||
785 | return -1; | ||
786 | } | ||
787 | |||
694 | if (old_priv.identity != priv->identity || | 788 | if (old_priv.identity != priv->identity || |
695 | old_priv.model_id != priv->model_id || | 789 | old_priv.model_id != priv->model_id || |
696 | old_priv.capabilities != priv->capabilities || | 790 | old_priv.capabilities != priv->capabilities || |
697 | old_priv.ext_cap != priv->ext_cap) | 791 | old_priv.ext_cap != priv->ext_cap) { |
698 | return -1; | 792 | printk(KERN_ERR "Synaptics hardware appears to be different: " |
699 | 793 | "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", | |
700 | if (synaptics_set_absolute_mode(psmouse)) { | 794 | old_priv.identity, priv->identity, |
701 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | 795 | old_priv.model_id, priv->model_id, |
796 | old_priv.capabilities, priv->capabilities, | ||
797 | old_priv.ext_cap, priv->ext_cap); | ||
702 | return -1; | 798 | return -1; |
703 | } | 799 | } |
704 | 800 | ||
@@ -740,19 +836,49 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = { | |||
740 | }, | 836 | }, |
741 | 837 | ||
742 | }, | 838 | }, |
839 | #endif | ||
743 | { } | 840 | { } |
841 | }; | ||
842 | |||
843 | static bool broken_olpc_ec; | ||
844 | |||
845 | static const struct dmi_system_id __initconst olpc_dmi_table[] = { | ||
846 | #if defined(CONFIG_DMI) && defined(CONFIG_OLPC) | ||
847 | { | ||
848 | /* OLPC XO-1 or XO-1.5 */ | ||
849 | .matches = { | ||
850 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), | ||
851 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), | ||
852 | }, | ||
853 | }, | ||
744 | #endif | 854 | #endif |
855 | { } | ||
745 | }; | 856 | }; |
746 | 857 | ||
747 | void __init synaptics_module_init(void) | 858 | void __init synaptics_module_init(void) |
748 | { | 859 | { |
749 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 860 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
861 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | ||
750 | } | 862 | } |
751 | 863 | ||
752 | int synaptics_init(struct psmouse *psmouse) | 864 | int synaptics_init(struct psmouse *psmouse) |
753 | { | 865 | { |
754 | struct synaptics_data *priv; | 866 | struct synaptics_data *priv; |
755 | 867 | ||
868 | /* | ||
869 | * The OLPC XO has issues with Synaptics' absolute mode; similarly to | ||
870 | * the HGPK, it quickly degrades and the hardware becomes jumpy and | ||
871 | * overly sensitive. Not only that, but the constant packet spew | ||
872 | * (even at a lowered 40pps rate) overloads the EC such that key | ||
873 | * presses on the keyboard are missed. Given all of that, don't | ||
874 | * even attempt to use Synaptics mode. Relative mode seems to work | ||
875 | * just fine. | ||
876 | */ | ||
877 | if (broken_olpc_ec) { | ||
878 | printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n"); | ||
879 | return -ENODEV; | ||
880 | } | ||
881 | |||
756 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); | 882 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); |
757 | if (!priv) | 883 | if (!priv) |
758 | return -ENOMEM; | 884 | return -ENOMEM; |
@@ -769,6 +895,11 @@ int synaptics_init(struct psmouse *psmouse) | |||
769 | goto init_fail; | 895 | goto init_fail; |
770 | } | 896 | } |
771 | 897 | ||
898 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
899 | printk(KERN_ERR "Advanced gesture mode init failed.\n"); | ||
900 | goto init_fail; | ||
901 | } | ||
902 | |||
772 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 903 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
773 | 904 | ||
774 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", | 905 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
@@ -802,8 +933,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
802 | 933 | ||
803 | /* | 934 | /* |
804 | * Toshiba's KBC seems to have trouble handling data from | 935 | * Toshiba's KBC seems to have trouble handling data from |
805 | * Synaptics as full rate, switch to lower rate which is roughly | 936 | * Synaptics at full rate. Switch to a lower rate (roughly |
806 | * thye same as rate of standard PS/2 mouse. | 937 | * the same rate as a standard PS/2 mouse). |
807 | */ | 938 | */ |
808 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { | 939 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
809 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", | 940 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 613a3652f98f..7453938bf5ef 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -51,8 +51,33 @@ | |||
51 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) | 51 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) |
52 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) | 52 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) |
53 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) | 53 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) |
54 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) | 54 | |
55 | /* | ||
56 | * The following describes response for the 0x0c query. | ||
57 | * | ||
58 | * byte mask name meaning | ||
59 | * ---- ---- ------- ------------ | ||
60 | * 1 0x01 adjustable threshold capacitive button sensitivity | ||
61 | * can be adjusted | ||
62 | * 1 0x02 report max query 0x0d gives max coord reported | ||
63 | * 1 0x04 clearpad sensor is ClearPad product | ||
64 | * 1 0x08 advanced gesture not particularly meaningful | ||
65 | * 1 0x10 clickpad bit 0 1-button ClickPad | ||
66 | * 1 0x60 multifinger mode identifies firmware finger counting | ||
67 | * (not reporting!) algorithm. | ||
68 | * Not particularly meaningful | ||
69 | * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered | ||
70 | * 2 0x01 clickpad bit 1 2-button ClickPad | ||
71 | * 2 0x02 deluxe LED controls touchpad support LED commands | ||
72 | * ala multimedia control bar | ||
73 | * 2 0x04 reduced filtering firmware does less filtering on | ||
74 | * position data, driver should watch | ||
75 | * for noise. | ||
76 | */ | ||
77 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | ||
78 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | ||
55 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) | 79 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) |
80 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | ||
56 | 81 | ||
57 | /* synaptics modes query bits */ | 82 | /* synaptics modes query bits */ |
58 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 83 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -112,6 +137,8 @@ struct synaptics_data { | |||
112 | int scroll; | 137 | int scroll; |
113 | 138 | ||
114 | struct serio *pt_port; /* Pass-through serio port */ | 139 | struct serio *pt_port; /* Pass-through serio port */ |
140 | |||
141 | struct synaptics_hw_state mt; /* current gesture packet */ | ||
115 | }; | 142 | }; |
116 | 143 | ||
117 | void synaptics_module_init(void); | 144 | void synaptics_module_init(void); |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 0ae62f0bcb32..cba3c84d2f21 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/pm.h> | ||
21 | 22 | ||
22 | #define DRIVER_NAME "synaptics_i2c" | 23 | #define DRIVER_NAME "synaptics_i2c" |
23 | /* maximum product id is 15 characters */ | 24 | /* maximum product id is 15 characters */ |
@@ -461,7 +462,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) | |||
461 | * While interrupt driven, there is no real need to poll the device. | 462 | * While interrupt driven, there is no real need to poll the device. |
462 | * But touchpads are very sensitive, so there could be errors | 463 | * But touchpads are very sensitive, so there could be errors |
463 | * related to physical environment and the attention line isn't | 464 | * related to physical environment and the attention line isn't |
464 | * neccesarily asserted. In such case we can lose the touchpad. | 465 | * necessarily asserted. In such case we can lose the touchpad. |
465 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | 466 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and |
466 | * if error is detected, we try to reset and reconfigure the touchpad. | 467 | * if error is detected, we try to reset and reconfigure the touchpad. |
467 | */ | 468 | */ |
@@ -619,8 +620,9 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) | |||
619 | } | 620 | } |
620 | 621 | ||
621 | #ifdef CONFIG_PM | 622 | #ifdef CONFIG_PM |
622 | static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 623 | static int synaptics_i2c_suspend(struct device *dev) |
623 | { | 624 | { |
625 | struct i2c_client *client = to_i2c_client(dev); | ||
624 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 626 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
625 | 627 | ||
626 | cancel_delayed_work_sync(&touch->dwork); | 628 | cancel_delayed_work_sync(&touch->dwork); |
@@ -631,9 +633,10 @@ static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | |||
631 | return 0; | 633 | return 0; |
632 | } | 634 | } |
633 | 635 | ||
634 | static int synaptics_i2c_resume(struct i2c_client *client) | 636 | static int synaptics_i2c_resume(struct device *dev) |
635 | { | 637 | { |
636 | int ret; | 638 | int ret; |
639 | struct i2c_client *client = to_i2c_client(dev); | ||
637 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 640 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
638 | 641 | ||
639 | ret = synaptics_i2c_reset_config(client); | 642 | ret = synaptics_i2c_reset_config(client); |
@@ -645,11 +648,11 @@ static int synaptics_i2c_resume(struct i2c_client *client) | |||
645 | 648 | ||
646 | return 0; | 649 | return 0; |
647 | } | 650 | } |
648 | #else | ||
649 | #define synaptics_i2c_suspend NULL | ||
650 | #define synaptics_i2c_resume NULL | ||
651 | #endif | 651 | #endif |
652 | 652 | ||
653 | static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, | ||
654 | synaptics_i2c_resume); | ||
655 | |||
653 | static const struct i2c_device_id synaptics_i2c_id_table[] = { | 656 | static const struct i2c_device_id synaptics_i2c_id_table[] = { |
654 | { "synaptics_i2c", 0 }, | 657 | { "synaptics_i2c", 0 }, |
655 | { }, | 658 | { }, |
@@ -660,13 +663,12 @@ static struct i2c_driver synaptics_i2c_driver = { | |||
660 | .driver = { | 663 | .driver = { |
661 | .name = DRIVER_NAME, | 664 | .name = DRIVER_NAME, |
662 | .owner = THIS_MODULE, | 665 | .owner = THIS_MODULE, |
666 | .pm = &synaptics_i2c_pm, | ||
663 | }, | 667 | }, |
664 | 668 | ||
665 | .probe = synaptics_i2c_probe, | 669 | .probe = synaptics_i2c_probe, |
666 | .remove = __devexit_p(synaptics_i2c_remove), | 670 | .remove = __devexit_p(synaptics_i2c_remove), |
667 | 671 | ||
668 | .suspend = synaptics_i2c_suspend, | ||
669 | .resume = synaptics_i2c_resume, | ||
670 | .id_table = synaptics_i2c_id_table, | 672 | .id_table = synaptics_i2c_id_table, |
671 | }; | 673 | }; |
672 | 674 | ||
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index bf2c0c80d6cc..eb9a3cfbeefa 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -334,7 +334,7 @@ static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse) | |||
334 | * M: manufacturer location code | 334 | * M: manufacturer location code |
335 | * R: revision code | 335 | * R: revision code |
336 | * E: Error code. If it's in the range of 0x00..0x1f, only some | 336 | * E: Error code. If it's in the range of 0x00..0x1f, only some |
337 | * minor problem occured. Errors >= 0x20 are considered bad | 337 | * minor problem occurred. Errors >= 0x20 are considered bad |
338 | * and the device may not work properly... | 338 | * and the device may not work properly... |
339 | * D: <0010> == mouse, <0100> == tablet | 339 | * D: <0010> == mouse, <0100> == tablet |
340 | */ | 340 | */ |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 2a00ddf4f23a..7630273e9474 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -9,6 +9,8 @@ | |||
9 | * the Free Software Foundation. | 9 | * the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
12 | #define MOUSEDEV_MINOR_BASE 32 | 14 | #define MOUSEDEV_MINOR_BASE 32 |
13 | #define MOUSEDEV_MINORS 32 | 15 | #define MOUSEDEV_MINORS 32 |
14 | #define MOUSEDEV_MIX 31 | 16 | #define MOUSEDEV_MIX 31 |
@@ -977,7 +979,7 @@ static int mousedev_connect(struct input_handler *handler, | |||
977 | break; | 979 | break; |
978 | 980 | ||
979 | if (minor == MOUSEDEV_MINORS) { | 981 | if (minor == MOUSEDEV_MINORS) { |
980 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | 982 | pr_err("no more free mousedev devices\n"); |
981 | return -ENFILE; | 983 | return -ENFILE; |
982 | } | 984 | } |
983 | 985 | ||
@@ -1087,13 +1089,13 @@ static int __init mousedev_init(void) | |||
1087 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX | 1089 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX |
1088 | error = misc_register(&psaux_mouse); | 1090 | error = misc_register(&psaux_mouse); |
1089 | if (error) | 1091 | if (error) |
1090 | printk(KERN_WARNING "mice: could not register psaux device, " | 1092 | pr_warning("could not register psaux device, error: %d\n", |
1091 | "error: %d\n", error); | 1093 | error); |
1092 | else | 1094 | else |
1093 | psaux_registered = 1; | 1095 | psaux_registered = 1; |
1094 | #endif | 1096 | #endif |
1095 | 1097 | ||
1096 | printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n"); | 1098 | pr_info("PS/2 mouse device common for all mice\n"); |
1097 | 1099 | ||
1098 | return 0; | 1100 | return 0; |
1099 | } | 1101 | } |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 6256233d2bfb..55f2c2293ec6 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Input core configuration | 2 | # Input core configuration |
3 | # | 3 | # |
4 | config SERIO | 4 | config SERIO |
5 | tristate "Serial I/O support" if EMBEDDED || !X86 | 5 | tristate "Serial I/O support" if EXPERT || !X86 |
6 | default y | 6 | default y |
7 | help | 7 | help |
8 | Say Yes here if you have any input device that uses serial I/O to | 8 | Say Yes here if you have any input device that uses serial I/O to |
@@ -19,7 +19,7 @@ config SERIO | |||
19 | if SERIO | 19 | if SERIO |
20 | 20 | ||
21 | config SERIO_I8042 | 21 | config SERIO_I8042 |
22 | tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 | 22 | tristate "i8042 PC Keyboard controller" if EXPERT || !X86 |
23 | default y | 23 | default y |
24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ | 24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ |
25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN | 25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN |
@@ -168,7 +168,7 @@ config SERIO_MACEPS2 | |||
168 | module will be called maceps2. | 168 | module will be called maceps2. |
169 | 169 | ||
170 | config SERIO_LIBPS2 | 170 | config SERIO_LIBPS2 |
171 | tristate "PS/2 driver library" if EMBEDDED | 171 | tristate "PS/2 driver library" if EXPERT |
172 | depends on SERIO_I8042 || SERIO_I8042=n | 172 | depends on SERIO_I8042 || SERIO_I8042=n |
173 | help | 173 | help |
174 | Say Y here if you are using a driver for device connected | 174 | Say Y here if you are using a driver for device connected |
@@ -214,7 +214,6 @@ config SERIO_AMS_DELTA | |||
214 | tristate "Amstrad Delta (E3) mailboard support" | 214 | tristate "Amstrad Delta (E3) mailboard support" |
215 | depends on MACH_AMS_DELTA | 215 | depends on MACH_AMS_DELTA |
216 | default y | 216 | default y |
217 | select AMS_DELTA_FIQ | ||
218 | ---help--- | 217 | ---help--- |
219 | Say Y here if you have an E3 and want to use its mailboard, | 218 | Say Y here if you have an E3 and want to use its mailboard, |
220 | or any standard AT keyboard connected to the mailboard port. | 219 | or any standard AT keyboard connected to the mailboard port. |
@@ -230,7 +229,7 @@ config SERIO_PS2MULT | |||
230 | tristate "TQC PS/2 multiplexer" | 229 | tristate "TQC PS/2 multiplexer" |
231 | help | 230 | help |
232 | Say Y here if you have the PS/2 line multiplexer like the one | 231 | Say Y here if you have the PS/2 line multiplexer like the one |
233 | present on TQC boads. | 232 | present on TQC boards. |
234 | 233 | ||
235 | To compile this driver as a module, choose M here: the | 234 | To compile this driver as a module, choose M here: the |
236 | module will be called ps2mult. | 235 | module will be called ps2mult. |
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 7998560a1904..d363dc4571a3 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of.h> | ||
22 | 23 | ||
23 | #define DRV_NAME "altera_ps2" | 24 | #define DRV_NAME "altera_ps2" |
24 | 25 | ||
@@ -173,6 +174,16 @@ static int __devexit altera_ps2_remove(struct platform_device *pdev) | |||
173 | return 0; | 174 | return 0; |
174 | } | 175 | } |
175 | 176 | ||
177 | #ifdef CONFIG_OF | ||
178 | static const struct of_device_id altera_ps2_match[] = { | ||
179 | { .compatible = "ALTR,ps2-1.0", }, | ||
180 | {}, | ||
181 | }; | ||
182 | MODULE_DEVICE_TABLE(of, altera_ps2_match); | ||
183 | #else /* CONFIG_OF */ | ||
184 | #define altera_ps2_match NULL | ||
185 | #endif /* CONFIG_OF */ | ||
186 | |||
176 | /* | 187 | /* |
177 | * Our device driver structure | 188 | * Our device driver structure |
178 | */ | 189 | */ |
@@ -182,6 +193,7 @@ static struct platform_driver altera_ps2_driver = { | |||
182 | .driver = { | 193 | .driver = { |
183 | .name = DRV_NAME, | 194 | .name = DRV_NAME, |
184 | .owner = THIS_MODULE, | 195 | .owner = THIS_MODULE, |
196 | .of_match_table = altera_ps2_match, | ||
185 | }, | 197 | }, |
186 | }; | 198 | }; |
187 | 199 | ||
@@ -189,13 +201,12 @@ static int __init altera_ps2_init(void) | |||
189 | { | 201 | { |
190 | return platform_driver_register(&altera_ps2_driver); | 202 | return platform_driver_register(&altera_ps2_driver); |
191 | } | 203 | } |
204 | module_init(altera_ps2_init); | ||
192 | 205 | ||
193 | static void __exit altera_ps2_exit(void) | 206 | static void __exit altera_ps2_exit(void) |
194 | { | 207 | { |
195 | platform_driver_unregister(&altera_ps2_driver); | 208 | platform_driver_unregister(&altera_ps2_driver); |
196 | } | 209 | } |
197 | |||
198 | module_init(altera_ps2_init); | ||
199 | module_exit(altera_ps2_exit); | 210 | module_exit(altera_ps2_exit); |
200 | 211 | ||
201 | MODULE_DESCRIPTION("Altera University Program PS2 controller driver"); | 212 | MODULE_DESCRIPTION("Altera University Program PS2 controller driver"); |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 92563a681d65..12abc50508e5 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
@@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io) | |||
107 | clk_disable(kmi->clk); | 107 | clk_disable(kmi->clk); |
108 | } | 108 | } |
109 | 109 | ||
110 | static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | 110 | static int __devinit amba_kmi_probe(struct amba_device *dev, |
111 | const struct amba_id *id) | ||
111 | { | 112 | { |
112 | struct amba_kmi_port *kmi; | 113 | struct amba_kmi_port *kmi; |
113 | struct serio *io; | 114 | struct serio *io; |
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index 8f1770e1e08b..4b2a42f9f0bb 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c | |||
@@ -149,7 +149,7 @@ static int __init ams_delta_serio_init(void) | |||
149 | * at FIQ level, switch back from edge to simple interrupt handler | 149 | * at FIQ level, switch back from edge to simple interrupt handler |
150 | * to avoid bad interaction. | 150 | * to avoid bad interaction. |
151 | */ | 151 | */ |
152 | set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), | 152 | irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), |
153 | handle_simple_irq); | 153 | handle_simple_irq); |
154 | 154 | ||
155 | serio_register_port(ams_delta_serio); | 155 | serio_register_port(ams_delta_serio); |
@@ -172,6 +172,5 @@ static void __exit ams_delta_serio_exit(void) | |||
172 | free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); | 172 | free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); |
173 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); | 173 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); |
174 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); | 174 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); |
175 | kfree(ams_delta_serio); | ||
176 | } | 175 | } |
177 | module_exit(ams_delta_serio_exit); | 176 | module_exit(ams_delta_serio_exit); |
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 4a3084695c00..852816567241 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c | |||
@@ -111,9 +111,11 @@ static void ct82c710_close(struct serio *serio) | |||
111 | static int ct82c710_open(struct serio *serio) | 111 | static int ct82c710_open(struct serio *serio) |
112 | { | 112 | { |
113 | unsigned char status; | 113 | unsigned char status; |
114 | int err; | ||
114 | 115 | ||
115 | if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL)) | 116 | err = request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL); |
116 | return -1; | 117 | if (err) |
118 | return err; | ||
117 | 119 | ||
118 | status = inb_p(CT82C710_STATUS); | 120 | status = inb_p(CT82C710_STATUS); |
119 | 121 | ||
@@ -131,7 +133,7 @@ static int ct82c710_open(struct serio *serio) | |||
131 | status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); | 133 | status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); |
132 | outb_p(status, CT82C710_STATUS); | 134 | outb_p(status, CT82C710_STATUS); |
133 | free_irq(CT82C710_IRQ, NULL); | 135 | free_irq(CT82C710_IRQ, NULL); |
134 | return -1; | 136 | return -EBUSY; |
135 | } | 137 | } |
136 | 138 | ||
137 | return 0; | 139 | return 0; |
@@ -191,6 +193,9 @@ static int __devinit ct82c710_probe(struct platform_device *dev) | |||
191 | 193 | ||
192 | serio_register_port(ct82c710_port); | 194 | serio_register_port(ct82c710_port); |
193 | 195 | ||
196 | printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n", | ||
197 | (unsigned long long)CT82C710_DATA, CT82C710_IRQ); | ||
198 | |||
194 | return 0; | 199 | return 0; |
195 | } | 200 | } |
196 | 201 | ||
@@ -237,11 +242,6 @@ static int __init ct82c710_init(void) | |||
237 | if (error) | 242 | if (error) |
238 | goto err_free_device; | 243 | goto err_free_device; |
239 | 244 | ||
240 | serio_register_port(ct82c710_port); | ||
241 | |||
242 | printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n", | ||
243 | (unsigned long long)CT82C710_DATA, CT82C710_IRQ); | ||
244 | |||
245 | return 0; | 245 | return 0; |
246 | 246 | ||
247 | err_free_device: | 247 | err_free_device: |
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index e5624d8f1709..bfd3865d886b 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
@@ -932,6 +932,11 @@ int hil_mlc_register(hil_mlc *mlc) | |||
932 | hil_mlc_copy_di_scratch(mlc, i); | 932 | hil_mlc_copy_di_scratch(mlc, i); |
933 | mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); | 933 | mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); |
934 | mlc->serio[i] = mlc_serio; | 934 | mlc->serio[i] = mlc_serio; |
935 | if (!mlc->serio[i]) { | ||
936 | for (; i >= 0; i--) | ||
937 | kfree(mlc->serio[i]); | ||
938 | return -ENOMEM; | ||
939 | } | ||
935 | snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); | 940 | snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); |
936 | snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); | 941 | snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); |
937 | mlc_serio->id = hil_mlc_serio_id; | 942 | mlc_serio->id = hil_mlc_serio_id; |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 8c0b51c31424..42206205e4f5 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -955,7 +955,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) | |||
955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); | 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); |
956 | 956 | ||
957 | ret = hp_sdc_init(); | 957 | ret = hp_sdc_init(); |
958 | /* after successfull initialization give SDC some time to settle | 958 | /* after successful initialization give SDC some time to settle |
959 | * and then load the hp_sdc_mlc upper layer driver */ | 959 | * and then load the hp_sdc_mlc upper layer driver */ |
960 | if (!ret) | 960 | if (!ret) |
961 | schedule_delayed_work(&moduleloader_work, | 961 | schedule_delayed_work(&moduleloader_work, |
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index 7d2b820ef58d..d50f0678bf47 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c | |||
@@ -305,6 +305,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc) | |||
305 | static int __init hp_sdc_mlc_init(void) | 305 | static int __init hp_sdc_mlc_init(void) |
306 | { | 306 | { |
307 | hil_mlc *mlc = &hp_sdc_mlc; | 307 | hil_mlc *mlc = &hp_sdc_mlc; |
308 | int err; | ||
308 | 309 | ||
309 | #ifdef __mc68000__ | 310 | #ifdef __mc68000__ |
310 | if (!MACH_IS_HP300) | 311 | if (!MACH_IS_HP300) |
@@ -323,22 +324,21 @@ static int __init hp_sdc_mlc_init(void) | |||
323 | mlc->out = &hp_sdc_mlc_out; | 324 | mlc->out = &hp_sdc_mlc_out; |
324 | mlc->priv = &hp_sdc_mlc_priv; | 325 | mlc->priv = &hp_sdc_mlc_priv; |
325 | 326 | ||
326 | if (hil_mlc_register(mlc)) { | 327 | err = hil_mlc_register(mlc); |
328 | if (err) { | ||
327 | printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); | 329 | printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); |
328 | goto err0; | 330 | return err; |
329 | } | 331 | } |
330 | 332 | ||
331 | if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { | 333 | if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { |
332 | printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); | 334 | printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); |
333 | goto err1; | 335 | if (hil_mlc_unregister(mlc)) |
336 | printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" | ||
337 | "This is bad. Could cause an oops.\n"); | ||
338 | return -EBUSY; | ||
334 | } | 339 | } |
340 | |||
335 | return 0; | 341 | return 0; |
336 | err1: | ||
337 | if (hil_mlc_unregister(mlc)) | ||
338 | printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" | ||
339 | "This is bad. Could cause an oops.\n"); | ||
340 | err0: | ||
341 | return -EBUSY; | ||
342 | } | 342 | } |
343 | 343 | ||
344 | static void __exit hp_sdc_mlc_exit(void) | 344 | static void __exit hp_sdc_mlc_exit(void) |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c5cc4508d6df..395a9af3adcd 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) | |||
49 | #define OBP_PS2MS_NAME1 "kdmouse" | 49 | #define OBP_PS2MS_NAME1 "kdmouse" |
50 | #define OBP_PS2MS_NAME2 "mouse" | 50 | #define OBP_PS2MS_NAME2 "mouse" |
51 | 51 | ||
52 | static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) | 52 | static int __devinit sparc_i8042_probe(struct platform_device *op) |
53 | { | 53 | { |
54 | struct device_node *dp = op->dev.of_node; | 54 | struct device_node *dp = op->dev.of_node; |
55 | 55 | ||
@@ -95,7 +95,7 @@ static const struct of_device_id sparc_i8042_match[] = { | |||
95 | }; | 95 | }; |
96 | MODULE_DEVICE_TABLE(of, sparc_i8042_match); | 96 | MODULE_DEVICE_TABLE(of, sparc_i8042_match); |
97 | 97 | ||
98 | static struct of_platform_driver sparc_i8042_driver = { | 98 | static struct platform_driver sparc_i8042_driver = { |
99 | .driver = { | 99 | .driver = { |
100 | .name = "i8042", | 100 | .name = "i8042", |
101 | .owner = THIS_MODULE, | 101 | .owner = THIS_MODULE, |
@@ -116,7 +116,7 @@ static int __init i8042_platform_init(void) | |||
116 | if (!kbd_iobase) | 116 | if (!kbd_iobase) |
117 | return -ENODEV; | 117 | return -ENODEV; |
118 | } else { | 118 | } else { |
119 | int err = of_register_platform_driver(&sparc_i8042_driver); | 119 | int err = platform_driver_register(&sparc_i8042_driver); |
120 | if (err) | 120 | if (err) |
121 | return err; | 121 | return err; |
122 | 122 | ||
@@ -140,7 +140,7 @@ static inline void i8042_platform_exit(void) | |||
140 | struct device_node *root = of_find_node_by_path("/"); | 140 | struct device_node *root = of_find_node_by_path("/"); |
141 | 141 | ||
142 | if (strcmp(root->name, "SUNW,JavaStation-1")) | 142 | if (strcmp(root->name, "SUNW,JavaStation-1")) |
143 | of_unregister_platform_driver(&sparc_i8042_driver); | 143 | platform_driver_unregister(&sparc_i8042_driver); |
144 | } | 144 | } |
145 | 145 | ||
146 | #else /* !CONFIG_PCI */ | 146 | #else /* !CONFIG_PCI */ |
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h new file mode 100644 index 000000000000..73f5cc124a36 --- /dev/null +++ b/drivers/input/serio/i8042-unicore32io.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Code specific to PKUnity SoC and UniCore ISA | ||
3 | * | ||
4 | * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> | ||
5 | * Copyright (C) 2001-2011 Guan Xuetao | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #ifndef _I8042_UNICORE32_H | ||
12 | #define _I8042_UNICORE32_H | ||
13 | |||
14 | #include <mach/hardware.h> | ||
15 | |||
16 | /* | ||
17 | * Names. | ||
18 | */ | ||
19 | #define I8042_KBD_PHYS_DESC "isa0060/serio0" | ||
20 | #define I8042_AUX_PHYS_DESC "isa0060/serio1" | ||
21 | #define I8042_MUX_PHYS_DESC "isa0060/serio%d" | ||
22 | |||
23 | /* | ||
24 | * IRQs. | ||
25 | */ | ||
26 | #define I8042_KBD_IRQ IRQ_PS2_KBD | ||
27 | #define I8042_AUX_IRQ IRQ_PS2_AUX | ||
28 | |||
29 | /* | ||
30 | * Register numbers. | ||
31 | */ | ||
32 | #define I8042_COMMAND_REG PS2_COMMAND | ||
33 | #define I8042_STATUS_REG PS2_STATUS | ||
34 | #define I8042_DATA_REG PS2_DATA | ||
35 | |||
36 | #define I8042_REGION_START (resource_size_t)(PS2_DATA) | ||
37 | #define I8042_REGION_SIZE (resource_size_t)(16) | ||
38 | |||
39 | static inline int i8042_read_data(void) | ||
40 | { | ||
41 | return readb(I8042_DATA_REG); | ||
42 | } | ||
43 | |||
44 | static inline int i8042_read_status(void) | ||
45 | { | ||
46 | return readb(I8042_STATUS_REG); | ||
47 | } | ||
48 | |||
49 | static inline void i8042_write_data(int val) | ||
50 | { | ||
51 | writeb(val, I8042_DATA_REG); | ||
52 | } | ||
53 | |||
54 | static inline void i8042_write_command(int val) | ||
55 | { | ||
56 | writeb(val, I8042_COMMAND_REG); | ||
57 | } | ||
58 | |||
59 | static inline int i8042_platform_init(void) | ||
60 | { | ||
61 | if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) | ||
62 | return -EBUSY; | ||
63 | |||
64 | i8042_reset = 1; | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static inline void i8042_platform_exit(void) | ||
69 | { | ||
70 | release_mem_region(I8042_REGION_START, I8042_REGION_SIZE); | ||
71 | } | ||
72 | |||
73 | #endif /* _I8042_UNICORE32_H */ | ||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index a5475b577086..bb9f5d31f0d0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -424,6 +424,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
424 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | 424 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), |
425 | }, | 425 | }, |
426 | }, | 426 | }, |
427 | { | ||
428 | /* Dell Vostro V13 */ | ||
429 | .matches = { | ||
430 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
431 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
432 | }, | ||
433 | }, | ||
427 | { } | 434 | { } |
428 | }; | 435 | }; |
429 | 436 | ||
@@ -545,6 +552,17 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { | |||
545 | }; | 552 | }; |
546 | #endif | 553 | #endif |
547 | 554 | ||
555 | static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { | ||
556 | { | ||
557 | /* Dell Vostro V13 */ | ||
558 | .matches = { | ||
559 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
560 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
561 | }, | ||
562 | }, | ||
563 | { } | ||
564 | }; | ||
565 | |||
548 | /* | 566 | /* |
549 | * Some Wistron based laptops need us to explicitly enable the 'Dritek | 567 | * Some Wistron based laptops need us to explicitly enable the 'Dritek |
550 | * keyboard extension' to make their extra keys start generating scancodes. | 568 | * keyboard extension' to make their extra keys start generating scancodes. |
@@ -553,6 +571,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { | |||
553 | */ | 571 | */ |
554 | static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { | 572 | static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { |
555 | { | 573 | { |
574 | /* Acer Aspire 5100 */ | ||
575 | .matches = { | ||
576 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
577 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), | ||
578 | }, | ||
579 | }, | ||
580 | { | ||
556 | /* Acer Aspire 5610 */ | 581 | /* Acer Aspire 5610 */ |
557 | .matches = { | 582 | .matches = { |
558 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 583 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
@@ -752,7 +777,7 @@ static int __init i8042_pnp_init(void) | |||
752 | #endif | 777 | #endif |
753 | 778 | ||
754 | if (i8042_nopnp) { | 779 | if (i8042_nopnp) { |
755 | printk(KERN_INFO "i8042: PNP detection disabled\n"); | 780 | pr_info("PNP detection disabled\n"); |
756 | return 0; | 781 | return 0; |
757 | } | 782 | } |
758 | 783 | ||
@@ -769,7 +794,7 @@ static int __init i8042_pnp_init(void) | |||
769 | #if defined(__ia64__) | 794 | #if defined(__ia64__) |
770 | return -ENODEV; | 795 | return -ENODEV; |
771 | #else | 796 | #else |
772 | printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n"); | 797 | pr_info("PNP: No PS/2 controller found. Probing ports directly.\n"); |
773 | return 0; | 798 | return 0; |
774 | #endif | 799 | #endif |
775 | } | 800 | } |
@@ -781,7 +806,7 @@ static int __init i8042_pnp_init(void) | |||
781 | snprintf(aux_irq_str, sizeof(aux_irq_str), | 806 | snprintf(aux_irq_str, sizeof(aux_irq_str), |
782 | "%d", i8042_pnp_aux_irq); | 807 | "%d", i8042_pnp_aux_irq); |
783 | 808 | ||
784 | printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", | 809 | pr_info("PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", |
785 | i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", | 810 | i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", |
786 | i8042_pnp_aux_name, | 811 | i8042_pnp_aux_name, |
787 | i8042_pnp_data_reg, i8042_pnp_command_reg, | 812 | i8042_pnp_data_reg, i8042_pnp_command_reg, |
@@ -798,9 +823,7 @@ static int __init i8042_pnp_init(void) | |||
798 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && | 823 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && |
799 | i8042_pnp_data_reg != i8042_data_reg) || | 824 | i8042_pnp_data_reg != i8042_data_reg) || |
800 | !i8042_pnp_data_reg) { | 825 | !i8042_pnp_data_reg) { |
801 | printk(KERN_WARNING | 826 | pr_warn("PNP: PS/2 controller has invalid data port %#x; using default %#x\n", |
802 | "PNP: PS/2 controller has invalid data port %#x; " | ||
803 | "using default %#x\n", | ||
804 | i8042_pnp_data_reg, i8042_data_reg); | 827 | i8042_pnp_data_reg, i8042_data_reg); |
805 | i8042_pnp_data_reg = i8042_data_reg; | 828 | i8042_pnp_data_reg = i8042_data_reg; |
806 | pnp_data_busted = true; | 829 | pnp_data_busted = true; |
@@ -809,33 +832,27 @@ static int __init i8042_pnp_init(void) | |||
809 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && | 832 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && |
810 | i8042_pnp_command_reg != i8042_command_reg) || | 833 | i8042_pnp_command_reg != i8042_command_reg) || |
811 | !i8042_pnp_command_reg) { | 834 | !i8042_pnp_command_reg) { |
812 | printk(KERN_WARNING | 835 | pr_warn("PNP: PS/2 controller has invalid command port %#x; using default %#x\n", |
813 | "PNP: PS/2 controller has invalid command port %#x; " | ||
814 | "using default %#x\n", | ||
815 | i8042_pnp_command_reg, i8042_command_reg); | 836 | i8042_pnp_command_reg, i8042_command_reg); |
816 | i8042_pnp_command_reg = i8042_command_reg; | 837 | i8042_pnp_command_reg = i8042_command_reg; |
817 | pnp_data_busted = true; | 838 | pnp_data_busted = true; |
818 | } | 839 | } |
819 | 840 | ||
820 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { | 841 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { |
821 | printk(KERN_WARNING | 842 | pr_warn("PNP: PS/2 controller doesn't have KBD irq; using default %d\n", |
822 | "PNP: PS/2 controller doesn't have KBD irq; " | 843 | i8042_kbd_irq); |
823 | "using default %d\n", i8042_kbd_irq); | ||
824 | i8042_pnp_kbd_irq = i8042_kbd_irq; | 844 | i8042_pnp_kbd_irq = i8042_kbd_irq; |
825 | pnp_data_busted = true; | 845 | pnp_data_busted = true; |
826 | } | 846 | } |
827 | 847 | ||
828 | if (!i8042_noaux && !i8042_pnp_aux_irq) { | 848 | if (!i8042_noaux && !i8042_pnp_aux_irq) { |
829 | if (!pnp_data_busted && i8042_pnp_kbd_irq) { | 849 | if (!pnp_data_busted && i8042_pnp_kbd_irq) { |
830 | printk(KERN_WARNING | 850 | pr_warn("PNP: PS/2 appears to have AUX port disabled, " |
831 | "PNP: PS/2 appears to have AUX port disabled, " | 851 | "if this is incorrect please boot with i8042.nopnp\n"); |
832 | "if this is incorrect please boot with " | ||
833 | "i8042.nopnp\n"); | ||
834 | i8042_noaux = true; | 852 | i8042_noaux = true; |
835 | } else { | 853 | } else { |
836 | printk(KERN_WARNING | 854 | pr_warn("PNP: PS/2 controller doesn't have AUX irq; using default %d\n", |
837 | "PNP: PS/2 controller doesn't have AUX irq; " | 855 | i8042_aux_irq); |
838 | "using default %d\n", i8042_aux_irq); | ||
839 | i8042_pnp_aux_irq = i8042_aux_irq; | 856 | i8042_pnp_aux_irq = i8042_aux_irq; |
840 | } | 857 | } |
841 | } | 858 | } |
@@ -897,6 +914,9 @@ static int __init i8042_platform_init(void) | |||
897 | if (dmi_check_system(i8042_dmi_nomux_table)) | 914 | if (dmi_check_system(i8042_dmi_nomux_table)) |
898 | i8042_nomux = true; | 915 | i8042_nomux = true; |
899 | 916 | ||
917 | if (dmi_check_system(i8042_dmi_notimeout_table)) | ||
918 | i8042_notimeout = true; | ||
919 | |||
900 | if (dmi_check_system(i8042_dmi_dritek_table)) | 920 | if (dmi_check_system(i8042_dmi_dritek_table)) |
901 | i8042_dritek = true; | 921 | i8042_dritek = true; |
902 | #endif /* CONFIG_X86 */ | 922 | #endif /* CONFIG_X86 */ |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 18db5a8c7478..d37a48e099d0 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * the Free Software Foundation. | 10 | * the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
13 | #include <linux/types.h> | 15 | #include <linux/types.h> |
14 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
@@ -61,6 +63,10 @@ static bool i8042_noloop; | |||
61 | module_param_named(noloop, i8042_noloop, bool, 0); | 63 | module_param_named(noloop, i8042_noloop, bool, 0); |
62 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 64 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
63 | 65 | ||
66 | static bool i8042_notimeout; | ||
67 | module_param_named(notimeout, i8042_notimeout, bool, 0); | ||
68 | MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); | ||
69 | |||
64 | #ifdef CONFIG_X86 | 70 | #ifdef CONFIG_X86 |
65 | static bool i8042_dritek; | 71 | static bool i8042_dritek; |
66 | module_param_named(dritek, i8042_dritek, bool, 0); | 72 | module_param_named(dritek, i8042_dritek, bool, 0); |
@@ -225,8 +231,8 @@ static int i8042_flush(void) | |||
225 | udelay(50); | 231 | udelay(50); |
226 | data = i8042_read_data(); | 232 | data = i8042_read_data(); |
227 | i++; | 233 | i++; |
228 | dbg("%02x <- i8042 (flush, %s)", data, | 234 | dbg("%02x <- i8042 (flush, %s)\n", |
229 | str & I8042_STR_AUXDATA ? "aux" : "kbd"); | 235 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); |
230 | } | 236 | } |
231 | 237 | ||
232 | spin_unlock_irqrestore(&i8042_lock, flags); | 238 | spin_unlock_irqrestore(&i8042_lock, flags); |
@@ -253,32 +259,32 @@ static int __i8042_command(unsigned char *param, int command) | |||
253 | if (error) | 259 | if (error) |
254 | return error; | 260 | return error; |
255 | 261 | ||
256 | dbg("%02x -> i8042 (command)", command & 0xff); | 262 | dbg("%02x -> i8042 (command)\n", command & 0xff); |
257 | i8042_write_command(command & 0xff); | 263 | i8042_write_command(command & 0xff); |
258 | 264 | ||
259 | for (i = 0; i < ((command >> 12) & 0xf); i++) { | 265 | for (i = 0; i < ((command >> 12) & 0xf); i++) { |
260 | error = i8042_wait_write(); | 266 | error = i8042_wait_write(); |
261 | if (error) | 267 | if (error) |
262 | return error; | 268 | return error; |
263 | dbg("%02x -> i8042 (parameter)", param[i]); | 269 | dbg("%02x -> i8042 (parameter)\n", param[i]); |
264 | i8042_write_data(param[i]); | 270 | i8042_write_data(param[i]); |
265 | } | 271 | } |
266 | 272 | ||
267 | for (i = 0; i < ((command >> 8) & 0xf); i++) { | 273 | for (i = 0; i < ((command >> 8) & 0xf); i++) { |
268 | error = i8042_wait_read(); | 274 | error = i8042_wait_read(); |
269 | if (error) { | 275 | if (error) { |
270 | dbg(" -- i8042 (timeout)"); | 276 | dbg(" -- i8042 (timeout)\n"); |
271 | return error; | 277 | return error; |
272 | } | 278 | } |
273 | 279 | ||
274 | if (command == I8042_CMD_AUX_LOOP && | 280 | if (command == I8042_CMD_AUX_LOOP && |
275 | !(i8042_read_status() & I8042_STR_AUXDATA)) { | 281 | !(i8042_read_status() & I8042_STR_AUXDATA)) { |
276 | dbg(" -- i8042 (auxerr)"); | 282 | dbg(" -- i8042 (auxerr)\n"); |
277 | return -1; | 283 | return -1; |
278 | } | 284 | } |
279 | 285 | ||
280 | param[i] = i8042_read_data(); | 286 | param[i] = i8042_read_data(); |
281 | dbg("%02x <- i8042 (return)", param[i]); | 287 | dbg("%02x <- i8042 (return)\n", param[i]); |
282 | } | 288 | } |
283 | 289 | ||
284 | return 0; | 290 | return 0; |
@@ -309,7 +315,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) | |||
309 | spin_lock_irqsave(&i8042_lock, flags); | 315 | spin_lock_irqsave(&i8042_lock, flags); |
310 | 316 | ||
311 | if (!(retval = i8042_wait_write())) { | 317 | if (!(retval = i8042_wait_write())) { |
312 | dbg("%02x -> i8042 (kbd-data)", c); | 318 | dbg("%02x -> i8042 (kbd-data)\n", c); |
313 | i8042_write_data(c); | 319 | i8042_write_data(c); |
314 | } | 320 | } |
315 | 321 | ||
@@ -355,17 +361,14 @@ static void i8042_port_close(struct serio *serio) | |||
355 | 361 | ||
356 | i8042_ctr &= ~irq_bit; | 362 | i8042_ctr &= ~irq_bit; |
357 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 363 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
358 | printk(KERN_WARNING | 364 | pr_warn("Can't write CTR while closing %s port\n", port_name); |
359 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
360 | port_name); | ||
361 | 365 | ||
362 | udelay(50); | 366 | udelay(50); |
363 | 367 | ||
364 | i8042_ctr &= ~disable_bit; | 368 | i8042_ctr &= ~disable_bit; |
365 | i8042_ctr |= irq_bit; | 369 | i8042_ctr |= irq_bit; |
366 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 370 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
367 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | 371 | pr_err("Can't reactivate %s port\n", port_name); |
368 | port_name); | ||
369 | 372 | ||
370 | /* | 373 | /* |
371 | * See if there is any data appeared while we were messing with | 374 | * See if there is any data appeared while we were messing with |
@@ -456,7 +459,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
456 | str = i8042_read_status(); | 459 | str = i8042_read_status(); |
457 | if (unlikely(~str & I8042_STR_OBF)) { | 460 | if (unlikely(~str & I8042_STR_OBF)) { |
458 | spin_unlock_irqrestore(&i8042_lock, flags); | 461 | spin_unlock_irqrestore(&i8042_lock, flags); |
459 | if (irq) dbg("Interrupt %d, without any data", irq); | 462 | if (irq) |
463 | dbg("Interrupt %d, without any data\n", irq); | ||
460 | ret = 0; | 464 | ret = 0; |
461 | goto out; | 465 | goto out; |
462 | } | 466 | } |
@@ -469,7 +473,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
469 | 473 | ||
470 | dfl = 0; | 474 | dfl = 0; |
471 | if (str & I8042_STR_MUXERR) { | 475 | if (str & I8042_STR_MUXERR) { |
472 | dbg("MUX error, status is %02x, data is %02x", str, data); | 476 | dbg("MUX error, status is %02x, data is %02x\n", |
477 | str, data); | ||
473 | /* | 478 | /* |
474 | * When MUXERR condition is signalled the data register can only contain | 479 | * When MUXERR condition is signalled the data register can only contain |
475 | * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately | 480 | * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately |
@@ -503,7 +508,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
503 | } else { | 508 | } else { |
504 | 509 | ||
505 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | | 510 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | |
506 | ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); | 511 | ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); |
507 | 512 | ||
508 | port_no = (str & I8042_STR_AUXDATA) ? | 513 | port_no = (str & I8042_STR_AUXDATA) ? |
509 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; | 514 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; |
@@ -512,7 +517,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
512 | port = &i8042_ports[port_no]; | 517 | port = &i8042_ports[port_no]; |
513 | serio = port->exists ? port->serio : NULL; | 518 | serio = port->exists ? port->serio : NULL; |
514 | 519 | ||
515 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", | 520 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n", |
516 | data, port_no, irq, | 521 | data, port_no, irq, |
517 | dfl & SERIO_PARITY ? ", bad parity" : "", | 522 | dfl & SERIO_PARITY ? ", bad parity" : "", |
518 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 523 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
@@ -540,7 +545,7 @@ static int i8042_enable_kbd_port(void) | |||
540 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 545 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
541 | i8042_ctr &= ~I8042_CTR_KBDINT; | 546 | i8042_ctr &= ~I8042_CTR_KBDINT; |
542 | i8042_ctr |= I8042_CTR_KBDDIS; | 547 | i8042_ctr |= I8042_CTR_KBDDIS; |
543 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | 548 | pr_err("Failed to enable KBD port\n"); |
544 | return -EIO; | 549 | return -EIO; |
545 | } | 550 | } |
546 | 551 | ||
@@ -559,7 +564,7 @@ static int i8042_enable_aux_port(void) | |||
559 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 564 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
560 | i8042_ctr &= ~I8042_CTR_AUXINT; | 565 | i8042_ctr &= ~I8042_CTR_AUXINT; |
561 | i8042_ctr |= I8042_CTR_AUXDIS; | 566 | i8042_ctr |= I8042_CTR_AUXDIS; |
562 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | 567 | pr_err("Failed to enable AUX port\n"); |
563 | return -EIO; | 568 | return -EIO; |
564 | } | 569 | } |
565 | 570 | ||
@@ -641,7 +646,7 @@ static int __init i8042_check_mux(void) | |||
641 | if (i8042_set_mux_mode(true, &mux_version)) | 646 | if (i8042_set_mux_mode(true, &mux_version)) |
642 | return -1; | 647 | return -1; |
643 | 648 | ||
644 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | 649 | pr_info("Detected active multiplexing controller, rev %d.%d\n", |
645 | (mux_version >> 4) & 0xf, mux_version & 0xf); | 650 | (mux_version >> 4) & 0xf, mux_version & 0xf); |
646 | 651 | ||
647 | /* | 652 | /* |
@@ -651,7 +656,7 @@ static int __init i8042_check_mux(void) | |||
651 | i8042_ctr &= ~I8042_CTR_AUXINT; | 656 | i8042_ctr &= ~I8042_CTR_AUXINT; |
652 | 657 | ||
653 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 658 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
654 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); | 659 | pr_err("Failed to disable AUX port, can't use MUX\n"); |
655 | return -EIO; | 660 | return -EIO; |
656 | } | 661 | } |
657 | 662 | ||
@@ -676,8 +681,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) | |||
676 | str = i8042_read_status(); | 681 | str = i8042_read_status(); |
677 | if (str & I8042_STR_OBF) { | 682 | if (str & I8042_STR_OBF) { |
678 | data = i8042_read_data(); | 683 | data = i8042_read_data(); |
679 | dbg("%02x <- i8042 (aux_test_irq, %s)", | 684 | dbg("%02x <- i8042 (aux_test_irq, %s)\n", |
680 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); | 685 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); |
681 | if (i8042_irq_being_tested && | 686 | if (i8042_irq_being_tested && |
682 | data == 0xa5 && (str & I8042_STR_AUXDATA)) | 687 | data == 0xa5 && (str & I8042_STR_AUXDATA)) |
683 | complete(&i8042_aux_irq_delivered); | 688 | complete(&i8042_aux_irq_delivered); |
@@ -770,8 +775,8 @@ static int __init i8042_check_aux(void) | |||
770 | */ | 775 | */ |
771 | 776 | ||
772 | if (i8042_toggle_aux(false)) { | 777 | if (i8042_toggle_aux(false)) { |
773 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 778 | pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
774 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 779 | pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n"); |
775 | } | 780 | } |
776 | 781 | ||
777 | if (i8042_toggle_aux(true)) | 782 | if (i8042_toggle_aux(true)) |
@@ -819,7 +824,7 @@ static int __init i8042_check_aux(void) | |||
819 | * AUX IRQ was never delivered so we need to flush the controller to | 824 | * AUX IRQ was never delivered so we need to flush the controller to |
820 | * get rid of the byte we put there; otherwise keyboard may not work. | 825 | * get rid of the byte we put there; otherwise keyboard may not work. |
821 | */ | 826 | */ |
822 | dbg(" -- i8042 (aux irq test timeout)"); | 827 | dbg(" -- i8042 (aux irq test timeout)\n"); |
823 | i8042_flush(); | 828 | i8042_flush(); |
824 | retval = -1; | 829 | retval = -1; |
825 | } | 830 | } |
@@ -845,7 +850,7 @@ static int __init i8042_check_aux(void) | |||
845 | static int i8042_controller_check(void) | 850 | static int i8042_controller_check(void) |
846 | { | 851 | { |
847 | if (i8042_flush() == I8042_BUFFER_SIZE) { | 852 | if (i8042_flush() == I8042_BUFFER_SIZE) { |
848 | printk(KERN_ERR "i8042.c: No controller found.\n"); | 853 | pr_err("No controller found\n"); |
849 | return -ENODEV; | 854 | return -ENODEV; |
850 | } | 855 | } |
851 | 856 | ||
@@ -864,15 +869,15 @@ static int i8042_controller_selftest(void) | |||
864 | do { | 869 | do { |
865 | 870 | ||
866 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 871 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { |
867 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 872 | pr_err("i8042 controller selftest timeout\n"); |
868 | return -ENODEV; | 873 | return -ENODEV; |
869 | } | 874 | } |
870 | 875 | ||
871 | if (param == I8042_RET_CTL_TEST) | 876 | if (param == I8042_RET_CTL_TEST) |
872 | return 0; | 877 | return 0; |
873 | 878 | ||
874 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 879 | dbg("i8042 controller selftest: %#x != %#x\n", |
875 | param, I8042_RET_CTL_TEST); | 880 | param, I8042_RET_CTL_TEST); |
876 | msleep(50); | 881 | msleep(50); |
877 | } while (i++ < 5); | 882 | } while (i++ < 5); |
878 | 883 | ||
@@ -883,10 +888,10 @@ static int i8042_controller_selftest(void) | |||
883 | * and user will still get a working keyboard. This is especially | 888 | * and user will still get a working keyboard. This is especially |
884 | * important on netbooks. On other arches we trust hardware more. | 889 | * important on netbooks. On other arches we trust hardware more. |
885 | */ | 890 | */ |
886 | printk(KERN_INFO | 891 | pr_info("giving up on controller selftest, continuing anyway...\n"); |
887 | "i8042: giving up on controller selftest, continuing anyway...\n"); | ||
888 | return 0; | 892 | return 0; |
889 | #else | 893 | #else |
894 | pr_err("i8042 controller selftest failed\n"); | ||
890 | return -EIO; | 895 | return -EIO; |
891 | #endif | 896 | #endif |
892 | } | 897 | } |
@@ -909,8 +914,7 @@ static int i8042_controller_init(void) | |||
909 | 914 | ||
910 | do { | 915 | do { |
911 | if (n >= 10) { | 916 | if (n >= 10) { |
912 | printk(KERN_ERR | 917 | pr_err("Unable to get stable CTR read\n"); |
913 | "i8042.c: Unable to get stable CTR read.\n"); | ||
914 | return -EIO; | 918 | return -EIO; |
915 | } | 919 | } |
916 | 920 | ||
@@ -918,8 +922,7 @@ static int i8042_controller_init(void) | |||
918 | udelay(50); | 922 | udelay(50); |
919 | 923 | ||
920 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { | 924 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { |
921 | printk(KERN_ERR | 925 | pr_err("Can't read CTR while initializing i8042\n"); |
922 | "i8042.c: Can't read CTR while initializing i8042.\n"); | ||
923 | return -EIO; | 926 | return -EIO; |
924 | } | 927 | } |
925 | 928 | ||
@@ -943,7 +946,7 @@ static int i8042_controller_init(void) | |||
943 | if (i8042_unlock) | 946 | if (i8042_unlock) |
944 | i8042_ctr |= I8042_CTR_IGNKEYLOCK; | 947 | i8042_ctr |= I8042_CTR_IGNKEYLOCK; |
945 | else | 948 | else |
946 | printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n"); | 949 | pr_warn("Warning: Keylock active\n"); |
947 | } | 950 | } |
948 | spin_unlock_irqrestore(&i8042_lock, flags); | 951 | spin_unlock_irqrestore(&i8042_lock, flags); |
949 | 952 | ||
@@ -970,7 +973,7 @@ static int i8042_controller_init(void) | |||
970 | */ | 973 | */ |
971 | 974 | ||
972 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 975 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
973 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); | 976 | pr_err("Can't write CTR while initializing i8042\n"); |
974 | return -EIO; | 977 | return -EIO; |
975 | } | 978 | } |
976 | 979 | ||
@@ -1000,7 +1003,7 @@ static void i8042_controller_reset(void) | |||
1000 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 1003 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
1001 | 1004 | ||
1002 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 1005 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
1003 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | 1006 | pr_warn("Can't write CTR while resetting\n"); |
1004 | 1007 | ||
1005 | /* | 1008 | /* |
1006 | * Disable MUX mode if present. | 1009 | * Disable MUX mode if present. |
@@ -1021,7 +1024,7 @@ static void i8042_controller_reset(void) | |||
1021 | */ | 1024 | */ |
1022 | 1025 | ||
1023 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | 1026 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) |
1024 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); | 1027 | pr_warn("Can't restore CTR\n"); |
1025 | } | 1028 | } |
1026 | 1029 | ||
1027 | 1030 | ||
@@ -1045,14 +1048,14 @@ static long i8042_panic_blink(int state) | |||
1045 | led = (state) ? 0x01 | 0x04 : 0; | 1048 | led = (state) ? 0x01 | 0x04 : 0; |
1046 | while (i8042_read_status() & I8042_STR_IBF) | 1049 | while (i8042_read_status() & I8042_STR_IBF) |
1047 | DELAY; | 1050 | DELAY; |
1048 | dbg("%02x -> i8042 (panic blink)", 0xed); | 1051 | dbg("%02x -> i8042 (panic blink)\n", 0xed); |
1049 | i8042_suppress_kbd_ack = 2; | 1052 | i8042_suppress_kbd_ack = 2; |
1050 | i8042_write_data(0xed); /* set leds */ | 1053 | i8042_write_data(0xed); /* set leds */ |
1051 | DELAY; | 1054 | DELAY; |
1052 | while (i8042_read_status() & I8042_STR_IBF) | 1055 | while (i8042_read_status() & I8042_STR_IBF) |
1053 | DELAY; | 1056 | DELAY; |
1054 | DELAY; | 1057 | DELAY; |
1055 | dbg("%02x -> i8042 (panic blink)", led); | 1058 | dbg("%02x -> i8042 (panic blink)\n", led); |
1056 | i8042_write_data(led); | 1059 | i8042_write_data(led); |
1057 | DELAY; | 1060 | DELAY; |
1058 | return delay; | 1061 | return delay; |
@@ -1068,9 +1071,7 @@ static void i8042_dritek_enable(void) | |||
1068 | 1071 | ||
1069 | error = i8042_command(¶m, 0x1059); | 1072 | error = i8042_command(¶m, 0x1059); |
1070 | if (error) | 1073 | if (error) |
1071 | printk(KERN_WARNING | 1074 | pr_warn("Failed to enable DRITEK extension: %d\n", error); |
1072 | "Failed to enable DRITEK extension: %d\n", | ||
1073 | error); | ||
1074 | } | 1075 | } |
1075 | #endif | 1076 | #endif |
1076 | 1077 | ||
@@ -1105,10 +1106,10 @@ static int i8042_controller_resume(bool force_reset) | |||
1105 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; | 1106 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; |
1106 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); | 1107 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); |
1107 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 1108 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
1108 | printk(KERN_WARNING "i8042: Can't write CTR to resume, retrying...\n"); | 1109 | pr_warn("Can't write CTR to resume, retrying...\n"); |
1109 | msleep(50); | 1110 | msleep(50); |
1110 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 1111 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
1111 | printk(KERN_ERR "i8042: CTR write retry failed\n"); | 1112 | pr_err("CTR write retry failed\n"); |
1112 | return -EIO; | 1113 | return -EIO; |
1113 | } | 1114 | } |
1114 | } | 1115 | } |
@@ -1121,9 +1122,7 @@ static int i8042_controller_resume(bool force_reset) | |||
1121 | 1122 | ||
1122 | if (i8042_mux_present) { | 1123 | if (i8042_mux_present) { |
1123 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) | 1124 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) |
1124 | printk(KERN_WARNING | 1125 | pr_warn("failed to resume active multiplexor, mouse won't work\n"); |
1125 | "i8042: failed to resume active multiplexor, " | ||
1126 | "mouse won't work.\n"); | ||
1127 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) | 1126 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) |
1128 | i8042_enable_aux_port(); | 1127 | i8042_enable_aux_port(); |
1129 | 1128 | ||
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index cbc1beb66574..3452708fbe3b 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "i8042-sparcio.h" | 26 | #include "i8042-sparcio.h" |
27 | #elif defined(CONFIG_X86) || defined(CONFIG_IA64) | 27 | #elif defined(CONFIG_X86) || defined(CONFIG_IA64) |
28 | #include "i8042-x86ia64io.h" | 28 | #include "i8042-x86ia64io.h" |
29 | #elif defined(CONFIG_UNICORE32) | ||
30 | #include "i8042-unicore32io.h" | ||
29 | #else | 31 | #else |
30 | #include "i8042-io.h" | 32 | #include "i8042-io.h" |
31 | #endif | 33 | #endif |
@@ -89,15 +91,19 @@ | |||
89 | #ifdef DEBUG | 91 | #ifdef DEBUG |
90 | static unsigned long i8042_start_time; | 92 | static unsigned long i8042_start_time; |
91 | #define dbg_init() do { i8042_start_time = jiffies; } while (0) | 93 | #define dbg_init() do { i8042_start_time = jiffies; } while (0) |
92 | #define dbg(format, arg...) \ | 94 | #define dbg(format, arg...) \ |
93 | do { \ | 95 | do { \ |
94 | if (i8042_debug) \ | 96 | if (i8042_debug) \ |
95 | printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" , \ | 97 | printk(KERN_DEBUG KBUILD_MODNAME ": [%d] " format, \ |
96 | ## arg, (int) (jiffies - i8042_start_time)); \ | 98 | (int) (jiffies - i8042_start_time), ##arg); \ |
97 | } while (0) | 99 | } while (0) |
98 | #else | 100 | #else |
99 | #define dbg_init() do { } while (0) | 101 | #define dbg_init() do { } while (0) |
100 | #define dbg(format, arg...) do {} while (0) | 102 | #define dbg(format, arg...) \ |
103 | do { \ | ||
104 | if (0) \ | ||
105 | printk(KERN_DEBUG pr_fmt(format), ##arg); \ | ||
106 | } while (0) | ||
101 | #endif | 107 | #endif |
102 | 108 | ||
103 | #endif /* _I8042_H */ | 109 | #endif /* _I8042_H */ |
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c index 6bce22e4e495..15aa81c9f1fb 100644 --- a/drivers/input/serio/ps2mult.c +++ b/drivers/input/serio/ps2mult.c | |||
@@ -207,7 +207,7 @@ static int ps2mult_connect(struct serio *serio, struct serio_driver *drv) | |||
207 | err_out: | 207 | err_out: |
208 | while (--i >= 0) | 208 | while (--i >= 0) |
209 | kfree(psm->ports[i].serio); | 209 | kfree(psm->ports[i].serio); |
210 | kfree(serio); | 210 | kfree(psm); |
211 | return error; | 211 | return error; |
212 | } | 212 | } |
213 | 213 | ||
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 9da6fbcaaa7e..7ec3c97dc1b9 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c | |||
@@ -90,7 +90,7 @@ static int rpckbd_open(struct serio *port) | |||
90 | 90 | ||
91 | if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { | 91 | if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { |
92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); | 92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); |
93 | free_irq(IRQ_KEYBOARDRX, NULL); | 93 | free_irq(IRQ_KEYBOARDRX, port); |
94 | return -EBUSY; | 94 | return -EBUSY; |
95 | } | 95 | } |
96 | 96 | ||
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 405bf214527c..ba70058e2be3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -32,10 +32,9 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/serio.h> | 33 | #include <linux/serio.h> |
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/wait.h> | ||
36 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/kthread.h> | 37 | #include <linux/workqueue.h> |
39 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
40 | 39 | ||
41 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
@@ -44,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
44 | 43 | ||
45 | /* | 44 | /* |
46 | * serio_mutex protects entire serio subsystem and is taken every time | 45 | * serio_mutex protects entire serio subsystem and is taken every time |
47 | * serio port or driver registrered or unregistered. | 46 | * serio port or driver registered or unregistered. |
48 | */ | 47 | */ |
49 | static DEFINE_MUTEX(serio_mutex); | 48 | static DEFINE_MUTEX(serio_mutex); |
50 | 49 | ||
@@ -165,58 +164,22 @@ struct serio_event { | |||
165 | 164 | ||
166 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 165 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
167 | static LIST_HEAD(serio_event_list); | 166 | static LIST_HEAD(serio_event_list); |
168 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | ||
169 | static struct task_struct *serio_task; | ||
170 | 167 | ||
171 | static int serio_queue_event(void *object, struct module *owner, | 168 | static struct serio_event *serio_get_event(void) |
172 | enum serio_event_type event_type) | ||
173 | { | 169 | { |
170 | struct serio_event *event = NULL; | ||
174 | unsigned long flags; | 171 | unsigned long flags; |
175 | struct serio_event *event; | ||
176 | int retval = 0; | ||
177 | 172 | ||
178 | spin_lock_irqsave(&serio_event_lock, flags); | 173 | spin_lock_irqsave(&serio_event_lock, flags); |
179 | 174 | ||
180 | /* | 175 | if (!list_empty(&serio_event_list)) { |
181 | * Scan event list for the other events for the same serio port, | 176 | event = list_first_entry(&serio_event_list, |
182 | * starting with the most recent one. If event is the same we | 177 | struct serio_event, node); |
183 | * do not need add new one. If event is of different type we | 178 | list_del_init(&event->node); |
184 | * need to add this event and should not look further because | ||
185 | * we need to preseve sequence of distinct events. | ||
186 | */ | ||
187 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
188 | if (event->object == object) { | ||
189 | if (event->type == event_type) | ||
190 | goto out; | ||
191 | break; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
196 | if (!event) { | ||
197 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
198 | retval = -ENOMEM; | ||
199 | goto out; | ||
200 | } | ||
201 | |||
202 | if (!try_module_get(owner)) { | ||
203 | pr_warning("Can't get module reference, dropping event %d\n", | ||
204 | event_type); | ||
205 | kfree(event); | ||
206 | retval = -EINVAL; | ||
207 | goto out; | ||
208 | } | 179 | } |
209 | 180 | ||
210 | event->type = event_type; | ||
211 | event->object = object; | ||
212 | event->owner = owner; | ||
213 | |||
214 | list_add_tail(&event->node, &serio_event_list); | ||
215 | wake_up(&serio_wait); | ||
216 | |||
217 | out: | ||
218 | spin_unlock_irqrestore(&serio_event_lock, flags); | 181 | spin_unlock_irqrestore(&serio_event_lock, flags); |
219 | return retval; | 182 | return event; |
220 | } | 183 | } |
221 | 184 | ||
222 | static void serio_free_event(struct serio_event *event) | 185 | static void serio_free_event(struct serio_event *event) |
@@ -225,7 +188,8 @@ static void serio_free_event(struct serio_event *event) | |||
225 | kfree(event); | 188 | kfree(event); |
226 | } | 189 | } |
227 | 190 | ||
228 | static void serio_remove_duplicate_events(struct serio_event *event) | 191 | static void serio_remove_duplicate_events(void *object, |
192 | enum serio_event_type type) | ||
229 | { | 193 | { |
230 | struct serio_event *e, *next; | 194 | struct serio_event *e, *next; |
231 | unsigned long flags; | 195 | unsigned long flags; |
@@ -233,13 +197,13 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
233 | spin_lock_irqsave(&serio_event_lock, flags); | 197 | spin_lock_irqsave(&serio_event_lock, flags); |
234 | 198 | ||
235 | list_for_each_entry_safe(e, next, &serio_event_list, node) { | 199 | list_for_each_entry_safe(e, next, &serio_event_list, node) { |
236 | if (event->object == e->object) { | 200 | if (object == e->object) { |
237 | /* | 201 | /* |
238 | * If this event is of different type we should not | 202 | * If this event is of different type we should not |
239 | * look further - we only suppress duplicate events | 203 | * look further - we only suppress duplicate events |
240 | * that were sent back-to-back. | 204 | * that were sent back-to-back. |
241 | */ | 205 | */ |
242 | if (event->type != e->type) | 206 | if (type != e->type) |
243 | break; | 207 | break; |
244 | 208 | ||
245 | list_del_init(&e->node); | 209 | list_del_init(&e->node); |
@@ -250,25 +214,7 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
250 | spin_unlock_irqrestore(&serio_event_lock, flags); | 214 | spin_unlock_irqrestore(&serio_event_lock, flags); |
251 | } | 215 | } |
252 | 216 | ||
253 | 217 | static void serio_handle_event(struct work_struct *work) | |
254 | static struct serio_event *serio_get_event(void) | ||
255 | { | ||
256 | struct serio_event *event = NULL; | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&serio_event_lock, flags); | ||
260 | |||
261 | if (!list_empty(&serio_event_list)) { | ||
262 | event = list_first_entry(&serio_event_list, | ||
263 | struct serio_event, node); | ||
264 | list_del_init(&event->node); | ||
265 | } | ||
266 | |||
267 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
268 | return event; | ||
269 | } | ||
270 | |||
271 | static void serio_handle_event(void) | ||
272 | { | 218 | { |
273 | struct serio_event *event; | 219 | struct serio_event *event; |
274 | 220 | ||
@@ -300,13 +246,66 @@ static void serio_handle_event(void) | |||
300 | break; | 246 | break; |
301 | } | 247 | } |
302 | 248 | ||
303 | serio_remove_duplicate_events(event); | 249 | serio_remove_duplicate_events(event->object, event->type); |
304 | serio_free_event(event); | 250 | serio_free_event(event); |
305 | } | 251 | } |
306 | 252 | ||
307 | mutex_unlock(&serio_mutex); | 253 | mutex_unlock(&serio_mutex); |
308 | } | 254 | } |
309 | 255 | ||
256 | static DECLARE_WORK(serio_event_work, serio_handle_event); | ||
257 | |||
258 | static int serio_queue_event(void *object, struct module *owner, | ||
259 | enum serio_event_type event_type) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | struct serio_event *event; | ||
263 | int retval = 0; | ||
264 | |||
265 | spin_lock_irqsave(&serio_event_lock, flags); | ||
266 | |||
267 | /* | ||
268 | * Scan event list for the other events for the same serio port, | ||
269 | * starting with the most recent one. If event is the same we | ||
270 | * do not need add new one. If event is of different type we | ||
271 | * need to add this event and should not look further because | ||
272 | * we need to preseve sequence of distinct events. | ||
273 | */ | ||
274 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
275 | if (event->object == object) { | ||
276 | if (event->type == event_type) | ||
277 | goto out; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
283 | if (!event) { | ||
284 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
285 | retval = -ENOMEM; | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | if (!try_module_get(owner)) { | ||
290 | pr_warning("Can't get module reference, dropping event %d\n", | ||
291 | event_type); | ||
292 | kfree(event); | ||
293 | retval = -EINVAL; | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | event->type = event_type; | ||
298 | event->object = object; | ||
299 | event->owner = owner; | ||
300 | |||
301 | list_add_tail(&event->node, &serio_event_list); | ||
302 | queue_work(system_long_wq, &serio_event_work); | ||
303 | |||
304 | out: | ||
305 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
306 | return retval; | ||
307 | } | ||
308 | |||
310 | /* | 309 | /* |
311 | * Remove all events that have been submitted for a given | 310 | * Remove all events that have been submitted for a given |
312 | * object, be it serio port or driver. | 311 | * object, be it serio port or driver. |
@@ -356,18 +355,6 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
356 | return child; | 355 | return child; |
357 | } | 356 | } |
358 | 357 | ||
359 | static int serio_thread(void *nothing) | ||
360 | { | ||
361 | do { | ||
362 | serio_handle_event(); | ||
363 | wait_event_interruptible(serio_wait, | ||
364 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
365 | } while (!kthread_should_stop()); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | |||
371 | /* | 358 | /* |
372 | * Serio port operations | 359 | * Serio port operations |
373 | */ | 360 | */ |
@@ -450,10 +437,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
450 | } else if (!strncmp(buf, "rescan", count)) { | 437 | } else if (!strncmp(buf, "rescan", count)) { |
451 | serio_disconnect_port(serio); | 438 | serio_disconnect_port(serio); |
452 | serio_find_driver(serio); | 439 | serio_find_driver(serio); |
440 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
453 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
454 | serio_disconnect_port(serio); | 442 | serio_disconnect_port(serio); |
455 | error = serio_bind_driver(serio, to_serio_driver(drv)); | 443 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
456 | put_driver(drv); | 444 | put_driver(drv); |
445 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
457 | } else { | 446 | } else { |
458 | error = -EINVAL; | 447 | error = -EINVAL; |
459 | } | 448 | } |
@@ -1040,21 +1029,18 @@ static int __init serio_init(void) | |||
1040 | return error; | 1029 | return error; |
1041 | } | 1030 | } |
1042 | 1031 | ||
1043 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); | ||
1044 | if (IS_ERR(serio_task)) { | ||
1045 | bus_unregister(&serio_bus); | ||
1046 | error = PTR_ERR(serio_task); | ||
1047 | pr_err("Failed to start kseriod, error: %d\n", error); | ||
1048 | return error; | ||
1049 | } | ||
1050 | |||
1051 | return 0; | 1032 | return 0; |
1052 | } | 1033 | } |
1053 | 1034 | ||
1054 | static void __exit serio_exit(void) | 1035 | static void __exit serio_exit(void) |
1055 | { | 1036 | { |
1056 | bus_unregister(&serio_bus); | 1037 | bus_unregister(&serio_bus); |
1057 | kthread_stop(serio_task); | 1038 | |
1039 | /* | ||
1040 | * There should not be any outstanding events but work may | ||
1041 | * still be scheduled so simply cancel it. | ||
1042 | */ | ||
1043 | cancel_work_sync(&serio_event_work); | ||
1058 | } | 1044 | } |
1059 | 1045 | ||
1060 | subsys_initcall(serio_init); | 1046 | subsys_initcall(serio_init); |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 6e362de3f412..8755f5f3ad37 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -116,14 +116,15 @@ static void serport_ldisc_close(struct tty_struct *tty) | |||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * serport_ldisc_receive() is called by the low level tty driver when characters | 118 | * serport_ldisc_receive() is called by the low level tty driver when characters |
119 | * are ready for us. We forward the characters, one by one to the 'interrupt' | 119 | * are ready for us. We forward the characters and flags, one by one to the |
120 | * routine. | 120 | * 'interrupt' routine. |
121 | */ | 121 | */ |
122 | 122 | ||
123 | static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) | 123 | static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) |
124 | { | 124 | { |
125 | struct serport *serport = (struct serport*) tty->disc_data; | 125 | struct serport *serport = (struct serport*) tty->disc_data; |
126 | unsigned long flags; | 126 | unsigned long flags; |
127 | unsigned int ch_flags; | ||
127 | int i; | 128 | int i; |
128 | 129 | ||
129 | spin_lock_irqsave(&serport->lock, flags); | 130 | spin_lock_irqsave(&serport->lock, flags); |
@@ -131,8 +132,23 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c | |||
131 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) | 132 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) |
132 | goto out; | 133 | goto out; |
133 | 134 | ||
134 | for (i = 0; i < count; i++) | 135 | for (i = 0; i < count; i++) { |
135 | serio_interrupt(serport->serio, cp[i], 0); | 136 | switch (fp[i]) { |
137 | case TTY_FRAME: | ||
138 | ch_flags = SERIO_FRAME; | ||
139 | break; | ||
140 | |||
141 | case TTY_PARITY: | ||
142 | ch_flags = SERIO_PARITY; | ||
143 | break; | ||
144 | |||
145 | default: | ||
146 | ch_flags = 0; | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | serio_interrupt(serport->serio, cp[i], ch_flags); | ||
151 | } | ||
136 | 152 | ||
137 | out: | 153 | out: |
138 | spin_unlock_irqrestore(&serport->lock, flags); | 154 | spin_unlock_irqrestore(&serport->lock, flags); |
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index bb14449fb022..80baa53da5b1 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -225,15 +225,14 @@ static void sxps2_close(struct serio *pserio) | |||
225 | /** | 225 | /** |
226 | * xps2_of_probe - probe method for the PS/2 device. | 226 | * xps2_of_probe - probe method for the PS/2 device. |
227 | * @of_dev: pointer to OF device structure | 227 | * @of_dev: pointer to OF device structure |
228 | * @match: pointer to the stucture used for matching a device | 228 | * @match: pointer to the structure used for matching a device |
229 | * | 229 | * |
230 | * This function probes the PS/2 device in the device tree. | 230 | * This function probes the PS/2 device in the device tree. |
231 | * It initializes the driver data structure and the hardware. | 231 | * It initializes the driver data structure and the hardware. |
232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative | 232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative |
233 | * value if there is an error. | 233 | * value if there is an error. |
234 | */ | 234 | */ |
235 | static int __devinit xps2_of_probe(struct platform_device *ofdev, | 235 | static int __devinit xps2_of_probe(struct platform_device *ofdev) |
236 | const struct of_device_id *match) | ||
237 | { | 236 | { |
238 | struct resource r_irq; /* Interrupt resources */ | 237 | struct resource r_irq; /* Interrupt resources */ |
239 | struct resource r_mem; /* IO mem resources */ | 238 | struct resource r_mem; /* IO mem resources */ |
@@ -361,7 +360,7 @@ static const struct of_device_id xps2_of_match[] __devinitconst = { | |||
361 | }; | 360 | }; |
362 | MODULE_DEVICE_TABLE(of, xps2_of_match); | 361 | MODULE_DEVICE_TABLE(of, xps2_of_match); |
363 | 362 | ||
364 | static struct of_platform_driver xps2_of_driver = { | 363 | static struct platform_driver xps2_of_driver = { |
365 | .driver = { | 364 | .driver = { |
366 | .name = DRIVER_NAME, | 365 | .name = DRIVER_NAME, |
367 | .owner = THIS_MODULE, | 366 | .owner = THIS_MODULE, |
@@ -373,12 +372,12 @@ static struct of_platform_driver xps2_of_driver = { | |||
373 | 372 | ||
374 | static int __init xps2_init(void) | 373 | static int __init xps2_init(void) |
375 | { | 374 | { |
376 | return of_register_platform_driver(&xps2_of_driver); | 375 | return platform_driver_register(&xps2_of_driver); |
377 | } | 376 | } |
378 | 377 | ||
379 | static void __exit xps2_cleanup(void) | 378 | static void __exit xps2_cleanup(void) |
380 | { | 379 | { |
381 | of_unregister_platform_driver(&xps2_of_driver); | 380 | platform_driver_unregister(&xps2_of_driver); |
382 | } | 381 | } |
383 | 382 | ||
384 | module_init(xps2_init); | 383 | module_init(xps2_init); |
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index a29a7812bd46..fdb6a3976f94 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c | |||
@@ -201,16 +201,23 @@ int sparse_keymap_setup(struct input_dev *dev, | |||
201 | break; | 201 | break; |
202 | 202 | ||
203 | case KE_SW: | 203 | case KE_SW: |
204 | case KE_VSW: | ||
204 | __set_bit(EV_SW, dev->evbit); | 205 | __set_bit(EV_SW, dev->evbit); |
205 | __set_bit(entry->sw.code, dev->swbit); | 206 | __set_bit(entry->sw.code, dev->swbit); |
206 | break; | 207 | break; |
207 | } | 208 | } |
208 | } | 209 | } |
209 | 210 | ||
211 | if (test_bit(EV_KEY, dev->evbit)) { | ||
212 | __set_bit(KEY_UNKNOWN, dev->keybit); | ||
213 | __set_bit(EV_MSC, dev->evbit); | ||
214 | __set_bit(MSC_SCAN, dev->mscbit); | ||
215 | } | ||
216 | |||
210 | dev->keycode = map; | 217 | dev->keycode = map; |
211 | dev->keycodemax = map_size; | 218 | dev->keycodemax = map_size; |
212 | dev->getkeycode_new = sparse_keymap_getkeycode; | 219 | dev->getkeycode = sparse_keymap_getkeycode; |
213 | dev->setkeycode_new = sparse_keymap_setkeycode; | 220 | dev->setkeycode = sparse_keymap_setkeycode; |
214 | 221 | ||
215 | return 0; | 222 | return 0; |
216 | 223 | ||
@@ -267,6 +274,7 @@ void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *k | |||
267 | { | 274 | { |
268 | switch (ke->type) { | 275 | switch (ke->type) { |
269 | case KE_KEY: | 276 | case KE_KEY: |
277 | input_event(dev, EV_MSC, MSC_SCAN, ke->code); | ||
270 | input_report_key(dev, ke->keycode, value); | 278 | input_report_key(dev, ke->keycode, value); |
271 | input_sync(dev); | 279 | input_sync(dev); |
272 | if (value && autorelease) { | 280 | if (value && autorelease) { |
@@ -304,12 +312,19 @@ bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code, | |||
304 | { | 312 | { |
305 | const struct key_entry *ke = | 313 | const struct key_entry *ke = |
306 | sparse_keymap_entry_from_scancode(dev, code); | 314 | sparse_keymap_entry_from_scancode(dev, code); |
315 | struct key_entry unknown_ke; | ||
307 | 316 | ||
308 | if (ke) { | 317 | if (ke) { |
309 | sparse_keymap_report_entry(dev, ke, value, autorelease); | 318 | sparse_keymap_report_entry(dev, ke, value, autorelease); |
310 | return true; | 319 | return true; |
311 | } | 320 | } |
312 | 321 | ||
322 | /* Report an unknown key event as a debugging aid */ | ||
323 | unknown_ke.type = KE_KEY; | ||
324 | unknown_ke.code = code; | ||
325 | unknown_ke.keycode = KEY_UNKNOWN; | ||
326 | sparse_keymap_report_entry(dev, &unknown_ke, value, true); | ||
327 | |||
313 | return false; | 328 | return false; |
314 | } | 329 | } |
315 | EXPORT_SYMBOL(sparse_keymap_report_event); | 330 | EXPORT_SYMBOL(sparse_keymap_report_event); |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index de5adb109030..23317bd09c82 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -103,6 +103,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
103 | MODULE_LICENSE(DRIVER_LICENSE); | 103 | MODULE_LICENSE(DRIVER_LICENSE); |
104 | 104 | ||
105 | #define USB_VENDOR_ID_WACOM 0x056a | 105 | #define USB_VENDOR_ID_WACOM 0x056a |
106 | #define USB_VENDOR_ID_LENOVO 0x17ef | ||
106 | 107 | ||
107 | struct wacom { | 108 | struct wacom { |
108 | dma_addr_t data_dma; | 109 | dma_addr_t data_dma; |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index fc381498b798..449c0a46dbac 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -193,16 +193,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
193 | case HID_USAGE_X: | 193 | case HID_USAGE_X: |
194 | if (usage == WCM_DESKTOP) { | 194 | if (usage == WCM_DESKTOP) { |
195 | if (finger) { | 195 | if (finger) { |
196 | features->device_type = BTN_TOOL_DOUBLETAP; | 196 | features->device_type = BTN_TOOL_FINGER; |
197 | if (features->type == TABLETPC2FG) { | 197 | if (features->type == TABLETPC2FG) { |
198 | /* need to reset back */ | 198 | /* need to reset back */ |
199 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 199 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
200 | features->device_type = BTN_TOOL_TRIPLETAP; | 200 | features->device_type = BTN_TOOL_DOUBLETAP; |
201 | } | 201 | } |
202 | if (features->type == BAMBOO_PT) { | 202 | if (features->type == BAMBOO_PT) { |
203 | /* need to reset back */ | 203 | /* need to reset back */ |
204 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | 204 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
205 | features->device_type = BTN_TOOL_TRIPLETAP; | 205 | features->device_type = BTN_TOOL_DOUBLETAP; |
206 | features->x_phy = | 206 | features->x_phy = |
207 | get_unaligned_le16(&report[i + 5]); | 207 | get_unaligned_le16(&report[i + 5]); |
208 | features->x_max = | 208 | features->x_max = |
@@ -241,11 +241,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
241 | case HID_USAGE_Y: | 241 | case HID_USAGE_Y: |
242 | if (usage == WCM_DESKTOP) { | 242 | if (usage == WCM_DESKTOP) { |
243 | if (finger) { | 243 | if (finger) { |
244 | features->device_type = BTN_TOOL_DOUBLETAP; | 244 | features->device_type = BTN_TOOL_FINGER; |
245 | if (features->type == TABLETPC2FG) { | 245 | if (features->type == TABLETPC2FG) { |
246 | /* need to reset back */ | 246 | /* need to reset back */ |
247 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 247 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
248 | features->device_type = BTN_TOOL_TRIPLETAP; | 248 | features->device_type = BTN_TOOL_DOUBLETAP; |
249 | features->y_max = | 249 | features->y_max = |
250 | get_unaligned_le16(&report[i + 3]); | 250 | get_unaligned_le16(&report[i + 3]); |
251 | features->y_phy = | 251 | features->y_phy = |
@@ -254,7 +254,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
254 | } else if (features->type == BAMBOO_PT) { | 254 | } else if (features->type == BAMBOO_PT) { |
255 | /* need to reset back */ | 255 | /* need to reset back */ |
256 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | 256 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
257 | features->device_type = BTN_TOOL_TRIPLETAP; | 257 | features->device_type = BTN_TOOL_DOUBLETAP; |
258 | features->y_phy = | 258 | features->y_phy = |
259 | get_unaligned_le16(&report[i + 3]); | 259 | get_unaligned_le16(&report[i + 3]); |
260 | features->y_max = | 260 | features->y_max = |
@@ -519,7 +519,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
519 | /* Retrieve the physical and logical size for OEM devices */ | 519 | /* Retrieve the physical and logical size for OEM devices */ |
520 | error = wacom_retrieve_hid_descriptor(intf, features); | 520 | error = wacom_retrieve_hid_descriptor(intf, features); |
521 | if (error) | 521 | if (error) |
522 | goto fail2; | 522 | goto fail3; |
523 | 523 | ||
524 | wacom_setup_device_quirks(features); | 524 | wacom_setup_device_quirks(features); |
525 | 525 | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b3252ef1e279..08ba5ad9c9be 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -14,6 +14,15 @@ | |||
14 | 14 | ||
15 | #include "wacom_wac.h" | 15 | #include "wacom_wac.h" |
16 | #include "wacom.h" | 16 | #include "wacom.h" |
17 | #include <linux/input/mt.h> | ||
18 | |||
19 | /* resolution for penabled devices */ | ||
20 | #define WACOM_PL_RES 20 | ||
21 | #define WACOM_PENPRTN_RES 40 | ||
22 | #define WACOM_VOLITO_RES 50 | ||
23 | #define WACOM_GRAPHIRE_RES 80 | ||
24 | #define WACOM_INTUOS_RES 100 | ||
25 | #define WACOM_INTUOS3_RES 200 | ||
17 | 26 | ||
18 | static int wacom_penpartner_irq(struct wacom_wac *wacom) | 27 | static int wacom_penpartner_irq(struct wacom_wac *wacom) |
19 | { | 28 | { |
@@ -674,169 +683,87 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
674 | return 1; | 683 | return 1; |
675 | } | 684 | } |
676 | 685 | ||
677 | 686 | static int wacom_tpc_mt_touch(struct wacom_wac *wacom) | |
678 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) | ||
679 | { | 687 | { |
680 | struct input_dev *input = wacom->input; | 688 | struct input_dev *input = wacom->input; |
681 | int finger = idx + 1; | 689 | unsigned char *data = wacom->data; |
682 | int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; | 690 | int contact_with_no_pen_down_count = 0; |
683 | int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; | 691 | int i; |
684 | 692 | ||
685 | /* | 693 | for (i = 0; i < 2; i++) { |
686 | * Work around input core suppressing "duplicate" events since | 694 | int p = data[1] & (1 << i); |
687 | * we are abusing ABS_X/ABS_Y to transmit multi-finger data. | 695 | bool touch = p && !wacom->shared->stylus_in_proximity; |
688 | * This should go away once we switch to true multitouch | 696 | |
689 | * protocol. | 697 | input_mt_slot(input, i); |
690 | */ | 698 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); |
691 | if (wacom->last_finger != finger) { | 699 | if (touch) { |
692 | if (x == input_abs_get_val(input, ABS_X)) | 700 | int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff; |
693 | x++; | 701 | int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff; |
694 | 702 | ||
695 | if (y == input_abs_get_val(input, ABS_Y)) | 703 | input_report_abs(input, ABS_MT_POSITION_X, x); |
696 | y++; | 704 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
705 | contact_with_no_pen_down_count++; | ||
706 | } | ||
697 | } | 707 | } |
698 | 708 | ||
699 | input_report_abs(input, ABS_X, x); | 709 | /* keep touch state for pen event */ |
700 | input_report_abs(input, ABS_Y, y); | 710 | wacom->shared->touch_down = (contact_with_no_pen_down_count > 0); |
701 | input_report_abs(input, ABS_MISC, wacom->id[0]); | ||
702 | input_report_key(input, wacom->tool[finger], 1); | ||
703 | if (!idx) | ||
704 | input_report_key(input, BTN_TOUCH, 1); | ||
705 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
706 | input_sync(input); | ||
707 | 711 | ||
708 | wacom->last_finger = finger; | 712 | input_mt_report_pointer_emulation(input, true); |
709 | } | ||
710 | 713 | ||
711 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) | 714 | return 1; |
712 | { | ||
713 | struct input_dev *input = wacom->input; | ||
714 | int finger = idx + 1; | ||
715 | |||
716 | input_report_abs(input, ABS_X, 0); | ||
717 | input_report_abs(input, ABS_Y, 0); | ||
718 | input_report_abs(input, ABS_MISC, 0); | ||
719 | input_report_key(input, wacom->tool[finger], 0); | ||
720 | if (!idx) | ||
721 | input_report_key(input, BTN_TOUCH, 0); | ||
722 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
723 | input_sync(input); | ||
724 | } | 715 | } |
725 | 716 | ||
726 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) | 717 | static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) |
727 | { | 718 | { |
728 | char *data = wacom->data; | 719 | char *data = wacom->data; |
729 | struct input_dev *input = wacom->input; | 720 | struct input_dev *input = wacom->input; |
721 | bool prox; | ||
722 | int x = 0, y = 0; | ||
730 | 723 | ||
731 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; | 724 | if (!wacom->shared->stylus_in_proximity) { |
732 | wacom->id[0] = TOUCH_DEVICE_ID; | 725 | if (len == WACOM_PKGLEN_TPC1FG) { |
733 | wacom->tool[2] = BTN_TOOL_TRIPLETAP; | 726 | prox = data[0] & 0x01; |
734 | 727 | x = get_unaligned_le16(&data[1]); | |
735 | if (len != WACOM_PKGLEN_TPC1FG) { | 728 | y = get_unaligned_le16(&data[3]); |
736 | 729 | } else { /* with capacity */ | |
737 | switch (data[0]) { | 730 | prox = data[1] & 0x01; |
731 | x = le16_to_cpup((__le16 *)&data[2]); | ||
732 | y = le16_to_cpup((__le16 *)&data[4]); | ||
733 | } | ||
734 | } else | ||
735 | /* force touch out when pen is in prox */ | ||
736 | prox = 0; | ||
738 | 737 | ||
739 | case WACOM_REPORT_TPC1FG: | 738 | if (prox) { |
740 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); | 739 | input_report_abs(input, ABS_X, x); |
741 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); | 740 | input_report_abs(input, ABS_Y, y); |
742 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); | 741 | } |
743 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); | 742 | input_report_key(input, BTN_TOUCH, prox); |
744 | input_report_abs(input, ABS_MISC, wacom->id[0]); | ||
745 | input_report_key(input, wacom->tool[1], 1); | ||
746 | input_sync(input); | ||
747 | break; | ||
748 | 743 | ||
749 | case WACOM_REPORT_TPC2FG: | 744 | /* keep touch state for pen events */ |
750 | if (data[1] & 0x01) | 745 | wacom->shared->touch_down = prox; |
751 | wacom_tpc_finger_in(wacom, data, 0); | ||
752 | else if (wacom->id[1] & 0x01) | ||
753 | wacom_tpc_touch_out(wacom, 0); | ||
754 | 746 | ||
755 | if (data[1] & 0x02) | 747 | return 1; |
756 | wacom_tpc_finger_in(wacom, data, 1); | ||
757 | else if (wacom->id[1] & 0x02) | ||
758 | wacom_tpc_touch_out(wacom, 1); | ||
759 | break; | ||
760 | } | ||
761 | } else { | ||
762 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); | ||
763 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); | ||
764 | input_report_key(input, BTN_TOUCH, 1); | ||
765 | input_report_abs(input, ABS_MISC, wacom->id[1]); | ||
766 | input_report_key(input, wacom->tool[1], 1); | ||
767 | input_sync(input); | ||
768 | } | ||
769 | } | 748 | } |
770 | 749 | ||
771 | static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | 750 | static int wacom_tpc_pen(struct wacom_wac *wacom) |
772 | { | 751 | { |
773 | struct wacom_features *features = &wacom->features; | 752 | struct wacom_features *features = &wacom->features; |
774 | char *data = wacom->data; | 753 | char *data = wacom->data; |
775 | struct input_dev *input = wacom->input; | 754 | struct input_dev *input = wacom->input; |
776 | int prox = 0, pressure; | 755 | int pressure; |
777 | int retval = 0; | 756 | bool prox = data[1] & 0x20; |
778 | |||
779 | dbg("wacom_tpc_irq: received report #%d", data[0]); | ||
780 | |||
781 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ | ||
782 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ | ||
783 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ | ||
784 | |||
785 | if (wacom->shared->stylus_in_proximity) { | ||
786 | if (wacom->id[1] & 0x01) | ||
787 | wacom_tpc_touch_out(wacom, 0); | ||
788 | |||
789 | if (wacom->id[1] & 0x02) | ||
790 | wacom_tpc_touch_out(wacom, 1); | ||
791 | |||
792 | wacom->id[1] = 0; | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ | ||
797 | prox = data[0] & 0x01; | ||
798 | } else { /* with capacity */ | ||
799 | if (data[0] == WACOM_REPORT_TPC1FG) | ||
800 | /* single touch */ | ||
801 | prox = data[1] & 0x01; | ||
802 | else | ||
803 | /* 2FG touch data */ | ||
804 | prox = data[1] & 0x03; | ||
805 | } | ||
806 | |||
807 | if (prox) { | ||
808 | if (!wacom->id[1]) | ||
809 | wacom->last_finger = 1; | ||
810 | wacom_tpc_touch_in(wacom, len); | ||
811 | } else { | ||
812 | if (data[0] == WACOM_REPORT_TPC2FG) { | ||
813 | /* 2FGT out-prox */ | ||
814 | if (wacom->id[1] & 0x01) | ||
815 | wacom_tpc_touch_out(wacom, 0); | ||
816 | 757 | ||
817 | if (wacom->id[1] & 0x02) | 758 | if (!wacom->shared->stylus_in_proximity) /* first in prox */ |
818 | wacom_tpc_touch_out(wacom, 1); | 759 | /* Going into proximity select tool */ |
819 | } else | 760 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
820 | /* one finger touch */ | ||
821 | wacom_tpc_touch_out(wacom, 0); | ||
822 | 761 | ||
823 | wacom->id[0] = 0; | 762 | /* keep pen state for touch events */ |
824 | } | 763 | wacom->shared->stylus_in_proximity = prox; |
825 | /* keep prox bit to send proper out-prox event */ | ||
826 | wacom->id[1] = prox; | ||
827 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ | ||
828 | prox = data[1] & 0x20; | ||
829 | |||
830 | if (!wacom->shared->stylus_in_proximity) { /* first in prox */ | ||
831 | /* Going into proximity select tool */ | ||
832 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
833 | if (wacom->tool[0] == BTN_TOOL_PEN) | ||
834 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
835 | else | ||
836 | wacom->id[0] = ERASER_DEVICE_ID; | ||
837 | 764 | ||
838 | wacom->shared->stylus_in_proximity = true; | 765 | /* send pen events only when touch is up or forced out */ |
839 | } | 766 | if (!wacom->shared->touch_down) { |
840 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); | 767 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); |
841 | input_report_key(input, BTN_STYLUS2, data[1] & 0x10); | 768 | input_report_key(input, BTN_STYLUS2, data[1] & 0x10); |
842 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); | 769 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); |
@@ -846,15 +773,27 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
846 | pressure = features->pressure_max + pressure + 1; | 773 | pressure = features->pressure_max + pressure + 1; |
847 | input_report_abs(input, ABS_PRESSURE, pressure); | 774 | input_report_abs(input, ABS_PRESSURE, pressure); |
848 | input_report_key(input, BTN_TOUCH, data[1] & 0x05); | 775 | input_report_key(input, BTN_TOUCH, data[1] & 0x05); |
849 | if (!prox) { /* out-prox */ | ||
850 | wacom->id[0] = 0; | ||
851 | wacom->shared->stylus_in_proximity = false; | ||
852 | } | ||
853 | input_report_key(input, wacom->tool[0], prox); | 776 | input_report_key(input, wacom->tool[0], prox); |
854 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 777 | return 1; |
855 | retval = 1; | ||
856 | } | 778 | } |
857 | return retval; | 779 | |
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | ||
784 | { | ||
785 | char *data = wacom->data; | ||
786 | |||
787 | dbg("wacom_tpc_irq: received report #%d", data[0]); | ||
788 | |||
789 | if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG) | ||
790 | return wacom_tpc_single_touch(wacom, len); | ||
791 | else if (data[0] == WACOM_REPORT_TPC2FG) | ||
792 | return wacom_tpc_mt_touch(wacom); | ||
793 | else if (data[0] == WACOM_REPORT_PENABLED) | ||
794 | return wacom_tpc_pen(wacom); | ||
795 | |||
796 | return 0; | ||
858 | } | 797 | } |
859 | 798 | ||
860 | static int wacom_bpt_touch(struct wacom_wac *wacom) | 799 | static int wacom_bpt_touch(struct wacom_wac *wacom) |
@@ -862,19 +801,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) | |||
862 | struct wacom_features *features = &wacom->features; | 801 | struct wacom_features *features = &wacom->features; |
863 | struct input_dev *input = wacom->input; | 802 | struct input_dev *input = wacom->input; |
864 | unsigned char *data = wacom->data; | 803 | unsigned char *data = wacom->data; |
865 | int sp = 0, sx = 0, sy = 0, count = 0; | ||
866 | int i; | 804 | int i; |
867 | 805 | ||
868 | for (i = 0; i < 2; i++) { | 806 | for (i = 0; i < 2; i++) { |
869 | int p = data[9 * i + 2]; | 807 | int p = data[9 * i + 2]; |
808 | bool touch = p && !wacom->shared->stylus_in_proximity; | ||
809 | |||
870 | input_mt_slot(input, i); | 810 | input_mt_slot(input, i); |
811 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
871 | /* | 812 | /* |
872 | * Touch events need to be disabled while stylus is | 813 | * Touch events need to be disabled while stylus is |
873 | * in proximity because user's hand is resting on touchpad | 814 | * in proximity because user's hand is resting on touchpad |
874 | * and sending unwanted events. User expects tablet buttons | 815 | * and sending unwanted events. User expects tablet buttons |
875 | * to continue working though. | 816 | * to continue working though. |
876 | */ | 817 | */ |
877 | if (p && !wacom->shared->stylus_in_proximity) { | 818 | if (touch) { |
878 | int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; | 819 | int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; |
879 | int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; | 820 | int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; |
880 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { | 821 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { |
@@ -884,23 +825,10 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) | |||
884 | input_report_abs(input, ABS_MT_PRESSURE, p); | 825 | input_report_abs(input, ABS_MT_PRESSURE, p); |
885 | input_report_abs(input, ABS_MT_POSITION_X, x); | 826 | input_report_abs(input, ABS_MT_POSITION_X, x); |
886 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 827 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
887 | if (wacom->id[i] < 0) | ||
888 | wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID; | ||
889 | if (!count++) | ||
890 | sp = p, sx = x, sy = y; | ||
891 | } else { | ||
892 | wacom->id[i] = -1; | ||
893 | } | 828 | } |
894 | input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]); | ||
895 | } | 829 | } |
896 | 830 | ||
897 | input_report_key(input, BTN_TOUCH, count > 0); | 831 | input_mt_report_pointer_emulation(input, true); |
898 | input_report_key(input, BTN_TOOL_FINGER, count == 1); | ||
899 | input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2); | ||
900 | |||
901 | input_report_abs(input, ABS_PRESSURE, sp); | ||
902 | input_report_abs(input, ABS_X, sx); | ||
903 | input_report_abs(input, ABS_Y, sy); | ||
904 | 832 | ||
905 | input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); | 833 | input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); |
906 | input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); | 834 | input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); |
@@ -1088,7 +1016,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) | |||
1088 | { | 1016 | { |
1089 | 1017 | ||
1090 | /* touch device found but size is not defined. use default */ | 1018 | /* touch device found but size is not defined. use default */ |
1091 | if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { | 1019 | if (features->device_type == BTN_TOOL_FINGER && !features->x_max) { |
1092 | features->x_max = 1023; | 1020 | features->x_max = 1023; |
1093 | features->y_max = 1023; | 1021 | features->y_max = 1023; |
1094 | } | 1022 | } |
@@ -1100,7 +1028,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) | |||
1100 | 1028 | ||
1101 | /* quirks for bamboo touch */ | 1029 | /* quirks for bamboo touch */ |
1102 | if (features->type == BAMBOO_PT && | 1030 | if (features->type == BAMBOO_PT && |
1103 | features->device_type == BTN_TOOL_TRIPLETAP) { | 1031 | features->device_type == BTN_TOOL_DOUBLETAP) { |
1104 | features->x_max <<= 5; | 1032 | features->x_max <<= 5; |
1105 | features->y_max <<= 5; | 1033 | features->y_max <<= 5; |
1106 | features->x_fuzz <<= 5; | 1034 | features->x_fuzz <<= 5; |
@@ -1111,6 +1039,13 @@ void wacom_setup_device_quirks(struct wacom_features *features) | |||
1111 | } | 1039 | } |
1112 | } | 1040 | } |
1113 | 1041 | ||
1042 | static unsigned int wacom_calculate_touch_res(unsigned int logical_max, | ||
1043 | unsigned int physical_max) | ||
1044 | { | ||
1045 | /* Touch physical dimensions are in 100th of mm */ | ||
1046 | return (logical_max * 100) / physical_max; | ||
1047 | } | ||
1048 | |||
1114 | void wacom_setup_input_capabilities(struct input_dev *input_dev, | 1049 | void wacom_setup_input_capabilities(struct input_dev *input_dev, |
1115 | struct wacom_wac *wacom_wac) | 1050 | struct wacom_wac *wacom_wac) |
1116 | { | 1051 | { |
@@ -1128,6 +1063,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1128 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, | 1063 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, |
1129 | features->pressure_fuzz, 0); | 1064 | features->pressure_fuzz, 0); |
1130 | 1065 | ||
1066 | if (features->device_type == BTN_TOOL_PEN) { | ||
1067 | /* penabled devices have fixed resolution for each model */ | ||
1068 | input_abs_set_res(input_dev, ABS_X, features->x_resolution); | ||
1069 | input_abs_set_res(input_dev, ABS_Y, features->y_resolution); | ||
1070 | } else { | ||
1071 | input_abs_set_res(input_dev, ABS_X, | ||
1072 | wacom_calculate_touch_res(features->x_max, | ||
1073 | features->x_phy)); | ||
1074 | input_abs_set_res(input_dev, ABS_Y, | ||
1075 | wacom_calculate_touch_res(features->y_max, | ||
1076 | features->y_phy)); | ||
1077 | } | ||
1078 | |||
1131 | __set_bit(ABS_MISC, input_dev->absbit); | 1079 | __set_bit(ABS_MISC, input_dev->absbit); |
1132 | 1080 | ||
1133 | switch (wacom_wac->features.type) { | 1081 | switch (wacom_wac->features.type) { |
@@ -1229,19 +1177,20 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1229 | break; | 1177 | break; |
1230 | 1178 | ||
1231 | case TABLETPC2FG: | 1179 | case TABLETPC2FG: |
1232 | if (features->device_type == BTN_TOOL_TRIPLETAP) { | 1180 | if (features->device_type == BTN_TOOL_DOUBLETAP) { |
1233 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 1181 | |
1234 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); | 1182 | input_mt_init_slots(input_dev, 2); |
1183 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, | ||
1184 | 0, MT_TOOL_MAX, 0, 0); | ||
1185 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
1186 | 0, features->x_max, 0, 0); | ||
1187 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
1188 | 0, features->y_max, 0, 0); | ||
1235 | } | 1189 | } |
1236 | /* fall through */ | 1190 | /* fall through */ |
1237 | 1191 | ||
1238 | case TABLETPC: | 1192 | case TABLETPC: |
1239 | if (features->device_type == BTN_TOOL_DOUBLETAP || | 1193 | __clear_bit(ABS_MISC, input_dev->absbit); |
1240 | features->device_type == BTN_TOOL_TRIPLETAP) { | ||
1241 | input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); | ||
1242 | input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); | ||
1243 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
1244 | } | ||
1245 | 1194 | ||
1246 | if (features->device_type != BTN_TOOL_PEN) | 1195 | if (features->device_type != BTN_TOOL_PEN) |
1247 | break; /* no need to process stylus stuff */ | 1196 | break; /* no need to process stylus stuff */ |
@@ -1263,7 +1212,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1263 | case BAMBOO_PT: | 1212 | case BAMBOO_PT: |
1264 | __clear_bit(ABS_MISC, input_dev->absbit); | 1213 | __clear_bit(ABS_MISC, input_dev->absbit); |
1265 | 1214 | ||
1266 | if (features->device_type == BTN_TOOL_TRIPLETAP) { | 1215 | if (features->device_type == BTN_TOOL_DOUBLETAP) { |
1267 | __set_bit(BTN_LEFT, input_dev->keybit); | 1216 | __set_bit(BTN_LEFT, input_dev->keybit); |
1268 | __set_bit(BTN_FORWARD, input_dev->keybit); | 1217 | __set_bit(BTN_FORWARD, input_dev->keybit); |
1269 | __set_bit(BTN_BACK, input_dev->keybit); | 1218 | __set_bit(BTN_BACK, input_dev->keybit); |
@@ -1272,7 +1221,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1272 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 1221 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
1273 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | 1222 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
1274 | 1223 | ||
1275 | input_mt_create_slots(input_dev, 2); | 1224 | input_mt_init_slots(input_dev, 2); |
1276 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1225 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
1277 | 0, features->x_max, | 1226 | 0, features->x_max, |
1278 | features->x_fuzz, 0); | 1227 | features->x_fuzz, 0); |
@@ -1282,8 +1231,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1282 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | 1231 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, |
1283 | 0, features->pressure_max, | 1232 | 0, features->pressure_max, |
1284 | features->pressure_fuzz, 0); | 1233 | features->pressure_fuzz, 0); |
1285 | input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, | ||
1286 | MAX_TRACKING_ID, 0, 0); | ||
1287 | } else if (features->device_type == BTN_TOOL_PEN) { | 1234 | } else if (features->device_type == BTN_TOOL_PEN) { |
1288 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 1235 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
1289 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 1236 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
@@ -1295,152 +1242,251 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1295 | } | 1242 | } |
1296 | 1243 | ||
1297 | static const struct wacom_features wacom_features_0x00 = | 1244 | static const struct wacom_features wacom_features_0x00 = |
1298 | { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }; | 1245 | { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, |
1246 | 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; | ||
1299 | static const struct wacom_features wacom_features_0x10 = | 1247 | static const struct wacom_features wacom_features_0x10 = |
1300 | { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; | 1248 | { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, |
1249 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1301 | static const struct wacom_features wacom_features_0x11 = | 1250 | static const struct wacom_features wacom_features_0x11 = |
1302 | { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; | 1251 | { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, |
1252 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1303 | static const struct wacom_features wacom_features_0x12 = | 1253 | static const struct wacom_features wacom_features_0x12 = |
1304 | { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }; | 1254 | { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, |
1255 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1305 | static const struct wacom_features wacom_features_0x13 = | 1256 | static const struct wacom_features wacom_features_0x13 = |
1306 | { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }; | 1257 | { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, |
1258 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1307 | static const struct wacom_features wacom_features_0x14 = | 1259 | static const struct wacom_features wacom_features_0x14 = |
1308 | { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; | 1260 | { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, |
1261 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1309 | static const struct wacom_features wacom_features_0x15 = | 1262 | static const struct wacom_features wacom_features_0x15 = |
1310 | { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }; | 1263 | { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, |
1264 | 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1311 | static const struct wacom_features wacom_features_0x16 = | 1265 | static const struct wacom_features wacom_features_0x16 = |
1312 | { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }; | 1266 | { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, |
1267 | 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1313 | static const struct wacom_features wacom_features_0x17 = | 1268 | static const struct wacom_features wacom_features_0x17 = |
1314 | { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; | 1269 | { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, |
1270 | 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1315 | static const struct wacom_features wacom_features_0x18 = | 1271 | static const struct wacom_features wacom_features_0x18 = |
1316 | { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }; | 1272 | { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, |
1273 | 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1317 | static const struct wacom_features wacom_features_0x19 = | 1274 | static const struct wacom_features wacom_features_0x19 = |
1318 | { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; | 1275 | { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, |
1276 | 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; | ||
1319 | static const struct wacom_features wacom_features_0x60 = | 1277 | static const struct wacom_features wacom_features_0x60 = |
1320 | { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; | 1278 | { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, |
1279 | 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; | ||
1321 | static const struct wacom_features wacom_features_0x61 = | 1280 | static const struct wacom_features wacom_features_0x61 = |
1322 | { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }; | 1281 | { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, |
1282 | 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; | ||
1323 | static const struct wacom_features wacom_features_0x62 = | 1283 | static const struct wacom_features wacom_features_0x62 = |
1324 | { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; | 1284 | { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, |
1285 | 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; | ||
1325 | static const struct wacom_features wacom_features_0x63 = | 1286 | static const struct wacom_features wacom_features_0x63 = |
1326 | { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }; | 1287 | { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, |
1288 | 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; | ||
1327 | static const struct wacom_features wacom_features_0x64 = | 1289 | static const struct wacom_features wacom_features_0x64 = |
1328 | { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }; | 1290 | { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, |
1291 | 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; | ||
1329 | static const struct wacom_features wacom_features_0x65 = | 1292 | static const struct wacom_features wacom_features_0x65 = |
1330 | { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; | 1293 | { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, |
1294 | 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1331 | static const struct wacom_features wacom_features_0x69 = | 1295 | static const struct wacom_features wacom_features_0x69 = |
1332 | { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; | 1296 | { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, |
1297 | 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; | ||
1333 | static const struct wacom_features wacom_features_0x20 = | 1298 | static const struct wacom_features wacom_features_0x20 = |
1334 | { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; | 1299 | { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, |
1300 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1335 | static const struct wacom_features wacom_features_0x21 = | 1301 | static const struct wacom_features wacom_features_0x21 = |
1336 | { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | 1302 | { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, |
1303 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1337 | static const struct wacom_features wacom_features_0x22 = | 1304 | static const struct wacom_features wacom_features_0x22 = |
1338 | { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; | 1305 | { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, |
1306 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1339 | static const struct wacom_features wacom_features_0x23 = | 1307 | static const struct wacom_features wacom_features_0x23 = |
1340 | { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; | 1308 | { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, |
1309 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1341 | static const struct wacom_features wacom_features_0x24 = | 1310 | static const struct wacom_features wacom_features_0x24 = |
1342 | { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; | 1311 | { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, |
1312 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1343 | static const struct wacom_features wacom_features_0x30 = | 1313 | static const struct wacom_features wacom_features_0x30 = |
1344 | { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }; | 1314 | { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, |
1315 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1345 | static const struct wacom_features wacom_features_0x31 = | 1316 | static const struct wacom_features wacom_features_0x31 = |
1346 | { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }; | 1317 | { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, |
1318 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1347 | static const struct wacom_features wacom_features_0x32 = | 1319 | static const struct wacom_features wacom_features_0x32 = |
1348 | { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }; | 1320 | { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, |
1321 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1349 | static const struct wacom_features wacom_features_0x33 = | 1322 | static const struct wacom_features wacom_features_0x33 = |
1350 | { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }; | 1323 | { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, |
1324 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1351 | static const struct wacom_features wacom_features_0x34 = | 1325 | static const struct wacom_features wacom_features_0x34 = |
1352 | { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }; | 1326 | { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, |
1327 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1353 | static const struct wacom_features wacom_features_0x35 = | 1328 | static const struct wacom_features wacom_features_0x35 = |
1354 | { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }; | 1329 | { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, |
1330 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1355 | static const struct wacom_features wacom_features_0x37 = | 1331 | static const struct wacom_features wacom_features_0x37 = |
1356 | { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }; | 1332 | { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, |
1333 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1357 | static const struct wacom_features wacom_features_0x38 = | 1334 | static const struct wacom_features wacom_features_0x38 = |
1358 | { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; | 1335 | { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, |
1336 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1359 | static const struct wacom_features wacom_features_0x39 = | 1337 | static const struct wacom_features wacom_features_0x39 = |
1360 | { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }; | 1338 | { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, |
1339 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1361 | static const struct wacom_features wacom_features_0xC4 = | 1340 | static const struct wacom_features wacom_features_0xC4 = |
1362 | { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; | 1341 | { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, |
1342 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1363 | static const struct wacom_features wacom_features_0xC0 = | 1343 | static const struct wacom_features wacom_features_0xC0 = |
1364 | { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; | 1344 | { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, |
1345 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1365 | static const struct wacom_features wacom_features_0xC2 = | 1346 | static const struct wacom_features wacom_features_0xC2 = |
1366 | { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; | 1347 | { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, |
1348 | 0, PL, WACOM_PL_RES, WACOM_PL_RES }; | ||
1367 | static const struct wacom_features wacom_features_0x03 = | 1349 | static const struct wacom_features wacom_features_0x03 = |
1368 | { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }; | 1350 | { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, |
1351 | 0, PTU, WACOM_PL_RES, WACOM_PL_RES }; | ||
1369 | static const struct wacom_features wacom_features_0x41 = | 1352 | static const struct wacom_features wacom_features_0x41 = |
1370 | { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; | 1353 | { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, |
1354 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1371 | static const struct wacom_features wacom_features_0x42 = | 1355 | static const struct wacom_features wacom_features_0x42 = |
1372 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | 1356 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, |
1357 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1373 | static const struct wacom_features wacom_features_0x43 = | 1358 | static const struct wacom_features wacom_features_0x43 = |
1374 | { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; | 1359 | { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, |
1360 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1375 | static const struct wacom_features wacom_features_0x44 = | 1361 | static const struct wacom_features wacom_features_0x44 = |
1376 | { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; | 1362 | { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, |
1363 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1377 | static const struct wacom_features wacom_features_0x45 = | 1364 | static const struct wacom_features wacom_features_0x45 = |
1378 | { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; | 1365 | { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, |
1366 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1379 | static const struct wacom_features wacom_features_0xB0 = | 1367 | static const struct wacom_features wacom_features_0xB0 = |
1380 | { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }; | 1368 | { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, |
1369 | 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1381 | static const struct wacom_features wacom_features_0xB1 = | 1370 | static const struct wacom_features wacom_features_0xB1 = |
1382 | { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }; | 1371 | { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, |
1372 | 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1383 | static const struct wacom_features wacom_features_0xB2 = | 1373 | static const struct wacom_features wacom_features_0xB2 = |
1384 | { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }; | 1374 | { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, |
1375 | 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1385 | static const struct wacom_features wacom_features_0xB3 = | 1376 | static const struct wacom_features wacom_features_0xB3 = |
1386 | { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }; | 1377 | { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, |
1378 | 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1387 | static const struct wacom_features wacom_features_0xB4 = | 1379 | static const struct wacom_features wacom_features_0xB4 = |
1388 | { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }; | 1380 | { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, |
1381 | 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1389 | static const struct wacom_features wacom_features_0xB5 = | 1382 | static const struct wacom_features wacom_features_0xB5 = |
1390 | { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }; | 1383 | { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, |
1384 | 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1391 | static const struct wacom_features wacom_features_0xB7 = | 1385 | static const struct wacom_features wacom_features_0xB7 = |
1392 | { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }; | 1386 | { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, |
1387 | 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1393 | static const struct wacom_features wacom_features_0xB8 = | 1388 | static const struct wacom_features wacom_features_0xB8 = |
1394 | { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }; | 1389 | { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, |
1390 | 63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1395 | static const struct wacom_features wacom_features_0xB9 = | 1391 | static const struct wacom_features wacom_features_0xB9 = |
1396 | { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }; | 1392 | { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, |
1393 | 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1397 | static const struct wacom_features wacom_features_0xBA = | 1394 | static const struct wacom_features wacom_features_0xBA = |
1398 | { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; | 1395 | { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, |
1396 | 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1399 | static const struct wacom_features wacom_features_0xBB = | 1397 | static const struct wacom_features wacom_features_0xBB = |
1400 | { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; | 1398 | { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, |
1399 | 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1401 | static const struct wacom_features wacom_features_0xBC = | 1400 | static const struct wacom_features wacom_features_0xBC = |
1402 | { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, 63, INTUOS4 }; | 1401 | { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, |
1402 | 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1403 | static const struct wacom_features wacom_features_0x3F = | 1403 | static const struct wacom_features wacom_features_0x3F = |
1404 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; | 1404 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, |
1405 | 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1405 | static const struct wacom_features wacom_features_0xC5 = | 1406 | static const struct wacom_features wacom_features_0xC5 = |
1406 | { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }; | 1407 | { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, |
1408 | 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1407 | static const struct wacom_features wacom_features_0xC6 = | 1409 | static const struct wacom_features wacom_features_0xC6 = |
1408 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; | 1410 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, |
1411 | 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1409 | static const struct wacom_features wacom_features_0xC7 = | 1412 | static const struct wacom_features wacom_features_0xC7 = |
1410 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; | 1413 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, |
1414 | 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1411 | static const struct wacom_features wacom_features_0xCE = | 1415 | static const struct wacom_features wacom_features_0xCE = |
1412 | { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, 0, DTU }; | 1416 | { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, |
1417 | 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1413 | static const struct wacom_features wacom_features_0xF0 = | 1418 | static const struct wacom_features wacom_features_0xF0 = |
1414 | { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU }; | 1419 | { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, |
1420 | 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1415 | static const struct wacom_features wacom_features_0xCC = | 1421 | static const struct wacom_features wacom_features_0xCC = |
1416 | { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 }; | 1422 | { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, |
1423 | 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
1417 | static const struct wacom_features wacom_features_0x90 = | 1424 | static const struct wacom_features wacom_features_0x90 = |
1418 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | 1425 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, |
1426 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1419 | static const struct wacom_features wacom_features_0x93 = | 1427 | static const struct wacom_features wacom_features_0x93 = |
1420 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | 1428 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, |
1429 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1421 | static const struct wacom_features wacom_features_0x9A = | 1430 | static const struct wacom_features wacom_features_0x9A = |
1422 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | 1431 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, |
1432 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1423 | static const struct wacom_features wacom_features_0x9F = | 1433 | static const struct wacom_features wacom_features_0x9F = |
1424 | { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | 1434 | { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, |
1435 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1425 | static const struct wacom_features wacom_features_0xE2 = | 1436 | static const struct wacom_features wacom_features_0xE2 = |
1426 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; | 1437 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, |
1438 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1427 | static const struct wacom_features wacom_features_0xE3 = | 1439 | static const struct wacom_features wacom_features_0xE3 = |
1428 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; | 1440 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, |
1441 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1442 | static const struct wacom_features wacom_features_0xE6 = | ||
1443 | { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, | ||
1444 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1429 | static const struct wacom_features wacom_features_0x47 = | 1445 | static const struct wacom_features wacom_features_0x47 = |
1430 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | 1446 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, |
1431 | static struct wacom_features wacom_features_0xD0 = | 1447 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1432 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | 1448 | static const struct wacom_features wacom_features_0xD0 = |
1433 | static struct wacom_features wacom_features_0xD1 = | 1449 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1434 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | 1450 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1435 | static struct wacom_features wacom_features_0xD2 = | 1451 | static const struct wacom_features wacom_features_0xD1 = |
1436 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | 1452 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1437 | static struct wacom_features wacom_features_0xD3 = | 1453 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1438 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; | 1454 | static const struct wacom_features wacom_features_0xD2 = |
1455 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | ||
1456 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1457 | static const struct wacom_features wacom_features_0xD3 = | ||
1458 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | ||
1459 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1460 | static const struct wacom_features wacom_features_0xD4 = | ||
1461 | { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, | ||
1462 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1463 | static const struct wacom_features wacom_features_0xD6 = | ||
1464 | { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | ||
1465 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1466 | static const struct wacom_features wacom_features_0xD7 = | ||
1467 | { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | ||
1468 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1469 | static const struct wacom_features wacom_features_0xD8 = | ||
1470 | { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | ||
1471 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1472 | static const struct wacom_features wacom_features_0xDA = | ||
1473 | { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | ||
1474 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1475 | static struct wacom_features wacom_features_0xDB = | ||
1476 | { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | ||
1477 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1478 | static const struct wacom_features wacom_features_0x6004 = | ||
1479 | { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, | ||
1480 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
1439 | 1481 | ||
1440 | #define USB_DEVICE_WACOM(prod) \ | 1482 | #define USB_DEVICE_WACOM(prod) \ |
1441 | USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ | 1483 | USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ |
1442 | .driver_info = (kernel_ulong_t)&wacom_features_##prod | 1484 | .driver_info = (kernel_ulong_t)&wacom_features_##prod |
1443 | 1485 | ||
1486 | #define USB_DEVICE_LENOVO(prod) \ | ||
1487 | USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ | ||
1488 | .driver_info = (kernel_ulong_t)&wacom_features_##prod | ||
1489 | |||
1444 | const struct usb_device_id wacom_ids[] = { | 1490 | const struct usb_device_id wacom_ids[] = { |
1445 | { USB_DEVICE_WACOM(0x00) }, | 1491 | { USB_DEVICE_WACOM(0x00) }, |
1446 | { USB_DEVICE_WACOM(0x10) }, | 1492 | { USB_DEVICE_WACOM(0x10) }, |
@@ -1504,6 +1550,12 @@ const struct usb_device_id wacom_ids[] = { | |||
1504 | { USB_DEVICE_WACOM(0xD1) }, | 1550 | { USB_DEVICE_WACOM(0xD1) }, |
1505 | { USB_DEVICE_WACOM(0xD2) }, | 1551 | { USB_DEVICE_WACOM(0xD2) }, |
1506 | { USB_DEVICE_WACOM(0xD3) }, | 1552 | { USB_DEVICE_WACOM(0xD3) }, |
1553 | { USB_DEVICE_WACOM(0xD4) }, | ||
1554 | { USB_DEVICE_WACOM(0xD6) }, | ||
1555 | { USB_DEVICE_WACOM(0xD7) }, | ||
1556 | { USB_DEVICE_WACOM(0xD8) }, | ||
1557 | { USB_DEVICE_WACOM(0xDA) }, | ||
1558 | { USB_DEVICE_WACOM(0xDB) }, | ||
1507 | { USB_DEVICE_WACOM(0xF0) }, | 1559 | { USB_DEVICE_WACOM(0xF0) }, |
1508 | { USB_DEVICE_WACOM(0xCC) }, | 1560 | { USB_DEVICE_WACOM(0xCC) }, |
1509 | { USB_DEVICE_WACOM(0x90) }, | 1561 | { USB_DEVICE_WACOM(0x90) }, |
@@ -1512,7 +1564,9 @@ const struct usb_device_id wacom_ids[] = { | |||
1512 | { USB_DEVICE_WACOM(0x9F) }, | 1564 | { USB_DEVICE_WACOM(0x9F) }, |
1513 | { USB_DEVICE_WACOM(0xE2) }, | 1565 | { USB_DEVICE_WACOM(0xE2) }, |
1514 | { USB_DEVICE_WACOM(0xE3) }, | 1566 | { USB_DEVICE_WACOM(0xE3) }, |
1567 | { USB_DEVICE_WACOM(0xE6) }, | ||
1515 | { USB_DEVICE_WACOM(0x47) }, | 1568 | { USB_DEVICE_WACOM(0x47) }, |
1569 | { USB_DEVICE_LENOVO(0x6004) }, | ||
1516 | { } | 1570 | { } |
1517 | }; | 1571 | }; |
1518 | MODULE_DEVICE_TABLE(usb, wacom_ids); | 1572 | MODULE_DEVICE_TABLE(usb, wacom_ids); |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 00ca01541d89..53eb71b68330 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -42,9 +42,6 @@ | |||
42 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 | 42 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 |
43 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 | 43 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 |
44 | 44 | ||
45 | /* largest reported tracking id */ | ||
46 | #define MAX_TRACKING_ID 0xfff | ||
47 | |||
48 | enum { | 45 | enum { |
49 | PENPARTNER = 0, | 46 | PENPARTNER = 0, |
50 | GRAPHIRE, | 47 | GRAPHIRE, |
@@ -77,6 +74,8 @@ struct wacom_features { | |||
77 | int pressure_max; | 74 | int pressure_max; |
78 | int distance_max; | 75 | int distance_max; |
79 | int type; | 76 | int type; |
77 | int x_resolution; | ||
78 | int y_resolution; | ||
80 | int device_type; | 79 | int device_type; |
81 | int x_phy; | 80 | int x_phy; |
82 | int y_phy; | 81 | int y_phy; |
@@ -91,16 +90,15 @@ struct wacom_features { | |||
91 | 90 | ||
92 | struct wacom_shared { | 91 | struct wacom_shared { |
93 | bool stylus_in_proximity; | 92 | bool stylus_in_proximity; |
93 | bool touch_down; | ||
94 | }; | 94 | }; |
95 | 95 | ||
96 | struct wacom_wac { | 96 | struct wacom_wac { |
97 | char name[64]; | 97 | char name[64]; |
98 | unsigned char *data; | 98 | unsigned char *data; |
99 | int tool[3]; | 99 | int tool[2]; |
100 | int id[3]; | 100 | int id[2]; |
101 | __u32 serial[2]; | 101 | __u32 serial[2]; |
102 | int last_finger; | ||
103 | int trk_id; | ||
104 | struct wacom_features features; | 102 | struct wacom_features features; |
105 | struct wacom_shared *shared; | 103 | struct wacom_shared *shared; |
106 | struct input_dev *input; | 104 | struct input_dev *input; |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 06ea8da95c62..434fd800cd24 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -86,6 +86,18 @@ config TOUCHSCREEN_AD7879_SPI | |||
86 | To compile this driver as a module, choose M here: the | 86 | To compile this driver as a module, choose M here: the |
87 | module will be called ad7879-spi. | 87 | module will be called ad7879-spi. |
88 | 88 | ||
89 | config TOUCHSCREEN_ATMEL_MXT | ||
90 | tristate "Atmel mXT I2C Touchscreen" | ||
91 | depends on I2C | ||
92 | help | ||
93 | Say Y here if you have Atmel mXT series I2C touchscreen, | ||
94 | such as AT42QT602240/ATMXT224, connected to your system. | ||
95 | |||
96 | If unsure, say N. | ||
97 | |||
98 | To compile this driver as a module, choose M here: the | ||
99 | module will be called atmel_mxt_ts. | ||
100 | |||
89 | config TOUCHSCREEN_BITSY | 101 | config TOUCHSCREEN_BITSY |
90 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" | 102 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" |
91 | depends on SA1100_BITSY | 103 | depends on SA1100_BITSY |
@@ -339,18 +351,6 @@ config TOUCHSCREEN_PENMOUNT | |||
339 | To compile this driver as a module, choose M here: the | 351 | To compile this driver as a module, choose M here: the |
340 | module will be called penmount. | 352 | module will be called penmount. |
341 | 353 | ||
342 | config TOUCHSCREEN_QT602240 | ||
343 | tristate "QT602240 I2C Touchscreen" | ||
344 | depends on I2C | ||
345 | help | ||
346 | Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen | ||
347 | connected to your system. | ||
348 | |||
349 | If unsure, say N. | ||
350 | |||
351 | To compile this driver as a module, choose M here: the | ||
352 | module will be called qt602240_ts. | ||
353 | |||
354 | config TOUCHSCREEN_MIGOR | 354 | config TOUCHSCREEN_MIGOR |
355 | tristate "Renesas MIGO-R touchscreen" | 355 | tristate "Renesas MIGO-R touchscreen" |
356 | depends on SH_MIGOR && I2C | 356 | depends on SH_MIGOR && I2C |
@@ -423,6 +423,16 @@ config TOUCHSCREEN_UCB1400 | |||
423 | To compile this driver as a module, choose M here: the | 423 | To compile this driver as a module, choose M here: the |
424 | module will be called ucb1400_ts. | 424 | module will be called ucb1400_ts. |
425 | 425 | ||
426 | config TOUCHSCREEN_WM831X | ||
427 | tristate "Support for WM831x touchscreen controllers" | ||
428 | depends on MFD_WM831X | ||
429 | help | ||
430 | This enables support for the touchscreen controller on the WM831x | ||
431 | series of PMICs. | ||
432 | |||
433 | To compile this driver as a module, choose M here: the | ||
434 | module will be called wm831x-ts. | ||
435 | |||
426 | config TOUCHSCREEN_WM97XX | 436 | config TOUCHSCREEN_WM97XX |
427 | tristate "Support for WM97xx AC97 touchscreen controllers" | 437 | tristate "Support for WM97xx AC97 touchscreen controllers" |
428 | depends on AC97_BUS | 438 | depends on AC97_BUS |
@@ -540,62 +550,62 @@ config TOUCHSCREEN_MC13783 | |||
540 | 550 | ||
541 | config TOUCHSCREEN_USB_EGALAX | 551 | config TOUCHSCREEN_USB_EGALAX |
542 | default y | 552 | default y |
543 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED | 553 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EXPERT |
544 | depends on TOUCHSCREEN_USB_COMPOSITE | 554 | depends on TOUCHSCREEN_USB_COMPOSITE |
545 | 555 | ||
546 | config TOUCHSCREEN_USB_PANJIT | 556 | config TOUCHSCREEN_USB_PANJIT |
547 | default y | 557 | default y |
548 | bool "PanJit device support" if EMBEDDED | 558 | bool "PanJit device support" if EXPERT |
549 | depends on TOUCHSCREEN_USB_COMPOSITE | 559 | depends on TOUCHSCREEN_USB_COMPOSITE |
550 | 560 | ||
551 | config TOUCHSCREEN_USB_3M | 561 | config TOUCHSCREEN_USB_3M |
552 | default y | 562 | default y |
553 | bool "3M/Microtouch EX II series device support" if EMBEDDED | 563 | bool "3M/Microtouch EX II series device support" if EXPERT |
554 | depends on TOUCHSCREEN_USB_COMPOSITE | 564 | depends on TOUCHSCREEN_USB_COMPOSITE |
555 | 565 | ||
556 | config TOUCHSCREEN_USB_ITM | 566 | config TOUCHSCREEN_USB_ITM |
557 | default y | 567 | default y |
558 | bool "ITM device support" if EMBEDDED | 568 | bool "ITM device support" if EXPERT |
559 | depends on TOUCHSCREEN_USB_COMPOSITE | 569 | depends on TOUCHSCREEN_USB_COMPOSITE |
560 | 570 | ||
561 | config TOUCHSCREEN_USB_ETURBO | 571 | config TOUCHSCREEN_USB_ETURBO |
562 | default y | 572 | default y |
563 | bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED | 573 | bool "eTurboTouch (non-eGalax compatible) device support" if EXPERT |
564 | depends on TOUCHSCREEN_USB_COMPOSITE | 574 | depends on TOUCHSCREEN_USB_COMPOSITE |
565 | 575 | ||
566 | config TOUCHSCREEN_USB_GUNZE | 576 | config TOUCHSCREEN_USB_GUNZE |
567 | default y | 577 | default y |
568 | bool "Gunze AHL61 device support" if EMBEDDED | 578 | bool "Gunze AHL61 device support" if EXPERT |
569 | depends on TOUCHSCREEN_USB_COMPOSITE | 579 | depends on TOUCHSCREEN_USB_COMPOSITE |
570 | 580 | ||
571 | config TOUCHSCREEN_USB_DMC_TSC10 | 581 | config TOUCHSCREEN_USB_DMC_TSC10 |
572 | default y | 582 | default y |
573 | bool "DMC TSC-10/25 device support" if EMBEDDED | 583 | bool "DMC TSC-10/25 device support" if EXPERT |
574 | depends on TOUCHSCREEN_USB_COMPOSITE | 584 | depends on TOUCHSCREEN_USB_COMPOSITE |
575 | 585 | ||
576 | config TOUCHSCREEN_USB_IRTOUCH | 586 | config TOUCHSCREEN_USB_IRTOUCH |
577 | default y | 587 | default y |
578 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED | 588 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EXPERT |
579 | depends on TOUCHSCREEN_USB_COMPOSITE | 589 | depends on TOUCHSCREEN_USB_COMPOSITE |
580 | 590 | ||
581 | config TOUCHSCREEN_USB_IDEALTEK | 591 | config TOUCHSCREEN_USB_IDEALTEK |
582 | default y | 592 | default y |
583 | bool "IdealTEK URTC1000 device support" if EMBEDDED | 593 | bool "IdealTEK URTC1000 device support" if EXPERT |
584 | depends on TOUCHSCREEN_USB_COMPOSITE | 594 | depends on TOUCHSCREEN_USB_COMPOSITE |
585 | 595 | ||
586 | config TOUCHSCREEN_USB_GENERAL_TOUCH | 596 | config TOUCHSCREEN_USB_GENERAL_TOUCH |
587 | default y | 597 | default y |
588 | bool "GeneralTouch Touchscreen device support" if EMBEDDED | 598 | bool "GeneralTouch Touchscreen device support" if EXPERT |
589 | depends on TOUCHSCREEN_USB_COMPOSITE | 599 | depends on TOUCHSCREEN_USB_COMPOSITE |
590 | 600 | ||
591 | config TOUCHSCREEN_USB_GOTOP | 601 | config TOUCHSCREEN_USB_GOTOP |
592 | default y | 602 | default y |
593 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED | 603 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EXPERT |
594 | depends on TOUCHSCREEN_USB_COMPOSITE | 604 | depends on TOUCHSCREEN_USB_COMPOSITE |
595 | 605 | ||
596 | config TOUCHSCREEN_USB_JASTEC | 606 | config TOUCHSCREEN_USB_JASTEC |
597 | default y | 607 | default y |
598 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED | 608 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT |
599 | depends on TOUCHSCREEN_USB_COMPOSITE | 609 | depends on TOUCHSCREEN_USB_COMPOSITE |
600 | 610 | ||
601 | config TOUCHSCREEN_USB_E2I | 611 | config TOUCHSCREEN_USB_E2I |
@@ -605,17 +615,17 @@ config TOUCHSCREEN_USB_E2I | |||
605 | 615 | ||
606 | config TOUCHSCREEN_USB_ZYTRONIC | 616 | config TOUCHSCREEN_USB_ZYTRONIC |
607 | default y | 617 | default y |
608 | bool "Zytronic controller" if EMBEDDED | 618 | bool "Zytronic controller" if EXPERT |
609 | depends on TOUCHSCREEN_USB_COMPOSITE | 619 | depends on TOUCHSCREEN_USB_COMPOSITE |
610 | 620 | ||
611 | config TOUCHSCREEN_USB_ETT_TC45USB | 621 | config TOUCHSCREEN_USB_ETT_TC45USB |
612 | default y | 622 | default y |
613 | bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED | 623 | bool "ET&T USB series TC4UM/TC5UH touchscreen controller support" if EXPERT |
614 | depends on TOUCHSCREEN_USB_COMPOSITE | 624 | depends on TOUCHSCREEN_USB_COMPOSITE |
615 | 625 | ||
616 | config TOUCHSCREEN_USB_NEXIO | 626 | config TOUCHSCREEN_USB_NEXIO |
617 | default y | 627 | default y |
618 | bool "NEXIO/iNexio device support" if EMBEDDED | 628 | bool "NEXIO/iNexio device support" if EXPERT |
619 | depends on TOUCHSCREEN_USB_COMPOSITE | 629 | depends on TOUCHSCREEN_USB_COMPOSITE |
620 | 630 | ||
621 | config TOUCHSCREEN_TOUCHIT213 | 631 | config TOUCHSCREEN_TOUCHIT213 |
@@ -629,6 +639,17 @@ config TOUCHSCREEN_TOUCHIT213 | |||
629 | To compile this driver as a module, choose M here: the | 639 | To compile this driver as a module, choose M here: the |
630 | module will be called touchit213. | 640 | module will be called touchit213. |
631 | 641 | ||
642 | config TOUCHSCREEN_TSC2005 | ||
643 | tristate "TSC2005 based touchscreens" | ||
644 | depends on SPI_MASTER && GENERIC_HARDIRQS | ||
645 | help | ||
646 | Say Y here if you have a TSC2005 based touchscreen. | ||
647 | |||
648 | If unsure, say N. | ||
649 | |||
650 | To compile this driver as a module, choose M here: the | ||
651 | module will be called tsc2005. | ||
652 | |||
632 | config TOUCHSCREEN_TSC2007 | 653 | config TOUCHSCREEN_TSC2007 |
633 | tristate "TSC2007 based touchscreens" | 654 | tristate "TSC2007 based touchscreens" |
634 | depends on I2C | 655 | depends on I2C |
@@ -659,17 +680,17 @@ config TOUCHSCREEN_PCAP | |||
659 | To compile this driver as a module, choose M here: the | 680 | To compile this driver as a module, choose M here: the |
660 | module will be called pcap_ts. | 681 | module will be called pcap_ts. |
661 | 682 | ||
662 | config TOUCHSCREEN_TPS6507X | 683 | config TOUCHSCREEN_ST1232 |
663 | tristate "TPS6507x based touchscreens" | 684 | tristate "Sitronix ST1232 touchscreen controllers" |
664 | depends on I2C | 685 | depends on I2C |
665 | help | 686 | help |
666 | Say Y here if you have a TPS6507x based touchscreen | 687 | Say Y here if you want to support Sitronix ST1232 |
667 | controller. | 688 | touchscreen controller. |
668 | 689 | ||
669 | If unsure, say N. | 690 | If unsure, say N. |
670 | 691 | ||
671 | To compile this driver as a module, choose M here: the | 692 | To compile this driver as a module, choose M here: the |
672 | module will be called tps6507x_ts. | 693 | module will be called st1232_ts. |
673 | 694 | ||
674 | config TOUCHSCREEN_STMPE | 695 | config TOUCHSCREEN_STMPE |
675 | tristate "STMicroelectronics STMPE touchscreens" | 696 | tristate "STMicroelectronics STMPE touchscreens" |
@@ -681,4 +702,16 @@ config TOUCHSCREEN_STMPE | |||
681 | To compile this driver as a module, choose M here: the | 702 | To compile this driver as a module, choose M here: the |
682 | module will be called stmpe-ts. | 703 | module will be called stmpe-ts. |
683 | 704 | ||
705 | config TOUCHSCREEN_TPS6507X | ||
706 | tristate "TPS6507x based touchscreens" | ||
707 | depends on I2C | ||
708 | help | ||
709 | Say Y here if you have a TPS6507x based touchscreen | ||
710 | controller. | ||
711 | |||
712 | If unsure, say N. | ||
713 | |||
714 | To compile this driver as a module, choose M here: the | ||
715 | module will be called tps6507x_ts. | ||
716 | |||
684 | endif | 717 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7cc1b4f4b677..ca94098d4c92 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | |||
12 | obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o | 12 | obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o |
13 | obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o | 13 | obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o |
14 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 14 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
15 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | ||
15 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
16 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 17 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
17 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
@@ -37,16 +38,18 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o | |||
37 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 38 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
38 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | 39 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o |
39 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 40 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
40 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | ||
41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
42 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | ||
42 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 43 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
43 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 44 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
44 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 45 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
45 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 46 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
46 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 47 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
48 | obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o | ||
47 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o | 49 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o |
48 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o | 50 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o |
49 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o | 51 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o |
52 | obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o | ||
50 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o | 53 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o |
51 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o | 54 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o |
52 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o | 55 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index a1952fcc083e..714d4e0f9f95 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/input.h> | 42 | #include <linux/input.h> |
43 | #include <linux/interrupt.h> | 43 | #include <linux/interrupt.h> |
44 | #include <linux/pm.h> | ||
44 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
45 | #include <linux/spi/spi.h> | 46 | #include <linux/spi/spi.h> |
46 | #include <linux/spi/ad7877.h> | 47 | #include <linux/spi/ad7877.h> |
@@ -826,39 +827,37 @@ static int __devexit ad7877_remove(struct spi_device *spi) | |||
826 | return 0; | 827 | return 0; |
827 | } | 828 | } |
828 | 829 | ||
829 | #ifdef CONFIG_PM | 830 | #ifdef CONFIG_PM_SLEEP |
830 | static int ad7877_suspend(struct spi_device *spi, pm_message_t message) | 831 | static int ad7877_suspend(struct device *dev) |
831 | { | 832 | { |
832 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | 833 | struct ad7877 *ts = dev_get_drvdata(dev); |
833 | 834 | ||
834 | ad7877_disable(ts); | 835 | ad7877_disable(ts); |
835 | 836 | ||
836 | return 0; | 837 | return 0; |
837 | } | 838 | } |
838 | 839 | ||
839 | static int ad7877_resume(struct spi_device *spi) | 840 | static int ad7877_resume(struct device *dev) |
840 | { | 841 | { |
841 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | 842 | struct ad7877 *ts = dev_get_drvdata(dev); |
842 | 843 | ||
843 | ad7877_enable(ts); | 844 | ad7877_enable(ts); |
844 | 845 | ||
845 | return 0; | 846 | return 0; |
846 | } | 847 | } |
847 | #else | ||
848 | #define ad7877_suspend NULL | ||
849 | #define ad7877_resume NULL | ||
850 | #endif | 848 | #endif |
851 | 849 | ||
850 | static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); | ||
851 | |||
852 | static struct spi_driver ad7877_driver = { | 852 | static struct spi_driver ad7877_driver = { |
853 | .driver = { | 853 | .driver = { |
854 | .name = "ad7877", | 854 | .name = "ad7877", |
855 | .bus = &spi_bus_type, | 855 | .bus = &spi_bus_type, |
856 | .owner = THIS_MODULE, | 856 | .owner = THIS_MODULE, |
857 | .pm = &ad7877_pm, | ||
857 | }, | 858 | }, |
858 | .probe = ad7877_probe, | 859 | .probe = ad7877_probe, |
859 | .remove = __devexit_p(ad7877_remove), | 860 | .remove = __devexit_p(ad7877_remove), |
860 | .suspend = ad7877_suspend, | ||
861 | .resume = ad7877_resume, | ||
862 | }; | 861 | }; |
863 | 862 | ||
864 | static int __init ad7877_init(void) | 863 | static int __init ad7877_init(void) |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index d82a38ee9a3e..4e4e58cec6c8 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
@@ -10,14 +10,16 @@ | |||
10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/pm.h> | ||
13 | 14 | ||
14 | #include "ad7879.h" | 15 | #include "ad7879.h" |
15 | 16 | ||
16 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ | 17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ |
17 | 18 | ||
18 | #ifdef CONFIG_PM | 19 | #ifdef CONFIG_PM |
19 | static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message) | 20 | static int ad7879_i2c_suspend(struct device *dev) |
20 | { | 21 | { |
22 | struct i2c_client *client = to_i2c_client(dev); | ||
21 | struct ad7879 *ts = i2c_get_clientdata(client); | 23 | struct ad7879 *ts = i2c_get_clientdata(client); |
22 | 24 | ||
23 | ad7879_suspend(ts); | 25 | ad7879_suspend(ts); |
@@ -25,17 +27,17 @@ static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message) | |||
25 | return 0; | 27 | return 0; |
26 | } | 28 | } |
27 | 29 | ||
28 | static int ad7879_i2c_resume(struct i2c_client *client) | 30 | static int ad7879_i2c_resume(struct device *dev) |
29 | { | 31 | { |
32 | struct i2c_client *client = to_i2c_client(dev); | ||
30 | struct ad7879 *ts = i2c_get_clientdata(client); | 33 | struct ad7879 *ts = i2c_get_clientdata(client); |
31 | 34 | ||
32 | ad7879_resume(ts); | 35 | ad7879_resume(ts); |
33 | 36 | ||
34 | return 0; | 37 | return 0; |
35 | } | 38 | } |
36 | #else | 39 | |
37 | # define ad7879_i2c_suspend NULL | 40 | static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); |
38 | # define ad7879_i2c_resume NULL | ||
39 | #endif | 41 | #endif |
40 | 42 | ||
41 | /* All registers are word-sized. | 43 | /* All registers are word-sized. |
@@ -117,11 +119,12 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
117 | .driver = { | 119 | .driver = { |
118 | .name = "ad7879", | 120 | .name = "ad7879", |
119 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
122 | #ifdef CONFIG_PM | ||
123 | .pm = &ad7879_i2c_pm, | ||
124 | #endif | ||
120 | }, | 125 | }, |
121 | .probe = ad7879_i2c_probe, | 126 | .probe = ad7879_i2c_probe, |
122 | .remove = __devexit_p(ad7879_i2c_remove), | 127 | .remove = __devexit_p(ad7879_i2c_remove), |
123 | .suspend = ad7879_i2c_suspend, | ||
124 | .resume = ad7879_i2c_resume, | ||
125 | .id_table = ad7879_id, | 128 | .id_table = ad7879_id, |
126 | }; | 129 | }; |
127 | 130 | ||
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 59c6e68c4325..ddf732f3cafc 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/input.h> /* BUS_SPI */ | 9 | #include <linux/input.h> /* BUS_SPI */ |
10 | #include <linux/pm.h> | ||
10 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
11 | 12 | ||
12 | #include "ad7879.h" | 13 | #include "ad7879.h" |
@@ -20,9 +21,10 @@ | |||
20 | #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) | 21 | #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) |
21 | #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) | 22 | #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) |
22 | 23 | ||
23 | #ifdef CONFIG_PM | 24 | #ifdef CONFIG_PM_SLEEP |
24 | static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message) | 25 | static int ad7879_spi_suspend(struct device *dev) |
25 | { | 26 | { |
27 | struct spi_device *spi = to_spi_device(dev); | ||
26 | struct ad7879 *ts = spi_get_drvdata(spi); | 28 | struct ad7879 *ts = spi_get_drvdata(spi); |
27 | 29 | ||
28 | ad7879_suspend(ts); | 30 | ad7879_suspend(ts); |
@@ -30,19 +32,19 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message) | |||
30 | return 0; | 32 | return 0; |
31 | } | 33 | } |
32 | 34 | ||
33 | static int ad7879_spi_resume(struct spi_device *spi) | 35 | static int ad7879_spi_resume(struct device *dev) |
34 | { | 36 | { |
37 | struct spi_device *spi = to_spi_device(dev); | ||
35 | struct ad7879 *ts = spi_get_drvdata(spi); | 38 | struct ad7879 *ts = spi_get_drvdata(spi); |
36 | 39 | ||
37 | ad7879_resume(ts); | 40 | ad7879_resume(ts); |
38 | 41 | ||
39 | return 0; | 42 | return 0; |
40 | } | 43 | } |
41 | #else | ||
42 | # define ad7879_spi_suspend NULL | ||
43 | # define ad7879_spi_resume NULL | ||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume); | ||
47 | |||
46 | /* | 48 | /* |
47 | * ad7879_read/write are only used for initial setup and for sysfs controls. | 49 | * ad7879_read/write are only used for initial setup and for sysfs controls. |
48 | * The main traffic is done in ad7879_collect(). | 50 | * The main traffic is done in ad7879_collect(). |
@@ -173,11 +175,10 @@ static struct spi_driver ad7879_spi_driver = { | |||
173 | .name = "ad7879", | 175 | .name = "ad7879", |
174 | .bus = &spi_bus_type, | 176 | .bus = &spi_bus_type, |
175 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
178 | .pm = &ad7879_spi_pm, | ||
176 | }, | 179 | }, |
177 | .probe = ad7879_spi_probe, | 180 | .probe = ad7879_spi_probe, |
178 | .remove = __devexit_p(ad7879_spi_remove), | 181 | .remove = __devexit_p(ad7879_spi_remove), |
179 | .suspend = ad7879_spi_suspend, | ||
180 | .resume = ad7879_spi_resume, | ||
181 | }; | 182 | }; |
182 | 183 | ||
183 | static int __init ad7879_spi_init(void) | 184 | static int __init ad7879_spi_init(void) |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 14ea54b78e46..c24946f51256 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/input.h> | 26 | #include <linux/input.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/pm.h> | ||
29 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
30 | #include <linux/spi/spi.h> | 31 | #include <linux/spi/spi.h> |
31 | #include <linux/spi/ads7846.h> | 32 | #include <linux/spi/ads7846.h> |
@@ -892,9 +893,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle) | |||
892 | return IRQ_HANDLED; | 893 | return IRQ_HANDLED; |
893 | } | 894 | } |
894 | 895 | ||
895 | static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | 896 | #ifdef CONFIG_PM_SLEEP |
897 | static int ads7846_suspend(struct device *dev) | ||
896 | { | 898 | { |
897 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 899 | struct ads7846 *ts = dev_get_drvdata(dev); |
898 | 900 | ||
899 | mutex_lock(&ts->lock); | 901 | mutex_lock(&ts->lock); |
900 | 902 | ||
@@ -914,9 +916,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
914 | return 0; | 916 | return 0; |
915 | } | 917 | } |
916 | 918 | ||
917 | static int ads7846_resume(struct spi_device *spi) | 919 | static int ads7846_resume(struct device *dev) |
918 | { | 920 | { |
919 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 921 | struct ads7846 *ts = dev_get_drvdata(dev); |
920 | 922 | ||
921 | mutex_lock(&ts->lock); | 923 | mutex_lock(&ts->lock); |
922 | 924 | ||
@@ -935,34 +937,38 @@ static int ads7846_resume(struct spi_device *spi) | |||
935 | 937 | ||
936 | return 0; | 938 | return 0; |
937 | } | 939 | } |
940 | #endif | ||
941 | |||
942 | static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); | ||
938 | 943 | ||
939 | static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) | 944 | static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) |
940 | { | 945 | { |
941 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 946 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
942 | int err; | 947 | int err; |
943 | 948 | ||
944 | /* REVISIT when the irq can be triggered active-low, or if for some | 949 | /* |
950 | * REVISIT when the irq can be triggered active-low, or if for some | ||
945 | * reason the touchscreen isn't hooked up, we don't need to access | 951 | * reason the touchscreen isn't hooked up, we don't need to access |
946 | * the pendown state. | 952 | * the pendown state. |
947 | */ | 953 | */ |
948 | if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { | ||
949 | dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); | ||
950 | return -EINVAL; | ||
951 | } | ||
952 | 954 | ||
953 | if (pdata->get_pendown_state) { | 955 | if (pdata->get_pendown_state) { |
954 | ts->get_pendown_state = pdata->get_pendown_state; | 956 | ts->get_pendown_state = pdata->get_pendown_state; |
955 | return 0; | 957 | } else if (gpio_is_valid(pdata->gpio_pendown)) { |
956 | } | ||
957 | 958 | ||
958 | err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); | 959 | err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); |
959 | if (err) { | 960 | if (err) { |
960 | dev_err(&spi->dev, "failed to request pendown GPIO%d\n", | 961 | dev_err(&spi->dev, "failed to request pendown GPIO%d\n", |
961 | pdata->gpio_pendown); | 962 | pdata->gpio_pendown); |
962 | return err; | 963 | return err; |
963 | } | 964 | } |
965 | |||
966 | ts->gpio_pendown = pdata->gpio_pendown; | ||
964 | 967 | ||
965 | ts->gpio_pendown = pdata->gpio_pendown; | 968 | } else { |
969 | dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); | ||
970 | return -EINVAL; | ||
971 | } | ||
966 | 972 | ||
967 | return 0; | 973 | return 0; |
968 | } | 974 | } |
@@ -1353,7 +1359,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1353 | err_put_regulator: | 1359 | err_put_regulator: |
1354 | regulator_put(ts->reg); | 1360 | regulator_put(ts->reg); |
1355 | err_free_gpio: | 1361 | err_free_gpio: |
1356 | if (ts->gpio_pendown != -1) | 1362 | if (!ts->get_pendown_state) |
1357 | gpio_free(ts->gpio_pendown); | 1363 | gpio_free(ts->gpio_pendown); |
1358 | err_cleanup_filter: | 1364 | err_cleanup_filter: |
1359 | if (ts->filter_cleanup) | 1365 | if (ts->filter_cleanup) |
@@ -1383,8 +1389,13 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1383 | regulator_disable(ts->reg); | 1389 | regulator_disable(ts->reg); |
1384 | regulator_put(ts->reg); | 1390 | regulator_put(ts->reg); |
1385 | 1391 | ||
1386 | if (ts->gpio_pendown != -1) | 1392 | if (!ts->get_pendown_state) { |
1393 | /* | ||
1394 | * If we are not using specialized pendown method we must | ||
1395 | * have been relying on gpio we set up ourselves. | ||
1396 | */ | ||
1387 | gpio_free(ts->gpio_pendown); | 1397 | gpio_free(ts->gpio_pendown); |
1398 | } | ||
1388 | 1399 | ||
1389 | if (ts->filter_cleanup) | 1400 | if (ts->filter_cleanup) |
1390 | ts->filter_cleanup(ts->filter_data); | 1401 | ts->filter_cleanup(ts->filter_data); |
@@ -1402,11 +1413,10 @@ static struct spi_driver ads7846_driver = { | |||
1402 | .name = "ads7846", | 1413 | .name = "ads7846", |
1403 | .bus = &spi_bus_type, | 1414 | .bus = &spi_bus_type, |
1404 | .owner = THIS_MODULE, | 1415 | .owner = THIS_MODULE, |
1416 | .pm = &ads7846_pm, | ||
1405 | }, | 1417 | }, |
1406 | .probe = ads7846_probe, | 1418 | .probe = ads7846_probe, |
1407 | .remove = __devexit_p(ads7846_remove), | 1419 | .remove = __devexit_p(ads7846_remove), |
1408 | .suspend = ads7846_suspend, | ||
1409 | .resume = ads7846_resume, | ||
1410 | }; | 1420 | }; |
1411 | 1421 | ||
1412 | static int __init ads7846_init(void) | 1422 | static int __init ads7846_init(void) |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c new file mode 100644 index 000000000000..4012436633b1 --- /dev/null +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -0,0 +1,1211 @@ | |||
1 | /* | ||
2 | * Atmel maXTouch Touchscreen driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
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 as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/firmware.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/i2c/atmel_mxt_ts.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | /* Version */ | ||
25 | #define MXT_VER_20 20 | ||
26 | #define MXT_VER_21 21 | ||
27 | #define MXT_VER_22 22 | ||
28 | |||
29 | /* Slave addresses */ | ||
30 | #define MXT_APP_LOW 0x4a | ||
31 | #define MXT_APP_HIGH 0x4b | ||
32 | #define MXT_BOOT_LOW 0x24 | ||
33 | #define MXT_BOOT_HIGH 0x25 | ||
34 | |||
35 | /* Firmware */ | ||
36 | #define MXT_FW_NAME "maxtouch.fw" | ||
37 | |||
38 | /* Registers */ | ||
39 | #define MXT_FAMILY_ID 0x00 | ||
40 | #define MXT_VARIANT_ID 0x01 | ||
41 | #define MXT_VERSION 0x02 | ||
42 | #define MXT_BUILD 0x03 | ||
43 | #define MXT_MATRIX_X_SIZE 0x04 | ||
44 | #define MXT_MATRIX_Y_SIZE 0x05 | ||
45 | #define MXT_OBJECT_NUM 0x06 | ||
46 | #define MXT_OBJECT_START 0x07 | ||
47 | |||
48 | #define MXT_OBJECT_SIZE 6 | ||
49 | |||
50 | /* Object types */ | ||
51 | #define MXT_DEBUG_DIAGNOSTIC 37 | ||
52 | #define MXT_GEN_MESSAGE 5 | ||
53 | #define MXT_GEN_COMMAND 6 | ||
54 | #define MXT_GEN_POWER 7 | ||
55 | #define MXT_GEN_ACQUIRE 8 | ||
56 | #define MXT_TOUCH_MULTI 9 | ||
57 | #define MXT_TOUCH_KEYARRAY 15 | ||
58 | #define MXT_TOUCH_PROXIMITY 23 | ||
59 | #define MXT_PROCI_GRIPFACE 20 | ||
60 | #define MXT_PROCG_NOISE 22 | ||
61 | #define MXT_PROCI_ONETOUCH 24 | ||
62 | #define MXT_PROCI_TWOTOUCH 27 | ||
63 | #define MXT_PROCI_GRIP 40 | ||
64 | #define MXT_PROCI_PALM 41 | ||
65 | #define MXT_SPT_COMMSCONFIG 18 | ||
66 | #define MXT_SPT_GPIOPWM 19 | ||
67 | #define MXT_SPT_SELFTEST 25 | ||
68 | #define MXT_SPT_CTECONFIG 28 | ||
69 | #define MXT_SPT_USERDATA 38 | ||
70 | #define MXT_SPT_DIGITIZER 43 | ||
71 | #define MXT_SPT_MESSAGECOUNT 44 | ||
72 | |||
73 | /* MXT_GEN_COMMAND field */ | ||
74 | #define MXT_COMMAND_RESET 0 | ||
75 | #define MXT_COMMAND_BACKUPNV 1 | ||
76 | #define MXT_COMMAND_CALIBRATE 2 | ||
77 | #define MXT_COMMAND_REPORTALL 3 | ||
78 | #define MXT_COMMAND_DIAGNOSTIC 5 | ||
79 | |||
80 | /* MXT_GEN_POWER field */ | ||
81 | #define MXT_POWER_IDLEACQINT 0 | ||
82 | #define MXT_POWER_ACTVACQINT 1 | ||
83 | #define MXT_POWER_ACTV2IDLETO 2 | ||
84 | |||
85 | /* MXT_GEN_ACQUIRE field */ | ||
86 | #define MXT_ACQUIRE_CHRGTIME 0 | ||
87 | #define MXT_ACQUIRE_TCHDRIFT 2 | ||
88 | #define MXT_ACQUIRE_DRIFTST 3 | ||
89 | #define MXT_ACQUIRE_TCHAUTOCAL 4 | ||
90 | #define MXT_ACQUIRE_SYNC 5 | ||
91 | #define MXT_ACQUIRE_ATCHCALST 6 | ||
92 | #define MXT_ACQUIRE_ATCHCALSTHR 7 | ||
93 | |||
94 | /* MXT_TOUCH_MULTI field */ | ||
95 | #define MXT_TOUCH_CTRL 0 | ||
96 | #define MXT_TOUCH_XORIGIN 1 | ||
97 | #define MXT_TOUCH_YORIGIN 2 | ||
98 | #define MXT_TOUCH_XSIZE 3 | ||
99 | #define MXT_TOUCH_YSIZE 4 | ||
100 | #define MXT_TOUCH_BLEN 6 | ||
101 | #define MXT_TOUCH_TCHTHR 7 | ||
102 | #define MXT_TOUCH_TCHDI 8 | ||
103 | #define MXT_TOUCH_ORIENT 9 | ||
104 | #define MXT_TOUCH_MOVHYSTI 11 | ||
105 | #define MXT_TOUCH_MOVHYSTN 12 | ||
106 | #define MXT_TOUCH_NUMTOUCH 14 | ||
107 | #define MXT_TOUCH_MRGHYST 15 | ||
108 | #define MXT_TOUCH_MRGTHR 16 | ||
109 | #define MXT_TOUCH_AMPHYST 17 | ||
110 | #define MXT_TOUCH_XRANGE_LSB 18 | ||
111 | #define MXT_TOUCH_XRANGE_MSB 19 | ||
112 | #define MXT_TOUCH_YRANGE_LSB 20 | ||
113 | #define MXT_TOUCH_YRANGE_MSB 21 | ||
114 | #define MXT_TOUCH_XLOCLIP 22 | ||
115 | #define MXT_TOUCH_XHICLIP 23 | ||
116 | #define MXT_TOUCH_YLOCLIP 24 | ||
117 | #define MXT_TOUCH_YHICLIP 25 | ||
118 | #define MXT_TOUCH_XEDGECTRL 26 | ||
119 | #define MXT_TOUCH_XEDGEDIST 27 | ||
120 | #define MXT_TOUCH_YEDGECTRL 28 | ||
121 | #define MXT_TOUCH_YEDGEDIST 29 | ||
122 | #define MXT_TOUCH_JUMPLIMIT 30 | ||
123 | |||
124 | /* MXT_PROCI_GRIPFACE field */ | ||
125 | #define MXT_GRIPFACE_CTRL 0 | ||
126 | #define MXT_GRIPFACE_XLOGRIP 1 | ||
127 | #define MXT_GRIPFACE_XHIGRIP 2 | ||
128 | #define MXT_GRIPFACE_YLOGRIP 3 | ||
129 | #define MXT_GRIPFACE_YHIGRIP 4 | ||
130 | #define MXT_GRIPFACE_MAXTCHS 5 | ||
131 | #define MXT_GRIPFACE_SZTHR1 7 | ||
132 | #define MXT_GRIPFACE_SZTHR2 8 | ||
133 | #define MXT_GRIPFACE_SHPTHR1 9 | ||
134 | #define MXT_GRIPFACE_SHPTHR2 10 | ||
135 | #define MXT_GRIPFACE_SUPEXTTO 11 | ||
136 | |||
137 | /* MXT_PROCI_NOISE field */ | ||
138 | #define MXT_NOISE_CTRL 0 | ||
139 | #define MXT_NOISE_OUTFLEN 1 | ||
140 | #define MXT_NOISE_GCAFUL_LSB 3 | ||
141 | #define MXT_NOISE_GCAFUL_MSB 4 | ||
142 | #define MXT_NOISE_GCAFLL_LSB 5 | ||
143 | #define MXT_NOISE_GCAFLL_MSB 6 | ||
144 | #define MXT_NOISE_ACTVGCAFVALID 7 | ||
145 | #define MXT_NOISE_NOISETHR 8 | ||
146 | #define MXT_NOISE_FREQHOPSCALE 10 | ||
147 | #define MXT_NOISE_FREQ0 11 | ||
148 | #define MXT_NOISE_FREQ1 12 | ||
149 | #define MXT_NOISE_FREQ2 13 | ||
150 | #define MXT_NOISE_FREQ3 14 | ||
151 | #define MXT_NOISE_FREQ4 15 | ||
152 | #define MXT_NOISE_IDLEGCAFVALID 16 | ||
153 | |||
154 | /* MXT_SPT_COMMSCONFIG */ | ||
155 | #define MXT_COMMS_CTRL 0 | ||
156 | #define MXT_COMMS_CMD 1 | ||
157 | |||
158 | /* MXT_SPT_CTECONFIG field */ | ||
159 | #define MXT_CTE_CTRL 0 | ||
160 | #define MXT_CTE_CMD 1 | ||
161 | #define MXT_CTE_MODE 2 | ||
162 | #define MXT_CTE_IDLEGCAFDEPTH 3 | ||
163 | #define MXT_CTE_ACTVGCAFDEPTH 4 | ||
164 | #define MXT_CTE_VOLTAGE 5 | ||
165 | |||
166 | #define MXT_VOLTAGE_DEFAULT 2700000 | ||
167 | #define MXT_VOLTAGE_STEP 10000 | ||
168 | |||
169 | /* Define for MXT_GEN_COMMAND */ | ||
170 | #define MXT_BOOT_VALUE 0xa5 | ||
171 | #define MXT_BACKUP_VALUE 0x55 | ||
172 | #define MXT_BACKUP_TIME 25 /* msec */ | ||
173 | #define MXT_RESET_TIME 65 /* msec */ | ||
174 | |||
175 | #define MXT_FWRESET_TIME 175 /* msec */ | ||
176 | |||
177 | /* Command to unlock bootloader */ | ||
178 | #define MXT_UNLOCK_CMD_MSB 0xaa | ||
179 | #define MXT_UNLOCK_CMD_LSB 0xdc | ||
180 | |||
181 | /* Bootloader mode status */ | ||
182 | #define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */ | ||
183 | #define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */ | ||
184 | #define MXT_FRAME_CRC_CHECK 0x02 | ||
185 | #define MXT_FRAME_CRC_FAIL 0x03 | ||
186 | #define MXT_FRAME_CRC_PASS 0x04 | ||
187 | #define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ | ||
188 | #define MXT_BOOT_STATUS_MASK 0x3f | ||
189 | |||
190 | /* Touch status */ | ||
191 | #define MXT_SUPPRESS (1 << 1) | ||
192 | #define MXT_AMP (1 << 2) | ||
193 | #define MXT_VECTOR (1 << 3) | ||
194 | #define MXT_MOVE (1 << 4) | ||
195 | #define MXT_RELEASE (1 << 5) | ||
196 | #define MXT_PRESS (1 << 6) | ||
197 | #define MXT_DETECT (1 << 7) | ||
198 | |||
199 | /* Touchscreen absolute values */ | ||
200 | #define MXT_MAX_XC 0x3ff | ||
201 | #define MXT_MAX_YC 0x3ff | ||
202 | #define MXT_MAX_AREA 0xff | ||
203 | |||
204 | #define MXT_MAX_FINGER 10 | ||
205 | |||
206 | struct mxt_info { | ||
207 | u8 family_id; | ||
208 | u8 variant_id; | ||
209 | u8 version; | ||
210 | u8 build; | ||
211 | u8 matrix_xsize; | ||
212 | u8 matrix_ysize; | ||
213 | u8 object_num; | ||
214 | }; | ||
215 | |||
216 | struct mxt_object { | ||
217 | u8 type; | ||
218 | u16 start_address; | ||
219 | u8 size; | ||
220 | u8 instances; | ||
221 | u8 num_report_ids; | ||
222 | |||
223 | /* to map object and message */ | ||
224 | u8 max_reportid; | ||
225 | }; | ||
226 | |||
227 | struct mxt_message { | ||
228 | u8 reportid; | ||
229 | u8 message[7]; | ||
230 | u8 checksum; | ||
231 | }; | ||
232 | |||
233 | struct mxt_finger { | ||
234 | int status; | ||
235 | int x; | ||
236 | int y; | ||
237 | int area; | ||
238 | }; | ||
239 | |||
240 | /* Each client has this additional data */ | ||
241 | struct mxt_data { | ||
242 | struct i2c_client *client; | ||
243 | struct input_dev *input_dev; | ||
244 | const struct mxt_platform_data *pdata; | ||
245 | struct mxt_object *object_table; | ||
246 | struct mxt_info info; | ||
247 | struct mxt_finger finger[MXT_MAX_FINGER]; | ||
248 | unsigned int irq; | ||
249 | }; | ||
250 | |||
251 | static bool mxt_object_readable(unsigned int type) | ||
252 | { | ||
253 | switch (type) { | ||
254 | case MXT_GEN_MESSAGE: | ||
255 | case MXT_GEN_COMMAND: | ||
256 | case MXT_GEN_POWER: | ||
257 | case MXT_GEN_ACQUIRE: | ||
258 | case MXT_TOUCH_MULTI: | ||
259 | case MXT_TOUCH_KEYARRAY: | ||
260 | case MXT_TOUCH_PROXIMITY: | ||
261 | case MXT_PROCI_GRIPFACE: | ||
262 | case MXT_PROCG_NOISE: | ||
263 | case MXT_PROCI_ONETOUCH: | ||
264 | case MXT_PROCI_TWOTOUCH: | ||
265 | case MXT_PROCI_GRIP: | ||
266 | case MXT_PROCI_PALM: | ||
267 | case MXT_SPT_COMMSCONFIG: | ||
268 | case MXT_SPT_GPIOPWM: | ||
269 | case MXT_SPT_SELFTEST: | ||
270 | case MXT_SPT_CTECONFIG: | ||
271 | case MXT_SPT_USERDATA: | ||
272 | return true; | ||
273 | default: | ||
274 | return false; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static bool mxt_object_writable(unsigned int type) | ||
279 | { | ||
280 | switch (type) { | ||
281 | case MXT_GEN_COMMAND: | ||
282 | case MXT_GEN_POWER: | ||
283 | case MXT_GEN_ACQUIRE: | ||
284 | case MXT_TOUCH_MULTI: | ||
285 | case MXT_TOUCH_KEYARRAY: | ||
286 | case MXT_TOUCH_PROXIMITY: | ||
287 | case MXT_PROCI_GRIPFACE: | ||
288 | case MXT_PROCG_NOISE: | ||
289 | case MXT_PROCI_ONETOUCH: | ||
290 | case MXT_PROCI_TWOTOUCH: | ||
291 | case MXT_PROCI_GRIP: | ||
292 | case MXT_PROCI_PALM: | ||
293 | case MXT_SPT_GPIOPWM: | ||
294 | case MXT_SPT_SELFTEST: | ||
295 | case MXT_SPT_CTECONFIG: | ||
296 | return true; | ||
297 | default: | ||
298 | return false; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | static void mxt_dump_message(struct device *dev, | ||
303 | struct mxt_message *message) | ||
304 | { | ||
305 | dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); | ||
306 | dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); | ||
307 | dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); | ||
308 | dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); | ||
309 | dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); | ||
310 | dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); | ||
311 | dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); | ||
312 | dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); | ||
313 | dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); | ||
314 | } | ||
315 | |||
316 | static int mxt_check_bootloader(struct i2c_client *client, | ||
317 | unsigned int state) | ||
318 | { | ||
319 | u8 val; | ||
320 | |||
321 | recheck: | ||
322 | if (i2c_master_recv(client, &val, 1) != 1) { | ||
323 | dev_err(&client->dev, "%s: i2c recv failed\n", __func__); | ||
324 | return -EIO; | ||
325 | } | ||
326 | |||
327 | switch (state) { | ||
328 | case MXT_WAITING_BOOTLOAD_CMD: | ||
329 | case MXT_WAITING_FRAME_DATA: | ||
330 | val &= ~MXT_BOOT_STATUS_MASK; | ||
331 | break; | ||
332 | case MXT_FRAME_CRC_PASS: | ||
333 | if (val == MXT_FRAME_CRC_CHECK) | ||
334 | goto recheck; | ||
335 | break; | ||
336 | default: | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | if (val != state) { | ||
341 | dev_err(&client->dev, "Unvalid bootloader mode state\n"); | ||
342 | return -EINVAL; | ||
343 | } | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int mxt_unlock_bootloader(struct i2c_client *client) | ||
349 | { | ||
350 | u8 buf[2]; | ||
351 | |||
352 | buf[0] = MXT_UNLOCK_CMD_LSB; | ||
353 | buf[1] = MXT_UNLOCK_CMD_MSB; | ||
354 | |||
355 | if (i2c_master_send(client, buf, 2) != 2) { | ||
356 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
357 | return -EIO; | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int mxt_fw_write(struct i2c_client *client, | ||
364 | const u8 *data, unsigned int frame_size) | ||
365 | { | ||
366 | if (i2c_master_send(client, data, frame_size) != frame_size) { | ||
367 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
368 | return -EIO; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int __mxt_read_reg(struct i2c_client *client, | ||
375 | u16 reg, u16 len, void *val) | ||
376 | { | ||
377 | struct i2c_msg xfer[2]; | ||
378 | u8 buf[2]; | ||
379 | |||
380 | buf[0] = reg & 0xff; | ||
381 | buf[1] = (reg >> 8) & 0xff; | ||
382 | |||
383 | /* Write register */ | ||
384 | xfer[0].addr = client->addr; | ||
385 | xfer[0].flags = 0; | ||
386 | xfer[0].len = 2; | ||
387 | xfer[0].buf = buf; | ||
388 | |||
389 | /* Read data */ | ||
390 | xfer[1].addr = client->addr; | ||
391 | xfer[1].flags = I2C_M_RD; | ||
392 | xfer[1].len = len; | ||
393 | xfer[1].buf = val; | ||
394 | |||
395 | if (i2c_transfer(client->adapter, xfer, 2) != 2) { | ||
396 | dev_err(&client->dev, "%s: i2c transfer failed\n", __func__); | ||
397 | return -EIO; | ||
398 | } | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) | ||
404 | { | ||
405 | return __mxt_read_reg(client, reg, 1, val); | ||
406 | } | ||
407 | |||
408 | static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) | ||
409 | { | ||
410 | u8 buf[3]; | ||
411 | |||
412 | buf[0] = reg & 0xff; | ||
413 | buf[1] = (reg >> 8) & 0xff; | ||
414 | buf[2] = val; | ||
415 | |||
416 | if (i2c_master_send(client, buf, 3) != 3) { | ||
417 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
418 | return -EIO; | ||
419 | } | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int mxt_read_object_table(struct i2c_client *client, | ||
425 | u16 reg, u8 *object_buf) | ||
426 | { | ||
427 | return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE, | ||
428 | object_buf); | ||
429 | } | ||
430 | |||
431 | static struct mxt_object * | ||
432 | mxt_get_object(struct mxt_data *data, u8 type) | ||
433 | { | ||
434 | struct mxt_object *object; | ||
435 | int i; | ||
436 | |||
437 | for (i = 0; i < data->info.object_num; i++) { | ||
438 | object = data->object_table + i; | ||
439 | if (object->type == type) | ||
440 | return object; | ||
441 | } | ||
442 | |||
443 | dev_err(&data->client->dev, "Invalid object type\n"); | ||
444 | return NULL; | ||
445 | } | ||
446 | |||
447 | static int mxt_read_message(struct mxt_data *data, | ||
448 | struct mxt_message *message) | ||
449 | { | ||
450 | struct mxt_object *object; | ||
451 | u16 reg; | ||
452 | |||
453 | object = mxt_get_object(data, MXT_GEN_MESSAGE); | ||
454 | if (!object) | ||
455 | return -EINVAL; | ||
456 | |||
457 | reg = object->start_address; | ||
458 | return __mxt_read_reg(data->client, reg, | ||
459 | sizeof(struct mxt_message), message); | ||
460 | } | ||
461 | |||
462 | static int mxt_read_object(struct mxt_data *data, | ||
463 | u8 type, u8 offset, u8 *val) | ||
464 | { | ||
465 | struct mxt_object *object; | ||
466 | u16 reg; | ||
467 | |||
468 | object = mxt_get_object(data, type); | ||
469 | if (!object) | ||
470 | return -EINVAL; | ||
471 | |||
472 | reg = object->start_address; | ||
473 | return __mxt_read_reg(data->client, reg + offset, 1, val); | ||
474 | } | ||
475 | |||
476 | static int mxt_write_object(struct mxt_data *data, | ||
477 | u8 type, u8 offset, u8 val) | ||
478 | { | ||
479 | struct mxt_object *object; | ||
480 | u16 reg; | ||
481 | |||
482 | object = mxt_get_object(data, type); | ||
483 | if (!object) | ||
484 | return -EINVAL; | ||
485 | |||
486 | reg = object->start_address; | ||
487 | return mxt_write_reg(data->client, reg + offset, val); | ||
488 | } | ||
489 | |||
490 | static void mxt_input_report(struct mxt_data *data, int single_id) | ||
491 | { | ||
492 | struct mxt_finger *finger = data->finger; | ||
493 | struct input_dev *input_dev = data->input_dev; | ||
494 | int status = finger[single_id].status; | ||
495 | int finger_num = 0; | ||
496 | int id; | ||
497 | |||
498 | for (id = 0; id < MXT_MAX_FINGER; id++) { | ||
499 | if (!finger[id].status) | ||
500 | continue; | ||
501 | |||
502 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, | ||
503 | finger[id].status != MXT_RELEASE ? | ||
504 | finger[id].area : 0); | ||
505 | input_report_abs(input_dev, ABS_MT_POSITION_X, | ||
506 | finger[id].x); | ||
507 | input_report_abs(input_dev, ABS_MT_POSITION_Y, | ||
508 | finger[id].y); | ||
509 | input_mt_sync(input_dev); | ||
510 | |||
511 | if (finger[id].status == MXT_RELEASE) | ||
512 | finger[id].status = 0; | ||
513 | else | ||
514 | finger_num++; | ||
515 | } | ||
516 | |||
517 | input_report_key(input_dev, BTN_TOUCH, finger_num > 0); | ||
518 | |||
519 | if (status != MXT_RELEASE) { | ||
520 | input_report_abs(input_dev, ABS_X, finger[single_id].x); | ||
521 | input_report_abs(input_dev, ABS_Y, finger[single_id].y); | ||
522 | } | ||
523 | |||
524 | input_sync(input_dev); | ||
525 | } | ||
526 | |||
527 | static void mxt_input_touchevent(struct mxt_data *data, | ||
528 | struct mxt_message *message, int id) | ||
529 | { | ||
530 | struct mxt_finger *finger = data->finger; | ||
531 | struct device *dev = &data->client->dev; | ||
532 | u8 status = message->message[0]; | ||
533 | int x; | ||
534 | int y; | ||
535 | int area; | ||
536 | |||
537 | /* Check the touch is present on the screen */ | ||
538 | if (!(status & MXT_DETECT)) { | ||
539 | if (status & MXT_RELEASE) { | ||
540 | dev_dbg(dev, "[%d] released\n", id); | ||
541 | |||
542 | finger[id].status = MXT_RELEASE; | ||
543 | mxt_input_report(data, id); | ||
544 | } | ||
545 | return; | ||
546 | } | ||
547 | |||
548 | /* Check only AMP detection */ | ||
549 | if (!(status & (MXT_PRESS | MXT_MOVE))) | ||
550 | return; | ||
551 | |||
552 | x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6); | ||
553 | y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2); | ||
554 | area = message->message[4]; | ||
555 | |||
556 | dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id, | ||
557 | status & MXT_MOVE ? "moved" : "pressed", | ||
558 | x, y, area); | ||
559 | |||
560 | finger[id].status = status & MXT_MOVE ? | ||
561 | MXT_MOVE : MXT_PRESS; | ||
562 | finger[id].x = x; | ||
563 | finger[id].y = y; | ||
564 | finger[id].area = area; | ||
565 | |||
566 | mxt_input_report(data, id); | ||
567 | } | ||
568 | |||
569 | static irqreturn_t mxt_interrupt(int irq, void *dev_id) | ||
570 | { | ||
571 | struct mxt_data *data = dev_id; | ||
572 | struct mxt_message message; | ||
573 | struct mxt_object *object; | ||
574 | struct device *dev = &data->client->dev; | ||
575 | int id; | ||
576 | u8 reportid; | ||
577 | u8 max_reportid; | ||
578 | u8 min_reportid; | ||
579 | |||
580 | do { | ||
581 | if (mxt_read_message(data, &message)) { | ||
582 | dev_err(dev, "Failed to read message\n"); | ||
583 | goto end; | ||
584 | } | ||
585 | |||
586 | reportid = message.reportid; | ||
587 | |||
588 | /* whether reportid is thing of MXT_TOUCH_MULTI */ | ||
589 | object = mxt_get_object(data, MXT_TOUCH_MULTI); | ||
590 | if (!object) | ||
591 | goto end; | ||
592 | |||
593 | max_reportid = object->max_reportid; | ||
594 | min_reportid = max_reportid - object->num_report_ids + 1; | ||
595 | id = reportid - min_reportid; | ||
596 | |||
597 | if (reportid >= min_reportid && reportid <= max_reportid) | ||
598 | mxt_input_touchevent(data, &message, id); | ||
599 | else | ||
600 | mxt_dump_message(dev, &message); | ||
601 | } while (reportid != 0xff); | ||
602 | |||
603 | end: | ||
604 | return IRQ_HANDLED; | ||
605 | } | ||
606 | |||
607 | static int mxt_check_reg_init(struct mxt_data *data) | ||
608 | { | ||
609 | const struct mxt_platform_data *pdata = data->pdata; | ||
610 | struct mxt_object *object; | ||
611 | struct device *dev = &data->client->dev; | ||
612 | int index = 0; | ||
613 | int i, j, config_offset; | ||
614 | |||
615 | if (!pdata->config) { | ||
616 | dev_dbg(dev, "No cfg data defined, skipping reg init\n"); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | for (i = 0; i < data->info.object_num; i++) { | ||
621 | object = data->object_table + i; | ||
622 | |||
623 | if (!mxt_object_writable(object->type)) | ||
624 | continue; | ||
625 | |||
626 | for (j = 0; j < object->size + 1; j++) { | ||
627 | config_offset = index + j; | ||
628 | if (config_offset > pdata->config_length) { | ||
629 | dev_err(dev, "Not enough config data!\n"); | ||
630 | return -EINVAL; | ||
631 | } | ||
632 | mxt_write_object(data, object->type, j, | ||
633 | pdata->config[config_offset]); | ||
634 | } | ||
635 | index += object->size + 1; | ||
636 | } | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int mxt_make_highchg(struct mxt_data *data) | ||
642 | { | ||
643 | struct device *dev = &data->client->dev; | ||
644 | struct mxt_message message; | ||
645 | int count = 10; | ||
646 | int error; | ||
647 | |||
648 | /* Read dummy message to make high CHG pin */ | ||
649 | do { | ||
650 | error = mxt_read_message(data, &message); | ||
651 | if (error) | ||
652 | return error; | ||
653 | } while (message.reportid != 0xff && --count); | ||
654 | |||
655 | if (!count) { | ||
656 | dev_err(dev, "CHG pin isn't cleared\n"); | ||
657 | return -EBUSY; | ||
658 | } | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static void mxt_handle_pdata(struct mxt_data *data) | ||
664 | { | ||
665 | const struct mxt_platform_data *pdata = data->pdata; | ||
666 | u8 voltage; | ||
667 | |||
668 | /* Set touchscreen lines */ | ||
669 | mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE, | ||
670 | pdata->x_line); | ||
671 | mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE, | ||
672 | pdata->y_line); | ||
673 | |||
674 | /* Set touchscreen orient */ | ||
675 | mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT, | ||
676 | pdata->orient); | ||
677 | |||
678 | /* Set touchscreen burst length */ | ||
679 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
680 | MXT_TOUCH_BLEN, pdata->blen); | ||
681 | |||
682 | /* Set touchscreen threshold */ | ||
683 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
684 | MXT_TOUCH_TCHTHR, pdata->threshold); | ||
685 | |||
686 | /* Set touchscreen resolution */ | ||
687 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
688 | MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); | ||
689 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
690 | MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); | ||
691 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
692 | MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); | ||
693 | mxt_write_object(data, MXT_TOUCH_MULTI, | ||
694 | MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); | ||
695 | |||
696 | /* Set touchscreen voltage */ | ||
697 | if (pdata->voltage) { | ||
698 | if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { | ||
699 | voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / | ||
700 | MXT_VOLTAGE_STEP; | ||
701 | voltage = 0xff - voltage + 1; | ||
702 | } else | ||
703 | voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / | ||
704 | MXT_VOLTAGE_STEP; | ||
705 | |||
706 | mxt_write_object(data, MXT_SPT_CTECONFIG, | ||
707 | MXT_CTE_VOLTAGE, voltage); | ||
708 | } | ||
709 | } | ||
710 | |||
711 | static int mxt_get_info(struct mxt_data *data) | ||
712 | { | ||
713 | struct i2c_client *client = data->client; | ||
714 | struct mxt_info *info = &data->info; | ||
715 | int error; | ||
716 | u8 val; | ||
717 | |||
718 | error = mxt_read_reg(client, MXT_FAMILY_ID, &val); | ||
719 | if (error) | ||
720 | return error; | ||
721 | info->family_id = val; | ||
722 | |||
723 | error = mxt_read_reg(client, MXT_VARIANT_ID, &val); | ||
724 | if (error) | ||
725 | return error; | ||
726 | info->variant_id = val; | ||
727 | |||
728 | error = mxt_read_reg(client, MXT_VERSION, &val); | ||
729 | if (error) | ||
730 | return error; | ||
731 | info->version = val; | ||
732 | |||
733 | error = mxt_read_reg(client, MXT_BUILD, &val); | ||
734 | if (error) | ||
735 | return error; | ||
736 | info->build = val; | ||
737 | |||
738 | error = mxt_read_reg(client, MXT_OBJECT_NUM, &val); | ||
739 | if (error) | ||
740 | return error; | ||
741 | info->object_num = val; | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | static int mxt_get_object_table(struct mxt_data *data) | ||
747 | { | ||
748 | int error; | ||
749 | int i; | ||
750 | u16 reg; | ||
751 | u8 reportid = 0; | ||
752 | u8 buf[MXT_OBJECT_SIZE]; | ||
753 | |||
754 | for (i = 0; i < data->info.object_num; i++) { | ||
755 | struct mxt_object *object = data->object_table + i; | ||
756 | |||
757 | reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i; | ||
758 | error = mxt_read_object_table(data->client, reg, buf); | ||
759 | if (error) | ||
760 | return error; | ||
761 | |||
762 | object->type = buf[0]; | ||
763 | object->start_address = (buf[2] << 8) | buf[1]; | ||
764 | object->size = buf[3]; | ||
765 | object->instances = buf[4]; | ||
766 | object->num_report_ids = buf[5]; | ||
767 | |||
768 | if (object->num_report_ids) { | ||
769 | reportid += object->num_report_ids * | ||
770 | (object->instances + 1); | ||
771 | object->max_reportid = reportid; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int mxt_initialize(struct mxt_data *data) | ||
779 | { | ||
780 | struct i2c_client *client = data->client; | ||
781 | struct mxt_info *info = &data->info; | ||
782 | int error; | ||
783 | u8 val; | ||
784 | |||
785 | error = mxt_get_info(data); | ||
786 | if (error) | ||
787 | return error; | ||
788 | |||
789 | data->object_table = kcalloc(info->object_num, | ||
790 | sizeof(struct mxt_object), | ||
791 | GFP_KERNEL); | ||
792 | if (!data->object_table) { | ||
793 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
794 | return -ENOMEM; | ||
795 | } | ||
796 | |||
797 | /* Get object table information */ | ||
798 | error = mxt_get_object_table(data); | ||
799 | if (error) | ||
800 | return error; | ||
801 | |||
802 | /* Check register init values */ | ||
803 | error = mxt_check_reg_init(data); | ||
804 | if (error) | ||
805 | return error; | ||
806 | |||
807 | error = mxt_make_highchg(data); | ||
808 | if (error) | ||
809 | return error; | ||
810 | |||
811 | mxt_handle_pdata(data); | ||
812 | |||
813 | /* Backup to memory */ | ||
814 | mxt_write_object(data, MXT_GEN_COMMAND, | ||
815 | MXT_COMMAND_BACKUPNV, | ||
816 | MXT_BACKUP_VALUE); | ||
817 | msleep(MXT_BACKUP_TIME); | ||
818 | |||
819 | /* Soft reset */ | ||
820 | mxt_write_object(data, MXT_GEN_COMMAND, | ||
821 | MXT_COMMAND_RESET, 1); | ||
822 | msleep(MXT_RESET_TIME); | ||
823 | |||
824 | /* Update matrix size at info struct */ | ||
825 | error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); | ||
826 | if (error) | ||
827 | return error; | ||
828 | info->matrix_xsize = val; | ||
829 | |||
830 | error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val); | ||
831 | if (error) | ||
832 | return error; | ||
833 | info->matrix_ysize = val; | ||
834 | |||
835 | dev_info(&client->dev, | ||
836 | "Family ID: %d Variant ID: %d Version: %d Build: %d\n", | ||
837 | info->family_id, info->variant_id, info->version, | ||
838 | info->build); | ||
839 | |||
840 | dev_info(&client->dev, | ||
841 | "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n", | ||
842 | info->matrix_xsize, info->matrix_ysize, | ||
843 | info->object_num); | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static ssize_t mxt_object_show(struct device *dev, | ||
849 | struct device_attribute *attr, char *buf) | ||
850 | { | ||
851 | struct mxt_data *data = dev_get_drvdata(dev); | ||
852 | struct mxt_object *object; | ||
853 | int count = 0; | ||
854 | int i, j; | ||
855 | int error; | ||
856 | u8 val; | ||
857 | |||
858 | for (i = 0; i < data->info.object_num; i++) { | ||
859 | object = data->object_table + i; | ||
860 | |||
861 | count += sprintf(buf + count, | ||
862 | "Object Table Element %d(Type %d)\n", | ||
863 | i + 1, object->type); | ||
864 | |||
865 | if (!mxt_object_readable(object->type)) { | ||
866 | count += sprintf(buf + count, "\n"); | ||
867 | continue; | ||
868 | } | ||
869 | |||
870 | for (j = 0; j < object->size + 1; j++) { | ||
871 | error = mxt_read_object(data, | ||
872 | object->type, j, &val); | ||
873 | if (error) | ||
874 | return error; | ||
875 | |||
876 | count += sprintf(buf + count, | ||
877 | " Byte %d: 0x%x (%d)\n", j, val, val); | ||
878 | } | ||
879 | |||
880 | count += sprintf(buf + count, "\n"); | ||
881 | } | ||
882 | |||
883 | return count; | ||
884 | } | ||
885 | |||
886 | static int mxt_load_fw(struct device *dev, const char *fn) | ||
887 | { | ||
888 | struct mxt_data *data = dev_get_drvdata(dev); | ||
889 | struct i2c_client *client = data->client; | ||
890 | const struct firmware *fw = NULL; | ||
891 | unsigned int frame_size; | ||
892 | unsigned int pos = 0; | ||
893 | int ret; | ||
894 | |||
895 | ret = request_firmware(&fw, fn, dev); | ||
896 | if (ret) { | ||
897 | dev_err(dev, "Unable to open firmware %s\n", fn); | ||
898 | return ret; | ||
899 | } | ||
900 | |||
901 | /* Change to the bootloader mode */ | ||
902 | mxt_write_object(data, MXT_GEN_COMMAND, | ||
903 | MXT_COMMAND_RESET, MXT_BOOT_VALUE); | ||
904 | msleep(MXT_RESET_TIME); | ||
905 | |||
906 | /* Change to slave address of bootloader */ | ||
907 | if (client->addr == MXT_APP_LOW) | ||
908 | client->addr = MXT_BOOT_LOW; | ||
909 | else | ||
910 | client->addr = MXT_BOOT_HIGH; | ||
911 | |||
912 | ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD); | ||
913 | if (ret) | ||
914 | goto out; | ||
915 | |||
916 | /* Unlock bootloader */ | ||
917 | mxt_unlock_bootloader(client); | ||
918 | |||
919 | while (pos < fw->size) { | ||
920 | ret = mxt_check_bootloader(client, | ||
921 | MXT_WAITING_FRAME_DATA); | ||
922 | if (ret) | ||
923 | goto out; | ||
924 | |||
925 | frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1)); | ||
926 | |||
927 | /* We should add 2 at frame size as the the firmware data is not | ||
928 | * included the CRC bytes. | ||
929 | */ | ||
930 | frame_size += 2; | ||
931 | |||
932 | /* Write one frame to device */ | ||
933 | mxt_fw_write(client, fw->data + pos, frame_size); | ||
934 | |||
935 | ret = mxt_check_bootloader(client, | ||
936 | MXT_FRAME_CRC_PASS); | ||
937 | if (ret) | ||
938 | goto out; | ||
939 | |||
940 | pos += frame_size; | ||
941 | |||
942 | dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size); | ||
943 | } | ||
944 | |||
945 | out: | ||
946 | release_firmware(fw); | ||
947 | |||
948 | /* Change to slave address of application */ | ||
949 | if (client->addr == MXT_BOOT_LOW) | ||
950 | client->addr = MXT_APP_LOW; | ||
951 | else | ||
952 | client->addr = MXT_APP_HIGH; | ||
953 | |||
954 | return ret; | ||
955 | } | ||
956 | |||
957 | static ssize_t mxt_update_fw_store(struct device *dev, | ||
958 | struct device_attribute *attr, | ||
959 | const char *buf, size_t count) | ||
960 | { | ||
961 | struct mxt_data *data = dev_get_drvdata(dev); | ||
962 | int error; | ||
963 | |||
964 | disable_irq(data->irq); | ||
965 | |||
966 | error = mxt_load_fw(dev, MXT_FW_NAME); | ||
967 | if (error) { | ||
968 | dev_err(dev, "The firmware update failed(%d)\n", error); | ||
969 | count = error; | ||
970 | } else { | ||
971 | dev_dbg(dev, "The firmware update succeeded\n"); | ||
972 | |||
973 | /* Wait for reset */ | ||
974 | msleep(MXT_FWRESET_TIME); | ||
975 | |||
976 | kfree(data->object_table); | ||
977 | data->object_table = NULL; | ||
978 | |||
979 | mxt_initialize(data); | ||
980 | } | ||
981 | |||
982 | enable_irq(data->irq); | ||
983 | |||
984 | return count; | ||
985 | } | ||
986 | |||
987 | static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); | ||
988 | static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); | ||
989 | |||
990 | static struct attribute *mxt_attrs[] = { | ||
991 | &dev_attr_object.attr, | ||
992 | &dev_attr_update_fw.attr, | ||
993 | NULL | ||
994 | }; | ||
995 | |||
996 | static const struct attribute_group mxt_attr_group = { | ||
997 | .attrs = mxt_attrs, | ||
998 | }; | ||
999 | |||
1000 | static void mxt_start(struct mxt_data *data) | ||
1001 | { | ||
1002 | /* Touch enable */ | ||
1003 | mxt_write_object(data, | ||
1004 | MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83); | ||
1005 | } | ||
1006 | |||
1007 | static void mxt_stop(struct mxt_data *data) | ||
1008 | { | ||
1009 | /* Touch disable */ | ||
1010 | mxt_write_object(data, | ||
1011 | MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0); | ||
1012 | } | ||
1013 | |||
1014 | static int mxt_input_open(struct input_dev *dev) | ||
1015 | { | ||
1016 | struct mxt_data *data = input_get_drvdata(dev); | ||
1017 | |||
1018 | mxt_start(data); | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | static void mxt_input_close(struct input_dev *dev) | ||
1024 | { | ||
1025 | struct mxt_data *data = input_get_drvdata(dev); | ||
1026 | |||
1027 | mxt_stop(data); | ||
1028 | } | ||
1029 | |||
1030 | static int __devinit mxt_probe(struct i2c_client *client, | ||
1031 | const struct i2c_device_id *id) | ||
1032 | { | ||
1033 | const struct mxt_platform_data *pdata = client->dev.platform_data; | ||
1034 | struct mxt_data *data; | ||
1035 | struct input_dev *input_dev; | ||
1036 | int error; | ||
1037 | |||
1038 | if (!pdata) | ||
1039 | return -EINVAL; | ||
1040 | |||
1041 | data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); | ||
1042 | input_dev = input_allocate_device(); | ||
1043 | if (!data || !input_dev) { | ||
1044 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
1045 | error = -ENOMEM; | ||
1046 | goto err_free_mem; | ||
1047 | } | ||
1048 | |||
1049 | input_dev->name = "Atmel maXTouch Touchscreen"; | ||
1050 | input_dev->id.bustype = BUS_I2C; | ||
1051 | input_dev->dev.parent = &client->dev; | ||
1052 | input_dev->open = mxt_input_open; | ||
1053 | input_dev->close = mxt_input_close; | ||
1054 | |||
1055 | __set_bit(EV_ABS, input_dev->evbit); | ||
1056 | __set_bit(EV_KEY, input_dev->evbit); | ||
1057 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
1058 | |||
1059 | /* For single touch */ | ||
1060 | input_set_abs_params(input_dev, ABS_X, | ||
1061 | 0, MXT_MAX_XC, 0, 0); | ||
1062 | input_set_abs_params(input_dev, ABS_Y, | ||
1063 | 0, MXT_MAX_YC, 0, 0); | ||
1064 | |||
1065 | /* For multi touch */ | ||
1066 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
1067 | 0, MXT_MAX_AREA, 0, 0); | ||
1068 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
1069 | 0, MXT_MAX_XC, 0, 0); | ||
1070 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
1071 | 0, MXT_MAX_YC, 0, 0); | ||
1072 | |||
1073 | input_set_drvdata(input_dev, data); | ||
1074 | |||
1075 | data->client = client; | ||
1076 | data->input_dev = input_dev; | ||
1077 | data->pdata = pdata; | ||
1078 | data->irq = client->irq; | ||
1079 | |||
1080 | i2c_set_clientdata(client, data); | ||
1081 | |||
1082 | error = mxt_initialize(data); | ||
1083 | if (error) | ||
1084 | goto err_free_object; | ||
1085 | |||
1086 | error = request_threaded_irq(client->irq, NULL, mxt_interrupt, | ||
1087 | pdata->irqflags, client->dev.driver->name, data); | ||
1088 | if (error) { | ||
1089 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
1090 | goto err_free_object; | ||
1091 | } | ||
1092 | |||
1093 | error = input_register_device(input_dev); | ||
1094 | if (error) | ||
1095 | goto err_free_irq; | ||
1096 | |||
1097 | error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); | ||
1098 | if (error) | ||
1099 | goto err_unregister_device; | ||
1100 | |||
1101 | return 0; | ||
1102 | |||
1103 | err_unregister_device: | ||
1104 | input_unregister_device(input_dev); | ||
1105 | input_dev = NULL; | ||
1106 | err_free_irq: | ||
1107 | free_irq(client->irq, data); | ||
1108 | err_free_object: | ||
1109 | kfree(data->object_table); | ||
1110 | err_free_mem: | ||
1111 | input_free_device(input_dev); | ||
1112 | kfree(data); | ||
1113 | return error; | ||
1114 | } | ||
1115 | |||
1116 | static int __devexit mxt_remove(struct i2c_client *client) | ||
1117 | { | ||
1118 | struct mxt_data *data = i2c_get_clientdata(client); | ||
1119 | |||
1120 | sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); | ||
1121 | free_irq(data->irq, data); | ||
1122 | input_unregister_device(data->input_dev); | ||
1123 | kfree(data->object_table); | ||
1124 | kfree(data); | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | #ifdef CONFIG_PM | ||
1130 | static int mxt_suspend(struct device *dev) | ||
1131 | { | ||
1132 | struct i2c_client *client = to_i2c_client(dev); | ||
1133 | struct mxt_data *data = i2c_get_clientdata(client); | ||
1134 | struct input_dev *input_dev = data->input_dev; | ||
1135 | |||
1136 | mutex_lock(&input_dev->mutex); | ||
1137 | |||
1138 | if (input_dev->users) | ||
1139 | mxt_stop(data); | ||
1140 | |||
1141 | mutex_unlock(&input_dev->mutex); | ||
1142 | |||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | static int mxt_resume(struct device *dev) | ||
1147 | { | ||
1148 | struct i2c_client *client = to_i2c_client(dev); | ||
1149 | struct mxt_data *data = i2c_get_clientdata(client); | ||
1150 | struct input_dev *input_dev = data->input_dev; | ||
1151 | |||
1152 | /* Soft reset */ | ||
1153 | mxt_write_object(data, MXT_GEN_COMMAND, | ||
1154 | MXT_COMMAND_RESET, 1); | ||
1155 | |||
1156 | msleep(MXT_RESET_TIME); | ||
1157 | |||
1158 | mutex_lock(&input_dev->mutex); | ||
1159 | |||
1160 | if (input_dev->users) | ||
1161 | mxt_start(data); | ||
1162 | |||
1163 | mutex_unlock(&input_dev->mutex); | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static const struct dev_pm_ops mxt_pm_ops = { | ||
1169 | .suspend = mxt_suspend, | ||
1170 | .resume = mxt_resume, | ||
1171 | }; | ||
1172 | #endif | ||
1173 | |||
1174 | static const struct i2c_device_id mxt_id[] = { | ||
1175 | { "qt602240_ts", 0 }, | ||
1176 | { "atmel_mxt_ts", 0 }, | ||
1177 | { "mXT224", 0 }, | ||
1178 | { } | ||
1179 | }; | ||
1180 | MODULE_DEVICE_TABLE(i2c, mxt_id); | ||
1181 | |||
1182 | static struct i2c_driver mxt_driver = { | ||
1183 | .driver = { | ||
1184 | .name = "atmel_mxt_ts", | ||
1185 | .owner = THIS_MODULE, | ||
1186 | #ifdef CONFIG_PM | ||
1187 | .pm = &mxt_pm_ops, | ||
1188 | #endif | ||
1189 | }, | ||
1190 | .probe = mxt_probe, | ||
1191 | .remove = __devexit_p(mxt_remove), | ||
1192 | .id_table = mxt_id, | ||
1193 | }; | ||
1194 | |||
1195 | static int __init mxt_init(void) | ||
1196 | { | ||
1197 | return i2c_add_driver(&mxt_driver); | ||
1198 | } | ||
1199 | |||
1200 | static void __exit mxt_exit(void) | ||
1201 | { | ||
1202 | i2c_del_driver(&mxt_driver); | ||
1203 | } | ||
1204 | |||
1205 | module_init(mxt_init); | ||
1206 | module_exit(mxt_exit); | ||
1207 | |||
1208 | /* Module information */ | ||
1209 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
1210 | MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver"); | ||
1211 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 2ca9e5d66460..1507ce108d5b 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/input.h> | 12 | #include <linux/input.h> |
13 | #include <linux/input/bu21013.h> | 13 | #include <linux/input/bu21013.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/regulator/consumer.h> | ||
15 | 16 | ||
16 | #define PEN_DOWN_INTR 0 | 17 | #define PEN_DOWN_INTR 0 |
17 | #define MAX_FINGERS 2 | 18 | #define MAX_FINGERS 2 |
@@ -139,6 +140,7 @@ | |||
139 | * @chip: pointer to the touch panel controller | 140 | * @chip: pointer to the touch panel controller |
140 | * @in_dev: pointer to the input device structure | 141 | * @in_dev: pointer to the input device structure |
141 | * @intr_pin: interrupt pin value | 142 | * @intr_pin: interrupt pin value |
143 | * @regulator: pointer to the Regulator used for touch screen | ||
142 | * | 144 | * |
143 | * Touch panel device data structure | 145 | * Touch panel device data structure |
144 | */ | 146 | */ |
@@ -149,6 +151,7 @@ struct bu21013_ts_data { | |||
149 | const struct bu21013_platform_device *chip; | 151 | const struct bu21013_platform_device *chip; |
150 | struct input_dev *in_dev; | 152 | struct input_dev *in_dev; |
151 | unsigned int intr_pin; | 153 | unsigned int intr_pin; |
154 | struct regulator *regulator; | ||
152 | }; | 155 | }; |
153 | 156 | ||
154 | /** | 157 | /** |
@@ -365,7 +368,7 @@ static int bu21013_init_chip(struct bu21013_ts_data *data) | |||
365 | } | 368 | } |
366 | 369 | ||
367 | retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, | 370 | retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, |
368 | BU21013_TH_OFF_4 || BU21013_TH_OFF_3); | 371 | BU21013_TH_OFF_4 | BU21013_TH_OFF_3); |
369 | if (retval < 0) { | 372 | if (retval < 0) { |
370 | dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); | 373 | dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); |
371 | return retval; | 374 | return retval; |
@@ -456,6 +459,20 @@ static int __devinit bu21013_probe(struct i2c_client *client, | |||
456 | bu21013_data->in_dev = in_dev; | 459 | bu21013_data->in_dev = in_dev; |
457 | bu21013_data->chip = pdata; | 460 | bu21013_data->chip = pdata; |
458 | bu21013_data->client = client; | 461 | bu21013_data->client = client; |
462 | |||
463 | bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH"); | ||
464 | if (IS_ERR(bu21013_data->regulator)) { | ||
465 | dev_err(&client->dev, "regulator_get failed\n"); | ||
466 | error = PTR_ERR(bu21013_data->regulator); | ||
467 | goto err_free_mem; | ||
468 | } | ||
469 | |||
470 | error = regulator_enable(bu21013_data->regulator); | ||
471 | if (error < 0) { | ||
472 | dev_err(&client->dev, "regulator enable failed\n"); | ||
473 | goto err_put_regulator; | ||
474 | } | ||
475 | |||
459 | bu21013_data->touch_stopped = false; | 476 | bu21013_data->touch_stopped = false; |
460 | init_waitqueue_head(&bu21013_data->wait); | 477 | init_waitqueue_head(&bu21013_data->wait); |
461 | 478 | ||
@@ -464,7 +481,7 @@ static int __devinit bu21013_probe(struct i2c_client *client, | |||
464 | error = pdata->cs_en(pdata->cs_pin); | 481 | error = pdata->cs_en(pdata->cs_pin); |
465 | if (error < 0) { | 482 | if (error < 0) { |
466 | dev_err(&client->dev, "chip init failed\n"); | 483 | dev_err(&client->dev, "chip init failed\n"); |
467 | goto err_free_mem; | 484 | goto err_disable_regulator; |
468 | } | 485 | } |
469 | } | 486 | } |
470 | 487 | ||
@@ -485,9 +502,9 @@ static int __devinit bu21013_probe(struct i2c_client *client, | |||
485 | __set_bit(EV_ABS, in_dev->evbit); | 502 | __set_bit(EV_ABS, in_dev->evbit); |
486 | 503 | ||
487 | input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, | 504 | input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, |
488 | pdata->x_max_res, 0, 0); | 505 | pdata->touch_x_max, 0, 0); |
489 | input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, | 506 | input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, |
490 | pdata->y_max_res, 0, 0); | 507 | pdata->touch_y_max, 0, 0); |
491 | input_set_drvdata(in_dev, bu21013_data); | 508 | input_set_drvdata(in_dev, bu21013_data); |
492 | 509 | ||
493 | error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, | 510 | error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, |
@@ -513,6 +530,10 @@ err_free_irq: | |||
513 | bu21013_free_irq(bu21013_data); | 530 | bu21013_free_irq(bu21013_data); |
514 | err_cs_disable: | 531 | err_cs_disable: |
515 | pdata->cs_dis(pdata->cs_pin); | 532 | pdata->cs_dis(pdata->cs_pin); |
533 | err_disable_regulator: | ||
534 | regulator_disable(bu21013_data->regulator); | ||
535 | err_put_regulator: | ||
536 | regulator_put(bu21013_data->regulator); | ||
516 | err_free_mem: | 537 | err_free_mem: |
517 | input_free_device(in_dev); | 538 | input_free_device(in_dev); |
518 | kfree(bu21013_data); | 539 | kfree(bu21013_data); |
@@ -535,6 +556,10 @@ static int __devexit bu21013_remove(struct i2c_client *client) | |||
535 | bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); | 556 | bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); |
536 | 557 | ||
537 | input_unregister_device(bu21013_data->in_dev); | 558 | input_unregister_device(bu21013_data->in_dev); |
559 | |||
560 | regulator_disable(bu21013_data->regulator); | ||
561 | regulator_put(bu21013_data->regulator); | ||
562 | |||
538 | kfree(bu21013_data); | 563 | kfree(bu21013_data); |
539 | 564 | ||
540 | device_init_wakeup(&client->dev, false); | 565 | device_init_wakeup(&client->dev, false); |
@@ -561,6 +586,8 @@ static int bu21013_suspend(struct device *dev) | |||
561 | else | 586 | else |
562 | disable_irq(bu21013_data->chip->irq); | 587 | disable_irq(bu21013_data->chip->irq); |
563 | 588 | ||
589 | regulator_disable(bu21013_data->regulator); | ||
590 | |||
564 | return 0; | 591 | return 0; |
565 | } | 592 | } |
566 | 593 | ||
@@ -577,6 +604,12 @@ static int bu21013_resume(struct device *dev) | |||
577 | struct i2c_client *client = bu21013_data->client; | 604 | struct i2c_client *client = bu21013_data->client; |
578 | int retval; | 605 | int retval; |
579 | 606 | ||
607 | retval = regulator_enable(bu21013_data->regulator); | ||
608 | if (retval < 0) { | ||
609 | dev_err(&client->dev, "bu21013 regulator enable failed\n"); | ||
610 | return retval; | ||
611 | } | ||
612 | |||
580 | retval = bu21013_init_chip(bu21013_data); | 613 | retval = bu21013_init_chip(bu21013_data); |
581 | if (retval < 0) { | 614 | if (retval < 0) { |
582 | dev_err(&client->dev, "bu21013 controller config failed\n"); | 615 | dev_err(&client->dev, "bu21013 controller config failed\n"); |
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d0c3a7229adf..a93c5c26ab3f 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
@@ -280,8 +280,9 @@ err_free_mem: | |||
280 | } | 280 | } |
281 | 281 | ||
282 | #ifdef CONFIG_PM | 282 | #ifdef CONFIG_PM |
283 | static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg) | 283 | static int cy8ctmg110_suspend(struct device *dev) |
284 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
285 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 286 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
286 | 287 | ||
287 | if (device_may_wakeup(&client->dev)) | 288 | if (device_may_wakeup(&client->dev)) |
@@ -293,8 +294,9 @@ static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg) | |||
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
295 | 296 | ||
296 | static int cy8ctmg110_resume(struct i2c_client *client) | 297 | static int cy8ctmg110_resume(struct device *dev) |
297 | { | 298 | { |
299 | struct i2c_client *client = to_i2c_client(dev); | ||
298 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 300 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
299 | 301 | ||
300 | if (device_may_wakeup(&client->dev)) | 302 | if (device_may_wakeup(&client->dev)) |
@@ -305,6 +307,8 @@ static int cy8ctmg110_resume(struct i2c_client *client) | |||
305 | } | 307 | } |
306 | return 0; | 308 | return 0; |
307 | } | 309 | } |
310 | |||
311 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); | ||
308 | #endif | 312 | #endif |
309 | 313 | ||
310 | static int __devexit cy8ctmg110_remove(struct i2c_client *client) | 314 | static int __devexit cy8ctmg110_remove(struct i2c_client *client) |
@@ -335,14 +339,13 @@ static struct i2c_driver cy8ctmg110_driver = { | |||
335 | .driver = { | 339 | .driver = { |
336 | .owner = THIS_MODULE, | 340 | .owner = THIS_MODULE, |
337 | .name = CY8CTMG110_DRIVER_NAME, | 341 | .name = CY8CTMG110_DRIVER_NAME, |
342 | #ifdef CONFIG_PM | ||
343 | .pm = &cy8ctmg110_pm, | ||
344 | #endif | ||
338 | }, | 345 | }, |
339 | .id_table = cy8ctmg110_idtable, | 346 | .id_table = cy8ctmg110_idtable, |
340 | .probe = cy8ctmg110_probe, | 347 | .probe = cy8ctmg110_probe, |
341 | .remove = __devexit_p(cy8ctmg110_remove), | 348 | .remove = __devexit_p(cy8ctmg110_remove), |
342 | #ifdef CONFIG_PM | ||
343 | .suspend = cy8ctmg110_suspend, | ||
344 | .resume = cy8ctmg110_resume, | ||
345 | #endif | ||
346 | }; | 349 | }; |
347 | 350 | ||
348 | static int __init cy8ctmg110_init(void) | 351 | static int __init cy8ctmg110_init(void) |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 7a3a916f84a8..7f8f538a9806 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -261,8 +261,9 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | #ifdef CONFIG_PM | 263 | #ifdef CONFIG_PM |
264 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 264 | static int eeti_ts_suspend(struct device *dev) |
265 | { | 265 | { |
266 | struct i2c_client *client = to_i2c_client(dev); | ||
266 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 267 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
267 | struct input_dev *input_dev = priv->input; | 268 | struct input_dev *input_dev = priv->input; |
268 | 269 | ||
@@ -279,8 +280,9 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
281 | 282 | ||
282 | static int eeti_ts_resume(struct i2c_client *client) | 283 | static int eeti_ts_resume(struct device *dev) |
283 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
284 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 286 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
285 | struct input_dev *input_dev = priv->input; | 287 | struct input_dev *input_dev = priv->input; |
286 | 288 | ||
@@ -296,9 +298,8 @@ static int eeti_ts_resume(struct i2c_client *client) | |||
296 | 298 | ||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
299 | #else | 301 | |
300 | #define eeti_ts_suspend NULL | 302 | static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); |
301 | #define eeti_ts_resume NULL | ||
302 | #endif | 303 | #endif |
303 | 304 | ||
304 | static const struct i2c_device_id eeti_ts_id[] = { | 305 | static const struct i2c_device_id eeti_ts_id[] = { |
@@ -310,11 +311,12 @@ MODULE_DEVICE_TABLE(i2c, eeti_ts_id); | |||
310 | static struct i2c_driver eeti_ts_driver = { | 311 | static struct i2c_driver eeti_ts_driver = { |
311 | .driver = { | 312 | .driver = { |
312 | .name = "eeti_ts", | 313 | .name = "eeti_ts", |
314 | #ifdef CONFIG_PM | ||
315 | .pm = &eeti_ts_pm, | ||
316 | #endif | ||
313 | }, | 317 | }, |
314 | .probe = eeti_ts_probe, | 318 | .probe = eeti_ts_probe, |
315 | .remove = __devexit_p(eeti_ts_remove), | 319 | .remove = __devexit_p(eeti_ts_remove), |
316 | .suspend = eeti_ts_suspend, | ||
317 | .resume = eeti_ts_resume, | ||
318 | .id_table = eeti_ts_id, | 320 | .id_table = eeti_ts_id, |
319 | }; | 321 | }; |
320 | 322 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index b4d7f63deff1..45f93d0f5592 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); | |||
62 | Programmer has no control over these numbers. | 62 | Programmer has no control over these numbers. |
63 | TODO there are holes - specifically 1,7,0x0a | 63 | TODO there are holes - specifically 1,7,0x0a |
64 | */ | 64 | */ |
65 | #define VERSION_ID 0 /* Get Version (request/respose) */ | 65 | #define VERSION_ID 0 /* Get Version (request/response) */ |
66 | #define KEYBD_ID 2 /* Keyboard (event) */ | 66 | #define KEYBD_ID 2 /* Keyboard (event) */ |
67 | #define TOUCHS_ID 3 /* Touch Screen (event)*/ | 67 | #define TOUCHS_ID 3 /* Touch Screen (event)*/ |
68 | #define EEPROM_READ_ID 4 /* (request/response) */ | 68 | #define EEPROM_READ_ID 4 /* (request/response) */ |
@@ -399,31 +399,34 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
399 | IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { | 399 | IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { |
400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
401 | err = -EBUSY; | 401 | err = -EBUSY; |
402 | goto fail2; | 402 | goto fail1; |
403 | } | 403 | } |
404 | 404 | ||
405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
406 | IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { | 406 | IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { |
407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); | 407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); |
408 | err = -EBUSY; | 408 | err = -EBUSY; |
409 | goto fail3; | 409 | goto fail2; |
410 | } | 410 | } |
411 | 411 | ||
412 | serio_set_drvdata(serio, ts); | 412 | serio_set_drvdata(serio, ts); |
413 | 413 | ||
414 | err = serio_open(serio, drv); | 414 | err = serio_open(serio, drv); |
415 | if (err) | 415 | if (err) |
416 | return err; | 416 | goto fail3; |
417 | 417 | ||
418 | //h3600_flite_control(1, 25); /* default brightness */ | 418 | //h3600_flite_control(1, 25); /* default brightness */ |
419 | input_register_device(ts->dev); | 419 | err = input_register_device(ts->dev); |
420 | if (err) | ||
421 | goto fail4; | ||
420 | 422 | ||
421 | return 0; | 423 | return 0; |
422 | 424 | ||
423 | fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); | 425 | fail4: serio_close(serio); |
426 | fail3: serio_set_drvdata(serio, NULL); | ||
427 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); | ||
424 | fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); | 428 | fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); |
425 | fail1: serio_set_drvdata(serio, NULL); | 429 | fail1: input_free_device(input_dev); |
426 | input_free_device(input_dev); | ||
427 | kfree(ts); | 430 | kfree(ts); |
428 | return err; | 431 | return err; |
429 | } | 432 | } |
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index c0307b22d86f..66c96bfc5522 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c | |||
@@ -542,7 +542,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev) | |||
542 | * ADC power on, start, enable PENDET and set loop delay | 542 | * ADC power on, start, enable PENDET and set loop delay |
543 | * ADC loop delay is set to 4.5 ms approximately | 543 | * ADC loop delay is set to 4.5 ms approximately |
544 | * Loop delay more than this results in jitter in adc readings | 544 | * Loop delay more than this results in jitter in adc readings |
545 | * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET | 545 | * Setting loop delay to 0 (continuous loop) in MAXIM stops PENDET |
546 | * interrupt generation sometimes. | 546 | * interrupt generation sometimes. |
547 | */ | 547 | */ |
548 | 548 | ||
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index b6b8b1c7ecea..3242e7076258 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -219,7 +219,7 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
219 | } | 219 | } |
220 | 220 | ||
221 | wm->pen_irq = gpio_to_irq(irq); | 221 | wm->pen_irq = gpio_to_irq(irq); |
222 | set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | 222 | irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); |
223 | } else /* pen irq not supported */ | 223 | } else /* pen irq not supported */ |
224 | pen_int = 0; | 224 | pen_int = 0; |
225 | 225 | ||
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 6ee9940aaf5b..2d84c80ceb66 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -261,25 +261,27 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | #ifdef CONFIG_PM | 263 | #ifdef CONFIG_PM |
264 | static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 264 | static int mcs5000_ts_suspend(struct device *dev) |
265 | { | 265 | { |
266 | struct i2c_client *client = to_i2c_client(dev); | ||
267 | |||
266 | /* Touch sleep mode */ | 268 | /* Touch sleep mode */ |
267 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); | 269 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); |
268 | 270 | ||
269 | return 0; | 271 | return 0; |
270 | } | 272 | } |
271 | 273 | ||
272 | static int mcs5000_ts_resume(struct i2c_client *client) | 274 | static int mcs5000_ts_resume(struct device *dev) |
273 | { | 275 | { |
276 | struct i2c_client *client = to_i2c_client(dev); | ||
274 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | 277 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); |
275 | 278 | ||
276 | mcs5000_ts_phys_init(data); | 279 | mcs5000_ts_phys_init(data); |
277 | 280 | ||
278 | return 0; | 281 | return 0; |
279 | } | 282 | } |
280 | #else | 283 | |
281 | #define mcs5000_ts_suspend NULL | 284 | static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume); |
282 | #define mcs5000_ts_resume NULL | ||
283 | #endif | 285 | #endif |
284 | 286 | ||
285 | static const struct i2c_device_id mcs5000_ts_id[] = { | 287 | static const struct i2c_device_id mcs5000_ts_id[] = { |
@@ -291,10 +293,11 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); | |||
291 | static struct i2c_driver mcs5000_ts_driver = { | 293 | static struct i2c_driver mcs5000_ts_driver = { |
292 | .probe = mcs5000_ts_probe, | 294 | .probe = mcs5000_ts_probe, |
293 | .remove = __devexit_p(mcs5000_ts_remove), | 295 | .remove = __devexit_p(mcs5000_ts_remove), |
294 | .suspend = mcs5000_ts_suspend, | ||
295 | .resume = mcs5000_ts_resume, | ||
296 | .driver = { | 296 | .driver = { |
297 | .name = "mcs5000_ts", | 297 | .name = "mcs5000_ts", |
298 | #ifdef CONFIG_PM | ||
299 | .pm = &mcs5000_ts_pm, | ||
300 | #endif | ||
298 | }, | 301 | }, |
299 | .id_table = mcs5000_ts_id, | 302 | .id_table = mcs5000_ts_id, |
300 | }; | 303 | }; |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index defe5dd3627c..5803bd0c1cca 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/pm.h> | ||
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
28 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
@@ -226,8 +227,9 @@ static int migor_ts_remove(struct i2c_client *client) | |||
226 | return 0; | 227 | return 0; |
227 | } | 228 | } |
228 | 229 | ||
229 | static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 230 | static int migor_ts_suspend(struct device *dev) |
230 | { | 231 | { |
232 | struct i2c_client *client = to_i2c_client(dev); | ||
231 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); | 233 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
232 | 234 | ||
233 | if (device_may_wakeup(&client->dev)) | 235 | if (device_may_wakeup(&client->dev)) |
@@ -236,8 +238,9 @@ static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
236 | return 0; | 238 | return 0; |
237 | } | 239 | } |
238 | 240 | ||
239 | static int migor_ts_resume(struct i2c_client *client) | 241 | static int migor_ts_resume(struct device *dev) |
240 | { | 242 | { |
243 | struct i2c_client *client = to_i2c_client(dev); | ||
241 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); | 244 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
242 | 245 | ||
243 | if (device_may_wakeup(&client->dev)) | 246 | if (device_may_wakeup(&client->dev)) |
@@ -246,6 +249,8 @@ static int migor_ts_resume(struct i2c_client *client) | |||
246 | return 0; | 249 | return 0; |
247 | } | 250 | } |
248 | 251 | ||
252 | static SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume); | ||
253 | |||
249 | static const struct i2c_device_id migor_ts_id[] = { | 254 | static const struct i2c_device_id migor_ts_id[] = { |
250 | { "migor_ts", 0 }, | 255 | { "migor_ts", 0 }, |
251 | { } | 256 | { } |
@@ -255,11 +260,10 @@ MODULE_DEVICE_TABLE(i2c, migor_ts); | |||
255 | static struct i2c_driver migor_ts_driver = { | 260 | static struct i2c_driver migor_ts_driver = { |
256 | .driver = { | 261 | .driver = { |
257 | .name = "migor_ts", | 262 | .name = "migor_ts", |
263 | .pm = &migor_ts_pm, | ||
258 | }, | 264 | }, |
259 | .probe = migor_ts_probe, | 265 | .probe = migor_ts_probe, |
260 | .remove = migor_ts_remove, | 266 | .remove = migor_ts_remove, |
261 | .suspend = migor_ts_suspend, | ||
262 | .resume = migor_ts_resume, | ||
263 | .id_table = migor_ts_id, | 267 | .id_table = migor_ts_id, |
264 | }; | 268 | }; |
265 | 269 | ||
diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/qt602240_ts.c deleted file mode 100644 index 66b26ad3032a..000000000000 --- a/drivers/input/touchscreen/qt602240_ts.c +++ /dev/null | |||
@@ -1,1401 +0,0 @@ | |||
1 | /* | ||
2 | * AT42QT602240/ATMXT224 Touchscreen driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
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 as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/firmware.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/i2c/qt602240_ts.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | /* Version */ | ||
25 | #define QT602240_VER_20 20 | ||
26 | #define QT602240_VER_21 21 | ||
27 | #define QT602240_VER_22 22 | ||
28 | |||
29 | /* Slave addresses */ | ||
30 | #define QT602240_APP_LOW 0x4a | ||
31 | #define QT602240_APP_HIGH 0x4b | ||
32 | #define QT602240_BOOT_LOW 0x24 | ||
33 | #define QT602240_BOOT_HIGH 0x25 | ||
34 | |||
35 | /* Firmware */ | ||
36 | #define QT602240_FW_NAME "qt602240.fw" | ||
37 | |||
38 | /* Registers */ | ||
39 | #define QT602240_FAMILY_ID 0x00 | ||
40 | #define QT602240_VARIANT_ID 0x01 | ||
41 | #define QT602240_VERSION 0x02 | ||
42 | #define QT602240_BUILD 0x03 | ||
43 | #define QT602240_MATRIX_X_SIZE 0x04 | ||
44 | #define QT602240_MATRIX_Y_SIZE 0x05 | ||
45 | #define QT602240_OBJECT_NUM 0x06 | ||
46 | #define QT602240_OBJECT_START 0x07 | ||
47 | |||
48 | #define QT602240_OBJECT_SIZE 6 | ||
49 | |||
50 | /* Object types */ | ||
51 | #define QT602240_DEBUG_DIAGNOSTIC 37 | ||
52 | #define QT602240_GEN_MESSAGE 5 | ||
53 | #define QT602240_GEN_COMMAND 6 | ||
54 | #define QT602240_GEN_POWER 7 | ||
55 | #define QT602240_GEN_ACQUIRE 8 | ||
56 | #define QT602240_TOUCH_MULTI 9 | ||
57 | #define QT602240_TOUCH_KEYARRAY 15 | ||
58 | #define QT602240_TOUCH_PROXIMITY 23 | ||
59 | #define QT602240_PROCI_GRIPFACE 20 | ||
60 | #define QT602240_PROCG_NOISE 22 | ||
61 | #define QT602240_PROCI_ONETOUCH 24 | ||
62 | #define QT602240_PROCI_TWOTOUCH 27 | ||
63 | #define QT602240_SPT_COMMSCONFIG 18 /* firmware ver 21 over */ | ||
64 | #define QT602240_SPT_GPIOPWM 19 | ||
65 | #define QT602240_SPT_SELFTEST 25 | ||
66 | #define QT602240_SPT_CTECONFIG 28 | ||
67 | #define QT602240_SPT_USERDATA 38 /* firmware ver 21 over */ | ||
68 | |||
69 | /* QT602240_GEN_COMMAND field */ | ||
70 | #define QT602240_COMMAND_RESET 0 | ||
71 | #define QT602240_COMMAND_BACKUPNV 1 | ||
72 | #define QT602240_COMMAND_CALIBRATE 2 | ||
73 | #define QT602240_COMMAND_REPORTALL 3 | ||
74 | #define QT602240_COMMAND_DIAGNOSTIC 5 | ||
75 | |||
76 | /* QT602240_GEN_POWER field */ | ||
77 | #define QT602240_POWER_IDLEACQINT 0 | ||
78 | #define QT602240_POWER_ACTVACQINT 1 | ||
79 | #define QT602240_POWER_ACTV2IDLETO 2 | ||
80 | |||
81 | /* QT602240_GEN_ACQUIRE field */ | ||
82 | #define QT602240_ACQUIRE_CHRGTIME 0 | ||
83 | #define QT602240_ACQUIRE_TCHDRIFT 2 | ||
84 | #define QT602240_ACQUIRE_DRIFTST 3 | ||
85 | #define QT602240_ACQUIRE_TCHAUTOCAL 4 | ||
86 | #define QT602240_ACQUIRE_SYNC 5 | ||
87 | #define QT602240_ACQUIRE_ATCHCALST 6 | ||
88 | #define QT602240_ACQUIRE_ATCHCALSTHR 7 | ||
89 | |||
90 | /* QT602240_TOUCH_MULTI field */ | ||
91 | #define QT602240_TOUCH_CTRL 0 | ||
92 | #define QT602240_TOUCH_XORIGIN 1 | ||
93 | #define QT602240_TOUCH_YORIGIN 2 | ||
94 | #define QT602240_TOUCH_XSIZE 3 | ||
95 | #define QT602240_TOUCH_YSIZE 4 | ||
96 | #define QT602240_TOUCH_BLEN 6 | ||
97 | #define QT602240_TOUCH_TCHTHR 7 | ||
98 | #define QT602240_TOUCH_TCHDI 8 | ||
99 | #define QT602240_TOUCH_ORIENT 9 | ||
100 | #define QT602240_TOUCH_MOVHYSTI 11 | ||
101 | #define QT602240_TOUCH_MOVHYSTN 12 | ||
102 | #define QT602240_TOUCH_NUMTOUCH 14 | ||
103 | #define QT602240_TOUCH_MRGHYST 15 | ||
104 | #define QT602240_TOUCH_MRGTHR 16 | ||
105 | #define QT602240_TOUCH_AMPHYST 17 | ||
106 | #define QT602240_TOUCH_XRANGE_LSB 18 | ||
107 | #define QT602240_TOUCH_XRANGE_MSB 19 | ||
108 | #define QT602240_TOUCH_YRANGE_LSB 20 | ||
109 | #define QT602240_TOUCH_YRANGE_MSB 21 | ||
110 | #define QT602240_TOUCH_XLOCLIP 22 | ||
111 | #define QT602240_TOUCH_XHICLIP 23 | ||
112 | #define QT602240_TOUCH_YLOCLIP 24 | ||
113 | #define QT602240_TOUCH_YHICLIP 25 | ||
114 | #define QT602240_TOUCH_XEDGECTRL 26 | ||
115 | #define QT602240_TOUCH_XEDGEDIST 27 | ||
116 | #define QT602240_TOUCH_YEDGECTRL 28 | ||
117 | #define QT602240_TOUCH_YEDGEDIST 29 | ||
118 | #define QT602240_TOUCH_JUMPLIMIT 30 /* firmware ver 22 over */ | ||
119 | |||
120 | /* QT602240_PROCI_GRIPFACE field */ | ||
121 | #define QT602240_GRIPFACE_CTRL 0 | ||
122 | #define QT602240_GRIPFACE_XLOGRIP 1 | ||
123 | #define QT602240_GRIPFACE_XHIGRIP 2 | ||
124 | #define QT602240_GRIPFACE_YLOGRIP 3 | ||
125 | #define QT602240_GRIPFACE_YHIGRIP 4 | ||
126 | #define QT602240_GRIPFACE_MAXTCHS 5 | ||
127 | #define QT602240_GRIPFACE_SZTHR1 7 | ||
128 | #define QT602240_GRIPFACE_SZTHR2 8 | ||
129 | #define QT602240_GRIPFACE_SHPTHR1 9 | ||
130 | #define QT602240_GRIPFACE_SHPTHR2 10 | ||
131 | #define QT602240_GRIPFACE_SUPEXTTO 11 | ||
132 | |||
133 | /* QT602240_PROCI_NOISE field */ | ||
134 | #define QT602240_NOISE_CTRL 0 | ||
135 | #define QT602240_NOISE_OUTFLEN 1 | ||
136 | #define QT602240_NOISE_GCAFUL_LSB 3 | ||
137 | #define QT602240_NOISE_GCAFUL_MSB 4 | ||
138 | #define QT602240_NOISE_GCAFLL_LSB 5 | ||
139 | #define QT602240_NOISE_GCAFLL_MSB 6 | ||
140 | #define QT602240_NOISE_ACTVGCAFVALID 7 | ||
141 | #define QT602240_NOISE_NOISETHR 8 | ||
142 | #define QT602240_NOISE_FREQHOPSCALE 10 | ||
143 | #define QT602240_NOISE_FREQ0 11 | ||
144 | #define QT602240_NOISE_FREQ1 12 | ||
145 | #define QT602240_NOISE_FREQ2 13 | ||
146 | #define QT602240_NOISE_FREQ3 14 | ||
147 | #define QT602240_NOISE_FREQ4 15 | ||
148 | #define QT602240_NOISE_IDLEGCAFVALID 16 | ||
149 | |||
150 | /* QT602240_SPT_COMMSCONFIG */ | ||
151 | #define QT602240_COMMS_CTRL 0 | ||
152 | #define QT602240_COMMS_CMD 1 | ||
153 | |||
154 | /* QT602240_SPT_CTECONFIG field */ | ||
155 | #define QT602240_CTE_CTRL 0 | ||
156 | #define QT602240_CTE_CMD 1 | ||
157 | #define QT602240_CTE_MODE 2 | ||
158 | #define QT602240_CTE_IDLEGCAFDEPTH 3 | ||
159 | #define QT602240_CTE_ACTVGCAFDEPTH 4 | ||
160 | #define QT602240_CTE_VOLTAGE 5 /* firmware ver 21 over */ | ||
161 | |||
162 | #define QT602240_VOLTAGE_DEFAULT 2700000 | ||
163 | #define QT602240_VOLTAGE_STEP 10000 | ||
164 | |||
165 | /* Define for QT602240_GEN_COMMAND */ | ||
166 | #define QT602240_BOOT_VALUE 0xa5 | ||
167 | #define QT602240_BACKUP_VALUE 0x55 | ||
168 | #define QT602240_BACKUP_TIME 25 /* msec */ | ||
169 | #define QT602240_RESET_TIME 65 /* msec */ | ||
170 | |||
171 | #define QT602240_FWRESET_TIME 175 /* msec */ | ||
172 | |||
173 | /* Command to unlock bootloader */ | ||
174 | #define QT602240_UNLOCK_CMD_MSB 0xaa | ||
175 | #define QT602240_UNLOCK_CMD_LSB 0xdc | ||
176 | |||
177 | /* Bootloader mode status */ | ||
178 | #define QT602240_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */ | ||
179 | #define QT602240_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */ | ||
180 | #define QT602240_FRAME_CRC_CHECK 0x02 | ||
181 | #define QT602240_FRAME_CRC_FAIL 0x03 | ||
182 | #define QT602240_FRAME_CRC_PASS 0x04 | ||
183 | #define QT602240_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ | ||
184 | #define QT602240_BOOT_STATUS_MASK 0x3f | ||
185 | |||
186 | /* Touch status */ | ||
187 | #define QT602240_SUPPRESS (1 << 1) | ||
188 | #define QT602240_AMP (1 << 2) | ||
189 | #define QT602240_VECTOR (1 << 3) | ||
190 | #define QT602240_MOVE (1 << 4) | ||
191 | #define QT602240_RELEASE (1 << 5) | ||
192 | #define QT602240_PRESS (1 << 6) | ||
193 | #define QT602240_DETECT (1 << 7) | ||
194 | |||
195 | /* Touchscreen absolute values */ | ||
196 | #define QT602240_MAX_XC 0x3ff | ||
197 | #define QT602240_MAX_YC 0x3ff | ||
198 | #define QT602240_MAX_AREA 0xff | ||
199 | |||
200 | #define QT602240_MAX_FINGER 10 | ||
201 | |||
202 | /* Initial register values recommended from chip vendor */ | ||
203 | static const u8 init_vals_ver_20[] = { | ||
204 | /* QT602240_GEN_COMMAND(6) */ | ||
205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
206 | /* QT602240_GEN_POWER(7) */ | ||
207 | 0x20, 0xff, 0x32, | ||
208 | /* QT602240_GEN_ACQUIRE(8) */ | ||
209 | 0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14, | ||
210 | /* QT602240_TOUCH_MULTI(9) */ | ||
211 | 0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, | ||
212 | 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, | ||
213 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64, | ||
214 | /* QT602240_TOUCH_KEYARRAY(15) */ | ||
215 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
216 | 0x00, | ||
217 | /* QT602240_SPT_GPIOPWM(19) */ | ||
218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
219 | 0x00, 0x00, | ||
220 | /* QT602240_PROCI_GRIPFACE(20) */ | ||
221 | 0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04, | ||
222 | 0x1e, 0x00, | ||
223 | /* QT602240_PROCG_NOISE(22) */ | ||
224 | 0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00, | ||
225 | 0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8, | ||
226 | /* QT602240_TOUCH_PROXIMITY(23) */ | ||
227 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
228 | 0x00, 0x00, 0x00, | ||
229 | /* QT602240_PROCI_ONETOUCH(24) */ | ||
230 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
231 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
232 | /* QT602240_SPT_SELFTEST(25) */ | ||
233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
234 | 0x00, 0x00, 0x00, 0x00, | ||
235 | /* QT602240_PROCI_TWOTOUCH(27) */ | ||
236 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
237 | /* QT602240_SPT_CTECONFIG(28) */ | ||
238 | 0x00, 0x00, 0x00, 0x04, 0x08, | ||
239 | }; | ||
240 | |||
241 | static const u8 init_vals_ver_21[] = { | ||
242 | /* QT602240_GEN_COMMAND(6) */ | ||
243 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
244 | /* QT602240_GEN_POWER(7) */ | ||
245 | 0x20, 0xff, 0x32, | ||
246 | /* QT602240_GEN_ACQUIRE(8) */ | ||
247 | 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, | ||
248 | /* QT602240_TOUCH_MULTI(9) */ | ||
249 | 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, | ||
250 | 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, | ||
251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
252 | /* QT602240_TOUCH_KEYARRAY(15) */ | ||
253 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
254 | 0x00, | ||
255 | /* QT602240_SPT_GPIOPWM(19) */ | ||
256 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
257 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
258 | /* QT602240_PROCI_GRIPFACE(20) */ | ||
259 | 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, | ||
260 | 0x0f, 0x0a, | ||
261 | /* QT602240_PROCG_NOISE(22) */ | ||
262 | 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, | ||
263 | 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, | ||
264 | /* QT602240_TOUCH_PROXIMITY(23) */ | ||
265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
266 | 0x00, 0x00, 0x00, | ||
267 | /* QT602240_PROCI_ONETOUCH(24) */ | ||
268 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
269 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
270 | /* QT602240_SPT_SELFTEST(25) */ | ||
271 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
272 | 0x00, 0x00, 0x00, 0x00, | ||
273 | /* QT602240_PROCI_TWOTOUCH(27) */ | ||
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
275 | /* QT602240_SPT_CTECONFIG(28) */ | ||
276 | 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, | ||
277 | }; | ||
278 | |||
279 | static const u8 init_vals_ver_22[] = { | ||
280 | /* QT602240_GEN_COMMAND(6) */ | ||
281 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
282 | /* QT602240_GEN_POWER(7) */ | ||
283 | 0x20, 0xff, 0x32, | ||
284 | /* QT602240_GEN_ACQUIRE(8) */ | ||
285 | 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, | ||
286 | /* QT602240_TOUCH_MULTI(9) */ | ||
287 | 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, | ||
288 | 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, | ||
289 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
290 | 0x00, | ||
291 | /* QT602240_TOUCH_KEYARRAY(15) */ | ||
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
293 | 0x00, | ||
294 | /* QT602240_SPT_GPIOPWM(19) */ | ||
295 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
296 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
297 | /* QT602240_PROCI_GRIPFACE(20) */ | ||
298 | 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, | ||
299 | 0x0f, 0x0a, | ||
300 | /* QT602240_PROCG_NOISE(22) */ | ||
301 | 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, | ||
302 | 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, | ||
303 | /* QT602240_TOUCH_PROXIMITY(23) */ | ||
304 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
305 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
306 | /* QT602240_PROCI_ONETOUCH(24) */ | ||
307 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
308 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
309 | /* QT602240_SPT_SELFTEST(25) */ | ||
310 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
311 | 0x00, 0x00, 0x00, 0x00, | ||
312 | /* QT602240_PROCI_TWOTOUCH(27) */ | ||
313 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
314 | /* QT602240_SPT_CTECONFIG(28) */ | ||
315 | 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, | ||
316 | }; | ||
317 | |||
318 | struct qt602240_info { | ||
319 | u8 family_id; | ||
320 | u8 variant_id; | ||
321 | u8 version; | ||
322 | u8 build; | ||
323 | u8 matrix_xsize; | ||
324 | u8 matrix_ysize; | ||
325 | u8 object_num; | ||
326 | }; | ||
327 | |||
328 | struct qt602240_object { | ||
329 | u8 type; | ||
330 | u16 start_address; | ||
331 | u8 size; | ||
332 | u8 instances; | ||
333 | u8 num_report_ids; | ||
334 | |||
335 | /* to map object and message */ | ||
336 | u8 max_reportid; | ||
337 | }; | ||
338 | |||
339 | struct qt602240_message { | ||
340 | u8 reportid; | ||
341 | u8 message[7]; | ||
342 | u8 checksum; | ||
343 | }; | ||
344 | |||
345 | struct qt602240_finger { | ||
346 | int status; | ||
347 | int x; | ||
348 | int y; | ||
349 | int area; | ||
350 | }; | ||
351 | |||
352 | /* Each client has this additional data */ | ||
353 | struct qt602240_data { | ||
354 | struct i2c_client *client; | ||
355 | struct input_dev *input_dev; | ||
356 | const struct qt602240_platform_data *pdata; | ||
357 | struct qt602240_object *object_table; | ||
358 | struct qt602240_info info; | ||
359 | struct qt602240_finger finger[QT602240_MAX_FINGER]; | ||
360 | unsigned int irq; | ||
361 | }; | ||
362 | |||
363 | static bool qt602240_object_readable(unsigned int type) | ||
364 | { | ||
365 | switch (type) { | ||
366 | case QT602240_GEN_MESSAGE: | ||
367 | case QT602240_GEN_COMMAND: | ||
368 | case QT602240_GEN_POWER: | ||
369 | case QT602240_GEN_ACQUIRE: | ||
370 | case QT602240_TOUCH_MULTI: | ||
371 | case QT602240_TOUCH_KEYARRAY: | ||
372 | case QT602240_TOUCH_PROXIMITY: | ||
373 | case QT602240_PROCI_GRIPFACE: | ||
374 | case QT602240_PROCG_NOISE: | ||
375 | case QT602240_PROCI_ONETOUCH: | ||
376 | case QT602240_PROCI_TWOTOUCH: | ||
377 | case QT602240_SPT_COMMSCONFIG: | ||
378 | case QT602240_SPT_GPIOPWM: | ||
379 | case QT602240_SPT_SELFTEST: | ||
380 | case QT602240_SPT_CTECONFIG: | ||
381 | case QT602240_SPT_USERDATA: | ||
382 | return true; | ||
383 | default: | ||
384 | return false; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | static bool qt602240_object_writable(unsigned int type) | ||
389 | { | ||
390 | switch (type) { | ||
391 | case QT602240_GEN_COMMAND: | ||
392 | case QT602240_GEN_POWER: | ||
393 | case QT602240_GEN_ACQUIRE: | ||
394 | case QT602240_TOUCH_MULTI: | ||
395 | case QT602240_TOUCH_KEYARRAY: | ||
396 | case QT602240_TOUCH_PROXIMITY: | ||
397 | case QT602240_PROCI_GRIPFACE: | ||
398 | case QT602240_PROCG_NOISE: | ||
399 | case QT602240_PROCI_ONETOUCH: | ||
400 | case QT602240_PROCI_TWOTOUCH: | ||
401 | case QT602240_SPT_GPIOPWM: | ||
402 | case QT602240_SPT_SELFTEST: | ||
403 | case QT602240_SPT_CTECONFIG: | ||
404 | return true; | ||
405 | default: | ||
406 | return false; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | static void qt602240_dump_message(struct device *dev, | ||
411 | struct qt602240_message *message) | ||
412 | { | ||
413 | dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); | ||
414 | dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); | ||
415 | dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); | ||
416 | dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); | ||
417 | dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); | ||
418 | dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); | ||
419 | dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); | ||
420 | dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); | ||
421 | dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); | ||
422 | } | ||
423 | |||
424 | static int qt602240_check_bootloader(struct i2c_client *client, | ||
425 | unsigned int state) | ||
426 | { | ||
427 | u8 val; | ||
428 | |||
429 | recheck: | ||
430 | if (i2c_master_recv(client, &val, 1) != 1) { | ||
431 | dev_err(&client->dev, "%s: i2c recv failed\n", __func__); | ||
432 | return -EIO; | ||
433 | } | ||
434 | |||
435 | switch (state) { | ||
436 | case QT602240_WAITING_BOOTLOAD_CMD: | ||
437 | case QT602240_WAITING_FRAME_DATA: | ||
438 | val &= ~QT602240_BOOT_STATUS_MASK; | ||
439 | break; | ||
440 | case QT602240_FRAME_CRC_PASS: | ||
441 | if (val == QT602240_FRAME_CRC_CHECK) | ||
442 | goto recheck; | ||
443 | break; | ||
444 | default: | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | if (val != state) { | ||
449 | dev_err(&client->dev, "Unvalid bootloader mode state\n"); | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int qt602240_unlock_bootloader(struct i2c_client *client) | ||
457 | { | ||
458 | u8 buf[2]; | ||
459 | |||
460 | buf[0] = QT602240_UNLOCK_CMD_LSB; | ||
461 | buf[1] = QT602240_UNLOCK_CMD_MSB; | ||
462 | |||
463 | if (i2c_master_send(client, buf, 2) != 2) { | ||
464 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
465 | return -EIO; | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int qt602240_fw_write(struct i2c_client *client, | ||
472 | const u8 *data, unsigned int frame_size) | ||
473 | { | ||
474 | if (i2c_master_send(client, data, frame_size) != frame_size) { | ||
475 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
476 | return -EIO; | ||
477 | } | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int __qt602240_read_reg(struct i2c_client *client, | ||
483 | u16 reg, u16 len, void *val) | ||
484 | { | ||
485 | struct i2c_msg xfer[2]; | ||
486 | u8 buf[2]; | ||
487 | |||
488 | buf[0] = reg & 0xff; | ||
489 | buf[1] = (reg >> 8) & 0xff; | ||
490 | |||
491 | /* Write register */ | ||
492 | xfer[0].addr = client->addr; | ||
493 | xfer[0].flags = 0; | ||
494 | xfer[0].len = 2; | ||
495 | xfer[0].buf = buf; | ||
496 | |||
497 | /* Read data */ | ||
498 | xfer[1].addr = client->addr; | ||
499 | xfer[1].flags = I2C_M_RD; | ||
500 | xfer[1].len = len; | ||
501 | xfer[1].buf = val; | ||
502 | |||
503 | if (i2c_transfer(client->adapter, xfer, 2) != 2) { | ||
504 | dev_err(&client->dev, "%s: i2c transfer failed\n", __func__); | ||
505 | return -EIO; | ||
506 | } | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static int qt602240_read_reg(struct i2c_client *client, u16 reg, u8 *val) | ||
512 | { | ||
513 | return __qt602240_read_reg(client, reg, 1, val); | ||
514 | } | ||
515 | |||
516 | static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val) | ||
517 | { | ||
518 | u8 buf[3]; | ||
519 | |||
520 | buf[0] = reg & 0xff; | ||
521 | buf[1] = (reg >> 8) & 0xff; | ||
522 | buf[2] = val; | ||
523 | |||
524 | if (i2c_master_send(client, buf, 3) != 3) { | ||
525 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
526 | return -EIO; | ||
527 | } | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static int qt602240_read_object_table(struct i2c_client *client, | ||
533 | u16 reg, u8 *object_buf) | ||
534 | { | ||
535 | return __qt602240_read_reg(client, reg, QT602240_OBJECT_SIZE, | ||
536 | object_buf); | ||
537 | } | ||
538 | |||
539 | static struct qt602240_object * | ||
540 | qt602240_get_object(struct qt602240_data *data, u8 type) | ||
541 | { | ||
542 | struct qt602240_object *object; | ||
543 | int i; | ||
544 | |||
545 | for (i = 0; i < data->info.object_num; i++) { | ||
546 | object = data->object_table + i; | ||
547 | if (object->type == type) | ||
548 | return object; | ||
549 | } | ||
550 | |||
551 | dev_err(&data->client->dev, "Invalid object type\n"); | ||
552 | return NULL; | ||
553 | } | ||
554 | |||
555 | static int qt602240_read_message(struct qt602240_data *data, | ||
556 | struct qt602240_message *message) | ||
557 | { | ||
558 | struct qt602240_object *object; | ||
559 | u16 reg; | ||
560 | |||
561 | object = qt602240_get_object(data, QT602240_GEN_MESSAGE); | ||
562 | if (!object) | ||
563 | return -EINVAL; | ||
564 | |||
565 | reg = object->start_address; | ||
566 | return __qt602240_read_reg(data->client, reg, | ||
567 | sizeof(struct qt602240_message), message); | ||
568 | } | ||
569 | |||
570 | static int qt602240_read_object(struct qt602240_data *data, | ||
571 | u8 type, u8 offset, u8 *val) | ||
572 | { | ||
573 | struct qt602240_object *object; | ||
574 | u16 reg; | ||
575 | |||
576 | object = qt602240_get_object(data, type); | ||
577 | if (!object) | ||
578 | return -EINVAL; | ||
579 | |||
580 | reg = object->start_address; | ||
581 | return __qt602240_read_reg(data->client, reg + offset, 1, val); | ||
582 | } | ||
583 | |||
584 | static int qt602240_write_object(struct qt602240_data *data, | ||
585 | u8 type, u8 offset, u8 val) | ||
586 | { | ||
587 | struct qt602240_object *object; | ||
588 | u16 reg; | ||
589 | |||
590 | object = qt602240_get_object(data, type); | ||
591 | if (!object) | ||
592 | return -EINVAL; | ||
593 | |||
594 | reg = object->start_address; | ||
595 | return qt602240_write_reg(data->client, reg + offset, val); | ||
596 | } | ||
597 | |||
598 | static void qt602240_input_report(struct qt602240_data *data, int single_id) | ||
599 | { | ||
600 | struct qt602240_finger *finger = data->finger; | ||
601 | struct input_dev *input_dev = data->input_dev; | ||
602 | int status = finger[single_id].status; | ||
603 | int finger_num = 0; | ||
604 | int id; | ||
605 | |||
606 | for (id = 0; id < QT602240_MAX_FINGER; id++) { | ||
607 | if (!finger[id].status) | ||
608 | continue; | ||
609 | |||
610 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, | ||
611 | finger[id].status != QT602240_RELEASE ? | ||
612 | finger[id].area : 0); | ||
613 | input_report_abs(input_dev, ABS_MT_POSITION_X, | ||
614 | finger[id].x); | ||
615 | input_report_abs(input_dev, ABS_MT_POSITION_Y, | ||
616 | finger[id].y); | ||
617 | input_mt_sync(input_dev); | ||
618 | |||
619 | if (finger[id].status == QT602240_RELEASE) | ||
620 | finger[id].status = 0; | ||
621 | else | ||
622 | finger_num++; | ||
623 | } | ||
624 | |||
625 | input_report_key(input_dev, BTN_TOUCH, finger_num > 0); | ||
626 | |||
627 | if (status != QT602240_RELEASE) { | ||
628 | input_report_abs(input_dev, ABS_X, finger[single_id].x); | ||
629 | input_report_abs(input_dev, ABS_Y, finger[single_id].y); | ||
630 | } | ||
631 | |||
632 | input_sync(input_dev); | ||
633 | } | ||
634 | |||
635 | static void qt602240_input_touchevent(struct qt602240_data *data, | ||
636 | struct qt602240_message *message, int id) | ||
637 | { | ||
638 | struct qt602240_finger *finger = data->finger; | ||
639 | struct device *dev = &data->client->dev; | ||
640 | u8 status = message->message[0]; | ||
641 | int x; | ||
642 | int y; | ||
643 | int area; | ||
644 | |||
645 | /* Check the touch is present on the screen */ | ||
646 | if (!(status & QT602240_DETECT)) { | ||
647 | if (status & QT602240_RELEASE) { | ||
648 | dev_dbg(dev, "[%d] released\n", id); | ||
649 | |||
650 | finger[id].status = QT602240_RELEASE; | ||
651 | qt602240_input_report(data, id); | ||
652 | } | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | /* Check only AMP detection */ | ||
657 | if (!(status & (QT602240_PRESS | QT602240_MOVE))) | ||
658 | return; | ||
659 | |||
660 | x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6); | ||
661 | y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2); | ||
662 | area = message->message[4]; | ||
663 | |||
664 | dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id, | ||
665 | status & QT602240_MOVE ? "moved" : "pressed", | ||
666 | x, y, area); | ||
667 | |||
668 | finger[id].status = status & QT602240_MOVE ? | ||
669 | QT602240_MOVE : QT602240_PRESS; | ||
670 | finger[id].x = x; | ||
671 | finger[id].y = y; | ||
672 | finger[id].area = area; | ||
673 | |||
674 | qt602240_input_report(data, id); | ||
675 | } | ||
676 | |||
677 | static irqreturn_t qt602240_interrupt(int irq, void *dev_id) | ||
678 | { | ||
679 | struct qt602240_data *data = dev_id; | ||
680 | struct qt602240_message message; | ||
681 | struct qt602240_object *object; | ||
682 | struct device *dev = &data->client->dev; | ||
683 | int id; | ||
684 | u8 reportid; | ||
685 | u8 max_reportid; | ||
686 | u8 min_reportid; | ||
687 | |||
688 | do { | ||
689 | if (qt602240_read_message(data, &message)) { | ||
690 | dev_err(dev, "Failed to read message\n"); | ||
691 | goto end; | ||
692 | } | ||
693 | |||
694 | reportid = message.reportid; | ||
695 | |||
696 | /* whether reportid is thing of QT602240_TOUCH_MULTI */ | ||
697 | object = qt602240_get_object(data, QT602240_TOUCH_MULTI); | ||
698 | if (!object) | ||
699 | goto end; | ||
700 | |||
701 | max_reportid = object->max_reportid; | ||
702 | min_reportid = max_reportid - object->num_report_ids + 1; | ||
703 | id = reportid - min_reportid; | ||
704 | |||
705 | if (reportid >= min_reportid && reportid <= max_reportid) | ||
706 | qt602240_input_touchevent(data, &message, id); | ||
707 | else | ||
708 | qt602240_dump_message(dev, &message); | ||
709 | } while (reportid != 0xff); | ||
710 | |||
711 | end: | ||
712 | return IRQ_HANDLED; | ||
713 | } | ||
714 | |||
715 | static int qt602240_check_reg_init(struct qt602240_data *data) | ||
716 | { | ||
717 | struct qt602240_object *object; | ||
718 | struct device *dev = &data->client->dev; | ||
719 | int index = 0; | ||
720 | int i, j; | ||
721 | u8 version = data->info.version; | ||
722 | u8 *init_vals; | ||
723 | |||
724 | switch (version) { | ||
725 | case QT602240_VER_20: | ||
726 | init_vals = (u8 *)init_vals_ver_20; | ||
727 | break; | ||
728 | case QT602240_VER_21: | ||
729 | init_vals = (u8 *)init_vals_ver_21; | ||
730 | break; | ||
731 | case QT602240_VER_22: | ||
732 | init_vals = (u8 *)init_vals_ver_22; | ||
733 | break; | ||
734 | default: | ||
735 | dev_err(dev, "Firmware version %d doesn't support\n", version); | ||
736 | return -EINVAL; | ||
737 | } | ||
738 | |||
739 | for (i = 0; i < data->info.object_num; i++) { | ||
740 | object = data->object_table + i; | ||
741 | |||
742 | if (!qt602240_object_writable(object->type)) | ||
743 | continue; | ||
744 | |||
745 | for (j = 0; j < object->size + 1; j++) | ||
746 | qt602240_write_object(data, object->type, j, | ||
747 | init_vals[index + j]); | ||
748 | |||
749 | index += object->size + 1; | ||
750 | } | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int qt602240_check_matrix_size(struct qt602240_data *data) | ||
756 | { | ||
757 | const struct qt602240_platform_data *pdata = data->pdata; | ||
758 | struct device *dev = &data->client->dev; | ||
759 | int mode = -1; | ||
760 | int error; | ||
761 | u8 val; | ||
762 | |||
763 | dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line); | ||
764 | dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line); | ||
765 | |||
766 | switch (pdata->x_line) { | ||
767 | case 0 ... 15: | ||
768 | if (pdata->y_line <= 14) | ||
769 | mode = 0; | ||
770 | break; | ||
771 | case 16: | ||
772 | if (pdata->y_line <= 12) | ||
773 | mode = 1; | ||
774 | if (pdata->y_line == 13 || pdata->y_line == 14) | ||
775 | mode = 0; | ||
776 | break; | ||
777 | case 17: | ||
778 | if (pdata->y_line <= 11) | ||
779 | mode = 2; | ||
780 | if (pdata->y_line == 12 || pdata->y_line == 13) | ||
781 | mode = 1; | ||
782 | break; | ||
783 | case 18: | ||
784 | if (pdata->y_line <= 10) | ||
785 | mode = 3; | ||
786 | if (pdata->y_line == 11 || pdata->y_line == 12) | ||
787 | mode = 2; | ||
788 | break; | ||
789 | case 19: | ||
790 | if (pdata->y_line <= 9) | ||
791 | mode = 4; | ||
792 | if (pdata->y_line == 10 || pdata->y_line == 11) | ||
793 | mode = 3; | ||
794 | break; | ||
795 | case 20: | ||
796 | mode = 4; | ||
797 | } | ||
798 | |||
799 | if (mode < 0) { | ||
800 | dev_err(dev, "Invalid X/Y lines\n"); | ||
801 | return -EINVAL; | ||
802 | } | ||
803 | |||
804 | error = qt602240_read_object(data, QT602240_SPT_CTECONFIG, | ||
805 | QT602240_CTE_MODE, &val); | ||
806 | if (error) | ||
807 | return error; | ||
808 | |||
809 | if (mode == val) | ||
810 | return 0; | ||
811 | |||
812 | /* Change the CTE configuration */ | ||
813 | qt602240_write_object(data, QT602240_SPT_CTECONFIG, | ||
814 | QT602240_CTE_CTRL, 1); | ||
815 | qt602240_write_object(data, QT602240_SPT_CTECONFIG, | ||
816 | QT602240_CTE_MODE, mode); | ||
817 | qt602240_write_object(data, QT602240_SPT_CTECONFIG, | ||
818 | QT602240_CTE_CTRL, 0); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static int qt602240_make_highchg(struct qt602240_data *data) | ||
824 | { | ||
825 | struct device *dev = &data->client->dev; | ||
826 | int count = 10; | ||
827 | int error; | ||
828 | u8 val; | ||
829 | |||
830 | /* Read dummy message to make high CHG pin */ | ||
831 | do { | ||
832 | error = qt602240_read_object(data, QT602240_GEN_MESSAGE, 0, &val); | ||
833 | if (error) | ||
834 | return error; | ||
835 | } while ((val != 0xff) && --count); | ||
836 | |||
837 | if (!count) { | ||
838 | dev_err(dev, "CHG pin isn't cleared\n"); | ||
839 | return -EBUSY; | ||
840 | } | ||
841 | |||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static void qt602240_handle_pdata(struct qt602240_data *data) | ||
846 | { | ||
847 | const struct qt602240_platform_data *pdata = data->pdata; | ||
848 | u8 voltage; | ||
849 | |||
850 | /* Set touchscreen lines */ | ||
851 | qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_XSIZE, | ||
852 | pdata->x_line); | ||
853 | qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_YSIZE, | ||
854 | pdata->y_line); | ||
855 | |||
856 | /* Set touchscreen orient */ | ||
857 | qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_ORIENT, | ||
858 | pdata->orient); | ||
859 | |||
860 | /* Set touchscreen burst length */ | ||
861 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
862 | QT602240_TOUCH_BLEN, pdata->blen); | ||
863 | |||
864 | /* Set touchscreen threshold */ | ||
865 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
866 | QT602240_TOUCH_TCHTHR, pdata->threshold); | ||
867 | |||
868 | /* Set touchscreen resolution */ | ||
869 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
870 | QT602240_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); | ||
871 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
872 | QT602240_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); | ||
873 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
874 | QT602240_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); | ||
875 | qt602240_write_object(data, QT602240_TOUCH_MULTI, | ||
876 | QT602240_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); | ||
877 | |||
878 | /* Set touchscreen voltage */ | ||
879 | if (data->info.version >= QT602240_VER_21 && pdata->voltage) { | ||
880 | if (pdata->voltage < QT602240_VOLTAGE_DEFAULT) { | ||
881 | voltage = (QT602240_VOLTAGE_DEFAULT - pdata->voltage) / | ||
882 | QT602240_VOLTAGE_STEP; | ||
883 | voltage = 0xff - voltage + 1; | ||
884 | } else | ||
885 | voltage = (pdata->voltage - QT602240_VOLTAGE_DEFAULT) / | ||
886 | QT602240_VOLTAGE_STEP; | ||
887 | |||
888 | qt602240_write_object(data, QT602240_SPT_CTECONFIG, | ||
889 | QT602240_CTE_VOLTAGE, voltage); | ||
890 | } | ||
891 | } | ||
892 | |||
893 | static int qt602240_get_info(struct qt602240_data *data) | ||
894 | { | ||
895 | struct i2c_client *client = data->client; | ||
896 | struct qt602240_info *info = &data->info; | ||
897 | int error; | ||
898 | u8 val; | ||
899 | |||
900 | error = qt602240_read_reg(client, QT602240_FAMILY_ID, &val); | ||
901 | if (error) | ||
902 | return error; | ||
903 | info->family_id = val; | ||
904 | |||
905 | error = qt602240_read_reg(client, QT602240_VARIANT_ID, &val); | ||
906 | if (error) | ||
907 | return error; | ||
908 | info->variant_id = val; | ||
909 | |||
910 | error = qt602240_read_reg(client, QT602240_VERSION, &val); | ||
911 | if (error) | ||
912 | return error; | ||
913 | info->version = val; | ||
914 | |||
915 | error = qt602240_read_reg(client, QT602240_BUILD, &val); | ||
916 | if (error) | ||
917 | return error; | ||
918 | info->build = val; | ||
919 | |||
920 | error = qt602240_read_reg(client, QT602240_OBJECT_NUM, &val); | ||
921 | if (error) | ||
922 | return error; | ||
923 | info->object_num = val; | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int qt602240_get_object_table(struct qt602240_data *data) | ||
929 | { | ||
930 | int error; | ||
931 | int i; | ||
932 | u16 reg; | ||
933 | u8 reportid = 0; | ||
934 | u8 buf[QT602240_OBJECT_SIZE]; | ||
935 | |||
936 | for (i = 0; i < data->info.object_num; i++) { | ||
937 | struct qt602240_object *object = data->object_table + i; | ||
938 | |||
939 | reg = QT602240_OBJECT_START + QT602240_OBJECT_SIZE * i; | ||
940 | error = qt602240_read_object_table(data->client, reg, buf); | ||
941 | if (error) | ||
942 | return error; | ||
943 | |||
944 | object->type = buf[0]; | ||
945 | object->start_address = (buf[2] << 8) | buf[1]; | ||
946 | object->size = buf[3]; | ||
947 | object->instances = buf[4]; | ||
948 | object->num_report_ids = buf[5]; | ||
949 | |||
950 | if (object->num_report_ids) { | ||
951 | reportid += object->num_report_ids * | ||
952 | (object->instances + 1); | ||
953 | object->max_reportid = reportid; | ||
954 | } | ||
955 | } | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static int qt602240_initialize(struct qt602240_data *data) | ||
961 | { | ||
962 | struct i2c_client *client = data->client; | ||
963 | struct qt602240_info *info = &data->info; | ||
964 | int error; | ||
965 | u8 val; | ||
966 | |||
967 | error = qt602240_get_info(data); | ||
968 | if (error) | ||
969 | return error; | ||
970 | |||
971 | data->object_table = kcalloc(info->object_num, | ||
972 | sizeof(struct qt602240_data), | ||
973 | GFP_KERNEL); | ||
974 | if (!data->object_table) { | ||
975 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
976 | return -ENOMEM; | ||
977 | } | ||
978 | |||
979 | /* Get object table information */ | ||
980 | error = qt602240_get_object_table(data); | ||
981 | if (error) | ||
982 | return error; | ||
983 | |||
984 | /* Check register init values */ | ||
985 | error = qt602240_check_reg_init(data); | ||
986 | if (error) | ||
987 | return error; | ||
988 | |||
989 | /* Check X/Y matrix size */ | ||
990 | error = qt602240_check_matrix_size(data); | ||
991 | if (error) | ||
992 | return error; | ||
993 | |||
994 | error = qt602240_make_highchg(data); | ||
995 | if (error) | ||
996 | return error; | ||
997 | |||
998 | qt602240_handle_pdata(data); | ||
999 | |||
1000 | /* Backup to memory */ | ||
1001 | qt602240_write_object(data, QT602240_GEN_COMMAND, | ||
1002 | QT602240_COMMAND_BACKUPNV, | ||
1003 | QT602240_BACKUP_VALUE); | ||
1004 | msleep(QT602240_BACKUP_TIME); | ||
1005 | |||
1006 | /* Soft reset */ | ||
1007 | qt602240_write_object(data, QT602240_GEN_COMMAND, | ||
1008 | QT602240_COMMAND_RESET, 1); | ||
1009 | msleep(QT602240_RESET_TIME); | ||
1010 | |||
1011 | /* Update matrix size at info struct */ | ||
1012 | error = qt602240_read_reg(client, QT602240_MATRIX_X_SIZE, &val); | ||
1013 | if (error) | ||
1014 | return error; | ||
1015 | info->matrix_xsize = val; | ||
1016 | |||
1017 | error = qt602240_read_reg(client, QT602240_MATRIX_Y_SIZE, &val); | ||
1018 | if (error) | ||
1019 | return error; | ||
1020 | info->matrix_ysize = val; | ||
1021 | |||
1022 | dev_info(&client->dev, | ||
1023 | "Family ID: %d Variant ID: %d Version: %d Build: %d\n", | ||
1024 | info->family_id, info->variant_id, info->version, | ||
1025 | info->build); | ||
1026 | |||
1027 | dev_info(&client->dev, | ||
1028 | "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n", | ||
1029 | info->matrix_xsize, info->matrix_ysize, | ||
1030 | info->object_num); | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static ssize_t qt602240_object_show(struct device *dev, | ||
1036 | struct device_attribute *attr, char *buf) | ||
1037 | { | ||
1038 | struct qt602240_data *data = dev_get_drvdata(dev); | ||
1039 | struct qt602240_object *object; | ||
1040 | int count = 0; | ||
1041 | int i, j; | ||
1042 | int error; | ||
1043 | u8 val; | ||
1044 | |||
1045 | for (i = 0; i < data->info.object_num; i++) { | ||
1046 | object = data->object_table + i; | ||
1047 | |||
1048 | count += sprintf(buf + count, | ||
1049 | "Object Table Element %d(Type %d)\n", | ||
1050 | i + 1, object->type); | ||
1051 | |||
1052 | if (!qt602240_object_readable(object->type)) { | ||
1053 | count += sprintf(buf + count, "\n"); | ||
1054 | continue; | ||
1055 | } | ||
1056 | |||
1057 | for (j = 0; j < object->size + 1; j++) { | ||
1058 | error = qt602240_read_object(data, | ||
1059 | object->type, j, &val); | ||
1060 | if (error) | ||
1061 | return error; | ||
1062 | |||
1063 | count += sprintf(buf + count, | ||
1064 | " Byte %d: 0x%x (%d)\n", j, val, val); | ||
1065 | } | ||
1066 | |||
1067 | count += sprintf(buf + count, "\n"); | ||
1068 | } | ||
1069 | |||
1070 | return count; | ||
1071 | } | ||
1072 | |||
1073 | static int qt602240_load_fw(struct device *dev, const char *fn) | ||
1074 | { | ||
1075 | struct qt602240_data *data = dev_get_drvdata(dev); | ||
1076 | struct i2c_client *client = data->client; | ||
1077 | const struct firmware *fw = NULL; | ||
1078 | unsigned int frame_size; | ||
1079 | unsigned int pos = 0; | ||
1080 | int ret; | ||
1081 | |||
1082 | ret = request_firmware(&fw, fn, dev); | ||
1083 | if (ret) { | ||
1084 | dev_err(dev, "Unable to open firmware %s\n", fn); | ||
1085 | return ret; | ||
1086 | } | ||
1087 | |||
1088 | /* Change to the bootloader mode */ | ||
1089 | qt602240_write_object(data, QT602240_GEN_COMMAND, | ||
1090 | QT602240_COMMAND_RESET, QT602240_BOOT_VALUE); | ||
1091 | msleep(QT602240_RESET_TIME); | ||
1092 | |||
1093 | /* Change to slave address of bootloader */ | ||
1094 | if (client->addr == QT602240_APP_LOW) | ||
1095 | client->addr = QT602240_BOOT_LOW; | ||
1096 | else | ||
1097 | client->addr = QT602240_BOOT_HIGH; | ||
1098 | |||
1099 | ret = qt602240_check_bootloader(client, QT602240_WAITING_BOOTLOAD_CMD); | ||
1100 | if (ret) | ||
1101 | goto out; | ||
1102 | |||
1103 | /* Unlock bootloader */ | ||
1104 | qt602240_unlock_bootloader(client); | ||
1105 | |||
1106 | while (pos < fw->size) { | ||
1107 | ret = qt602240_check_bootloader(client, | ||
1108 | QT602240_WAITING_FRAME_DATA); | ||
1109 | if (ret) | ||
1110 | goto out; | ||
1111 | |||
1112 | frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1)); | ||
1113 | |||
1114 | /* We should add 2 at frame size as the the firmware data is not | ||
1115 | * included the CRC bytes. | ||
1116 | */ | ||
1117 | frame_size += 2; | ||
1118 | |||
1119 | /* Write one frame to device */ | ||
1120 | qt602240_fw_write(client, fw->data + pos, frame_size); | ||
1121 | |||
1122 | ret = qt602240_check_bootloader(client, | ||
1123 | QT602240_FRAME_CRC_PASS); | ||
1124 | if (ret) | ||
1125 | goto out; | ||
1126 | |||
1127 | pos += frame_size; | ||
1128 | |||
1129 | dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size); | ||
1130 | } | ||
1131 | |||
1132 | out: | ||
1133 | release_firmware(fw); | ||
1134 | |||
1135 | /* Change to slave address of application */ | ||
1136 | if (client->addr == QT602240_BOOT_LOW) | ||
1137 | client->addr = QT602240_APP_LOW; | ||
1138 | else | ||
1139 | client->addr = QT602240_APP_HIGH; | ||
1140 | |||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | static ssize_t qt602240_update_fw_store(struct device *dev, | ||
1145 | struct device_attribute *attr, | ||
1146 | const char *buf, size_t count) | ||
1147 | { | ||
1148 | struct qt602240_data *data = dev_get_drvdata(dev); | ||
1149 | unsigned int version; | ||
1150 | int error; | ||
1151 | |||
1152 | if (sscanf(buf, "%u", &version) != 1) { | ||
1153 | dev_err(dev, "Invalid values\n"); | ||
1154 | return -EINVAL; | ||
1155 | } | ||
1156 | |||
1157 | if (data->info.version < QT602240_VER_21 || version < QT602240_VER_21) { | ||
1158 | dev_err(dev, "FW update supported starting with version 21\n"); | ||
1159 | return -EINVAL; | ||
1160 | } | ||
1161 | |||
1162 | disable_irq(data->irq); | ||
1163 | |||
1164 | error = qt602240_load_fw(dev, QT602240_FW_NAME); | ||
1165 | if (error) { | ||
1166 | dev_err(dev, "The firmware update failed(%d)\n", error); | ||
1167 | count = error; | ||
1168 | } else { | ||
1169 | dev_dbg(dev, "The firmware update succeeded\n"); | ||
1170 | |||
1171 | /* Wait for reset */ | ||
1172 | msleep(QT602240_FWRESET_TIME); | ||
1173 | |||
1174 | kfree(data->object_table); | ||
1175 | data->object_table = NULL; | ||
1176 | |||
1177 | qt602240_initialize(data); | ||
1178 | } | ||
1179 | |||
1180 | enable_irq(data->irq); | ||
1181 | |||
1182 | return count; | ||
1183 | } | ||
1184 | |||
1185 | static DEVICE_ATTR(object, 0444, qt602240_object_show, NULL); | ||
1186 | static DEVICE_ATTR(update_fw, 0664, NULL, qt602240_update_fw_store); | ||
1187 | |||
1188 | static struct attribute *qt602240_attrs[] = { | ||
1189 | &dev_attr_object.attr, | ||
1190 | &dev_attr_update_fw.attr, | ||
1191 | NULL | ||
1192 | }; | ||
1193 | |||
1194 | static const struct attribute_group qt602240_attr_group = { | ||
1195 | .attrs = qt602240_attrs, | ||
1196 | }; | ||
1197 | |||
1198 | static void qt602240_start(struct qt602240_data *data) | ||
1199 | { | ||
1200 | /* Touch enable */ | ||
1201 | qt602240_write_object(data, | ||
1202 | QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0x83); | ||
1203 | } | ||
1204 | |||
1205 | static void qt602240_stop(struct qt602240_data *data) | ||
1206 | { | ||
1207 | /* Touch disable */ | ||
1208 | qt602240_write_object(data, | ||
1209 | QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0); | ||
1210 | } | ||
1211 | |||
1212 | static int qt602240_input_open(struct input_dev *dev) | ||
1213 | { | ||
1214 | struct qt602240_data *data = input_get_drvdata(dev); | ||
1215 | |||
1216 | qt602240_start(data); | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | static void qt602240_input_close(struct input_dev *dev) | ||
1222 | { | ||
1223 | struct qt602240_data *data = input_get_drvdata(dev); | ||
1224 | |||
1225 | qt602240_stop(data); | ||
1226 | } | ||
1227 | |||
1228 | static int __devinit qt602240_probe(struct i2c_client *client, | ||
1229 | const struct i2c_device_id *id) | ||
1230 | { | ||
1231 | struct qt602240_data *data; | ||
1232 | struct input_dev *input_dev; | ||
1233 | int error; | ||
1234 | |||
1235 | if (!client->dev.platform_data) | ||
1236 | return -EINVAL; | ||
1237 | |||
1238 | data = kzalloc(sizeof(struct qt602240_data), GFP_KERNEL); | ||
1239 | input_dev = input_allocate_device(); | ||
1240 | if (!data || !input_dev) { | ||
1241 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
1242 | error = -ENOMEM; | ||
1243 | goto err_free_mem; | ||
1244 | } | ||
1245 | |||
1246 | input_dev->name = "AT42QT602240/ATMXT224 Touchscreen"; | ||
1247 | input_dev->id.bustype = BUS_I2C; | ||
1248 | input_dev->dev.parent = &client->dev; | ||
1249 | input_dev->open = qt602240_input_open; | ||
1250 | input_dev->close = qt602240_input_close; | ||
1251 | |||
1252 | __set_bit(EV_ABS, input_dev->evbit); | ||
1253 | __set_bit(EV_KEY, input_dev->evbit); | ||
1254 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
1255 | |||
1256 | /* For single touch */ | ||
1257 | input_set_abs_params(input_dev, ABS_X, | ||
1258 | 0, QT602240_MAX_XC, 0, 0); | ||
1259 | input_set_abs_params(input_dev, ABS_Y, | ||
1260 | 0, QT602240_MAX_YC, 0, 0); | ||
1261 | |||
1262 | /* For multi touch */ | ||
1263 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
1264 | 0, QT602240_MAX_AREA, 0, 0); | ||
1265 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
1266 | 0, QT602240_MAX_XC, 0, 0); | ||
1267 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
1268 | 0, QT602240_MAX_YC, 0, 0); | ||
1269 | |||
1270 | input_set_drvdata(input_dev, data); | ||
1271 | |||
1272 | data->client = client; | ||
1273 | data->input_dev = input_dev; | ||
1274 | data->pdata = client->dev.platform_data; | ||
1275 | data->irq = client->irq; | ||
1276 | |||
1277 | i2c_set_clientdata(client, data); | ||
1278 | |||
1279 | error = qt602240_initialize(data); | ||
1280 | if (error) | ||
1281 | goto err_free_object; | ||
1282 | |||
1283 | error = request_threaded_irq(client->irq, NULL, qt602240_interrupt, | ||
1284 | IRQF_TRIGGER_FALLING, client->dev.driver->name, data); | ||
1285 | if (error) { | ||
1286 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
1287 | goto err_free_object; | ||
1288 | } | ||
1289 | |||
1290 | error = input_register_device(input_dev); | ||
1291 | if (error) | ||
1292 | goto err_free_irq; | ||
1293 | |||
1294 | error = sysfs_create_group(&client->dev.kobj, &qt602240_attr_group); | ||
1295 | if (error) | ||
1296 | goto err_unregister_device; | ||
1297 | |||
1298 | return 0; | ||
1299 | |||
1300 | err_unregister_device: | ||
1301 | input_unregister_device(input_dev); | ||
1302 | input_dev = NULL; | ||
1303 | err_free_irq: | ||
1304 | free_irq(client->irq, data); | ||
1305 | err_free_object: | ||
1306 | kfree(data->object_table); | ||
1307 | err_free_mem: | ||
1308 | input_free_device(input_dev); | ||
1309 | kfree(data); | ||
1310 | return error; | ||
1311 | } | ||
1312 | |||
1313 | static int __devexit qt602240_remove(struct i2c_client *client) | ||
1314 | { | ||
1315 | struct qt602240_data *data = i2c_get_clientdata(client); | ||
1316 | |||
1317 | sysfs_remove_group(&client->dev.kobj, &qt602240_attr_group); | ||
1318 | free_irq(data->irq, data); | ||
1319 | input_unregister_device(data->input_dev); | ||
1320 | kfree(data->object_table); | ||
1321 | kfree(data); | ||
1322 | |||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | #ifdef CONFIG_PM | ||
1327 | static int qt602240_suspend(struct i2c_client *client, pm_message_t mesg) | ||
1328 | { | ||
1329 | struct qt602240_data *data = i2c_get_clientdata(client); | ||
1330 | struct input_dev *input_dev = data->input_dev; | ||
1331 | |||
1332 | mutex_lock(&input_dev->mutex); | ||
1333 | |||
1334 | if (input_dev->users) | ||
1335 | qt602240_stop(data); | ||
1336 | |||
1337 | mutex_unlock(&input_dev->mutex); | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | static int qt602240_resume(struct i2c_client *client) | ||
1343 | { | ||
1344 | struct qt602240_data *data = i2c_get_clientdata(client); | ||
1345 | struct input_dev *input_dev = data->input_dev; | ||
1346 | |||
1347 | /* Soft reset */ | ||
1348 | qt602240_write_object(data, QT602240_GEN_COMMAND, | ||
1349 | QT602240_COMMAND_RESET, 1); | ||
1350 | |||
1351 | msleep(QT602240_RESET_TIME); | ||
1352 | |||
1353 | mutex_lock(&input_dev->mutex); | ||
1354 | |||
1355 | if (input_dev->users) | ||
1356 | qt602240_start(data); | ||
1357 | |||
1358 | mutex_unlock(&input_dev->mutex); | ||
1359 | |||
1360 | return 0; | ||
1361 | } | ||
1362 | #else | ||
1363 | #define qt602240_suspend NULL | ||
1364 | #define qt602240_resume NULL | ||
1365 | #endif | ||
1366 | |||
1367 | static const struct i2c_device_id qt602240_id[] = { | ||
1368 | { "qt602240_ts", 0 }, | ||
1369 | { } | ||
1370 | }; | ||
1371 | MODULE_DEVICE_TABLE(i2c, qt602240_id); | ||
1372 | |||
1373 | static struct i2c_driver qt602240_driver = { | ||
1374 | .driver = { | ||
1375 | .name = "qt602240_ts", | ||
1376 | .owner = THIS_MODULE, | ||
1377 | }, | ||
1378 | .probe = qt602240_probe, | ||
1379 | .remove = __devexit_p(qt602240_remove), | ||
1380 | .suspend = qt602240_suspend, | ||
1381 | .resume = qt602240_resume, | ||
1382 | .id_table = qt602240_id, | ||
1383 | }; | ||
1384 | |||
1385 | static int __init qt602240_init(void) | ||
1386 | { | ||
1387 | return i2c_add_driver(&qt602240_driver); | ||
1388 | } | ||
1389 | |||
1390 | static void __exit qt602240_exit(void) | ||
1391 | { | ||
1392 | i2c_del_driver(&qt602240_driver); | ||
1393 | } | ||
1394 | |||
1395 | module_init(qt602240_init); | ||
1396 | module_exit(qt602240_exit); | ||
1397 | |||
1398 | /* Module information */ | ||
1399 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
1400 | MODULE_DESCRIPTION("AT42QT602240/ATMXT224 Touchscreen driver"); | ||
1401 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c new file mode 100644 index 000000000000..4ab371358b33 --- /dev/null +++ b/drivers/input/touchscreen/st1232.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * ST1232 Touchscreen Controller Driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Renesas Solutions Corp. | ||
5 | * Tony SIM <chinyeow.sim.xt@renesas.com> | ||
6 | * | ||
7 | * Using code from: | ||
8 | * - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c | ||
9 | * Copyright (C) 2007 Google, Inc. | ||
10 | * | ||
11 | * This software is licensed under the terms of the GNU General Public | ||
12 | * License version 2, as published by the Free Software Foundation, and | ||
13 | * may be copied, distributed, and modified under those terms. | ||
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 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | ||
28 | |||
29 | #define ST1232_TS_NAME "st1232-ts" | ||
30 | |||
31 | #define MIN_X 0x00 | ||
32 | #define MIN_Y 0x00 | ||
33 | #define MAX_X 0x31f /* (800 - 1) */ | ||
34 | #define MAX_Y 0x1df /* (480 - 1) */ | ||
35 | #define MAX_AREA 0xff | ||
36 | #define MAX_FINGERS 2 | ||
37 | |||
38 | struct st1232_ts_finger { | ||
39 | u16 x; | ||
40 | u16 y; | ||
41 | u8 t; | ||
42 | bool is_valid; | ||
43 | }; | ||
44 | |||
45 | struct st1232_ts_data { | ||
46 | struct i2c_client *client; | ||
47 | struct input_dev *input_dev; | ||
48 | struct st1232_ts_finger finger[MAX_FINGERS]; | ||
49 | }; | ||
50 | |||
51 | static int st1232_ts_read_data(struct st1232_ts_data *ts) | ||
52 | { | ||
53 | struct st1232_ts_finger *finger = ts->finger; | ||
54 | struct i2c_client *client = ts->client; | ||
55 | struct i2c_msg msg[2]; | ||
56 | int error; | ||
57 | u8 start_reg; | ||
58 | u8 buf[10]; | ||
59 | |||
60 | /* read touchscreen data from ST1232 */ | ||
61 | msg[0].addr = client->addr; | ||
62 | msg[0].flags = 0; | ||
63 | msg[0].len = 1; | ||
64 | msg[0].buf = &start_reg; | ||
65 | start_reg = 0x10; | ||
66 | |||
67 | msg[1].addr = ts->client->addr; | ||
68 | msg[1].flags = I2C_M_RD; | ||
69 | msg[1].len = sizeof(buf); | ||
70 | msg[1].buf = buf; | ||
71 | |||
72 | error = i2c_transfer(client->adapter, msg, 2); | ||
73 | if (error < 0) | ||
74 | return error; | ||
75 | |||
76 | /* get "valid" bits */ | ||
77 | finger[0].is_valid = buf[2] >> 7; | ||
78 | finger[1].is_valid = buf[5] >> 7; | ||
79 | |||
80 | /* get xy coordinate */ | ||
81 | if (finger[0].is_valid) { | ||
82 | finger[0].x = ((buf[2] & 0x0070) << 4) | buf[3]; | ||
83 | finger[0].y = ((buf[2] & 0x0007) << 8) | buf[4]; | ||
84 | finger[0].t = buf[8]; | ||
85 | } | ||
86 | |||
87 | if (finger[1].is_valid) { | ||
88 | finger[1].x = ((buf[5] & 0x0070) << 4) | buf[6]; | ||
89 | finger[1].y = ((buf[5] & 0x0007) << 8) | buf[7]; | ||
90 | finger[1].t = buf[9]; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | ||
97 | { | ||
98 | struct st1232_ts_data *ts = dev_id; | ||
99 | struct st1232_ts_finger *finger = ts->finger; | ||
100 | struct input_dev *input_dev = ts->input_dev; | ||
101 | int count = 0; | ||
102 | int i, ret; | ||
103 | |||
104 | ret = st1232_ts_read_data(ts); | ||
105 | if (ret < 0) | ||
106 | goto end; | ||
107 | |||
108 | /* multi touch protocol */ | ||
109 | for (i = 0; i < MAX_FINGERS; i++) { | ||
110 | if (!finger[i].is_valid) | ||
111 | continue; | ||
112 | |||
113 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t); | ||
114 | input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x); | ||
115 | input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y); | ||
116 | input_mt_sync(input_dev); | ||
117 | count++; | ||
118 | } | ||
119 | |||
120 | /* SYN_MT_REPORT only if no contact */ | ||
121 | if (!count) | ||
122 | input_mt_sync(input_dev); | ||
123 | |||
124 | /* SYN_REPORT */ | ||
125 | input_sync(input_dev); | ||
126 | |||
127 | end: | ||
128 | return IRQ_HANDLED; | ||
129 | } | ||
130 | |||
131 | static int __devinit st1232_ts_probe(struct i2c_client *client, | ||
132 | const struct i2c_device_id *id) | ||
133 | { | ||
134 | struct st1232_ts_data *ts; | ||
135 | struct input_dev *input_dev; | ||
136 | int error; | ||
137 | |||
138 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
139 | dev_err(&client->dev, "need I2C_FUNC_I2C\n"); | ||
140 | return -EIO; | ||
141 | } | ||
142 | |||
143 | if (!client->irq) { | ||
144 | dev_err(&client->dev, "no IRQ?\n"); | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | |||
148 | |||
149 | ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL); | ||
150 | input_dev = input_allocate_device(); | ||
151 | if (!ts || !input_dev) { | ||
152 | error = -ENOMEM; | ||
153 | goto err_free_mem; | ||
154 | } | ||
155 | |||
156 | ts->client = client; | ||
157 | ts->input_dev = input_dev; | ||
158 | |||
159 | input_dev->name = "st1232-touchscreen"; | ||
160 | input_dev->id.bustype = BUS_I2C; | ||
161 | input_dev->dev.parent = &client->dev; | ||
162 | |||
163 | __set_bit(EV_SYN, input_dev->evbit); | ||
164 | __set_bit(EV_KEY, input_dev->evbit); | ||
165 | __set_bit(EV_ABS, input_dev->evbit); | ||
166 | |||
167 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); | ||
168 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0); | ||
169 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0); | ||
170 | |||
171 | error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler, | ||
172 | IRQF_ONESHOT, client->name, ts); | ||
173 | if (error) { | ||
174 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
175 | goto err_free_mem; | ||
176 | } | ||
177 | |||
178 | error = input_register_device(ts->input_dev); | ||
179 | if (error) { | ||
180 | dev_err(&client->dev, "Unable to register %s input device\n", | ||
181 | input_dev->name); | ||
182 | goto err_free_irq; | ||
183 | } | ||
184 | |||
185 | i2c_set_clientdata(client, ts); | ||
186 | device_init_wakeup(&client->dev, 1); | ||
187 | |||
188 | return 0; | ||
189 | |||
190 | err_free_irq: | ||
191 | free_irq(client->irq, ts); | ||
192 | err_free_mem: | ||
193 | input_free_device(input_dev); | ||
194 | kfree(ts); | ||
195 | return error; | ||
196 | } | ||
197 | |||
198 | static int __devexit st1232_ts_remove(struct i2c_client *client) | ||
199 | { | ||
200 | struct st1232_ts_data *ts = i2c_get_clientdata(client); | ||
201 | |||
202 | device_init_wakeup(&client->dev, 0); | ||
203 | free_irq(client->irq, ts); | ||
204 | input_unregister_device(ts->input_dev); | ||
205 | kfree(ts); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | #ifdef CONFIG_PM | ||
211 | static int st1232_ts_suspend(struct device *dev) | ||
212 | { | ||
213 | struct i2c_client *client = to_i2c_client(dev); | ||
214 | |||
215 | if (device_may_wakeup(&client->dev)) | ||
216 | enable_irq_wake(client->irq); | ||
217 | else | ||
218 | disable_irq(client->irq); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int st1232_ts_resume(struct device *dev) | ||
224 | { | ||
225 | struct i2c_client *client = to_i2c_client(dev); | ||
226 | |||
227 | if (device_may_wakeup(&client->dev)) | ||
228 | disable_irq_wake(client->irq); | ||
229 | else | ||
230 | enable_irq(client->irq); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static const struct dev_pm_ops st1232_ts_pm_ops = { | ||
236 | .suspend = st1232_ts_suspend, | ||
237 | .resume = st1232_ts_resume, | ||
238 | }; | ||
239 | #endif | ||
240 | |||
241 | static const struct i2c_device_id st1232_ts_id[] = { | ||
242 | { ST1232_TS_NAME, 0 }, | ||
243 | { } | ||
244 | }; | ||
245 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | ||
246 | |||
247 | static struct i2c_driver st1232_ts_driver = { | ||
248 | .probe = st1232_ts_probe, | ||
249 | .remove = __devexit_p(st1232_ts_remove), | ||
250 | .id_table = st1232_ts_id, | ||
251 | .driver = { | ||
252 | .name = ST1232_TS_NAME, | ||
253 | .owner = THIS_MODULE, | ||
254 | #ifdef CONFIG_PM | ||
255 | .pm = &st1232_ts_pm_ops, | ||
256 | #endif | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static int __init st1232_ts_init(void) | ||
261 | { | ||
262 | return i2c_add_driver(&st1232_ts_driver); | ||
263 | } | ||
264 | module_init(st1232_ts_init); | ||
265 | |||
266 | static void __exit st1232_ts_exit(void) | ||
267 | { | ||
268 | i2c_del_driver(&st1232_ts_driver); | ||
269 | } | ||
270 | module_exit(st1232_ts_exit); | ||
271 | |||
272 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | ||
273 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); | ||
274 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index cf1dba2e267c..22a3411e93c5 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/err.h> | ||
17 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
18 | #include <linux/input.h> | 19 | #include <linux/input.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -289,9 +290,9 @@ static int __devinit tsc_probe(struct platform_device *pdev) | |||
289 | } | 290 | } |
290 | 291 | ||
291 | ts->clk = clk_get(dev, NULL); | 292 | ts->clk = clk_get(dev, NULL); |
292 | if (!ts->clk) { | 293 | if (IS_ERR(ts->clk)) { |
293 | dev_err(dev, "cannot claim device clock\n"); | 294 | dev_err(dev, "cannot claim device clock\n"); |
294 | error = -EINVAL; | 295 | error = PTR_ERR(ts->clk); |
295 | goto error_clk; | 296 | goto error_clk; |
296 | } | 297 | } |
297 | 298 | ||
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index c8c136cf7bbc..43031492d733 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c | |||
@@ -43,7 +43,6 @@ struct tps6507x_ts { | |||
43 | struct input_dev *input_dev; | 43 | struct input_dev *input_dev; |
44 | struct device *dev; | 44 | struct device *dev; |
45 | char phys[32]; | 45 | char phys[32]; |
46 | struct workqueue_struct *wq; | ||
47 | struct delayed_work work; | 46 | struct delayed_work work; |
48 | unsigned polling; /* polling is active */ | 47 | unsigned polling; /* polling is active */ |
49 | struct ts_event tc; | 48 | struct ts_event tc; |
@@ -220,8 +219,8 @@ done: | |||
220 | poll = 1; | 219 | poll = 1; |
221 | 220 | ||
222 | if (poll) { | 221 | if (poll) { |
223 | schd = queue_delayed_work(tsc->wq, &tsc->work, | 222 | schd = schedule_delayed_work(&tsc->work, |
224 | msecs_to_jiffies(tsc->poll_period)); | 223 | msecs_to_jiffies(tsc->poll_period)); |
225 | if (schd) | 224 | if (schd) |
226 | tsc->polling = 1; | 225 | tsc->polling = 1; |
227 | else { | 226 | else { |
@@ -303,7 +302,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev) | |||
303 | tsc->input_dev = input_dev; | 302 | tsc->input_dev = input_dev; |
304 | 303 | ||
305 | INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler); | 304 | INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler); |
306 | tsc->wq = create_workqueue("TPS6507x Touchscreen"); | ||
307 | 305 | ||
308 | if (init_data) { | 306 | if (init_data) { |
309 | tsc->poll_period = init_data->poll_period; | 307 | tsc->poll_period = init_data->poll_period; |
@@ -325,8 +323,8 @@ static int tps6507x_ts_probe(struct platform_device *pdev) | |||
325 | if (error) | 323 | if (error) |
326 | goto err2; | 324 | goto err2; |
327 | 325 | ||
328 | schd = queue_delayed_work(tsc->wq, &tsc->work, | 326 | schd = schedule_delayed_work(&tsc->work, |
329 | msecs_to_jiffies(tsc->poll_period)); | 327 | msecs_to_jiffies(tsc->poll_period)); |
330 | 328 | ||
331 | if (schd) | 329 | if (schd) |
332 | tsc->polling = 1; | 330 | tsc->polling = 1; |
@@ -341,7 +339,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev) | |||
341 | 339 | ||
342 | err2: | 340 | err2: |
343 | cancel_delayed_work_sync(&tsc->work); | 341 | cancel_delayed_work_sync(&tsc->work); |
344 | destroy_workqueue(tsc->wq); | ||
345 | input_free_device(input_dev); | 342 | input_free_device(input_dev); |
346 | err1: | 343 | err1: |
347 | kfree(tsc); | 344 | kfree(tsc); |
@@ -357,7 +354,6 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev) | |||
357 | struct input_dev *input_dev = tsc->input_dev; | 354 | struct input_dev *input_dev = tsc->input_dev; |
358 | 355 | ||
359 | cancel_delayed_work_sync(&tsc->work); | 356 | cancel_delayed_work_sync(&tsc->work); |
360 | destroy_workqueue(tsc->wq); | ||
361 | 357 | ||
362 | input_unregister_device(input_dev); | 358 | input_unregister_device(input_dev); |
363 | 359 | ||
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c new file mode 100644 index 000000000000..cbf0ff322676 --- /dev/null +++ b/drivers/input/touchscreen/tsc2005.c | |||
@@ -0,0 +1,764 @@ | |||
1 | /* | ||
2 | * TSC2005 touchscreen driver | ||
3 | * | ||
4 | * Copyright (C) 2006-2010 Nokia Corporation | ||
5 | * | ||
6 | * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> | ||
7 | * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <linux/spi/spi.h> | ||
32 | #include <linux/spi/tsc2005.h> | ||
33 | |||
34 | /* | ||
35 | * The touchscreen interface operates as follows: | ||
36 | * | ||
37 | * 1) Pen is pressed against the touchscreen. | ||
38 | * 2) TSC2005 performs AD conversion. | ||
39 | * 3) After the conversion is done TSC2005 drives DAV line down. | ||
40 | * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled. | ||
41 | * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2 | ||
42 | * values. | ||
43 | * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up | ||
44 | * tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms). | ||
45 | * 7) When the penup timer expires, there have not been touch or DAV interrupts | ||
46 | * during the last 40ms which means the pen has been lifted. | ||
47 | * | ||
48 | * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond | ||
49 | * after a configurable period (in ms) of activity. If esd_timeout is 0, the | ||
50 | * watchdog is disabled. | ||
51 | */ | ||
52 | |||
53 | /* control byte 1 */ | ||
54 | #define TSC2005_CMD 0x80 | ||
55 | #define TSC2005_CMD_NORMAL 0x00 | ||
56 | #define TSC2005_CMD_STOP 0x01 | ||
57 | #define TSC2005_CMD_12BIT 0x04 | ||
58 | |||
59 | /* control byte 0 */ | ||
60 | #define TSC2005_REG_READ 0x0001 | ||
61 | #define TSC2005_REG_PND0 0x0002 | ||
62 | #define TSC2005_REG_X 0x0000 | ||
63 | #define TSC2005_REG_Y 0x0008 | ||
64 | #define TSC2005_REG_Z1 0x0010 | ||
65 | #define TSC2005_REG_Z2 0x0018 | ||
66 | #define TSC2005_REG_TEMP_HIGH 0x0050 | ||
67 | #define TSC2005_REG_CFR0 0x0060 | ||
68 | #define TSC2005_REG_CFR1 0x0068 | ||
69 | #define TSC2005_REG_CFR2 0x0070 | ||
70 | |||
71 | /* configuration register 0 */ | ||
72 | #define TSC2005_CFR0_PRECHARGE_276US 0x0040 | ||
73 | #define TSC2005_CFR0_STABTIME_1MS 0x0300 | ||
74 | #define TSC2005_CFR0_CLOCK_1MHZ 0x1000 | ||
75 | #define TSC2005_CFR0_RESOLUTION12 0x2000 | ||
76 | #define TSC2005_CFR0_PENMODE 0x8000 | ||
77 | #define TSC2005_CFR0_INITVALUE (TSC2005_CFR0_STABTIME_1MS | \ | ||
78 | TSC2005_CFR0_CLOCK_1MHZ | \ | ||
79 | TSC2005_CFR0_RESOLUTION12 | \ | ||
80 | TSC2005_CFR0_PRECHARGE_276US | \ | ||
81 | TSC2005_CFR0_PENMODE) | ||
82 | |||
83 | /* bits common to both read and write of configuration register 0 */ | ||
84 | #define TSC2005_CFR0_RW_MASK 0x3fff | ||
85 | |||
86 | /* configuration register 1 */ | ||
87 | #define TSC2005_CFR1_BATCHDELAY_4MS 0x0003 | ||
88 | #define TSC2005_CFR1_INITVALUE TSC2005_CFR1_BATCHDELAY_4MS | ||
89 | |||
90 | /* configuration register 2 */ | ||
91 | #define TSC2005_CFR2_MAVE_Z 0x0004 | ||
92 | #define TSC2005_CFR2_MAVE_Y 0x0008 | ||
93 | #define TSC2005_CFR2_MAVE_X 0x0010 | ||
94 | #define TSC2005_CFR2_AVG_7 0x0800 | ||
95 | #define TSC2005_CFR2_MEDIUM_15 0x3000 | ||
96 | #define TSC2005_CFR2_INITVALUE (TSC2005_CFR2_MAVE_X | \ | ||
97 | TSC2005_CFR2_MAVE_Y | \ | ||
98 | TSC2005_CFR2_MAVE_Z | \ | ||
99 | TSC2005_CFR2_MEDIUM_15 | \ | ||
100 | TSC2005_CFR2_AVG_7) | ||
101 | |||
102 | #define MAX_12BIT 0xfff | ||
103 | #define TSC2005_SPI_MAX_SPEED_HZ 10000000 | ||
104 | #define TSC2005_PENUP_TIME_MS 40 | ||
105 | |||
106 | struct tsc2005_spi_rd { | ||
107 | struct spi_transfer spi_xfer; | ||
108 | u32 spi_tx; | ||
109 | u32 spi_rx; | ||
110 | }; | ||
111 | |||
112 | struct tsc2005 { | ||
113 | struct spi_device *spi; | ||
114 | |||
115 | struct spi_message spi_read_msg; | ||
116 | struct tsc2005_spi_rd spi_x; | ||
117 | struct tsc2005_spi_rd spi_y; | ||
118 | struct tsc2005_spi_rd spi_z1; | ||
119 | struct tsc2005_spi_rd spi_z2; | ||
120 | |||
121 | struct input_dev *idev; | ||
122 | char phys[32]; | ||
123 | |||
124 | struct mutex mutex; | ||
125 | |||
126 | /* raw copy of previous x,y,z */ | ||
127 | int in_x; | ||
128 | int in_y; | ||
129 | int in_z1; | ||
130 | int in_z2; | ||
131 | |||
132 | spinlock_t lock; | ||
133 | struct timer_list penup_timer; | ||
134 | |||
135 | unsigned int esd_timeout; | ||
136 | struct delayed_work esd_work; | ||
137 | unsigned long last_valid_interrupt; | ||
138 | |||
139 | unsigned int x_plate_ohm; | ||
140 | |||
141 | bool opened; | ||
142 | bool suspended; | ||
143 | |||
144 | bool pen_down; | ||
145 | |||
146 | void (*set_reset)(bool enable); | ||
147 | }; | ||
148 | |||
149 | static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd) | ||
150 | { | ||
151 | u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; | ||
152 | struct spi_transfer xfer = { | ||
153 | .tx_buf = &tx, | ||
154 | .len = 1, | ||
155 | .bits_per_word = 8, | ||
156 | }; | ||
157 | struct spi_message msg; | ||
158 | int error; | ||
159 | |||
160 | spi_message_init(&msg); | ||
161 | spi_message_add_tail(&xfer, &msg); | ||
162 | |||
163 | error = spi_sync(ts->spi, &msg); | ||
164 | if (error) { | ||
165 | dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n", | ||
166 | __func__, cmd, error); | ||
167 | return error; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) | ||
174 | { | ||
175 | u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value; | ||
176 | struct spi_transfer xfer = { | ||
177 | .tx_buf = &tx, | ||
178 | .len = 4, | ||
179 | .bits_per_word = 24, | ||
180 | }; | ||
181 | struct spi_message msg; | ||
182 | int error; | ||
183 | |||
184 | spi_message_init(&msg); | ||
185 | spi_message_add_tail(&xfer, &msg); | ||
186 | |||
187 | error = spi_sync(ts->spi, &msg); | ||
188 | if (error) { | ||
189 | dev_err(&ts->spi->dev, | ||
190 | "%s: failed, register: %x, value: %x, error: %d\n", | ||
191 | __func__, reg, value, error); | ||
192 | return error; | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) | ||
199 | { | ||
200 | memset(rd, 0, sizeof(*rd)); | ||
201 | |||
202 | rd->spi_tx = (reg | TSC2005_REG_READ) << 16; | ||
203 | rd->spi_xfer.tx_buf = &rd->spi_tx; | ||
204 | rd->spi_xfer.rx_buf = &rd->spi_rx; | ||
205 | rd->spi_xfer.len = 4; | ||
206 | rd->spi_xfer.bits_per_word = 24; | ||
207 | rd->spi_xfer.cs_change = !last; | ||
208 | } | ||
209 | |||
210 | static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) | ||
211 | { | ||
212 | struct tsc2005_spi_rd spi_rd; | ||
213 | struct spi_message msg; | ||
214 | int error; | ||
215 | |||
216 | tsc2005_setup_read(&spi_rd, reg, true); | ||
217 | |||
218 | spi_message_init(&msg); | ||
219 | spi_message_add_tail(&spi_rd.spi_xfer, &msg); | ||
220 | |||
221 | error = spi_sync(ts->spi, &msg); | ||
222 | if (error) | ||
223 | return error; | ||
224 | |||
225 | *value = spi_rd.spi_rx; | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static void tsc2005_update_pen_state(struct tsc2005 *ts, | ||
230 | int x, int y, int pressure) | ||
231 | { | ||
232 | if (pressure) { | ||
233 | input_report_abs(ts->idev, ABS_X, x); | ||
234 | input_report_abs(ts->idev, ABS_Y, y); | ||
235 | input_report_abs(ts->idev, ABS_PRESSURE, pressure); | ||
236 | if (!ts->pen_down) { | ||
237 | input_report_key(ts->idev, BTN_TOUCH, !!pressure); | ||
238 | ts->pen_down = true; | ||
239 | } | ||
240 | } else { | ||
241 | input_report_abs(ts->idev, ABS_PRESSURE, 0); | ||
242 | if (ts->pen_down) { | ||
243 | input_report_key(ts->idev, BTN_TOUCH, 0); | ||
244 | ts->pen_down = false; | ||
245 | } | ||
246 | } | ||
247 | input_sync(ts->idev); | ||
248 | dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y, | ||
249 | pressure); | ||
250 | } | ||
251 | |||
252 | static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) | ||
253 | { | ||
254 | struct tsc2005 *ts = _ts; | ||
255 | unsigned long flags; | ||
256 | unsigned int pressure; | ||
257 | u32 x, y; | ||
258 | u32 z1, z2; | ||
259 | int error; | ||
260 | |||
261 | /* read the coordinates */ | ||
262 | error = spi_sync(ts->spi, &ts->spi_read_msg); | ||
263 | if (unlikely(error)) | ||
264 | goto out; | ||
265 | |||
266 | x = ts->spi_x.spi_rx; | ||
267 | y = ts->spi_y.spi_rx; | ||
268 | z1 = ts->spi_z1.spi_rx; | ||
269 | z2 = ts->spi_z2.spi_rx; | ||
270 | |||
271 | /* validate position */ | ||
272 | if (unlikely(x > MAX_12BIT || y > MAX_12BIT)) | ||
273 | goto out; | ||
274 | |||
275 | /* Skip reading if the pressure components are out of range */ | ||
276 | if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2)) | ||
277 | goto out; | ||
278 | |||
279 | /* | ||
280 | * Skip point if this is a pen down with the exact same values as | ||
281 | * the value before pen-up - that implies SPI fed us stale data | ||
282 | */ | ||
283 | if (!ts->pen_down && | ||
284 | ts->in_x == x && ts->in_y == y && | ||
285 | ts->in_z1 == z1 && ts->in_z2 == z2) { | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * At this point we are happy we have a valid and useful reading. | ||
291 | * Remember it for later comparisons. We may now begin downsampling. | ||
292 | */ | ||
293 | ts->in_x = x; | ||
294 | ts->in_y = y; | ||
295 | ts->in_z1 = z1; | ||
296 | ts->in_z2 = z2; | ||
297 | |||
298 | /* Compute touch pressure resistance using equation #1 */ | ||
299 | pressure = x * (z2 - z1) / z1; | ||
300 | pressure = pressure * ts->x_plate_ohm / 4096; | ||
301 | if (unlikely(pressure > MAX_12BIT)) | ||
302 | goto out; | ||
303 | |||
304 | spin_lock_irqsave(&ts->lock, flags); | ||
305 | |||
306 | tsc2005_update_pen_state(ts, x, y, pressure); | ||
307 | mod_timer(&ts->penup_timer, | ||
308 | jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); | ||
309 | |||
310 | spin_unlock_irqrestore(&ts->lock, flags); | ||
311 | |||
312 | ts->last_valid_interrupt = jiffies; | ||
313 | out: | ||
314 | return IRQ_HANDLED; | ||
315 | } | ||
316 | |||
317 | static void tsc2005_penup_timer(unsigned long data) | ||
318 | { | ||
319 | struct tsc2005 *ts = (struct tsc2005 *)data; | ||
320 | unsigned long flags; | ||
321 | |||
322 | spin_lock_irqsave(&ts->lock, flags); | ||
323 | tsc2005_update_pen_state(ts, 0, 0, 0); | ||
324 | spin_unlock_irqrestore(&ts->lock, flags); | ||
325 | } | ||
326 | |||
327 | static void tsc2005_start_scan(struct tsc2005 *ts) | ||
328 | { | ||
329 | tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE); | ||
330 | tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE); | ||
331 | tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE); | ||
332 | tsc2005_cmd(ts, TSC2005_CMD_NORMAL); | ||
333 | } | ||
334 | |||
335 | static void tsc2005_stop_scan(struct tsc2005 *ts) | ||
336 | { | ||
337 | tsc2005_cmd(ts, TSC2005_CMD_STOP); | ||
338 | } | ||
339 | |||
340 | /* must be called with ts->mutex held */ | ||
341 | static void __tsc2005_disable(struct tsc2005 *ts) | ||
342 | { | ||
343 | tsc2005_stop_scan(ts); | ||
344 | |||
345 | disable_irq(ts->spi->irq); | ||
346 | del_timer_sync(&ts->penup_timer); | ||
347 | |||
348 | cancel_delayed_work_sync(&ts->esd_work); | ||
349 | |||
350 | enable_irq(ts->spi->irq); | ||
351 | } | ||
352 | |||
353 | /* must be called with ts->mutex held */ | ||
354 | static void __tsc2005_enable(struct tsc2005 *ts) | ||
355 | { | ||
356 | tsc2005_start_scan(ts); | ||
357 | |||
358 | if (ts->esd_timeout && ts->set_reset) { | ||
359 | ts->last_valid_interrupt = jiffies; | ||
360 | schedule_delayed_work(&ts->esd_work, | ||
361 | round_jiffies_relative( | ||
362 | msecs_to_jiffies(ts->esd_timeout))); | ||
363 | } | ||
364 | |||
365 | } | ||
366 | |||
367 | static ssize_t tsc2005_selftest_show(struct device *dev, | ||
368 | struct device_attribute *attr, | ||
369 | char *buf) | ||
370 | { | ||
371 | struct spi_device *spi = to_spi_device(dev); | ||
372 | struct tsc2005 *ts = spi_get_drvdata(spi); | ||
373 | u16 temp_high; | ||
374 | u16 temp_high_orig; | ||
375 | u16 temp_high_test; | ||
376 | bool success = true; | ||
377 | int error; | ||
378 | |||
379 | mutex_lock(&ts->mutex); | ||
380 | |||
381 | /* | ||
382 | * Test TSC2005 communications via temp high register. | ||
383 | */ | ||
384 | __tsc2005_disable(ts); | ||
385 | |||
386 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); | ||
387 | if (error) { | ||
388 | dev_warn(dev, "selftest failed: read error %d\n", error); | ||
389 | success = false; | ||
390 | goto out; | ||
391 | } | ||
392 | |||
393 | temp_high_test = (temp_high_orig - 1) & MAX_12BIT; | ||
394 | |||
395 | error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); | ||
396 | if (error) { | ||
397 | dev_warn(dev, "selftest failed: write error %d\n", error); | ||
398 | success = false; | ||
399 | goto out; | ||
400 | } | ||
401 | |||
402 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); | ||
403 | if (error) { | ||
404 | dev_warn(dev, "selftest failed: read error %d after write\n", | ||
405 | error); | ||
406 | success = false; | ||
407 | goto out; | ||
408 | } | ||
409 | |||
410 | if (temp_high != temp_high_test) { | ||
411 | dev_warn(dev, "selftest failed: %d != %d\n", | ||
412 | temp_high, temp_high_test); | ||
413 | success = false; | ||
414 | } | ||
415 | |||
416 | /* hardware reset */ | ||
417 | ts->set_reset(false); | ||
418 | usleep_range(100, 500); /* only 10us required */ | ||
419 | ts->set_reset(true); | ||
420 | |||
421 | if (!success) | ||
422 | goto out; | ||
423 | |||
424 | /* test that the reset really happened */ | ||
425 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); | ||
426 | if (error) { | ||
427 | dev_warn(dev, "selftest failed: read error %d after reset\n", | ||
428 | error); | ||
429 | success = false; | ||
430 | goto out; | ||
431 | } | ||
432 | |||
433 | if (temp_high != temp_high_orig) { | ||
434 | dev_warn(dev, "selftest failed after reset: %d != %d\n", | ||
435 | temp_high, temp_high_orig); | ||
436 | success = false; | ||
437 | } | ||
438 | |||
439 | out: | ||
440 | __tsc2005_enable(ts); | ||
441 | mutex_unlock(&ts->mutex); | ||
442 | |||
443 | return sprintf(buf, "%d\n", success); | ||
444 | } | ||
445 | |||
446 | static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); | ||
447 | |||
448 | static struct attribute *tsc2005_attrs[] = { | ||
449 | &dev_attr_selftest.attr, | ||
450 | NULL | ||
451 | }; | ||
452 | |||
453 | static mode_t tsc2005_attr_is_visible(struct kobject *kobj, | ||
454 | struct attribute *attr, int n) | ||
455 | { | ||
456 | struct device *dev = container_of(kobj, struct device, kobj); | ||
457 | struct spi_device *spi = to_spi_device(dev); | ||
458 | struct tsc2005 *ts = spi_get_drvdata(spi); | ||
459 | mode_t mode = attr->mode; | ||
460 | |||
461 | if (attr == &dev_attr_selftest.attr) { | ||
462 | if (!ts->set_reset) | ||
463 | mode = 0; | ||
464 | } | ||
465 | |||
466 | return mode; | ||
467 | } | ||
468 | |||
469 | static const struct attribute_group tsc2005_attr_group = { | ||
470 | .is_visible = tsc2005_attr_is_visible, | ||
471 | .attrs = tsc2005_attrs, | ||
472 | }; | ||
473 | |||
474 | static void tsc2005_esd_work(struct work_struct *work) | ||
475 | { | ||
476 | struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work); | ||
477 | int error; | ||
478 | u16 r; | ||
479 | |||
480 | if (!mutex_trylock(&ts->mutex)) { | ||
481 | /* | ||
482 | * If the mutex is taken, it means that disable or enable is in | ||
483 | * progress. In that case just reschedule the work. If the work | ||
484 | * is not needed, it will be canceled by disable. | ||
485 | */ | ||
486 | goto reschedule; | ||
487 | } | ||
488 | |||
489 | if (time_is_after_jiffies(ts->last_valid_interrupt + | ||
490 | msecs_to_jiffies(ts->esd_timeout))) | ||
491 | goto out; | ||
492 | |||
493 | /* We should be able to read register without disabling interrupts. */ | ||
494 | error = tsc2005_read(ts, TSC2005_REG_CFR0, &r); | ||
495 | if (!error && | ||
496 | !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { | ||
497 | goto out; | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * If we could not read our known value from configuration register 0 | ||
502 | * then we should reset the controller as if from power-up and start | ||
503 | * scanning again. | ||
504 | */ | ||
505 | dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); | ||
506 | |||
507 | disable_irq(ts->spi->irq); | ||
508 | del_timer_sync(&ts->penup_timer); | ||
509 | |||
510 | tsc2005_update_pen_state(ts, 0, 0, 0); | ||
511 | |||
512 | ts->set_reset(false); | ||
513 | usleep_range(100, 500); /* only 10us required */ | ||
514 | ts->set_reset(true); | ||
515 | |||
516 | enable_irq(ts->spi->irq); | ||
517 | tsc2005_start_scan(ts); | ||
518 | |||
519 | out: | ||
520 | mutex_unlock(&ts->mutex); | ||
521 | reschedule: | ||
522 | /* re-arm the watchdog */ | ||
523 | schedule_delayed_work(&ts->esd_work, | ||
524 | round_jiffies_relative( | ||
525 | msecs_to_jiffies(ts->esd_timeout))); | ||
526 | } | ||
527 | |||
528 | static int tsc2005_open(struct input_dev *input) | ||
529 | { | ||
530 | struct tsc2005 *ts = input_get_drvdata(input); | ||
531 | |||
532 | mutex_lock(&ts->mutex); | ||
533 | |||
534 | if (!ts->suspended) | ||
535 | __tsc2005_enable(ts); | ||
536 | |||
537 | ts->opened = true; | ||
538 | |||
539 | mutex_unlock(&ts->mutex); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static void tsc2005_close(struct input_dev *input) | ||
545 | { | ||
546 | struct tsc2005 *ts = input_get_drvdata(input); | ||
547 | |||
548 | mutex_lock(&ts->mutex); | ||
549 | |||
550 | if (!ts->suspended) | ||
551 | __tsc2005_disable(ts); | ||
552 | |||
553 | ts->opened = false; | ||
554 | |||
555 | mutex_unlock(&ts->mutex); | ||
556 | } | ||
557 | |||
558 | static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) | ||
559 | { | ||
560 | tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false); | ||
561 | tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false); | ||
562 | tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, false); | ||
563 | tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, true); | ||
564 | |||
565 | spi_message_init(&ts->spi_read_msg); | ||
566 | spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg); | ||
567 | spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg); | ||
568 | spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg); | ||
569 | spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); | ||
570 | } | ||
571 | |||
572 | static int __devinit tsc2005_probe(struct spi_device *spi) | ||
573 | { | ||
574 | const struct tsc2005_platform_data *pdata = spi->dev.platform_data; | ||
575 | struct tsc2005 *ts; | ||
576 | struct input_dev *input_dev; | ||
577 | unsigned int max_x, max_y, max_p; | ||
578 | unsigned int fudge_x, fudge_y, fudge_p; | ||
579 | int error; | ||
580 | |||
581 | if (!pdata) { | ||
582 | dev_dbg(&spi->dev, "no platform data\n"); | ||
583 | return -ENODEV; | ||
584 | } | ||
585 | |||
586 | fudge_x = pdata->ts_x_fudge ? : 4; | ||
587 | fudge_y = pdata->ts_y_fudge ? : 8; | ||
588 | fudge_p = pdata->ts_pressure_fudge ? : 2; | ||
589 | max_x = pdata->ts_x_max ? : MAX_12BIT; | ||
590 | max_y = pdata->ts_y_max ? : MAX_12BIT; | ||
591 | max_p = pdata->ts_pressure_max ? : MAX_12BIT; | ||
592 | |||
593 | if (spi->irq <= 0) { | ||
594 | dev_dbg(&spi->dev, "no irq\n"); | ||
595 | return -ENODEV; | ||
596 | } | ||
597 | |||
598 | spi->mode = SPI_MODE_0; | ||
599 | spi->bits_per_word = 8; | ||
600 | if (!spi->max_speed_hz) | ||
601 | spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ; | ||
602 | |||
603 | error = spi_setup(spi); | ||
604 | if (error) | ||
605 | return error; | ||
606 | |||
607 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
608 | input_dev = input_allocate_device(); | ||
609 | if (!ts || !input_dev) { | ||
610 | error = -ENOMEM; | ||
611 | goto err_free_mem; | ||
612 | } | ||
613 | |||
614 | ts->spi = spi; | ||
615 | ts->idev = input_dev; | ||
616 | |||
617 | ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; | ||
618 | ts->esd_timeout = pdata->esd_timeout_ms; | ||
619 | ts->set_reset = pdata->set_reset; | ||
620 | |||
621 | mutex_init(&ts->mutex); | ||
622 | |||
623 | spin_lock_init(&ts->lock); | ||
624 | setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); | ||
625 | |||
626 | INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work); | ||
627 | |||
628 | tsc2005_setup_spi_xfer(ts); | ||
629 | |||
630 | snprintf(ts->phys, sizeof(ts->phys), | ||
631 | "%s/input-ts", dev_name(&spi->dev)); | ||
632 | |||
633 | input_dev->name = "TSC2005 touchscreen"; | ||
634 | input_dev->phys = ts->phys; | ||
635 | input_dev->id.bustype = BUS_SPI; | ||
636 | input_dev->dev.parent = &spi->dev; | ||
637 | input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); | ||
638 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
639 | |||
640 | input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0); | ||
641 | input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); | ||
642 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); | ||
643 | |||
644 | input_dev->open = tsc2005_open; | ||
645 | input_dev->close = tsc2005_close; | ||
646 | |||
647 | input_set_drvdata(input_dev, ts); | ||
648 | |||
649 | /* Ensure the touchscreen is off */ | ||
650 | tsc2005_stop_scan(ts); | ||
651 | |||
652 | error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, | ||
653 | IRQF_TRIGGER_RISING, "tsc2005", ts); | ||
654 | if (error) { | ||
655 | dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); | ||
656 | goto err_free_mem; | ||
657 | } | ||
658 | |||
659 | spi_set_drvdata(spi, ts); | ||
660 | error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group); | ||
661 | if (error) { | ||
662 | dev_err(&spi->dev, | ||
663 | "Failed to create sysfs attributes, err: %d\n", error); | ||
664 | goto err_clear_drvdata; | ||
665 | } | ||
666 | |||
667 | error = input_register_device(ts->idev); | ||
668 | if (error) { | ||
669 | dev_err(&spi->dev, | ||
670 | "Failed to register input device, err: %d\n", error); | ||
671 | goto err_remove_sysfs; | ||
672 | } | ||
673 | |||
674 | irq_set_irq_wake(spi->irq, 1); | ||
675 | return 0; | ||
676 | |||
677 | err_remove_sysfs: | ||
678 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); | ||
679 | err_clear_drvdata: | ||
680 | spi_set_drvdata(spi, NULL); | ||
681 | free_irq(spi->irq, ts); | ||
682 | err_free_mem: | ||
683 | input_free_device(input_dev); | ||
684 | kfree(ts); | ||
685 | return error; | ||
686 | } | ||
687 | |||
688 | static int __devexit tsc2005_remove(struct spi_device *spi) | ||
689 | { | ||
690 | struct tsc2005 *ts = spi_get_drvdata(spi); | ||
691 | |||
692 | sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); | ||
693 | |||
694 | free_irq(ts->spi->irq, ts); | ||
695 | input_unregister_device(ts->idev); | ||
696 | kfree(ts); | ||
697 | |||
698 | spi_set_drvdata(spi, NULL); | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | #ifdef CONFIG_PM_SLEEP | ||
703 | static int tsc2005_suspend(struct device *dev) | ||
704 | { | ||
705 | struct spi_device *spi = to_spi_device(dev); | ||
706 | struct tsc2005 *ts = spi_get_drvdata(spi); | ||
707 | |||
708 | mutex_lock(&ts->mutex); | ||
709 | |||
710 | if (!ts->suspended && ts->opened) | ||
711 | __tsc2005_disable(ts); | ||
712 | |||
713 | ts->suspended = true; | ||
714 | |||
715 | mutex_unlock(&ts->mutex); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int tsc2005_resume(struct device *dev) | ||
721 | { | ||
722 | struct spi_device *spi = to_spi_device(dev); | ||
723 | struct tsc2005 *ts = spi_get_drvdata(spi); | ||
724 | |||
725 | mutex_lock(&ts->mutex); | ||
726 | |||
727 | if (ts->suspended && ts->opened) | ||
728 | __tsc2005_enable(ts); | ||
729 | |||
730 | ts->suspended = false; | ||
731 | |||
732 | mutex_unlock(&ts->mutex); | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | #endif | ||
737 | |||
738 | static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume); | ||
739 | |||
740 | static struct spi_driver tsc2005_driver = { | ||
741 | .driver = { | ||
742 | .name = "tsc2005", | ||
743 | .owner = THIS_MODULE, | ||
744 | .pm = &tsc2005_pm_ops, | ||
745 | }, | ||
746 | .probe = tsc2005_probe, | ||
747 | .remove = __devexit_p(tsc2005_remove), | ||
748 | }; | ||
749 | |||
750 | static int __init tsc2005_init(void) | ||
751 | { | ||
752 | return spi_register_driver(&tsc2005_driver); | ||
753 | } | ||
754 | module_init(tsc2005_init); | ||
755 | |||
756 | static void __exit tsc2005_exit(void) | ||
757 | { | ||
758 | spi_unregister_driver(&tsc2005_driver); | ||
759 | } | ||
760 | module_exit(tsc2005_exit); | ||
761 | |||
762 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); | ||
763 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); | ||
764 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 028a5363eea1..3b5b5df04dd6 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright: MontaVista Software, Inc. | 6 | * Copyright: MontaVista Software, Inc. |
7 | * | 7 | * |
8 | * Spliting done by: Marek Vasut <marek.vasut@gmail.com> | 8 | * Spliting done by: Marek Vasut <marek.vasut@gmail.com> |
9 | * If something doesnt work and it worked before spliting, e-mail me, | 9 | * If something doesn't work and it worked before spliting, e-mail me, |
10 | * dont bother Nicolas please ;-) | 10 | * dont bother Nicolas please ;-) |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index f45f80f6d336..73fd6642b681 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -178,6 +178,7 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
178 | 178 | ||
179 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 179 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM |
180 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, | 180 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, |
181 | {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, | ||
181 | #endif | 182 | #endif |
182 | 183 | ||
183 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 184 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9ae4c7b16ba7..c14412ef4648 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2008 Jaya Kumar | 4 | * Copyright (c) 2008 Jaya Kumar |
5 | * Copyright (c) 2010 Red Hat, Inc. | 5 | * Copyright (c) 2010 Red Hat, Inc. |
6 | * Copyright (c) 2010 - 2011 Ping Cheng, Wacom. <pingc@wacom.com> | ||
6 | * | 7 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License. See the file COPYING in the main directory of this archive for | 9 | * License. See the file COPYING in the main directory of this archive for |
@@ -15,10 +16,11 @@ | |||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/input.h> | 19 | #include <linux/input/mt.h> |
19 | #include <linux/serio.h> | 20 | #include <linux/serio.h> |
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <linux/delay.h> | ||
22 | 24 | ||
23 | #define DRIVER_DESC "Wacom W8001 serial touchscreen driver" | 25 | #define DRIVER_DESC "Wacom W8001 serial touchscreen driver" |
24 | 26 | ||
@@ -37,6 +39,7 @@ MODULE_LICENSE("GPL"); | |||
37 | 39 | ||
38 | #define W8001_QUERY_PACKET 0x20 | 40 | #define W8001_QUERY_PACKET 0x20 |
39 | 41 | ||
42 | #define W8001_CMD_STOP '0' | ||
40 | #define W8001_CMD_START '1' | 43 | #define W8001_CMD_START '1' |
41 | #define W8001_CMD_QUERY '*' | 44 | #define W8001_CMD_QUERY '*' |
42 | #define W8001_CMD_TOUCHQUERY '%' | 45 | #define W8001_CMD_TOUCHQUERY '%' |
@@ -48,7 +51,9 @@ MODULE_LICENSE("GPL"); | |||
48 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ | 51 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ |
49 | #define W8001_PKTLEN_TOUCH2FG 13 | 52 | #define W8001_PKTLEN_TOUCH2FG 13 |
50 | 53 | ||
51 | #define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */ | 54 | /* resolution in points/mm */ |
55 | #define W8001_PEN_RESOLUTION 100 | ||
56 | #define W8001_TOUCH_RESOLUTION 10 | ||
52 | 57 | ||
53 | struct w8001_coord { | 58 | struct w8001_coord { |
54 | u8 rdy; | 59 | u8 rdy; |
@@ -64,11 +69,11 @@ struct w8001_coord { | |||
64 | 69 | ||
65 | /* touch query reply packet */ | 70 | /* touch query reply packet */ |
66 | struct w8001_touch_query { | 71 | struct w8001_touch_query { |
72 | u16 x; | ||
73 | u16 y; | ||
67 | u8 panel_res; | 74 | u8 panel_res; |
68 | u8 capacity_res; | 75 | u8 capacity_res; |
69 | u8 sensor_id; | 76 | u8 sensor_id; |
70 | u16 x; | ||
71 | u16 y; | ||
72 | }; | 77 | }; |
73 | 78 | ||
74 | /* | 79 | /* |
@@ -87,10 +92,14 @@ struct w8001 { | |||
87 | char phys[32]; | 92 | char phys[32]; |
88 | int type; | 93 | int type; |
89 | unsigned int pktlen; | 94 | unsigned int pktlen; |
90 | int trkid[2]; | 95 | u16 max_touch_x; |
96 | u16 max_touch_y; | ||
97 | u16 max_pen_x; | ||
98 | u16 max_pen_y; | ||
99 | char name[64]; | ||
91 | }; | 100 | }; |
92 | 101 | ||
93 | static void parse_data(u8 *data, struct w8001_coord *coord) | 102 | static void parse_pen_data(u8 *data, struct w8001_coord *coord) |
94 | { | 103 | { |
95 | memset(coord, 0, sizeof(*coord)); | 104 | memset(coord, 0, sizeof(*coord)); |
96 | 105 | ||
@@ -114,30 +123,58 @@ static void parse_data(u8 *data, struct w8001_coord *coord) | |||
114 | coord->tilt_y = data[8] & 0x7F; | 123 | coord->tilt_y = data[8] & 0x7F; |
115 | } | 124 | } |
116 | 125 | ||
117 | static void parse_touch(struct w8001 *w8001) | 126 | static void parse_single_touch(u8 *data, struct w8001_coord *coord) |
127 | { | ||
128 | coord->x = (data[1] << 7) | data[2]; | ||
129 | coord->y = (data[3] << 7) | data[4]; | ||
130 | coord->tsw = data[0] & 0x01; | ||
131 | } | ||
132 | |||
133 | static void scale_touch_coordinates(struct w8001 *w8001, | ||
134 | unsigned int *x, unsigned int *y) | ||
135 | { | ||
136 | if (w8001->max_pen_x && w8001->max_touch_x) | ||
137 | *x = *x * w8001->max_pen_x / w8001->max_touch_x; | ||
138 | |||
139 | if (w8001->max_pen_y && w8001->max_touch_y) | ||
140 | *y = *y * w8001->max_pen_y / w8001->max_touch_y; | ||
141 | } | ||
142 | |||
143 | static void parse_multi_touch(struct w8001 *w8001) | ||
118 | { | 144 | { |
119 | static int trkid; | ||
120 | struct input_dev *dev = w8001->dev; | 145 | struct input_dev *dev = w8001->dev; |
121 | unsigned char *data = w8001->data; | 146 | unsigned char *data = w8001->data; |
147 | unsigned int x, y; | ||
122 | int i; | 148 | int i; |
149 | int count = 0; | ||
123 | 150 | ||
124 | for (i = 0; i < 2; i++) { | 151 | for (i = 0; i < 2; i++) { |
125 | input_mt_slot(dev, i); | 152 | bool touch = data[0] & (1 << i); |
126 | 153 | ||
127 | if (data[0] & (1 << i)) { | 154 | input_mt_slot(dev, i); |
128 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); | 155 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); |
129 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); | 156 | if (touch) { |
157 | x = (data[6 * i + 1] << 7) | data[6 * i + 2]; | ||
158 | y = (data[6 * i + 3] << 7) | data[6 * i + 4]; | ||
130 | /* data[5,6] and [11,12] is finger capacity */ | 159 | /* data[5,6] and [11,12] is finger capacity */ |
131 | 160 | ||
161 | /* scale to pen maximum */ | ||
162 | scale_touch_coordinates(w8001, &x, &y); | ||
163 | |||
132 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 164 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
133 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 165 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
134 | input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER); | 166 | count++; |
135 | if (w8001->trkid[i] < 0) | ||
136 | w8001->trkid[i] = trkid++ & MAX_TRACKING_ID; | ||
137 | } else { | ||
138 | w8001->trkid[i] = -1; | ||
139 | } | 167 | } |
140 | input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]); | 168 | } |
169 | |||
170 | /* emulate single touch events when stylus is out of proximity. | ||
171 | * This is to make single touch backward support consistent | ||
172 | * across all Wacom single touch devices. | ||
173 | */ | ||
174 | if (w8001->type != BTN_TOOL_PEN && | ||
175 | w8001->type != BTN_TOOL_RUBBER) { | ||
176 | w8001->type = count == 1 ? BTN_TOOL_FINGER : KEY_RESERVED; | ||
177 | input_mt_report_pointer_emulation(dev, true); | ||
141 | } | 178 | } |
142 | 179 | ||
143 | input_sync(dev); | 180 | input_sync(dev); |
@@ -158,6 +195,15 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) | |||
158 | query->y = data[5] << 9; | 195 | query->y = data[5] << 9; |
159 | query->y |= data[6] << 2; | 196 | query->y |= data[6] << 2; |
160 | query->y |= (data[2] >> 3) & 0x3; | 197 | query->y |= (data[2] >> 3) & 0x3; |
198 | |||
199 | /* Early days' single-finger touch models need the following defaults */ | ||
200 | if (!query->x && !query->y) { | ||
201 | query->x = 1024; | ||
202 | query->y = 1024; | ||
203 | if (query->panel_res) | ||
204 | query->x = query->y = (1 << query->panel_res); | ||
205 | query->panel_res = W8001_TOUCH_RESOLUTION; | ||
206 | } | ||
161 | } | 207 | } |
162 | 208 | ||
163 | static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | 209 | static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) |
@@ -167,16 +213,15 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
167 | /* | 213 | /* |
168 | * We have 1 bit for proximity (rdy) and 3 bits for tip, side, | 214 | * We have 1 bit for proximity (rdy) and 3 bits for tip, side, |
169 | * side2/eraser. If rdy && f2 are set, this can be either pen + side2, | 215 | * side2/eraser. If rdy && f2 are set, this can be either pen + side2, |
170 | * or eraser. assume | 216 | * or eraser. Assume: |
171 | * - if dev is already in proximity and f2 is toggled → pen + side2 | 217 | * - if dev is already in proximity and f2 is toggled → pen + side2 |
172 | * - if dev comes into proximity with f2 set → eraser | 218 | * - if dev comes into proximity with f2 set → eraser |
173 | * If f2 disappears after assuming eraser, fake proximity out for | 219 | * If f2 disappears after assuming eraser, fake proximity out for |
174 | * eraser and in for pen. | 220 | * eraser and in for pen. |
175 | */ | 221 | */ |
176 | 222 | ||
177 | if (!w8001->type) { | 223 | switch (w8001->type) { |
178 | w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 224 | case BTN_TOOL_RUBBER: |
179 | } else if (w8001->type == BTN_TOOL_RUBBER) { | ||
180 | if (!coord->f2) { | 225 | if (!coord->f2) { |
181 | input_report_abs(dev, ABS_PRESSURE, 0); | 226 | input_report_abs(dev, ABS_PRESSURE, 0); |
182 | input_report_key(dev, BTN_TOUCH, 0); | 227 | input_report_key(dev, BTN_TOUCH, 0); |
@@ -186,8 +231,21 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
186 | input_sync(dev); | 231 | input_sync(dev); |
187 | w8001->type = BTN_TOOL_PEN; | 232 | w8001->type = BTN_TOOL_PEN; |
188 | } | 233 | } |
189 | } else { | 234 | break; |
235 | |||
236 | case BTN_TOOL_FINGER: | ||
237 | input_report_key(dev, BTN_TOUCH, 0); | ||
238 | input_report_key(dev, BTN_TOOL_FINGER, 0); | ||
239 | input_sync(dev); | ||
240 | /* fall through */ | ||
241 | |||
242 | case KEY_RESERVED: | ||
243 | w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
244 | break; | ||
245 | |||
246 | default: | ||
190 | input_report_key(dev, BTN_STYLUS2, coord->f2); | 247 | input_report_key(dev, BTN_STYLUS2, coord->f2); |
248 | break; | ||
191 | } | 249 | } |
192 | 250 | ||
193 | input_report_abs(dev, ABS_X, coord->x); | 251 | input_report_abs(dev, ABS_X, coord->x); |
@@ -199,7 +257,26 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
199 | input_sync(dev); | 257 | input_sync(dev); |
200 | 258 | ||
201 | if (!coord->rdy) | 259 | if (!coord->rdy) |
202 | w8001->type = 0; | 260 | w8001->type = KEY_RESERVED; |
261 | } | ||
262 | |||
263 | static void report_single_touch(struct w8001 *w8001, struct w8001_coord *coord) | ||
264 | { | ||
265 | struct input_dev *dev = w8001->dev; | ||
266 | unsigned int x = coord->x; | ||
267 | unsigned int y = coord->y; | ||
268 | |||
269 | /* scale to pen maximum */ | ||
270 | scale_touch_coordinates(w8001, &x, &y); | ||
271 | |||
272 | input_report_abs(dev, ABS_X, x); | ||
273 | input_report_abs(dev, ABS_Y, y); | ||
274 | input_report_key(dev, BTN_TOUCH, coord->tsw); | ||
275 | input_report_key(dev, BTN_TOOL_FINGER, coord->tsw); | ||
276 | |||
277 | input_sync(dev); | ||
278 | |||
279 | w8001->type = coord->tsw ? BTN_TOOL_FINGER : KEY_RESERVED; | ||
203 | } | 280 | } |
204 | 281 | ||
205 | static irqreturn_t w8001_interrupt(struct serio *serio, | 282 | static irqreturn_t w8001_interrupt(struct serio *serio, |
@@ -220,9 +297,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
220 | 297 | ||
221 | case W8001_PKTLEN_TOUCH93 - 1: | 298 | case W8001_PKTLEN_TOUCH93 - 1: |
222 | case W8001_PKTLEN_TOUCH9A - 1: | 299 | case W8001_PKTLEN_TOUCH9A - 1: |
223 | /* ignore one-finger touch packet. */ | 300 | tmp = w8001->data[0] & W8001_TOUCH_BYTE; |
224 | if (w8001->pktlen == w8001->idx) | 301 | if (tmp != W8001_TOUCH_BYTE) |
302 | break; | ||
303 | |||
304 | if (w8001->pktlen == w8001->idx) { | ||
225 | w8001->idx = 0; | 305 | w8001->idx = 0; |
306 | if (w8001->type != BTN_TOOL_PEN && | ||
307 | w8001->type != BTN_TOOL_RUBBER) { | ||
308 | parse_single_touch(w8001->data, &coord); | ||
309 | report_single_touch(w8001, &coord); | ||
310 | } | ||
311 | } | ||
226 | break; | 312 | break; |
227 | 313 | ||
228 | /* Pen coordinates packet */ | 314 | /* Pen coordinates packet */ |
@@ -231,18 +317,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
231 | if (unlikely(tmp == W8001_TAB_BYTE)) | 317 | if (unlikely(tmp == W8001_TAB_BYTE)) |
232 | break; | 318 | break; |
233 | 319 | ||
234 | tmp = (w8001->data[0] & W8001_TOUCH_BYTE); | 320 | tmp = w8001->data[0] & W8001_TOUCH_BYTE; |
235 | if (tmp == W8001_TOUCH_BYTE) | 321 | if (tmp == W8001_TOUCH_BYTE) |
236 | break; | 322 | break; |
237 | 323 | ||
238 | w8001->idx = 0; | 324 | w8001->idx = 0; |
239 | parse_data(w8001->data, &coord); | 325 | parse_pen_data(w8001->data, &coord); |
240 | report_pen_events(w8001, &coord); | 326 | report_pen_events(w8001, &coord); |
241 | break; | 327 | break; |
242 | 328 | ||
243 | /* control packet */ | 329 | /* control packet */ |
244 | case W8001_PKTLEN_TPCCTL - 1: | 330 | case W8001_PKTLEN_TPCCTL - 1: |
245 | tmp = (w8001->data[0] & W8001_TOUCH_MASK); | 331 | tmp = w8001->data[0] & W8001_TOUCH_MASK; |
246 | if (tmp == W8001_TOUCH_BYTE) | 332 | if (tmp == W8001_TOUCH_BYTE) |
247 | break; | 333 | break; |
248 | 334 | ||
@@ -255,7 +341,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
255 | /* 2 finger touch packet */ | 341 | /* 2 finger touch packet */ |
256 | case W8001_PKTLEN_TOUCH2FG - 1: | 342 | case W8001_PKTLEN_TOUCH2FG - 1: |
257 | w8001->idx = 0; | 343 | w8001->idx = 0; |
258 | parse_touch(w8001); | 344 | parse_multi_touch(w8001); |
259 | break; | 345 | break; |
260 | } | 346 | } |
261 | 347 | ||
@@ -285,52 +371,109 @@ static int w8001_setup(struct w8001 *w8001) | |||
285 | { | 371 | { |
286 | struct input_dev *dev = w8001->dev; | 372 | struct input_dev *dev = w8001->dev; |
287 | struct w8001_coord coord; | 373 | struct w8001_coord coord; |
374 | struct w8001_touch_query touch; | ||
288 | int error; | 375 | int error; |
289 | 376 | ||
290 | error = w8001_command(w8001, W8001_CMD_QUERY, true); | 377 | error = w8001_command(w8001, W8001_CMD_STOP, false); |
291 | if (error) | 378 | if (error) |
292 | return error; | 379 | return error; |
293 | 380 | ||
294 | parse_data(w8001->response, &coord); | 381 | msleep(250); /* wait 250ms before querying the device */ |
295 | 382 | ||
296 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 383 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
297 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 384 | strlcat(w8001->name, "Wacom Serial", sizeof(w8001->name)); |
298 | input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); | ||
299 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | ||
300 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | ||
301 | 385 | ||
302 | error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); | 386 | /* penabled? */ |
387 | error = w8001_command(w8001, W8001_CMD_QUERY, true); | ||
303 | if (!error) { | 388 | if (!error) { |
304 | struct w8001_touch_query touch; | 389 | __set_bit(BTN_TOUCH, dev->keybit); |
390 | __set_bit(BTN_TOOL_PEN, dev->keybit); | ||
391 | __set_bit(BTN_TOOL_RUBBER, dev->keybit); | ||
392 | __set_bit(BTN_STYLUS, dev->keybit); | ||
393 | __set_bit(BTN_STYLUS2, dev->keybit); | ||
394 | |||
395 | parse_pen_data(w8001->response, &coord); | ||
396 | w8001->max_pen_x = coord.x; | ||
397 | w8001->max_pen_y = coord.y; | ||
398 | |||
399 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | ||
400 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | ||
401 | input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION); | ||
402 | input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION); | ||
403 | input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); | ||
404 | if (coord.tilt_x && coord.tilt_y) { | ||
405 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | ||
406 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | ||
407 | } | ||
408 | w8001->id = 0x90; | ||
409 | strlcat(w8001->name, " Penabled", sizeof(w8001->name)); | ||
410 | } | ||
411 | |||
412 | /* Touch enabled? */ | ||
413 | error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); | ||
414 | |||
415 | /* | ||
416 | * Some non-touch devices may reply to the touch query. But their | ||
417 | * second byte is empty, which indicates touch is not supported. | ||
418 | */ | ||
419 | if (!error && w8001->response[1]) { | ||
420 | __set_bit(BTN_TOUCH, dev->keybit); | ||
421 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
305 | 422 | ||
306 | parse_touchquery(w8001->response, &touch); | 423 | parse_touchquery(w8001->response, &touch); |
424 | w8001->max_touch_x = touch.x; | ||
425 | w8001->max_touch_y = touch.y; | ||
426 | |||
427 | if (w8001->max_pen_x && w8001->max_pen_y) { | ||
428 | /* if pen is supported scale to pen maximum */ | ||
429 | touch.x = w8001->max_pen_x; | ||
430 | touch.y = w8001->max_pen_y; | ||
431 | touch.panel_res = W8001_PEN_RESOLUTION; | ||
432 | } | ||
433 | |||
434 | input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); | ||
435 | input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); | ||
436 | input_abs_set_res(dev, ABS_X, touch.panel_res); | ||
437 | input_abs_set_res(dev, ABS_Y, touch.panel_res); | ||
307 | 438 | ||
308 | switch (touch.sensor_id) { | 439 | switch (touch.sensor_id) { |
309 | case 0: | 440 | case 0: |
310 | case 2: | 441 | case 2: |
311 | w8001->pktlen = W8001_PKTLEN_TOUCH93; | 442 | w8001->pktlen = W8001_PKTLEN_TOUCH93; |
443 | w8001->id = 0x93; | ||
444 | strlcat(w8001->name, " 1FG", sizeof(w8001->name)); | ||
312 | break; | 445 | break; |
446 | |||
313 | case 1: | 447 | case 1: |
314 | case 3: | 448 | case 3: |
315 | case 4: | 449 | case 4: |
316 | w8001->pktlen = W8001_PKTLEN_TOUCH9A; | 450 | w8001->pktlen = W8001_PKTLEN_TOUCH9A; |
451 | strlcat(w8001->name, " 1FG", sizeof(w8001->name)); | ||
452 | w8001->id = 0x9a; | ||
317 | break; | 453 | break; |
454 | |||
318 | case 5: | 455 | case 5: |
319 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 456 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
320 | 457 | ||
321 | input_mt_create_slots(dev, 2); | 458 | input_mt_init_slots(dev, 2); |
322 | input_set_abs_params(dev, ABS_MT_TRACKING_ID, | ||
323 | 0, MAX_TRACKING_ID, 0, 0); | ||
324 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 459 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
325 | 0, touch.x, 0, 0); | 460 | 0, touch.x, 0, 0); |
326 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | 461 | input_set_abs_params(dev, ABS_MT_POSITION_Y, |
327 | 0, touch.y, 0, 0); | 462 | 0, touch.y, 0, 0); |
328 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, | 463 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, |
329 | 0, 0, 0, 0); | 464 | 0, MT_TOOL_MAX, 0, 0); |
465 | |||
466 | strlcat(w8001->name, " 2FG", sizeof(w8001->name)); | ||
467 | if (w8001->max_pen_x && w8001->max_pen_y) | ||
468 | w8001->id = 0xE3; | ||
469 | else | ||
470 | w8001->id = 0xE2; | ||
330 | break; | 471 | break; |
331 | } | 472 | } |
332 | } | 473 | } |
333 | 474 | ||
475 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); | ||
476 | |||
334 | return w8001_command(w8001, W8001_CMD_START, false); | 477 | return w8001_command(w8001, W8001_CMD_START, false); |
335 | } | 478 | } |
336 | 479 | ||
@@ -370,27 +513,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
370 | } | 513 | } |
371 | 514 | ||
372 | w8001->serio = serio; | 515 | w8001->serio = serio; |
373 | w8001->id = serio->id.id; | ||
374 | w8001->dev = input_dev; | 516 | w8001->dev = input_dev; |
375 | w8001->trkid[0] = w8001->trkid[1] = -1; | ||
376 | init_completion(&w8001->cmd_done); | 517 | init_completion(&w8001->cmd_done); |
377 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 518 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
378 | 519 | ||
379 | input_dev->name = "Wacom W8001 Penabled Serial TouchScreen"; | ||
380 | input_dev->phys = w8001->phys; | ||
381 | input_dev->id.bustype = BUS_RS232; | ||
382 | input_dev->id.vendor = SERIO_W8001; | ||
383 | input_dev->id.product = w8001->id; | ||
384 | input_dev->id.version = 0x0100; | ||
385 | input_dev->dev.parent = &serio->dev; | ||
386 | |||
387 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
388 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
389 | input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN); | ||
390 | input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER); | ||
391 | input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS); | ||
392 | input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2); | ||
393 | |||
394 | serio_set_drvdata(serio, w8001); | 520 | serio_set_drvdata(serio, w8001); |
395 | err = serio_open(serio, drv); | 521 | err = serio_open(serio, drv); |
396 | if (err) | 522 | if (err) |
@@ -400,6 +526,14 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
400 | if (err) | 526 | if (err) |
401 | goto fail3; | 527 | goto fail3; |
402 | 528 | ||
529 | input_dev->name = w8001->name; | ||
530 | input_dev->phys = w8001->phys; | ||
531 | input_dev->id.product = w8001->id; | ||
532 | input_dev->id.bustype = BUS_RS232; | ||
533 | input_dev->id.vendor = 0x056a; | ||
534 | input_dev->id.version = 0x0100; | ||
535 | input_dev->dev.parent = &serio->dev; | ||
536 | |||
403 | err = input_register_device(w8001->dev); | 537 | err = input_register_device(w8001->dev); |
404 | if (err) | 538 | if (err) |
405 | goto fail3; | 539 | goto fail3; |
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c new file mode 100644 index 000000000000..9175d49d2546 --- /dev/null +++ b/drivers/input/touchscreen/wm831x-ts.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /* | ||
2 | * Touchscreen driver for WM831x PMICs | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
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 as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/mfd/wm831x/core.h> | ||
23 | #include <linux/mfd/wm831x/irq.h> | ||
24 | #include <linux/mfd/wm831x/pdata.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | ||
28 | |||
29 | /* | ||
30 | * R16424 (0x4028) - Touch Control 1 | ||
31 | */ | ||
32 | #define WM831X_TCH_ENA 0x8000 /* TCH_ENA */ | ||
33 | #define WM831X_TCH_CVT_ENA 0x4000 /* TCH_CVT_ENA */ | ||
34 | #define WM831X_TCH_SLPENA 0x1000 /* TCH_SLPENA */ | ||
35 | #define WM831X_TCH_Z_ENA 0x0400 /* TCH_Z_ENA */ | ||
36 | #define WM831X_TCH_Y_ENA 0x0200 /* TCH_Y_ENA */ | ||
37 | #define WM831X_TCH_X_ENA 0x0100 /* TCH_X_ENA */ | ||
38 | #define WM831X_TCH_DELAY_MASK 0x00E0 /* TCH_DELAY - [7:5] */ | ||
39 | #define WM831X_TCH_DELAY_SHIFT 5 /* TCH_DELAY - [7:5] */ | ||
40 | #define WM831X_TCH_DELAY_WIDTH 3 /* TCH_DELAY - [7:5] */ | ||
41 | #define WM831X_TCH_RATE_MASK 0x001F /* TCH_RATE - [4:0] */ | ||
42 | #define WM831X_TCH_RATE_SHIFT 0 /* TCH_RATE - [4:0] */ | ||
43 | #define WM831X_TCH_RATE_WIDTH 5 /* TCH_RATE - [4:0] */ | ||
44 | |||
45 | /* | ||
46 | * R16425 (0x4029) - Touch Control 2 | ||
47 | */ | ||
48 | #define WM831X_TCH_PD_WK 0x2000 /* TCH_PD_WK */ | ||
49 | #define WM831X_TCH_5WIRE 0x1000 /* TCH_5WIRE */ | ||
50 | #define WM831X_TCH_PDONLY 0x0800 /* TCH_PDONLY */ | ||
51 | #define WM831X_TCH_ISEL 0x0100 /* TCH_ISEL */ | ||
52 | #define WM831X_TCH_RPU_MASK 0x000F /* TCH_RPU - [3:0] */ | ||
53 | #define WM831X_TCH_RPU_SHIFT 0 /* TCH_RPU - [3:0] */ | ||
54 | #define WM831X_TCH_RPU_WIDTH 4 /* TCH_RPU - [3:0] */ | ||
55 | |||
56 | /* | ||
57 | * R16426-8 (0x402A-C) - Touch Data X/Y/X | ||
58 | */ | ||
59 | #define WM831X_TCH_PD 0x8000 /* TCH_PD1 */ | ||
60 | #define WM831X_TCH_DATA_MASK 0x0FFF /* TCH_DATA - [11:0] */ | ||
61 | #define WM831X_TCH_DATA_SHIFT 0 /* TCH_DATA - [11:0] */ | ||
62 | #define WM831X_TCH_DATA_WIDTH 12 /* TCH_DATA - [11:0] */ | ||
63 | |||
64 | struct wm831x_ts { | ||
65 | struct input_dev *input_dev; | ||
66 | struct wm831x *wm831x; | ||
67 | unsigned int data_irq; | ||
68 | unsigned int pd_irq; | ||
69 | bool pressure; | ||
70 | bool pen_down; | ||
71 | struct work_struct pd_data_work; | ||
72 | }; | ||
73 | |||
74 | static void wm831x_pd_data_work(struct work_struct *work) | ||
75 | { | ||
76 | struct wm831x_ts *wm831x_ts = | ||
77 | container_of(work, struct wm831x_ts, pd_data_work); | ||
78 | |||
79 | if (wm831x_ts->pen_down) { | ||
80 | enable_irq(wm831x_ts->data_irq); | ||
81 | dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n"); | ||
82 | } else { | ||
83 | enable_irq(wm831x_ts->pd_irq); | ||
84 | dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n"); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) | ||
89 | { | ||
90 | struct wm831x_ts *wm831x_ts = irq_data; | ||
91 | struct wm831x *wm831x = wm831x_ts->wm831x; | ||
92 | static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE }; | ||
93 | u16 data[3]; | ||
94 | int count; | ||
95 | int i, ret; | ||
96 | |||
97 | if (wm831x_ts->pressure) | ||
98 | count = 3; | ||
99 | else | ||
100 | count = 2; | ||
101 | |||
102 | wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, | ||
103 | WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT); | ||
104 | |||
105 | ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, | ||
106 | data); | ||
107 | if (ret != 0) { | ||
108 | dev_err(wm831x->dev, "Failed to read touch data: %d\n", | ||
109 | ret); | ||
110 | return IRQ_NONE; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * We get a pen down reading on every reading, report pen up if any | ||
115 | * individual reading does so. | ||
116 | */ | ||
117 | wm831x_ts->pen_down = true; | ||
118 | for (i = 0; i < count; i++) { | ||
119 | if (!(data[i] & WM831X_TCH_PD)) { | ||
120 | wm831x_ts->pen_down = false; | ||
121 | continue; | ||
122 | } | ||
123 | input_report_abs(wm831x_ts->input_dev, data_types[i], | ||
124 | data[i] & WM831X_TCH_DATA_MASK); | ||
125 | } | ||
126 | |||
127 | if (!wm831x_ts->pen_down) { | ||
128 | /* Switch from data to pen down */ | ||
129 | dev_dbg(wm831x->dev, "IRQ DATA->PD\n"); | ||
130 | |||
131 | disable_irq_nosync(wm831x_ts->data_irq); | ||
132 | |||
133 | /* Don't need data any more */ | ||
134 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
135 | WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | | ||
136 | WM831X_TCH_Z_ENA, 0); | ||
137 | |||
138 | /* Flush any final samples that arrived while reading */ | ||
139 | wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, | ||
140 | WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT); | ||
141 | |||
142 | wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data); | ||
143 | |||
144 | if (wm831x_ts->pressure) | ||
145 | input_report_abs(wm831x_ts->input_dev, | ||
146 | ABS_PRESSURE, 0); | ||
147 | |||
148 | input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); | ||
149 | |||
150 | schedule_work(&wm831x_ts->pd_data_work); | ||
151 | } else { | ||
152 | input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1); | ||
153 | } | ||
154 | |||
155 | input_sync(wm831x_ts->input_dev); | ||
156 | |||
157 | return IRQ_HANDLED; | ||
158 | } | ||
159 | |||
160 | static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data) | ||
161 | { | ||
162 | struct wm831x_ts *wm831x_ts = irq_data; | ||
163 | struct wm831x *wm831x = wm831x_ts->wm831x; | ||
164 | int ena = 0; | ||
165 | |||
166 | if (wm831x_ts->pen_down) | ||
167 | return IRQ_HANDLED; | ||
168 | |||
169 | disable_irq_nosync(wm831x_ts->pd_irq); | ||
170 | |||
171 | /* Start collecting data */ | ||
172 | if (wm831x_ts->pressure) | ||
173 | ena |= WM831X_TCH_Z_ENA; | ||
174 | |||
175 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
176 | WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, | ||
177 | WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena); | ||
178 | |||
179 | wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, | ||
180 | WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); | ||
181 | |||
182 | wm831x_ts->pen_down = true; | ||
183 | |||
184 | /* Switch from pen down to data */ | ||
185 | dev_dbg(wm831x->dev, "IRQ PD->DATA\n"); | ||
186 | schedule_work(&wm831x_ts->pd_data_work); | ||
187 | |||
188 | return IRQ_HANDLED; | ||
189 | } | ||
190 | |||
191 | static int wm831x_ts_input_open(struct input_dev *idev) | ||
192 | { | ||
193 | struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); | ||
194 | struct wm831x *wm831x = wm831x_ts->wm831x; | ||
195 | |||
196 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
197 | WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | | ||
198 | WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | | ||
199 | WM831X_TCH_Z_ENA, WM831X_TCH_ENA); | ||
200 | |||
201 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
202 | WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static void wm831x_ts_input_close(struct input_dev *idev) | ||
208 | { | ||
209 | struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); | ||
210 | struct wm831x *wm831x = wm831x_ts->wm831x; | ||
211 | |||
212 | /* Shut the controller down, disabling all other functionality too */ | ||
213 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
214 | WM831X_TCH_ENA | WM831X_TCH_X_ENA | | ||
215 | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0); | ||
216 | |||
217 | /* Make sure any pending IRQs are done, the above will prevent | ||
218 | * new ones firing. | ||
219 | */ | ||
220 | synchronize_irq(wm831x_ts->data_irq); | ||
221 | synchronize_irq(wm831x_ts->pd_irq); | ||
222 | |||
223 | /* Make sure the IRQ completion work is quiesced */ | ||
224 | flush_work_sync(&wm831x_ts->pd_data_work); | ||
225 | |||
226 | /* If we ended up with the pen down then make sure we revert back | ||
227 | * to pen detection state for the next time we start up. | ||
228 | */ | ||
229 | if (wm831x_ts->pen_down) { | ||
230 | disable_irq(wm831x_ts->data_irq); | ||
231 | enable_irq(wm831x_ts->pd_irq); | ||
232 | wm831x_ts->pen_down = false; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | static __devinit int wm831x_ts_probe(struct platform_device *pdev) | ||
237 | { | ||
238 | struct wm831x_ts *wm831x_ts; | ||
239 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | ||
240 | struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent); | ||
241 | struct wm831x_touch_pdata *pdata = NULL; | ||
242 | struct input_dev *input_dev; | ||
243 | int error, irqf; | ||
244 | |||
245 | if (core_pdata) | ||
246 | pdata = core_pdata->touch; | ||
247 | |||
248 | wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL); | ||
249 | input_dev = input_allocate_device(); | ||
250 | if (!wm831x_ts || !input_dev) { | ||
251 | error = -ENOMEM; | ||
252 | goto err_alloc; | ||
253 | } | ||
254 | |||
255 | wm831x_ts->wm831x = wm831x; | ||
256 | wm831x_ts->input_dev = input_dev; | ||
257 | INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work); | ||
258 | |||
259 | /* | ||
260 | * If we have a direct IRQ use it, otherwise use the interrupt | ||
261 | * from the WM831x IRQ controller. | ||
262 | */ | ||
263 | if (pdata && pdata->data_irq) | ||
264 | wm831x_ts->data_irq = pdata->data_irq; | ||
265 | else | ||
266 | wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); | ||
267 | |||
268 | if (pdata && pdata->pd_irq) | ||
269 | wm831x_ts->pd_irq = pdata->pd_irq; | ||
270 | else | ||
271 | wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); | ||
272 | |||
273 | if (pdata) | ||
274 | wm831x_ts->pressure = pdata->pressure; | ||
275 | else | ||
276 | wm831x_ts->pressure = true; | ||
277 | |||
278 | /* Five wire touchscreens can't report pressure */ | ||
279 | if (pdata && pdata->fivewire) { | ||
280 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, | ||
281 | WM831X_TCH_5WIRE, WM831X_TCH_5WIRE); | ||
282 | |||
283 | /* Pressure measurements are not possible for five wire mode */ | ||
284 | WARN_ON(pdata->pressure && pdata->fivewire); | ||
285 | wm831x_ts->pressure = false; | ||
286 | } else { | ||
287 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, | ||
288 | WM831X_TCH_5WIRE, 0); | ||
289 | } | ||
290 | |||
291 | if (pdata) { | ||
292 | switch (pdata->isel) { | ||
293 | default: | ||
294 | dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n", | ||
295 | pdata->isel); | ||
296 | /* Fall through */ | ||
297 | case 200: | ||
298 | case 0: | ||
299 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, | ||
300 | WM831X_TCH_ISEL, 0); | ||
301 | break; | ||
302 | case 400: | ||
303 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, | ||
304 | WM831X_TCH_ISEL, WM831X_TCH_ISEL); | ||
305 | break; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, | ||
310 | WM831X_TCH_PDONLY, 0); | ||
311 | |||
312 | /* Default to 96 samples/sec */ | ||
313 | wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, | ||
314 | WM831X_TCH_RATE_MASK, 6); | ||
315 | |||
316 | if (pdata && pdata->data_irqf) | ||
317 | irqf = pdata->data_irqf; | ||
318 | else | ||
319 | irqf = IRQF_TRIGGER_HIGH; | ||
320 | |||
321 | error = request_threaded_irq(wm831x_ts->data_irq, | ||
322 | NULL, wm831x_ts_data_irq, | ||
323 | irqf | IRQF_ONESHOT, | ||
324 | "Touchscreen data", wm831x_ts); | ||
325 | if (error) { | ||
326 | dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n", | ||
327 | wm831x_ts->data_irq, error); | ||
328 | goto err_alloc; | ||
329 | } | ||
330 | disable_irq(wm831x_ts->data_irq); | ||
331 | |||
332 | if (pdata && pdata->pd_irqf) | ||
333 | irqf = pdata->pd_irqf; | ||
334 | else | ||
335 | irqf = IRQF_TRIGGER_HIGH; | ||
336 | |||
337 | error = request_threaded_irq(wm831x_ts->pd_irq, | ||
338 | NULL, wm831x_ts_pen_down_irq, | ||
339 | irqf | IRQF_ONESHOT, | ||
340 | "Touchscreen pen down", wm831x_ts); | ||
341 | if (error) { | ||
342 | dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n", | ||
343 | wm831x_ts->pd_irq, error); | ||
344 | goto err_data_irq; | ||
345 | } | ||
346 | |||
347 | /* set up touch configuration */ | ||
348 | input_dev->name = "WM831x touchscreen"; | ||
349 | input_dev->phys = "wm831x"; | ||
350 | input_dev->open = wm831x_ts_input_open; | ||
351 | input_dev->close = wm831x_ts_input_close; | ||
352 | |||
353 | __set_bit(EV_ABS, input_dev->evbit); | ||
354 | __set_bit(EV_KEY, input_dev->evbit); | ||
355 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
356 | |||
357 | input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0); | ||
358 | input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0); | ||
359 | if (wm831x_ts->pressure) | ||
360 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0); | ||
361 | |||
362 | input_set_drvdata(input_dev, wm831x_ts); | ||
363 | input_dev->dev.parent = &pdev->dev; | ||
364 | |||
365 | error = input_register_device(input_dev); | ||
366 | if (error) | ||
367 | goto err_pd_irq; | ||
368 | |||
369 | platform_set_drvdata(pdev, wm831x_ts); | ||
370 | return 0; | ||
371 | |||
372 | err_pd_irq: | ||
373 | free_irq(wm831x_ts->pd_irq, wm831x_ts); | ||
374 | err_data_irq: | ||
375 | free_irq(wm831x_ts->data_irq, wm831x_ts); | ||
376 | err_alloc: | ||
377 | input_free_device(input_dev); | ||
378 | kfree(wm831x_ts); | ||
379 | |||
380 | return error; | ||
381 | } | ||
382 | |||
383 | static __devexit int wm831x_ts_remove(struct platform_device *pdev) | ||
384 | { | ||
385 | struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev); | ||
386 | |||
387 | free_irq(wm831x_ts->pd_irq, wm831x_ts); | ||
388 | free_irq(wm831x_ts->data_irq, wm831x_ts); | ||
389 | input_unregister_device(wm831x_ts->input_dev); | ||
390 | kfree(wm831x_ts); | ||
391 | |||
392 | platform_set_drvdata(pdev, NULL); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static struct platform_driver wm831x_ts_driver = { | ||
397 | .driver = { | ||
398 | .name = "wm831x-touch", | ||
399 | .owner = THIS_MODULE, | ||
400 | }, | ||
401 | .probe = wm831x_ts_probe, | ||
402 | .remove = __devexit_p(wm831x_ts_remove), | ||
403 | }; | ||
404 | |||
405 | static int __init wm831x_ts_init(void) | ||
406 | { | ||
407 | return platform_driver_register(&wm831x_ts_driver); | ||
408 | } | ||
409 | module_init(wm831x_ts_init); | ||
410 | |||
411 | static void __exit wm831x_ts_exit(void) | ||
412 | { | ||
413 | platform_driver_unregister(&wm831x_ts_driver); | ||
414 | } | ||
415 | module_exit(wm831x_ts_exit); | ||
416 | |||
417 | /* Module information */ | ||
418 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
419 | MODULE_DESCRIPTION("WM831x PMIC touchscreen driver"); | ||
420 | MODULE_LICENSE("GPL"); | ||
421 | MODULE_ALIAS("platform:wm831x-touch"); | ||
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 6b5be742c27d..98e61175d3f5 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c | |||
@@ -306,7 +306,7 @@ static int wm9705_acc_enable(struct wm97xx *wm, int enable) | |||
306 | dig2 = wm->dig[2]; | 306 | dig2 = wm->dig[2]; |
307 | 307 | ||
308 | if (enable) { | 308 | if (enable) { |
309 | /* continous mode */ | 309 | /* continuous mode */ |
310 | if (wm->mach_ops->acc_startup && | 310 | if (wm->mach_ops->acc_startup && |
311 | (ret = wm->mach_ops->acc_startup(wm)) < 0) | 311 | (ret = wm->mach_ops->acc_startup(wm)) < 0) |
312 | return ret; | 312 | return ret; |
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 7490b05c3566..2bc2fb801009 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c | |||
@@ -419,7 +419,7 @@ static int wm9712_acc_enable(struct wm97xx *wm, int enable) | |||
419 | dig2 = wm->dig[2]; | 419 | dig2 = wm->dig[2]; |
420 | 420 | ||
421 | if (enable) { | 421 | if (enable) { |
422 | /* continous mode */ | 422 | /* continuous mode */ |
423 | if (wm->mach_ops->acc_startup) { | 423 | if (wm->mach_ops->acc_startup) { |
424 | ret = wm->mach_ops->acc_startup(wm); | 424 | ret = wm->mach_ops->acc_startup(wm); |
425 | if (ret < 0) | 425 | if (ret < 0) |
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 238b5132712e..73ec99568f12 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c | |||
@@ -431,7 +431,7 @@ static int wm9713_acc_enable(struct wm97xx *wm, int enable) | |||
431 | dig3 = wm->dig[2]; | 431 | dig3 = wm->dig[2]; |
432 | 432 | ||
433 | if (enable) { | 433 | if (enable) { |
434 | /* continous mode */ | 434 | /* continuous mode */ |
435 | if (wm->mach_ops->acc_startup && | 435 | if (wm->mach_ops->acc_startup && |
436 | (ret = wm->mach_ops->acc_startup(wm)) < 0) | 436 | (ret = wm->mach_ops->acc_startup(wm)) < 0) |
437 | return ret; | 437 | return ret; |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 6b75c9f660ae..5dbe73af2f8f 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -335,7 +335,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
335 | */ | 335 | */ |
336 | if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) { | 336 | if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) { |
337 | if (wm->pen_is_down && !pen_was_down) { | 337 | if (wm->pen_is_down && !pen_was_down) { |
338 | /* Data is not availiable immediately on pen down */ | 338 | /* Data is not available immediately on pen down */ |
339 | queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1); | 339 | queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1); |
340 | } | 340 | } |
341 | 341 | ||
@@ -354,7 +354,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
354 | * Codec PENDOWN irq handler | 354 | * Codec PENDOWN irq handler |
355 | * | 355 | * |
356 | * We have to disable the codec interrupt in the handler because it | 356 | * We have to disable the codec interrupt in the handler because it |
357 | * can take upto 1ms to clear the interrupt source. We schedule a task | 357 | * can take up to 1ms to clear the interrupt source. We schedule a task |
358 | * in a work queue to do the actual interaction with the chip. The | 358 | * in a work queue to do the actual interaction with the chip. The |
359 | * interrupt is then enabled again in the slow handler when the source | 359 | * interrupt is then enabled again in the slow handler when the source |
360 | * has been cleared. | 360 | * has been cleared. |
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index 048849867643..5b0f15ec874a 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c | |||
@@ -193,7 +193,7 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev) | |||
193 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); | 193 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); |
194 | 194 | ||
195 | wm->pen_irq = IRQ_GPIO(gpio_touch_irq); | 195 | wm->pen_irq = IRQ_GPIO(gpio_touch_irq); |
196 | set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); | 196 | irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); |
197 | 197 | ||
198 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 198 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
199 | WM97XX_GPIO_POL_HIGH, | 199 | WM97XX_GPIO_POL_HIGH, |