diff options
Diffstat (limited to 'drivers/input')
99 files changed, 3977 insertions, 924 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 001b147c7f95..332597980817 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -25,6 +25,10 @@ config INPUT | |||
25 | 25 | ||
26 | if INPUT | 26 | if INPUT |
27 | 27 | ||
28 | config INPUT_OF_MATRIX_KEYMAP | ||
29 | depends on USE_OF | ||
30 | bool | ||
31 | |||
28 | config INPUT_FF_MEMLESS | 32 | config INPUT_FF_MEMLESS |
29 | tristate "Support for memoryless force-feedback devices" | 33 | tristate "Support for memoryless force-feedback devices" |
30 | help | 34 | help |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 0c789490e0b3..b173a13a73ca 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -24,3 +24,4 @@ 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 | obj-$(CONFIG_INPUT_OF_MATRIX_KEYMAP) += of_keymap.o | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 7df5bfef2624..4b2e10d5d641 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input/mt.h> |
24 | #include <linux/major.h> | 24 | #include <linux/major.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include "input-compat.h" | 26 | #include "input-compat.h" |
@@ -46,6 +46,7 @@ struct evdev_client { | |||
46 | struct fasync_struct *fasync; | 46 | struct fasync_struct *fasync; |
47 | struct evdev *evdev; | 47 | struct evdev *evdev; |
48 | struct list_head node; | 48 | struct list_head node; |
49 | int clkid; | ||
49 | unsigned int bufsize; | 50 | unsigned int bufsize; |
50 | struct input_event buffer[]; | 51 | struct input_event buffer[]; |
51 | }; | 52 | }; |
@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS]; | |||
54 | static DEFINE_MUTEX(evdev_table_mutex); | 55 | static DEFINE_MUTEX(evdev_table_mutex); |
55 | 56 | ||
56 | static void evdev_pass_event(struct evdev_client *client, | 57 | static void evdev_pass_event(struct evdev_client *client, |
57 | struct input_event *event) | 58 | struct input_event *event, |
59 | ktime_t mono, ktime_t real) | ||
58 | { | 60 | { |
61 | event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? | ||
62 | mono : real); | ||
63 | |||
59 | /* Interrupts are disabled, just acquire the lock. */ | 64 | /* Interrupts are disabled, just acquire the lock. */ |
60 | spin_lock(&client->buffer_lock); | 65 | spin_lock(&client->buffer_lock); |
61 | 66 | ||
@@ -94,8 +99,11 @@ static void evdev_event(struct input_handle *handle, | |||
94 | struct evdev *evdev = handle->private; | 99 | struct evdev *evdev = handle->private; |
95 | struct evdev_client *client; | 100 | struct evdev_client *client; |
96 | struct input_event event; | 101 | struct input_event event; |
102 | ktime_t time_mono, time_real; | ||
103 | |||
104 | time_mono = ktime_get(); | ||
105 | time_real = ktime_sub(time_mono, ktime_get_monotonic_offset()); | ||
97 | 106 | ||
98 | do_gettimeofday(&event.time); | ||
99 | event.type = type; | 107 | event.type = type; |
100 | event.code = code; | 108 | event.code = code; |
101 | event.value = value; | 109 | event.value = value; |
@@ -103,11 +111,12 @@ static void evdev_event(struct input_handle *handle, | |||
103 | rcu_read_lock(); | 111 | rcu_read_lock(); |
104 | 112 | ||
105 | client = rcu_dereference(evdev->grab); | 113 | client = rcu_dereference(evdev->grab); |
114 | |||
106 | if (client) | 115 | if (client) |
107 | evdev_pass_event(client, &event); | 116 | evdev_pass_event(client, &event, time_mono, time_real); |
108 | else | 117 | else |
109 | list_for_each_entry_rcu(client, &evdev->client_list, node) | 118 | list_for_each_entry_rcu(client, &evdev->client_list, node) |
110 | evdev_pass_event(client, &event); | 119 | evdev_pass_event(client, &event, time_mono, time_real); |
111 | 120 | ||
112 | rcu_read_unlock(); | 121 | rcu_read_unlock(); |
113 | 122 | ||
@@ -623,6 +632,28 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) | |||
623 | return input_set_keycode(dev, &ke); | 632 | return input_set_keycode(dev, &ke); |
624 | } | 633 | } |
625 | 634 | ||
635 | static int evdev_handle_mt_request(struct input_dev *dev, | ||
636 | unsigned int size, | ||
637 | int __user *ip) | ||
638 | { | ||
639 | const struct input_mt_slot *mt = dev->mt; | ||
640 | unsigned int code; | ||
641 | int max_slots; | ||
642 | int i; | ||
643 | |||
644 | if (get_user(code, &ip[0])) | ||
645 | return -EFAULT; | ||
646 | if (!input_is_mt_value(code)) | ||
647 | return -EINVAL; | ||
648 | |||
649 | max_slots = (size - sizeof(__u32)) / sizeof(__s32); | ||
650 | for (i = 0; i < dev->mtsize && i < max_slots; i++) | ||
651 | if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i])) | ||
652 | return -EFAULT; | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
626 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, | 657 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
627 | void __user *p, int compat_mode) | 658 | void __user *p, int compat_mode) |
628 | { | 659 | { |
@@ -685,6 +716,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
685 | else | 716 | else |
686 | return evdev_ungrab(evdev, client); | 717 | return evdev_ungrab(evdev, client); |
687 | 718 | ||
719 | case EVIOCSCLOCKID: | ||
720 | if (copy_from_user(&i, p, sizeof(unsigned int))) | ||
721 | return -EFAULT; | ||
722 | if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME) | ||
723 | return -EINVAL; | ||
724 | client->clkid = i; | ||
725 | return 0; | ||
726 | |||
688 | case EVIOCGKEYCODE: | 727 | case EVIOCGKEYCODE: |
689 | return evdev_handle_get_keycode(dev, p); | 728 | return evdev_handle_get_keycode(dev, p); |
690 | 729 | ||
@@ -708,6 +747,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
708 | return bits_to_user(dev->propbit, INPUT_PROP_MAX, | 747 | return bits_to_user(dev->propbit, INPUT_PROP_MAX, |
709 | size, p, compat_mode); | 748 | size, p, compat_mode); |
710 | 749 | ||
750 | case EVIOCGMTSLOTS(0): | ||
751 | return evdev_handle_mt_request(dev, size, ip); | ||
752 | |||
711 | case EVIOCGKEY(0): | 753 | case EVIOCGKEY(0): |
712 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); | 754 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); |
713 | 755 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index da38d97a51b1..8921c6180c51 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -180,7 +180,7 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
180 | return INPUT_IGNORE_EVENT; | 180 | return INPUT_IGNORE_EVENT; |
181 | } | 181 | } |
182 | 182 | ||
183 | is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; | 183 | is_mt_event = input_is_mt_value(code); |
184 | 184 | ||
185 | if (!is_mt_event) { | 185 | if (!is_mt_event) { |
186 | pold = &dev->absinfo[code].value; | 186 | pold = &dev->absinfo[code].value; |
@@ -1624,7 +1624,7 @@ static struct device_type input_dev_type = { | |||
1624 | #endif | 1624 | #endif |
1625 | }; | 1625 | }; |
1626 | 1626 | ||
1627 | static char *input_devnode(struct device *dev, mode_t *mode) | 1627 | static char *input_devnode(struct device *dev, umode_t *mode) |
1628 | { | 1628 | { |
1629 | return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev)); | 1629 | return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev)); |
1630 | } | 1630 | } |
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 6d6e7418dc21..3063464474bf 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c | |||
@@ -355,14 +355,4 @@ static struct i2c_driver as5011_driver = { | |||
355 | .id_table = as5011_id, | 355 | .id_table = as5011_id, |
356 | }; | 356 | }; |
357 | 357 | ||
358 | static int __init as5011_init(void) | 358 | module_i2c_driver(as5011_driver); |
359 | { | ||
360 | return i2c_add_driver(&as5011_driver); | ||
361 | } | ||
362 | module_init(as5011_init); | ||
363 | |||
364 | static void __exit as5011_exit(void) | ||
365 | { | ||
366 | i2c_del_driver(&as5011_driver); | ||
367 | } | ||
368 | module_exit(as5011_exit); | ||
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d72887585a14..fd7a0d5bc94d 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -98,15 +98,15 @@ | |||
98 | #define XTYPE_XBOX360W 2 | 98 | #define XTYPE_XBOX360W 2 |
99 | #define XTYPE_UNKNOWN 3 | 99 | #define XTYPE_UNKNOWN 3 |
100 | 100 | ||
101 | static int dpad_to_buttons; | 101 | static bool dpad_to_buttons; |
102 | module_param(dpad_to_buttons, bool, S_IRUGO); | 102 | module_param(dpad_to_buttons, bool, S_IRUGO); |
103 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); | 103 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); |
104 | 104 | ||
105 | static int triggers_to_buttons; | 105 | static bool triggers_to_buttons; |
106 | module_param(triggers_to_buttons, bool, S_IRUGO); | 106 | module_param(triggers_to_buttons, bool, S_IRUGO); |
107 | MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); | 107 | MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); |
108 | 108 | ||
109 | static int sticks_to_null; | 109 | static bool sticks_to_null; |
110 | module_param(sticks_to_null, bool, S_IRUGO); | 110 | module_param(sticks_to_null, bool, S_IRUGO); |
111 | MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads"); | 111 | MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads"); |
112 | 112 | ||
@@ -1041,18 +1041,7 @@ static struct usb_driver xpad_driver = { | |||
1041 | .id_table = xpad_table, | 1041 | .id_table = xpad_table, |
1042 | }; | 1042 | }; |
1043 | 1043 | ||
1044 | static int __init usb_xpad_init(void) | 1044 | module_usb_driver(xpad_driver); |
1045 | { | ||
1046 | return usb_register(&xpad_driver); | ||
1047 | } | ||
1048 | |||
1049 | static void __exit usb_xpad_exit(void) | ||
1050 | { | ||
1051 | usb_deregister(&xpad_driver); | ||
1052 | } | ||
1053 | |||
1054 | module_init(usb_xpad_init); | ||
1055 | module_exit(usb_xpad_exit); | ||
1056 | 1045 | ||
1057 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1046 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1058 | MODULE_DESCRIPTION(DRIVER_DESC); | 1047 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index cdc385b2cf7d..f354813a13e8 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -394,6 +394,7 @@ config KEYBOARD_NOMADIK | |||
394 | config KEYBOARD_TEGRA | 394 | config KEYBOARD_TEGRA |
395 | tristate "NVIDIA Tegra internal matrix keyboard controller support" | 395 | tristate "NVIDIA Tegra internal matrix keyboard controller support" |
396 | depends on ARCH_TEGRA | 396 | depends on ARCH_TEGRA |
397 | select INPUT_OF_MATRIX_KEYMAP if USE_OF | ||
397 | help | 398 | help |
398 | Say Y here if you want to use a matrix keyboard connected directly | 399 | Say Y here if you want to use a matrix keyboard connected directly |
399 | to the internal keyboard controller on Tegra SoCs. | 400 | to the internal keyboard controller on Tegra SoCs. |
@@ -512,7 +513,6 @@ config KEYBOARD_OMAP | |||
512 | 513 | ||
513 | config KEYBOARD_OMAP4 | 514 | config KEYBOARD_OMAP4 |
514 | tristate "TI OMAP4 keypad support" | 515 | tristate "TI OMAP4 keypad support" |
515 | depends on ARCH_OMAP4 | ||
516 | help | 516 | help |
517 | Say Y here if you want to use the OMAP4 keypad. | 517 | Say Y here if you want to use the OMAP4 keypad. |
518 | 518 | ||
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 4a7f534cf64b..39ebffac207e 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
@@ -653,17 +653,7 @@ static struct i2c_driver adp5588_driver = { | |||
653 | .id_table = adp5588_id, | 653 | .id_table = adp5588_id, |
654 | }; | 654 | }; |
655 | 655 | ||
656 | static int __init adp5588_init(void) | 656 | module_i2c_driver(adp5588_driver); |
657 | { | ||
658 | return i2c_add_driver(&adp5588_driver); | ||
659 | } | ||
660 | module_init(adp5588_init); | ||
661 | |||
662 | static void __exit adp5588_exit(void) | ||
663 | { | ||
664 | i2c_del_driver(&adp5588_driver); | ||
665 | } | ||
666 | module_exit(adp5588_exit); | ||
667 | 657 | ||
668 | MODULE_LICENSE("GPL"); | 658 | MODULE_LICENSE("GPL"); |
669 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 659 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 02b5d53031bf..74e603213386 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c | |||
@@ -1108,17 +1108,7 @@ static struct i2c_driver adp5589_driver = { | |||
1108 | .id_table = adp5589_id, | 1108 | .id_table = adp5589_id, |
1109 | }; | 1109 | }; |
1110 | 1110 | ||
1111 | static int __init adp5589_init(void) | 1111 | module_i2c_driver(adp5589_driver); |
1112 | { | ||
1113 | return i2c_add_driver(&adp5589_driver); | ||
1114 | } | ||
1115 | module_init(adp5589_init); | ||
1116 | |||
1117 | static void __exit adp5589_exit(void) | ||
1118 | { | ||
1119 | i2c_del_driver(&adp5589_driver); | ||
1120 | } | ||
1121 | module_exit(adp5589_exit); | ||
1122 | 1112 | ||
1123 | MODULE_LICENSE("GPL"); | 1113 | MODULE_LICENSE("GPL"); |
1124 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 1114 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 21823bfc7911..39ac2787e275 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -851,17 +851,7 @@ static struct i2c_driver lm8323_i2c_driver = { | |||
851 | }; | 851 | }; |
852 | MODULE_DEVICE_TABLE(i2c, lm8323_id); | 852 | MODULE_DEVICE_TABLE(i2c, lm8323_id); |
853 | 853 | ||
854 | static int __init lm8323_init(void) | 854 | module_i2c_driver(lm8323_i2c_driver); |
855 | { | ||
856 | return i2c_add_driver(&lm8323_i2c_driver); | ||
857 | } | ||
858 | module_init(lm8323_init); | ||
859 | |||
860 | static void __exit lm8323_exit(void) | ||
861 | { | ||
862 | i2c_del_driver(&lm8323_i2c_driver); | ||
863 | } | ||
864 | module_exit(lm8323_exit); | ||
865 | 855 | ||
866 | MODULE_AUTHOR("Timo O. Karjalainen <timo.o.karjalainen@nokia.com>"); | 856 | MODULE_AUTHOR("Timo O. Karjalainen <timo.o.karjalainen@nokia.com>"); |
867 | MODULE_AUTHOR("Daniel Stone"); | 857 | MODULE_AUTHOR("Daniel Stone"); |
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 5afe35ad24d3..8edada8ae712 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c | |||
@@ -316,17 +316,7 @@ static struct i2c_driver max7359_i2c_driver = { | |||
316 | .id_table = max7359_ids, | 316 | .id_table = max7359_ids, |
317 | }; | 317 | }; |
318 | 318 | ||
319 | static int __init max7359_init(void) | 319 | module_i2c_driver(max7359_i2c_driver); |
320 | { | ||
321 | return i2c_add_driver(&max7359_i2c_driver); | ||
322 | } | ||
323 | module_init(max7359_init); | ||
324 | |||
325 | static void __exit max7359_exit(void) | ||
326 | { | ||
327 | i2c_del_driver(&max7359_i2c_driver); | ||
328 | } | ||
329 | module_exit(max7359_exit); | ||
330 | 320 | ||
331 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | 321 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); |
332 | MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver"); | 322 | MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver"); |
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index af1aab324a4c..64a0ca4c92f3 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c | |||
@@ -274,18 +274,7 @@ static struct i2c_driver mcs_touchkey_driver = { | |||
274 | .id_table = mcs_touchkey_id, | 274 | .id_table = mcs_touchkey_id, |
275 | }; | 275 | }; |
276 | 276 | ||
277 | static int __init mcs_touchkey_init(void) | 277 | module_i2c_driver(mcs_touchkey_driver); |
278 | { | ||
279 | return i2c_add_driver(&mcs_touchkey_driver); | ||
280 | } | ||
281 | |||
282 | static void __exit mcs_touchkey_exit(void) | ||
283 | { | ||
284 | i2c_del_driver(&mcs_touchkey_driver); | ||
285 | } | ||
286 | |||
287 | module_init(mcs_touchkey_init); | ||
288 | module_exit(mcs_touchkey_exit); | ||
289 | 278 | ||
290 | /* Module information */ | 279 | /* Module information */ |
291 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 280 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 1c1615d9a7f9..caa218a51b5a 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c | |||
@@ -330,17 +330,7 @@ static struct i2c_driver mpr_touchkey_driver = { | |||
330 | .remove = __devexit_p(mpr_touchkey_remove), | 330 | .remove = __devexit_p(mpr_touchkey_remove), |
331 | }; | 331 | }; |
332 | 332 | ||
333 | static int __init mpr_touchkey_init(void) | 333 | module_i2c_driver(mpr_touchkey_driver); |
334 | { | ||
335 | return i2c_add_driver(&mpr_touchkey_driver); | ||
336 | } | ||
337 | module_init(mpr_touchkey_init); | ||
338 | |||
339 | static void __exit mpr_touchkey_exit(void) | ||
340 | { | ||
341 | i2c_del_driver(&mpr_touchkey_driver); | ||
342 | } | ||
343 | module_exit(mpr_touchkey_exit); | ||
344 | 334 | ||
345 | MODULE_LICENSE("GPL"); | 335 | MODULE_LICENSE("GPL"); |
346 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); | 336 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); |
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index e35566aa102f..101e245944e7 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c | |||
@@ -88,7 +88,7 @@ static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr, | |||
88 | * | 88 | * |
89 | * Enable Multi key press detection, auto scan mode | 89 | * Enable Multi key press detection, auto scan mode |
90 | */ | 90 | */ |
91 | static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad) | 91 | static int __init ske_keypad_chip_init(struct ske_keypad *keypad) |
92 | { | 92 | { |
93 | u32 value; | 93 | u32 value; |
94 | int timeout = 50; | 94 | int timeout = 50; |
@@ -198,7 +198,7 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id) | |||
198 | return IRQ_HANDLED; | 198 | return IRQ_HANDLED; |
199 | } | 199 | } |
200 | 200 | ||
201 | static int __devinit ske_keypad_probe(struct platform_device *pdev) | 201 | static int __init ske_keypad_probe(struct platform_device *pdev) |
202 | { | 202 | { |
203 | const struct ske_keypad_platform_data *plat = pdev->dev.platform_data; | 203 | const struct ske_keypad_platform_data *plat = pdev->dev.platform_data; |
204 | struct ske_keypad *keypad; | 204 | struct ske_keypad *keypad; |
@@ -344,7 +344,7 @@ static int __devexit ske_keypad_remove(struct platform_device *pdev) | |||
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | 346 | ||
347 | #ifdef CONFIG_PM | 347 | #ifdef CONFIG_PM_SLEEP |
348 | static int ske_keypad_suspend(struct device *dev) | 348 | static int ske_keypad_suspend(struct device *dev) |
349 | { | 349 | { |
350 | struct platform_device *pdev = to_platform_device(dev); | 350 | struct platform_device *pdev = to_platform_device(dev); |
@@ -372,22 +372,17 @@ static int ske_keypad_resume(struct device *dev) | |||
372 | 372 | ||
373 | return 0; | 373 | return 0; |
374 | } | 374 | } |
375 | |||
376 | static const struct dev_pm_ops ske_keypad_dev_pm_ops = { | ||
377 | .suspend = ske_keypad_suspend, | ||
378 | .resume = ske_keypad_resume, | ||
379 | }; | ||
380 | #endif | 375 | #endif |
381 | 376 | ||
377 | static SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops, | ||
378 | ske_keypad_suspend, ske_keypad_resume); | ||
379 | |||
382 | static struct platform_driver ske_keypad_driver = { | 380 | static struct platform_driver ske_keypad_driver = { |
383 | .driver = { | 381 | .driver = { |
384 | .name = "nmk-ske-keypad", | 382 | .name = "nmk-ske-keypad", |
385 | .owner = THIS_MODULE, | 383 | .owner = THIS_MODULE, |
386 | #ifdef CONFIG_PM | ||
387 | .pm = &ske_keypad_dev_pm_ops, | 384 | .pm = &ske_keypad_dev_pm_ops, |
388 | #endif | ||
389 | }, | 385 | }, |
390 | .probe = ske_keypad_probe, | ||
391 | .remove = __devexit_p(ske_keypad_remove), | 386 | .remove = __devexit_p(ske_keypad_remove), |
392 | }; | 387 | }; |
393 | 388 | ||
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index d5c5d77f4b82..e809ac095a38 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | 33 | ||
34 | #include <plat/omap4-keypad.h> | 34 | #include <linux/platform_data/omap4-keypad.h> |
35 | 35 | ||
36 | /* OMAP4 registers */ | 36 | /* OMAP4 registers */ |
37 | #define OMAP4_KBD_REVISION 0x00 | 37 | #define OMAP4_KBD_REVISION 0x00 |
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index b21bf5b876bb..0b7b2f891752 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c | |||
@@ -258,17 +258,7 @@ static struct i2c_driver qt1070_driver = { | |||
258 | .remove = __devexit_p(qt1070_remove), | 258 | .remove = __devexit_p(qt1070_remove), |
259 | }; | 259 | }; |
260 | 260 | ||
261 | static int __init qt1070_init(void) | 261 | module_i2c_driver(qt1070_driver); |
262 | { | ||
263 | return i2c_add_driver(&qt1070_driver); | ||
264 | } | ||
265 | module_init(qt1070_init); | ||
266 | |||
267 | static void __exit qt1070_exit(void) | ||
268 | { | ||
269 | i2c_del_driver(&qt1070_driver); | ||
270 | } | ||
271 | module_exit(qt1070_exit); | ||
272 | 262 | ||
273 | MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>"); | 263 | MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>"); |
274 | MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor"); | 264 | MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor"); |
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index fac695157e8a..e7a5e36e1203 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c | |||
@@ -379,17 +379,7 @@ static struct i2c_driver qt2160_driver = { | |||
379 | .remove = __devexit_p(qt2160_remove), | 379 | .remove = __devexit_p(qt2160_remove), |
380 | }; | 380 | }; |
381 | 381 | ||
382 | static int __init qt2160_init(void) | 382 | module_i2c_driver(qt2160_driver); |
383 | { | ||
384 | return i2c_add_driver(&qt2160_driver); | ||
385 | } | ||
386 | module_init(qt2160_init); | ||
387 | |||
388 | static void __exit qt2160_cleanup(void) | ||
389 | { | ||
390 | i2c_del_driver(&qt2160_driver); | ||
391 | } | ||
392 | module_exit(qt2160_cleanup); | ||
393 | 383 | ||
394 | MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); | 384 | MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); |
395 | MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); | 385 | MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); |
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index b746fce2d120..2391ae884fee 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/of.h> | ||
27 | #include <linux/of_gpio.h> | ||
26 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
27 | #include <linux/input/samsung-keypad.h> | 29 | #include <linux/input/samsung-keypad.h> |
28 | 30 | ||
@@ -72,31 +74,26 @@ struct samsung_keypad { | |||
72 | bool stopped; | 74 | bool stopped; |
73 | bool wake_enabled; | 75 | bool wake_enabled; |
74 | int irq; | 76 | int irq; |
77 | enum samsung_keypad_type type; | ||
75 | unsigned int row_shift; | 78 | unsigned int row_shift; |
76 | unsigned int rows; | 79 | unsigned int rows; |
77 | unsigned int cols; | 80 | unsigned int cols; |
78 | unsigned int row_state[SAMSUNG_MAX_COLS]; | 81 | unsigned int row_state[SAMSUNG_MAX_COLS]; |
82 | #ifdef CONFIG_OF | ||
83 | int row_gpios[SAMSUNG_MAX_ROWS]; | ||
84 | int col_gpios[SAMSUNG_MAX_COLS]; | ||
85 | #endif | ||
79 | unsigned short keycodes[]; | 86 | unsigned short keycodes[]; |
80 | }; | 87 | }; |
81 | 88 | ||
82 | static int samsung_keypad_is_s5pv210(struct device *dev) | ||
83 | { | ||
84 | struct platform_device *pdev = to_platform_device(dev); | ||
85 | enum samsung_keypad_type type = | ||
86 | platform_get_device_id(pdev)->driver_data; | ||
87 | |||
88 | return type == KEYPAD_TYPE_S5PV210; | ||
89 | } | ||
90 | |||
91 | static void samsung_keypad_scan(struct samsung_keypad *keypad, | 89 | static void samsung_keypad_scan(struct samsung_keypad *keypad, |
92 | unsigned int *row_state) | 90 | unsigned int *row_state) |
93 | { | 91 | { |
94 | struct device *dev = keypad->input_dev->dev.parent; | ||
95 | unsigned int col; | 92 | unsigned int col; |
96 | unsigned int val; | 93 | unsigned int val; |
97 | 94 | ||
98 | for (col = 0; col < keypad->cols; col++) { | 95 | for (col = 0; col < keypad->cols; col++) { |
99 | if (samsung_keypad_is_s5pv210(dev)) { | 96 | if (keypad->type == KEYPAD_TYPE_S5PV210) { |
100 | val = S5PV210_KEYIFCOLEN_MASK; | 97 | val = S5PV210_KEYIFCOLEN_MASK; |
101 | val &= ~(1 << col) << 8; | 98 | val &= ~(1 << col) << 8; |
102 | } else { | 99 | } else { |
@@ -178,7 +175,7 @@ static irqreturn_t samsung_keypad_irq(int irq, void *dev_id) | |||
178 | 175 | ||
179 | } while (key_down && !keypad->stopped); | 176 | } while (key_down && !keypad->stopped); |
180 | 177 | ||
181 | pm_runtime_put_sync(&keypad->pdev->dev); | 178 | pm_runtime_put(&keypad->pdev->dev); |
182 | 179 | ||
183 | return IRQ_HANDLED; | 180 | return IRQ_HANDLED; |
184 | } | 181 | } |
@@ -202,7 +199,7 @@ static void samsung_keypad_start(struct samsung_keypad *keypad) | |||
202 | /* KEYIFCOL reg clear. */ | 199 | /* KEYIFCOL reg clear. */ |
203 | writel(0, keypad->base + SAMSUNG_KEYIFCOL); | 200 | writel(0, keypad->base + SAMSUNG_KEYIFCOL); |
204 | 201 | ||
205 | pm_runtime_put_sync(&keypad->pdev->dev); | 202 | pm_runtime_put(&keypad->pdev->dev); |
206 | } | 203 | } |
207 | 204 | ||
208 | static void samsung_keypad_stop(struct samsung_keypad *keypad) | 205 | static void samsung_keypad_stop(struct samsung_keypad *keypad) |
@@ -232,7 +229,7 @@ static void samsung_keypad_stop(struct samsung_keypad *keypad) | |||
232 | */ | 229 | */ |
233 | enable_irq(keypad->irq); | 230 | enable_irq(keypad->irq); |
234 | 231 | ||
235 | pm_runtime_put_sync(&keypad->pdev->dev); | 232 | pm_runtime_put(&keypad->pdev->dev); |
236 | } | 233 | } |
237 | 234 | ||
238 | static int samsung_keypad_open(struct input_dev *input_dev) | 235 | static int samsung_keypad_open(struct input_dev *input_dev) |
@@ -251,6 +248,126 @@ static void samsung_keypad_close(struct input_dev *input_dev) | |||
251 | samsung_keypad_stop(keypad); | 248 | samsung_keypad_stop(keypad); |
252 | } | 249 | } |
253 | 250 | ||
251 | #ifdef CONFIG_OF | ||
252 | static struct samsung_keypad_platdata *samsung_keypad_parse_dt( | ||
253 | struct device *dev) | ||
254 | { | ||
255 | struct samsung_keypad_platdata *pdata; | ||
256 | struct matrix_keymap_data *keymap_data; | ||
257 | uint32_t *keymap, num_rows = 0, num_cols = 0; | ||
258 | struct device_node *np = dev->of_node, *key_np; | ||
259 | unsigned int key_count = 0; | ||
260 | |||
261 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
262 | if (!pdata) { | ||
263 | dev_err(dev, "could not allocate memory for platform data\n"); | ||
264 | return NULL; | ||
265 | } | ||
266 | |||
267 | of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows); | ||
268 | of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols); | ||
269 | if (!num_rows || !num_cols) { | ||
270 | dev_err(dev, "number of keypad rows/columns not specified\n"); | ||
271 | return NULL; | ||
272 | } | ||
273 | pdata->rows = num_rows; | ||
274 | pdata->cols = num_cols; | ||
275 | |||
276 | keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL); | ||
277 | if (!keymap_data) { | ||
278 | dev_err(dev, "could not allocate memory for keymap data\n"); | ||
279 | return NULL; | ||
280 | } | ||
281 | pdata->keymap_data = keymap_data; | ||
282 | |||
283 | for_each_child_of_node(np, key_np) | ||
284 | key_count++; | ||
285 | |||
286 | keymap_data->keymap_size = key_count; | ||
287 | keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); | ||
288 | if (!keymap) { | ||
289 | dev_err(dev, "could not allocate memory for keymap\n"); | ||
290 | return NULL; | ||
291 | } | ||
292 | keymap_data->keymap = keymap; | ||
293 | |||
294 | for_each_child_of_node(np, key_np) { | ||
295 | u32 row, col, key_code; | ||
296 | of_property_read_u32(key_np, "keypad,row", &row); | ||
297 | of_property_read_u32(key_np, "keypad,column", &col); | ||
298 | of_property_read_u32(key_np, "linux,code", &key_code); | ||
299 | *keymap++ = KEY(row, col, key_code); | ||
300 | } | ||
301 | |||
302 | if (of_get_property(np, "linux,input-no-autorepeat", NULL)) | ||
303 | pdata->no_autorepeat = true; | ||
304 | if (of_get_property(np, "linux,input-wakeup", NULL)) | ||
305 | pdata->wakeup = true; | ||
306 | |||
307 | return pdata; | ||
308 | } | ||
309 | |||
310 | static void samsung_keypad_parse_dt_gpio(struct device *dev, | ||
311 | struct samsung_keypad *keypad) | ||
312 | { | ||
313 | struct device_node *np = dev->of_node; | ||
314 | int gpio, ret, row, col; | ||
315 | |||
316 | for (row = 0; row < keypad->rows; row++) { | ||
317 | gpio = of_get_named_gpio(np, "row-gpios", row); | ||
318 | keypad->row_gpios[row] = gpio; | ||
319 | if (!gpio_is_valid(gpio)) { | ||
320 | dev_err(dev, "keypad row[%d]: invalid gpio %d\n", | ||
321 | row, gpio); | ||
322 | continue; | ||
323 | } | ||
324 | |||
325 | ret = gpio_request(gpio, "keypad-row"); | ||
326 | if (ret) | ||
327 | dev_err(dev, "keypad row[%d] gpio request failed\n", | ||
328 | row); | ||
329 | } | ||
330 | |||
331 | for (col = 0; col < keypad->cols; col++) { | ||
332 | gpio = of_get_named_gpio(np, "col-gpios", col); | ||
333 | keypad->col_gpios[col] = gpio; | ||
334 | if (!gpio_is_valid(gpio)) { | ||
335 | dev_err(dev, "keypad column[%d]: invalid gpio %d\n", | ||
336 | col, gpio); | ||
337 | continue; | ||
338 | } | ||
339 | |||
340 | ret = gpio_request(gpio, "keypad-col"); | ||
341 | if (ret) | ||
342 | dev_err(dev, "keypad column[%d] gpio request failed\n", | ||
343 | col); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) | ||
348 | { | ||
349 | int cnt; | ||
350 | |||
351 | for (cnt = 0; cnt < keypad->rows; cnt++) | ||
352 | if (gpio_is_valid(keypad->row_gpios[cnt])) | ||
353 | gpio_free(keypad->row_gpios[cnt]); | ||
354 | |||
355 | for (cnt = 0; cnt < keypad->cols; cnt++) | ||
356 | if (gpio_is_valid(keypad->col_gpios[cnt])) | ||
357 | gpio_free(keypad->col_gpios[cnt]); | ||
358 | } | ||
359 | #else | ||
360 | static | ||
361 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) | ||
362 | { | ||
363 | return NULL; | ||
364 | } | ||
365 | |||
366 | static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) | ||
367 | { | ||
368 | } | ||
369 | #endif | ||
370 | |||
254 | static int __devinit samsung_keypad_probe(struct platform_device *pdev) | 371 | static int __devinit samsung_keypad_probe(struct platform_device *pdev) |
255 | { | 372 | { |
256 | const struct samsung_keypad_platdata *pdata; | 373 | const struct samsung_keypad_platdata *pdata; |
@@ -262,7 +379,10 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) | |||
262 | unsigned int keymap_size; | 379 | unsigned int keymap_size; |
263 | int error; | 380 | int error; |
264 | 381 | ||
265 | pdata = pdev->dev.platform_data; | 382 | if (pdev->dev.of_node) |
383 | pdata = samsung_keypad_parse_dt(&pdev->dev); | ||
384 | else | ||
385 | pdata = pdev->dev.platform_data; | ||
266 | if (!pdata) { | 386 | if (!pdata) { |
267 | dev_err(&pdev->dev, "no platform data defined\n"); | 387 | dev_err(&pdev->dev, "no platform data defined\n"); |
268 | return -EINVAL; | 388 | return -EINVAL; |
@@ -321,6 +441,16 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) | |||
321 | keypad->stopped = true; | 441 | keypad->stopped = true; |
322 | init_waitqueue_head(&keypad->wait); | 442 | init_waitqueue_head(&keypad->wait); |
323 | 443 | ||
444 | if (pdev->dev.of_node) { | ||
445 | #ifdef CONFIG_OF | ||
446 | samsung_keypad_parse_dt_gpio(&pdev->dev, keypad); | ||
447 | keypad->type = of_device_is_compatible(pdev->dev.of_node, | ||
448 | "samsung,s5pv210-keypad"); | ||
449 | #endif | ||
450 | } else { | ||
451 | keypad->type = platform_get_device_id(pdev)->driver_data; | ||
452 | } | ||
453 | |||
324 | input_dev->name = pdev->name; | 454 | input_dev->name = pdev->name; |
325 | input_dev->id.bustype = BUS_HOST; | 455 | input_dev->id.bustype = BUS_HOST; |
326 | input_dev->dev.parent = &pdev->dev; | 456 | input_dev->dev.parent = &pdev->dev; |
@@ -363,6 +493,11 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) | |||
363 | if (error) | 493 | if (error) |
364 | goto err_free_irq; | 494 | goto err_free_irq; |
365 | 495 | ||
496 | if (pdev->dev.of_node) { | ||
497 | devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); | ||
498 | devm_kfree(&pdev->dev, (void *)pdata->keymap_data); | ||
499 | devm_kfree(&pdev->dev, (void *)pdata); | ||
500 | } | ||
366 | return 0; | 501 | return 0; |
367 | 502 | ||
368 | err_free_irq: | 503 | err_free_irq: |
@@ -372,6 +507,7 @@ err_free_irq: | |||
372 | platform_set_drvdata(pdev, NULL); | 507 | platform_set_drvdata(pdev, NULL); |
373 | err_put_clk: | 508 | err_put_clk: |
374 | clk_put(keypad->clk); | 509 | clk_put(keypad->clk); |
510 | samsung_keypad_dt_gpio_free(keypad); | ||
375 | err_unmap_base: | 511 | err_unmap_base: |
376 | iounmap(keypad->base); | 512 | iounmap(keypad->base); |
377 | err_free_mem: | 513 | err_free_mem: |
@@ -398,6 +534,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev) | |||
398 | free_irq(keypad->irq, keypad); | 534 | free_irq(keypad->irq, keypad); |
399 | 535 | ||
400 | clk_put(keypad->clk); | 536 | clk_put(keypad->clk); |
537 | samsung_keypad_dt_gpio_free(keypad); | ||
401 | 538 | ||
402 | iounmap(keypad->base); | 539 | iounmap(keypad->base); |
403 | kfree(keypad); | 540 | kfree(keypad); |
@@ -518,6 +655,17 @@ static const struct dev_pm_ops samsung_keypad_pm_ops = { | |||
518 | samsung_keypad_runtime_resume, NULL) | 655 | samsung_keypad_runtime_resume, NULL) |
519 | }; | 656 | }; |
520 | 657 | ||
658 | #ifdef CONFIG_OF | ||
659 | static const struct of_device_id samsung_keypad_dt_match[] = { | ||
660 | { .compatible = "samsung,s3c6410-keypad" }, | ||
661 | { .compatible = "samsung,s5pv210-keypad" }, | ||
662 | {}, | ||
663 | }; | ||
664 | MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); | ||
665 | #else | ||
666 | #define samsung_keypad_dt_match NULL | ||
667 | #endif | ||
668 | |||
521 | static struct platform_device_id samsung_keypad_driver_ids[] = { | 669 | static struct platform_device_id samsung_keypad_driver_ids[] = { |
522 | { | 670 | { |
523 | .name = "samsung-keypad", | 671 | .name = "samsung-keypad", |
@@ -536,6 +684,7 @@ static struct platform_driver samsung_keypad_driver = { | |||
536 | .driver = { | 684 | .driver = { |
537 | .name = "samsung-keypad", | 685 | .name = "samsung-keypad", |
538 | .owner = THIS_MODULE, | 686 | .owner = THIS_MODULE, |
687 | .of_match_table = samsung_keypad_dt_match, | ||
539 | .pm = &samsung_keypad_pm_ops, | 688 | .pm = &samsung_keypad_pm_ops, |
540 | }, | 689 | }, |
541 | .id_table = samsung_keypad_driver_ids, | 690 | .id_table = samsung_keypad_driver_ids, |
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index c88bd63dc9cc..3b6b528f02fd 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #define ROW_MASK 0xF0 | 50 | #define ROW_MASK 0xF0 |
51 | #define COLUMN_MASK 0x0F | 51 | #define COLUMN_MASK 0x0F |
52 | #define ROW_SHIFT 4 | 52 | #define ROW_SHIFT 4 |
53 | #define KEY_MATRIX_SHIFT 6 | ||
53 | 54 | ||
54 | struct spear_kbd { | 55 | struct spear_kbd { |
55 | struct input_dev *input; | 56 | struct input_dev *input; |
@@ -57,6 +58,7 @@ struct spear_kbd { | |||
57 | void __iomem *io_base; | 58 | void __iomem *io_base; |
58 | struct clk *clk; | 59 | struct clk *clk; |
59 | unsigned int irq; | 60 | unsigned int irq; |
61 | unsigned int mode; | ||
60 | unsigned short last_key; | 62 | unsigned short last_key; |
61 | unsigned short keycodes[256]; | 63 | unsigned short keycodes[256]; |
62 | }; | 64 | }; |
@@ -106,7 +108,8 @@ static int spear_kbd_open(struct input_dev *dev) | |||
106 | return error; | 108 | return error; |
107 | 109 | ||
108 | /* program keyboard */ | 110 | /* program keyboard */ |
109 | val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK; | 111 | val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK | |
112 | (kbd->mode << KEY_MATRIX_SHIFT); | ||
110 | writew(val, kbd->io_base + MODE_REG); | 113 | writew(val, kbd->io_base + MODE_REG); |
111 | writeb(1, kbd->io_base + STATUS_REG); | 114 | writeb(1, kbd->io_base + STATUS_REG); |
112 | 115 | ||
@@ -176,6 +179,8 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) | |||
176 | 179 | ||
177 | kbd->input = input_dev; | 180 | kbd->input = input_dev; |
178 | kbd->irq = irq; | 181 | kbd->irq = irq; |
182 | kbd->mode = pdata->mode; | ||
183 | |||
179 | kbd->res = request_mem_region(res->start, resource_size(res), | 184 | kbd->res = request_mem_region(res->start, resource_size(res), |
180 | pdev->name); | 185 | pdev->name); |
181 | if (!kbd->res) { | 186 | if (!kbd->res) { |
@@ -308,22 +313,17 @@ static int spear_kbd_resume(struct device *dev) | |||
308 | 313 | ||
309 | return 0; | 314 | return 0; |
310 | } | 315 | } |
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 | 316 | #endif |
317 | 317 | ||
318 | static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); | ||
319 | |||
318 | static struct platform_driver spear_kbd_driver = { | 320 | static struct platform_driver spear_kbd_driver = { |
319 | .probe = spear_kbd_probe, | 321 | .probe = spear_kbd_probe, |
320 | .remove = __devexit_p(spear_kbd_remove), | 322 | .remove = __devexit_p(spear_kbd_remove), |
321 | .driver = { | 323 | .driver = { |
322 | .name = "keyboard", | 324 | .name = "keyboard", |
323 | .owner = THIS_MODULE, | 325 | .owner = THIS_MODULE, |
324 | #ifdef CONFIG_PM | ||
325 | .pm = &spear_kbd_pm_ops, | 326 | .pm = &spear_kbd_pm_ops, |
326 | #endif | ||
327 | }, | 327 | }, |
328 | }; | 328 | }; |
329 | module_platform_driver(spear_kbd_driver); | 329 | module_platform_driver(spear_kbd_driver); |
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index a136e2e832be..21c42f852343 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14) | 48 | #define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14) |
49 | #define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4) | 49 | #define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4) |
50 | #define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3) | 50 | #define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3) |
51 | #define KBC_CONTROL_KEYPRESS_INT_EN (1 << 1) | ||
51 | #define KBC_CONTROL_KBC_EN (1 << 0) | 52 | #define KBC_CONTROL_KBC_EN (1 << 0) |
52 | 53 | ||
53 | /* KBC Interrupt Register */ | 54 | /* KBC Interrupt Register */ |
@@ -356,6 +357,18 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) | |||
356 | writel(val, kbc->mmio + KBC_CONTROL_0); | 357 | writel(val, kbc->mmio + KBC_CONTROL_0); |
357 | } | 358 | } |
358 | 359 | ||
360 | static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) | ||
361 | { | ||
362 | u32 val; | ||
363 | |||
364 | val = readl(kbc->mmio + KBC_CONTROL_0); | ||
365 | if (enable) | ||
366 | val |= KBC_CONTROL_KEYPRESS_INT_EN; | ||
367 | else | ||
368 | val &= ~KBC_CONTROL_KEYPRESS_INT_EN; | ||
369 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
370 | } | ||
371 | |||
359 | static void tegra_kbc_keypress_timer(unsigned long data) | 372 | static void tegra_kbc_keypress_timer(unsigned long data) |
360 | { | 373 | { |
361 | struct tegra_kbc *kbc = (struct tegra_kbc *)data; | 374 | struct tegra_kbc *kbc = (struct tegra_kbc *)data; |
@@ -455,10 +468,18 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) | |||
455 | row_cfg &= ~r_mask; | 468 | row_cfg &= ~r_mask; |
456 | col_cfg &= ~c_mask; | 469 | col_cfg &= ~c_mask; |
457 | 470 | ||
458 | if (pdata->pin_cfg[i].is_row) | 471 | switch (pdata->pin_cfg[i].type) { |
472 | case PIN_CFG_ROW: | ||
459 | row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; | 473 | row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; |
460 | else | 474 | break; |
475 | |||
476 | case PIN_CFG_COL: | ||
461 | col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; | 477 | col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; |
478 | break; | ||
479 | |||
480 | case PIN_CFG_IGNORE: | ||
481 | break; | ||
482 | } | ||
462 | 483 | ||
463 | writel(row_cfg, kbc->mmio + r_offs); | 484 | writel(row_cfg, kbc->mmio + r_offs); |
464 | writel(col_cfg, kbc->mmio + c_offs); | 485 | writel(col_cfg, kbc->mmio + c_offs); |
@@ -563,7 +584,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, | |||
563 | for (i = 0; i < KBC_MAX_GPIO; i++) { | 584 | for (i = 0; i < KBC_MAX_GPIO; i++) { |
564 | const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; | 585 | const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; |
565 | 586 | ||
566 | if (pin_cfg->is_row) { | 587 | switch (pin_cfg->type) { |
588 | case PIN_CFG_ROW: | ||
567 | if (pin_cfg->num >= KBC_MAX_ROW) { | 589 | if (pin_cfg->num >= KBC_MAX_ROW) { |
568 | dev_err(dev, | 590 | dev_err(dev, |
569 | "pin_cfg[%d]: invalid row number %d\n", | 591 | "pin_cfg[%d]: invalid row number %d\n", |
@@ -571,13 +593,25 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, | |||
571 | return false; | 593 | return false; |
572 | } | 594 | } |
573 | (*num_rows)++; | 595 | (*num_rows)++; |
574 | } else { | 596 | break; |
597 | |||
598 | case PIN_CFG_COL: | ||
575 | if (pin_cfg->num >= KBC_MAX_COL) { | 599 | if (pin_cfg->num >= KBC_MAX_COL) { |
576 | dev_err(dev, | 600 | dev_err(dev, |
577 | "pin_cfg[%d]: invalid column number %d\n", | 601 | "pin_cfg[%d]: invalid column number %d\n", |
578 | i, pin_cfg->num); | 602 | i, pin_cfg->num); |
579 | return false; | 603 | return false; |
580 | } | 604 | } |
605 | break; | ||
606 | |||
607 | case PIN_CFG_IGNORE: | ||
608 | break; | ||
609 | |||
610 | default: | ||
611 | dev_err(dev, | ||
612 | "pin_cfg[%d]: invalid entry type %d\n", | ||
613 | pin_cfg->type, pin_cfg->num); | ||
614 | return false; | ||
581 | } | 615 | } |
582 | } | 616 | } |
583 | 617 | ||
@@ -590,24 +624,25 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | |||
590 | { | 624 | { |
591 | struct tegra_kbc_platform_data *pdata; | 625 | struct tegra_kbc_platform_data *pdata; |
592 | struct device_node *np = pdev->dev.of_node; | 626 | struct device_node *np = pdev->dev.of_node; |
627 | u32 prop; | ||
628 | int i; | ||
593 | 629 | ||
594 | if (!np) | 630 | if (!np) |
595 | return NULL; | 631 | return NULL; |
596 | 632 | ||
597 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
598 | if (!pdata) | 633 | if (!pdata) |
599 | return NULL; | 634 | return NULL; |
600 | 635 | ||
601 | if (!of_property_read_u32(np, "debounce-delay", &prop)) | 636 | if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) |
602 | pdata->debounce_cnt = prop; | 637 | pdata->debounce_cnt = prop; |
603 | 638 | ||
604 | if (!of_property_read_u32(np, "repeat-delay", &prop)) | 639 | if (!of_property_read_u32(np, "nvidia,repeat-delay-ms", &prop)) |
605 | pdata->repeat_cnt = prop; | 640 | pdata->repeat_cnt = prop; |
606 | 641 | ||
607 | if (of_find_property(np, "needs-ghost-filter", NULL)) | 642 | if (of_find_property(np, "nvidia,needs-ghost-filter", NULL)) |
608 | pdata->use_ghost_filter = true; | 643 | pdata->use_ghost_filter = true; |
609 | 644 | ||
610 | if (of_find_property(np, "wakeup-source", NULL)) | 645 | if (of_find_property(np, "nvidia,wakeup-source", NULL)) |
611 | pdata->wakeup = true; | 646 | pdata->wakeup = true; |
612 | 647 | ||
613 | /* | 648 | /* |
@@ -616,14 +651,18 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | |||
616 | */ | 651 | */ |
617 | for (i = 0; i < KBC_MAX_ROW; i++) { | 652 | for (i = 0; i < KBC_MAX_ROW; i++) { |
618 | pdata->pin_cfg[i].num = i; | 653 | pdata->pin_cfg[i].num = i; |
619 | pdata->pin_cfg[i].is_row = true; | 654 | pdata->pin_cfg[i].type = PIN_CFG_ROW; |
620 | } | 655 | } |
621 | 656 | ||
622 | for (i = 0; i < KBC_MAX_COL; i++) { | 657 | for (i = 0; i < KBC_MAX_COL; i++) { |
623 | pdata->pin_cfg[KBC_MAX_ROW + i].num = i; | 658 | pdata->pin_cfg[KBC_MAX_ROW + i].num = i; |
624 | pdata->pin_cfg[KBC_MAX_ROW + i].is_row = false; | 659 | pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; |
625 | } | 660 | } |
626 | 661 | ||
662 | pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap"); | ||
663 | |||
664 | /* FIXME: Add handling of linux,fn-keymap here */ | ||
665 | |||
627 | return pdata; | 666 | return pdata; |
628 | } | 667 | } |
629 | #else | 668 | #else |
@@ -759,6 +798,9 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
759 | platform_set_drvdata(pdev, kbc); | 798 | platform_set_drvdata(pdev, kbc); |
760 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 799 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
761 | 800 | ||
801 | if (!pdev->dev.platform_data) | ||
802 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
803 | |||
762 | return 0; | 804 | return 0; |
763 | 805 | ||
764 | err_free_irq: | 806 | err_free_irq: |
@@ -773,8 +815,10 @@ err_free_mem: | |||
773 | input_free_device(input_dev); | 815 | input_free_device(input_dev); |
774 | kfree(kbc); | 816 | kfree(kbc); |
775 | err_free_pdata: | 817 | err_free_pdata: |
776 | if (!pdev->dev.platform_data) | 818 | if (!pdev->dev.platform_data) { |
819 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
777 | kfree(pdata); | 820 | kfree(pdata); |
821 | } | ||
778 | 822 | ||
779 | return err; | 823 | return err; |
780 | } | 824 | } |
@@ -831,6 +875,8 @@ static int tegra_kbc_suspend(struct device *dev) | |||
831 | msleep(30); | 875 | msleep(30); |
832 | 876 | ||
833 | kbc->keypress_caused_wake = false; | 877 | kbc->keypress_caused_wake = false; |
878 | /* Enable keypress interrupt before going into suspend. */ | ||
879 | tegra_kbc_set_keypress_interrupt(kbc, true); | ||
834 | enable_irq(kbc->irq); | 880 | enable_irq(kbc->irq); |
835 | enable_irq_wake(kbc->irq); | 881 | enable_irq_wake(kbc->irq); |
836 | } else { | 882 | } else { |
@@ -852,6 +898,8 @@ static int tegra_kbc_resume(struct device *dev) | |||
852 | if (device_may_wakeup(&pdev->dev)) { | 898 | if (device_may_wakeup(&pdev->dev)) { |
853 | disable_irq_wake(kbc->irq); | 899 | disable_irq_wake(kbc->irq); |
854 | tegra_kbc_setup_wakekeys(kbc, false); | 900 | tegra_kbc_setup_wakekeys(kbc, false); |
901 | /* We will use fifo interrupts for key detection. */ | ||
902 | tegra_kbc_set_keypress_interrupt(kbc, false); | ||
855 | 903 | ||
856 | /* Restore the resident time of continuous polling mode. */ | 904 | /* Restore the resident time of continuous polling mode. */ |
857 | writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0); | 905 | writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0); |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7b46781c30c9..d62827271802 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -134,6 +134,18 @@ config INPUT_MAX8925_ONKEY | |||
134 | To compile this driver as a module, choose M here: the module | 134 | To compile this driver as a module, choose M here: the module |
135 | will be called max8925_onkey. | 135 | will be called max8925_onkey. |
136 | 136 | ||
137 | config INPUT_MAX8997_HAPTIC | ||
138 | tristate "MAXIM MAX8997 haptic controller support" | ||
139 | depends on HAVE_PWM && MFD_MAX8997 | ||
140 | select INPUT_FF_MEMLESS | ||
141 | help | ||
142 | This option enables device driver support for the haptic controller | ||
143 | on MAXIM MAX8997 chip. This driver supports ff-memless interface | ||
144 | from input framework. | ||
145 | |||
146 | To compile this driver as module, choose M here: the | ||
147 | module will be called max8997-haptic. | ||
148 | |||
137 | config INPUT_MC13783_PWRBUTTON | 149 | config INPUT_MC13783_PWRBUTTON |
138 | tristate "MC13783 ON buttons" | 150 | tristate "MC13783 ON buttons" |
139 | depends on MFD_MC13783 | 151 | depends on MFD_MC13783 |
@@ -415,7 +427,7 @@ config INPUT_PCF8574 | |||
415 | tristate "PCF8574 Keypad input device" | 427 | tristate "PCF8574 Keypad input device" |
416 | depends on I2C && EXPERIMENTAL | 428 | depends on I2C && EXPERIMENTAL |
417 | help | 429 | help |
418 | Say Y here if you want to support a keypad connetced via I2C | 430 | Say Y here if you want to support a keypad connected via I2C |
419 | with a PCF8574. | 431 | with a PCF8574. |
420 | 432 | ||
421 | To compile this driver as a module, choose M here: the | 433 | To compile this driver as a module, choose M here: the |
@@ -455,6 +467,16 @@ config INPUT_RB532_BUTTON | |||
455 | To compile this driver as a module, choose M here: the | 467 | To compile this driver as a module, choose M here: the |
456 | module will be called rb532_button. | 468 | module will be called rb532_button. |
457 | 469 | ||
470 | config INPUT_DA9052_ONKEY | ||
471 | tristate "Dialog DA9052/DA9053 Onkey" | ||
472 | depends on PMIC_DA9052 | ||
473 | help | ||
474 | Support the ONKEY of Dialog DA9052 PMICs as an input device | ||
475 | reporting power button status. | ||
476 | |||
477 | To compile this driver as a module, choose M here: the | ||
478 | module will be called da9052_onkey. | ||
479 | |||
458 | config INPUT_DM355EVM | 480 | config INPUT_DM355EVM |
459 | tristate "TI DaVinci DM355 EVM Keypad and IR Remote" | 481 | tristate "TI DaVinci DM355 EVM Keypad and IR Remote" |
460 | depends on MFD_DM355EVM_MSP | 482 | depends on MFD_DM355EVM_MSP |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 46671a875b91..f55cdf4916fa 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o | |||
21 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o | 21 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o |
22 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o | 22 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o |
23 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 23 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
24 | obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o | ||
24 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 25 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
25 | obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o | 26 | obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o |
26 | obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o | 27 | obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o |
@@ -30,6 +31,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | |||
30 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o | 31 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o |
31 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 32 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
32 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o | 33 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o |
34 | obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o | ||
33 | obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o | 35 | obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o |
34 | obj-$(CONFIG_INPUT_MMA8450) += mma8450.o | 36 | obj-$(CONFIG_INPUT_MMA8450) += mma8450.o |
35 | obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o | 37 | obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o |
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 79d901633635..350fd0c385d2 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/input.h> | 13 | #include <linux/input.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/mfd/ab8500.h> | 15 | #include <linux/mfd/abx500/ab8500.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | /** | 18 | /** |
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 56810fb4eadd..c8a79015472a 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c | |||
@@ -116,17 +116,7 @@ static struct i2c_driver ad714x_i2c_driver = { | |||
116 | .id_table = ad714x_id, | 116 | .id_table = ad714x_id, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | static int __init ad714x_i2c_init(void) | 119 | module_i2c_driver(ad714x_i2c_driver); |
120 | { | ||
121 | return i2c_add_driver(&ad714x_i2c_driver); | ||
122 | } | ||
123 | module_init(ad714x_i2c_init); | ||
124 | |||
125 | static void __exit ad714x_i2c_exit(void) | ||
126 | { | ||
127 | i2c_del_driver(&ad714x_i2c_driver); | ||
128 | } | ||
129 | module_exit(ad714x_i2c_exit); | ||
130 | 120 | ||
131 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver"); | 121 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver"); |
132 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 122 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 875b50811361..75f6136d608e 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c | |||
@@ -123,17 +123,7 @@ static struct spi_driver ad714x_spi_driver = { | |||
123 | .remove = __devexit_p(ad714x_spi_remove), | 123 | .remove = __devexit_p(ad714x_spi_remove), |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static __init int ad714x_spi_init(void) | 126 | module_spi_driver(ad714x_spi_driver); |
127 | { | ||
128 | return spi_register_driver(&ad714x_spi_driver); | ||
129 | } | ||
130 | module_init(ad714x_spi_init); | ||
131 | |||
132 | static __exit void ad714x_spi_exit(void) | ||
133 | { | ||
134 | spi_unregister_driver(&ad714x_spi_driver); | ||
135 | } | ||
136 | module_exit(ad714x_spi_exit); | ||
137 | 127 | ||
138 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver"); | 128 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver"); |
139 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 129 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index ccacf2bb06a4..dd1d1c145a7f 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c | |||
@@ -148,17 +148,7 @@ static struct i2c_driver adxl34x_driver = { | |||
148 | .id_table = adxl34x_id, | 148 | .id_table = adxl34x_id, |
149 | }; | 149 | }; |
150 | 150 | ||
151 | static int __init adxl34x_i2c_init(void) | 151 | module_i2c_driver(adxl34x_driver); |
152 | { | ||
153 | return i2c_add_driver(&adxl34x_driver); | ||
154 | } | ||
155 | module_init(adxl34x_i2c_init); | ||
156 | |||
157 | static void __exit adxl34x_i2c_exit(void) | ||
158 | { | ||
159 | i2c_del_driver(&adxl34x_driver); | ||
160 | } | ||
161 | module_exit(adxl34x_i2c_exit); | ||
162 | 152 | ||
163 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 153 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
164 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver"); | 154 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver"); |
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 34d401efd4a1..820a802a1e6e 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c | |||
@@ -129,17 +129,7 @@ static struct spi_driver adxl34x_driver = { | |||
129 | .remove = __devexit_p(adxl34x_spi_remove), | 129 | .remove = __devexit_p(adxl34x_spi_remove), |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static int __init adxl34x_spi_init(void) | 132 | module_spi_driver(adxl34x_driver); |
133 | { | ||
134 | return spi_register_driver(&adxl34x_driver); | ||
135 | } | ||
136 | module_init(adxl34x_spi_init); | ||
137 | |||
138 | static void __exit adxl34x_spi_exit(void) | ||
139 | { | ||
140 | spi_unregister_driver(&adxl34x_driver); | ||
141 | } | ||
142 | module_exit(adxl34x_spi_exit); | ||
143 | 133 | ||
144 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 134 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
145 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver"); | 135 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver"); |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index a34896ed7ed3..f63341f20b91 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -1013,23 +1013,4 @@ static int ati_remote2_post_reset(struct usb_interface *interface) | |||
1013 | return r; | 1013 | return r; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static int __init ati_remote2_init(void) | 1016 | module_usb_driver(ati_remote2_driver); |
1017 | { | ||
1018 | int r; | ||
1019 | |||
1020 | r = usb_register(&ati_remote2_driver); | ||
1021 | if (r) | ||
1022 | printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); | ||
1023 | else | ||
1024 | printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); | ||
1025 | |||
1026 | return r; | ||
1027 | } | ||
1028 | |||
1029 | static void __exit ati_remote2_exit(void) | ||
1030 | { | ||
1031 | usb_deregister(&ati_remote2_driver); | ||
1032 | } | ||
1033 | |||
1034 | module_init(ati_remote2_init); | ||
1035 | module_exit(ati_remote2_exit); | ||
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 8f55b54352b6..e2f1e9f952b1 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c | |||
@@ -673,19 +673,8 @@ static struct i2c_driver bma150_driver = { | |||
673 | .remove = __devexit_p(bma150_remove), | 673 | .remove = __devexit_p(bma150_remove), |
674 | }; | 674 | }; |
675 | 675 | ||
676 | static int __init BMA150_init(void) | 676 | module_i2c_driver(bma150_driver); |
677 | { | ||
678 | return i2c_add_driver(&bma150_driver); | ||
679 | } | ||
680 | |||
681 | static void __exit BMA150_exit(void) | ||
682 | { | ||
683 | i2c_del_driver(&bma150_driver); | ||
684 | } | ||
685 | 677 | ||
686 | MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>"); | 678 | MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>"); |
687 | MODULE_DESCRIPTION("BMA150 driver"); | 679 | MODULE_DESCRIPTION("BMA150 driver"); |
688 | MODULE_LICENSE("GPL"); | 680 | MODULE_LICENSE("GPL"); |
689 | |||
690 | module_init(BMA150_init); | ||
691 | module_exit(BMA150_exit); | ||
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index d100cc5c5783..fe9b85f07792 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c | |||
@@ -125,18 +125,7 @@ static struct i2c_driver cma3000_i2c_driver = { | |||
125 | }, | 125 | }, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | static int __init cma3000_i2c_init(void) | 128 | module_i2c_driver(cma3000_i2c_driver); |
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 | 129 | ||
141 | MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver"); | 130 | MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver"); |
142 | MODULE_LICENSE("GPL"); | 131 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c new file mode 100644 index 000000000000..34aebb8cd080 --- /dev/null +++ b/drivers/input/misc/da9052_onkey.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * ON pin driver for Dialog DA9052 PMICs | ||
3 | * | ||
4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/workqueue.h> | ||
19 | |||
20 | #include <linux/mfd/da9052/da9052.h> | ||
21 | #include <linux/mfd/da9052/reg.h> | ||
22 | |||
23 | struct da9052_onkey { | ||
24 | struct da9052 *da9052; | ||
25 | struct input_dev *input; | ||
26 | struct delayed_work work; | ||
27 | unsigned int irq; | ||
28 | }; | ||
29 | |||
30 | static void da9052_onkey_query(struct da9052_onkey *onkey) | ||
31 | { | ||
32 | int key_stat; | ||
33 | |||
34 | key_stat = da9052_reg_read(onkey->da9052, DA9052_EVENT_B_REG); | ||
35 | if (key_stat < 0) { | ||
36 | dev_err(onkey->da9052->dev, | ||
37 | "Failed to read onkey event %d\n", key_stat); | ||
38 | } else { | ||
39 | /* | ||
40 | * Since interrupt for deassertion of ONKEY pin is not | ||
41 | * generated, onkey event state determines the onkey | ||
42 | * button state. | ||
43 | */ | ||
44 | key_stat &= DA9052_EVENTB_ENONKEY; | ||
45 | input_report_key(onkey->input, KEY_POWER, key_stat); | ||
46 | input_sync(onkey->input); | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Interrupt is generated only when the ONKEY pin is asserted. | ||
51 | * Hence the deassertion of the pin is simulated through work queue. | ||
52 | */ | ||
53 | if (key_stat) | ||
54 | schedule_delayed_work(&onkey->work, msecs_to_jiffies(50)); | ||
55 | } | ||
56 | |||
57 | static void da9052_onkey_work(struct work_struct *work) | ||
58 | { | ||
59 | struct da9052_onkey *onkey = container_of(work, struct da9052_onkey, | ||
60 | work.work); | ||
61 | |||
62 | da9052_onkey_query(onkey); | ||
63 | } | ||
64 | |||
65 | static irqreturn_t da9052_onkey_irq(int irq, void *data) | ||
66 | { | ||
67 | struct da9052_onkey *onkey = data; | ||
68 | |||
69 | da9052_onkey_query(onkey); | ||
70 | |||
71 | return IRQ_HANDLED; | ||
72 | } | ||
73 | |||
74 | static int __devinit da9052_onkey_probe(struct platform_device *pdev) | ||
75 | { | ||
76 | struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent); | ||
77 | struct da9052_onkey *onkey; | ||
78 | struct input_dev *input_dev; | ||
79 | int irq; | ||
80 | int error; | ||
81 | |||
82 | if (!da9052) { | ||
83 | dev_err(&pdev->dev, "Failed to get the driver's data\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | irq = platform_get_irq_byname(pdev, "ONKEY"); | ||
88 | if (irq < 0) { | ||
89 | dev_err(&pdev->dev, | ||
90 | "Failed to get an IRQ for input device, %d\n", irq); | ||
91 | return -EINVAL; | ||
92 | } | ||
93 | |||
94 | onkey = kzalloc(sizeof(*onkey), GFP_KERNEL); | ||
95 | input_dev = input_allocate_device(); | ||
96 | if (!onkey || !input_dev) { | ||
97 | dev_err(&pdev->dev, "Failed to allocate memory\n"); | ||
98 | return -ENOMEM; | ||
99 | } | ||
100 | |||
101 | onkey->input = input_dev; | ||
102 | onkey->da9052 = da9052; | ||
103 | onkey->irq = irq; | ||
104 | INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work); | ||
105 | |||
106 | input_dev->name = "da9052-onkey"; | ||
107 | input_dev->phys = "da9052-onkey/input0"; | ||
108 | input_dev->dev.parent = &pdev->dev; | ||
109 | |||
110 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
111 | __set_bit(KEY_POWER, input_dev->keybit); | ||
112 | |||
113 | error = request_threaded_irq(onkey->irq, NULL, da9052_onkey_irq, | ||
114 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
115 | "ONKEY", onkey); | ||
116 | if (error < 0) { | ||
117 | dev_err(onkey->da9052->dev, | ||
118 | "Failed to register ONKEY IRQ %d, error = %d\n", | ||
119 | onkey->irq, error); | ||
120 | goto err_free_mem; | ||
121 | } | ||
122 | |||
123 | error = input_register_device(onkey->input); | ||
124 | if (error) { | ||
125 | dev_err(&pdev->dev, "Unable to register input device, %d\n", | ||
126 | error); | ||
127 | goto err_free_irq; | ||
128 | } | ||
129 | |||
130 | platform_set_drvdata(pdev, onkey); | ||
131 | return 0; | ||
132 | |||
133 | err_free_irq: | ||
134 | free_irq(onkey->irq, onkey); | ||
135 | cancel_delayed_work_sync(&onkey->work); | ||
136 | err_free_mem: | ||
137 | input_free_device(input_dev); | ||
138 | kfree(onkey); | ||
139 | |||
140 | return error; | ||
141 | } | ||
142 | |||
143 | static int __devexit da9052_onkey_remove(struct platform_device *pdev) | ||
144 | { | ||
145 | struct da9052_onkey *onkey = platform_get_drvdata(pdev); | ||
146 | |||
147 | free_irq(onkey->irq, onkey); | ||
148 | cancel_delayed_work_sync(&onkey->work); | ||
149 | |||
150 | input_unregister_device(onkey->input); | ||
151 | kfree(onkey); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static struct platform_driver da9052_onkey_driver = { | ||
157 | .probe = da9052_onkey_probe, | ||
158 | .remove = __devexit_p(da9052_onkey_remove), | ||
159 | .driver = { | ||
160 | .name = "da9052-onkey", | ||
161 | .owner = THIS_MODULE, | ||
162 | }, | ||
163 | }; | ||
164 | module_platform_driver(da9052_onkey_driver); | ||
165 | |||
166 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
167 | MODULE_DESCRIPTION("Onkey driver for DA9052"); | ||
168 | MODULE_LICENSE("GPL"); | ||
169 | MODULE_ALIAS("platform:da9052-onkey"); | ||
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index 71fba8c2fc66..b6664cfa340a 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c | |||
@@ -281,18 +281,7 @@ static struct i2c_driver gp2a_i2c_driver = { | |||
281 | .id_table = gp2a_i2c_id, | 281 | .id_table = gp2a_i2c_id, |
282 | }; | 282 | }; |
283 | 283 | ||
284 | static int __init gp2a_init(void) | 284 | module_i2c_driver(gp2a_i2c_driver); |
285 | { | ||
286 | return i2c_add_driver(&gp2a_i2c_driver); | ||
287 | } | ||
288 | |||
289 | static void __exit gp2a_exit(void) | ||
290 | { | ||
291 | i2c_del_driver(&gp2a_i2c_driver); | ||
292 | } | ||
293 | |||
294 | module_init(gp2a_init); | ||
295 | module_exit(gp2a_exit); | ||
296 | 285 | ||
297 | MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>"); | 286 | MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>"); |
298 | MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"); | 287 | MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"); |
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index fc62256c963f..d99151a8bf10 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c | |||
@@ -580,26 +580,7 @@ static struct usb_driver keyspan_driver = | |||
580 | .id_table = keyspan_table | 580 | .id_table = keyspan_table |
581 | }; | 581 | }; |
582 | 582 | ||
583 | static int __init usb_keyspan_init(void) | 583 | module_usb_driver(keyspan_driver); |
584 | { | ||
585 | int result; | ||
586 | |||
587 | /* register this driver with the USB subsystem */ | ||
588 | result = usb_register(&keyspan_driver); | ||
589 | if (result) | ||
590 | err("usb_register failed. Error number %d\n", result); | ||
591 | |||
592 | return result; | ||
593 | } | ||
594 | |||
595 | static void __exit usb_keyspan_exit(void) | ||
596 | { | ||
597 | /* deregister this driver with the USB subsystem */ | ||
598 | usb_deregister(&keyspan_driver); | ||
599 | } | ||
600 | |||
601 | module_init(usb_keyspan_init); | ||
602 | module_exit(usb_keyspan_exit); | ||
603 | 584 | ||
604 | MODULE_DEVICE_TABLE(usb, keyspan_table); | 585 | MODULE_DEVICE_TABLE(usb, keyspan_table); |
605 | MODULE_AUTHOR(DRIVER_AUTHOR); | 586 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index 783597a9a64a..f46139f19ff1 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c | |||
@@ -41,6 +41,14 @@ | |||
41 | #define PC1_ON (1 << 7) | 41 | #define PC1_ON (1 << 7) |
42 | /* Data ready funtion enable bit: set during probe if using irq mode */ | 42 | /* Data ready funtion enable bit: set during probe if using irq mode */ |
43 | #define DRDYE (1 << 5) | 43 | #define DRDYE (1 << 5) |
44 | /* DATA CONTROL REGISTER BITS */ | ||
45 | #define ODR12_5F 0 | ||
46 | #define ODR25F 1 | ||
47 | #define ODR50F 2 | ||
48 | #define ODR100F 3 | ||
49 | #define ODR200F 4 | ||
50 | #define ODR400F 5 | ||
51 | #define ODR800F 6 | ||
44 | /* INTERRUPT CONTROL REGISTER 1 BITS */ | 52 | /* INTERRUPT CONTROL REGISTER 1 BITS */ |
45 | /* Set these during probe if using irq mode */ | 53 | /* Set these during probe if using irq mode */ |
46 | #define KXTJ9_IEL (1 << 3) | 54 | #define KXTJ9_IEL (1 << 3) |
@@ -116,9 +124,13 @@ static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9) | |||
116 | if (err < 0) | 124 | if (err < 0) |
117 | dev_err(&tj9->client->dev, "accelerometer data read failed\n"); | 125 | dev_err(&tj9->client->dev, "accelerometer data read failed\n"); |
118 | 126 | ||
119 | x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift; | 127 | x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]); |
120 | y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift; | 128 | y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]); |
121 | z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift; | 129 | z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]); |
130 | |||
131 | x >>= tj9->shift; | ||
132 | y >>= tj9->shift; | ||
133 | z >>= tj9->shift; | ||
122 | 134 | ||
123 | input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x); | 135 | input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x); |
124 | input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y); | 136 | input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y); |
@@ -487,7 +499,7 @@ static int __devinit kxtj9_verify(struct kxtj9_data *tj9) | |||
487 | goto out; | 499 | goto out; |
488 | } | 500 | } |
489 | 501 | ||
490 | retval = retval != 0x06 ? -EIO : 0; | 502 | retval = (retval != 0x07 && retval != 0x08) ? -EIO : 0; |
491 | 503 | ||
492 | out: | 504 | out: |
493 | kxtj9_device_power_off(tj9); | 505 | kxtj9_device_power_off(tj9); |
@@ -537,7 +549,7 @@ static int __devinit kxtj9_probe(struct i2c_client *client, | |||
537 | i2c_set_clientdata(client, tj9); | 549 | i2c_set_clientdata(client, tj9); |
538 | 550 | ||
539 | tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range; | 551 | tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range; |
540 | tj9->data_ctrl = tj9->pdata.data_odr_init; | 552 | tj9->last_poll_interval = tj9->pdata.init_interval; |
541 | 553 | ||
542 | if (client->irq) { | 554 | if (client->irq) { |
543 | /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */ | 555 | /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */ |
@@ -655,17 +667,7 @@ static struct i2c_driver kxtj9_driver = { | |||
655 | .id_table = kxtj9_id, | 667 | .id_table = kxtj9_id, |
656 | }; | 668 | }; |
657 | 669 | ||
658 | static int __init kxtj9_init(void) | 670 | module_i2c_driver(kxtj9_driver); |
659 | { | ||
660 | return i2c_add_driver(&kxtj9_driver); | ||
661 | } | ||
662 | module_init(kxtj9_init); | ||
663 | |||
664 | static void __exit kxtj9_exit(void) | ||
665 | { | ||
666 | i2c_del_driver(&kxtj9_driver); | ||
667 | } | ||
668 | module_exit(kxtj9_exit); | ||
669 | 671 | ||
670 | MODULE_DESCRIPTION("KXTJ9 accelerometer driver"); | 672 | MODULE_DESCRIPTION("KXTJ9 accelerometer driver"); |
671 | MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>"); | 673 | MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>"); |
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index 23cf08271049..0a12b74140d3 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * max8925_onkey.c - MAX8925 ONKEY driver | 2 | * MAX8925 ONKEY driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Marvell International Ltd. | 4 | * Copyright (C) 2009 Marvell International Ltd. |
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> |
@@ -35,7 +35,7 @@ struct max8925_onkey_info { | |||
35 | struct input_dev *idev; | 35 | struct input_dev *idev; |
36 | struct i2c_client *i2c; | 36 | struct i2c_client *i2c; |
37 | struct device *dev; | 37 | struct device *dev; |
38 | int irq[2]; | 38 | unsigned int irq[2]; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -46,17 +46,14 @@ struct max8925_onkey_info { | |||
46 | static irqreturn_t max8925_onkey_handler(int irq, void *data) | 46 | static irqreturn_t max8925_onkey_handler(int irq, void *data) |
47 | { | 47 | { |
48 | struct max8925_onkey_info *info = data; | 48 | struct max8925_onkey_info *info = data; |
49 | int ret, event; | 49 | int state; |
50 | 50 | ||
51 | ret = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS); | 51 | state = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS); |
52 | if (ret & SW_INPUT) | 52 | |
53 | event = 1; | 53 | input_report_key(info->idev, KEY_POWER, state & SW_INPUT); |
54 | else | ||
55 | event = 0; | ||
56 | input_report_key(info->idev, KEY_POWER, event); | ||
57 | input_sync(info->idev); | 54 | input_sync(info->idev); |
58 | 55 | ||
59 | dev_dbg(info->dev, "onkey event:%d\n", event); | 56 | dev_dbg(info->dev, "onkey state:%d\n", state); |
60 | 57 | ||
61 | /* Enable hardreset to halt if system isn't shutdown on time */ | 58 | /* Enable hardreset to halt if system isn't shutdown on time */ |
62 | max8925_set_bits(info->i2c, MAX8925_SYSENSEL, | 59 | max8925_set_bits(info->i2c, MAX8925_SYSENSEL, |
@@ -69,6 +66,7 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
69 | { | 66 | { |
70 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 67 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
71 | struct max8925_onkey_info *info; | 68 | struct max8925_onkey_info *info; |
69 | struct input_dev *input; | ||
72 | int irq[2], error; | 70 | int irq[2], error; |
73 | 71 | ||
74 | irq[0] = platform_get_irq(pdev, 0); | 72 | irq[0] = platform_get_irq(pdev, 0); |
@@ -76,6 +74,7 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
76 | dev_err(&pdev->dev, "No IRQ resource!\n"); | 74 | dev_err(&pdev->dev, "No IRQ resource!\n"); |
77 | return -EINVAL; | 75 | return -EINVAL; |
78 | } | 76 | } |
77 | |||
79 | irq[1] = platform_get_irq(pdev, 1); | 78 | irq[1] = platform_get_irq(pdev, 1); |
80 | if (irq[1] < 0) { | 79 | if (irq[1] < 0) { |
81 | dev_err(&pdev->dev, "No IRQ resource!\n"); | 80 | dev_err(&pdev->dev, "No IRQ resource!\n"); |
@@ -83,11 +82,24 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
83 | } | 82 | } |
84 | 83 | ||
85 | info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); | 84 | info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); |
86 | if (!info) | 85 | input = input_allocate_device(); |
87 | return -ENOMEM; | 86 | if (!info || !input) { |
87 | error = -ENOMEM; | ||
88 | goto err_free_mem; | ||
89 | } | ||
88 | 90 | ||
91 | info->idev = input; | ||
89 | info->i2c = chip->i2c; | 92 | info->i2c = chip->i2c; |
90 | info->dev = &pdev->dev; | 93 | info->dev = &pdev->dev; |
94 | info->irq[0] = irq[0]; | ||
95 | info->irq[1] = irq[1]; | ||
96 | |||
97 | input->name = "max8925_on"; | ||
98 | input->phys = "max8925_on/input0"; | ||
99 | input->id.bustype = BUS_I2C; | ||
100 | input->dev.parent = &pdev->dev; | ||
101 | input_set_capability(input, EV_KEY, KEY_POWER); | ||
102 | |||
91 | irq[0] += chip->irq_base; | 103 | irq[0] += chip->irq_base; |
92 | irq[1] += chip->irq_base; | 104 | irq[1] += chip->irq_base; |
93 | 105 | ||
@@ -96,60 +108,46 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
96 | if (error < 0) { | 108 | if (error < 0) { |
97 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | 109 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", |
98 | irq[0], error); | 110 | irq[0], error); |
99 | goto out; | 111 | goto err_free_mem; |
100 | } | 112 | } |
113 | |||
101 | error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, | 114 | error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, |
102 | IRQF_ONESHOT, "onkey-up", info); | 115 | IRQF_ONESHOT, "onkey-up", info); |
103 | if (error < 0) { | 116 | if (error < 0) { |
104 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | 117 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", |
105 | irq[1], error); | 118 | irq[1], error); |
106 | goto out_irq; | 119 | goto err_free_irq0; |
107 | } | 120 | } |
108 | 121 | ||
109 | info->idev = input_allocate_device(); | ||
110 | if (!info->idev) { | ||
111 | dev_err(chip->dev, "Failed to allocate input dev\n"); | ||
112 | error = -ENOMEM; | ||
113 | goto out_input; | ||
114 | } | ||
115 | |||
116 | info->idev->name = "max8925_on"; | ||
117 | info->idev->phys = "max8925_on/input0"; | ||
118 | info->idev->id.bustype = BUS_I2C; | ||
119 | info->idev->dev.parent = &pdev->dev; | ||
120 | info->irq[0] = irq[0]; | ||
121 | info->irq[1] = irq[1]; | ||
122 | info->idev->evbit[0] = BIT_MASK(EV_KEY); | ||
123 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | ||
124 | |||
125 | |||
126 | error = input_register_device(info->idev); | 122 | error = input_register_device(info->idev); |
127 | if (error) { | 123 | if (error) { |
128 | dev_err(chip->dev, "Can't register input device: %d\n", error); | 124 | dev_err(chip->dev, "Can't register input device: %d\n", error); |
129 | goto out_reg; | 125 | goto err_free_irq1; |
130 | } | 126 | } |
131 | 127 | ||
132 | platform_set_drvdata(pdev, info); | 128 | platform_set_drvdata(pdev, info); |
129 | device_init_wakeup(&pdev->dev, 1); | ||
133 | 130 | ||
134 | return 0; | 131 | return 0; |
135 | 132 | ||
136 | out_reg: | 133 | err_free_irq1: |
137 | input_free_device(info->idev); | 134 | free_irq(irq[1], info); |
138 | out_input: | 135 | err_free_irq0: |
139 | free_irq(info->irq[1], info); | 136 | free_irq(irq[0], info); |
140 | out_irq: | 137 | err_free_mem: |
141 | free_irq(info->irq[0], info); | 138 | input_free_device(input); |
142 | out: | ||
143 | kfree(info); | 139 | kfree(info); |
140 | |||
144 | return error; | 141 | return error; |
145 | } | 142 | } |
146 | 143 | ||
147 | static int __devexit max8925_onkey_remove(struct platform_device *pdev) | 144 | static int __devexit max8925_onkey_remove(struct platform_device *pdev) |
148 | { | 145 | { |
149 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); | 146 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); |
147 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
150 | 148 | ||
151 | free_irq(info->irq[0], info); | 149 | free_irq(info->irq[0] + chip->irq_base, info); |
152 | free_irq(info->irq[1], info); | 150 | free_irq(info->irq[1] + chip->irq_base, info); |
153 | input_unregister_device(info->idev); | 151 | input_unregister_device(info->idev); |
154 | kfree(info); | 152 | kfree(info); |
155 | 153 | ||
@@ -158,10 +156,43 @@ static int __devexit max8925_onkey_remove(struct platform_device *pdev) | |||
158 | return 0; | 156 | return 0; |
159 | } | 157 | } |
160 | 158 | ||
159 | #ifdef CONFIG_PM_SLEEP | ||
160 | static int max8925_onkey_suspend(struct device *dev) | ||
161 | { | ||
162 | struct platform_device *pdev = to_platform_device(dev); | ||
163 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); | ||
164 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
165 | |||
166 | if (device_may_wakeup(dev)) { | ||
167 | chip->wakeup_flag |= 1 << info->irq[0]; | ||
168 | chip->wakeup_flag |= 1 << info->irq[1]; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int max8925_onkey_resume(struct device *dev) | ||
175 | { | ||
176 | struct platform_device *pdev = to_platform_device(dev); | ||
177 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); | ||
178 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
179 | |||
180 | if (device_may_wakeup(dev)) { | ||
181 | chip->wakeup_flag &= ~(1 << info->irq[0]); | ||
182 | chip->wakeup_flag &= ~(1 << info->irq[1]); | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | #endif | ||
188 | |||
189 | static SIMPLE_DEV_PM_OPS(max8925_onkey_pm_ops, max8925_onkey_suspend, max8925_onkey_resume); | ||
190 | |||
161 | static struct platform_driver max8925_onkey_driver = { | 191 | static struct platform_driver max8925_onkey_driver = { |
162 | .driver = { | 192 | .driver = { |
163 | .name = "max8925-onkey", | 193 | .name = "max8925-onkey", |
164 | .owner = THIS_MODULE, | 194 | .owner = THIS_MODULE, |
195 | .pm = &max8925_onkey_pm_ops, | ||
165 | }, | 196 | }, |
166 | .probe = max8925_onkey_probe, | 197 | .probe = max8925_onkey_probe, |
167 | .remove = __devexit_p(max8925_onkey_remove), | 198 | .remove = __devexit_p(max8925_onkey_remove), |
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c new file mode 100644 index 000000000000..05b7b8bfaf0a --- /dev/null +++ b/drivers/input/misc/max8997_haptic.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * MAX8997-haptic controller driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Samsung Electronics | ||
5 | * Donggeun Kim <dg77.kim@samsung.com> | ||
6 | * | ||
7 | * This program is not provided / owned by Maxim Integrated Products. | ||
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/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/pwm.h> | ||
31 | #include <linux/input.h> | ||
32 | #include <linux/mfd/max8997-private.h> | ||
33 | #include <linux/mfd/max8997.h> | ||
34 | #include <linux/regulator/consumer.h> | ||
35 | |||
36 | /* Haptic configuration 2 register */ | ||
37 | #define MAX8997_MOTOR_TYPE_SHIFT 7 | ||
38 | #define MAX8997_ENABLE_SHIFT 6 | ||
39 | #define MAX8997_MODE_SHIFT 5 | ||
40 | |||
41 | /* Haptic driver configuration register */ | ||
42 | #define MAX8997_CYCLE_SHIFT 6 | ||
43 | #define MAX8997_SIG_PERIOD_SHIFT 4 | ||
44 | #define MAX8997_SIG_DUTY_SHIFT 2 | ||
45 | #define MAX8997_PWM_DUTY_SHIFT 0 | ||
46 | |||
47 | struct max8997_haptic { | ||
48 | struct device *dev; | ||
49 | struct i2c_client *client; | ||
50 | struct input_dev *input_dev; | ||
51 | struct regulator *regulator; | ||
52 | |||
53 | struct work_struct work; | ||
54 | struct mutex mutex; | ||
55 | |||
56 | bool enabled; | ||
57 | unsigned int level; | ||
58 | |||
59 | struct pwm_device *pwm; | ||
60 | unsigned int pwm_period; | ||
61 | enum max8997_haptic_pwm_divisor pwm_divisor; | ||
62 | |||
63 | enum max8997_haptic_motor_type type; | ||
64 | enum max8997_haptic_pulse_mode mode; | ||
65 | |||
66 | unsigned int internal_mode_pattern; | ||
67 | unsigned int pattern_cycle; | ||
68 | unsigned int pattern_signal_period; | ||
69 | }; | ||
70 | |||
71 | static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip) | ||
72 | { | ||
73 | int ret = 0; | ||
74 | |||
75 | if (chip->mode == MAX8997_EXTERNAL_MODE) { | ||
76 | unsigned int duty = chip->pwm_period * chip->level / 100; | ||
77 | ret = pwm_config(chip->pwm, duty, chip->pwm_period); | ||
78 | } else { | ||
79 | int i; | ||
80 | u8 duty_index = 0; | ||
81 | |||
82 | for (i = 0; i <= 64; i++) { | ||
83 | if (chip->level <= i * 100 / 64) { | ||
84 | duty_index = i; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | switch (chip->internal_mode_pattern) { | ||
89 | case 0: | ||
90 | max8997_write_reg(chip->client, | ||
91 | MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index); | ||
92 | break; | ||
93 | case 1: | ||
94 | max8997_write_reg(chip->client, | ||
95 | MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index); | ||
96 | break; | ||
97 | case 2: | ||
98 | max8997_write_reg(chip->client, | ||
99 | MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index); | ||
100 | break; | ||
101 | case 3: | ||
102 | max8997_write_reg(chip->client, | ||
103 | MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index); | ||
104 | break; | ||
105 | default: | ||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static void max8997_haptic_configure(struct max8997_haptic *chip) | ||
113 | { | ||
114 | u8 value; | ||
115 | |||
116 | value = chip->type << MAX8997_MOTOR_TYPE_SHIFT | | ||
117 | chip->enabled << MAX8997_ENABLE_SHIFT | | ||
118 | chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor; | ||
119 | max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value); | ||
120 | |||
121 | if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) { | ||
122 | value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT | | ||
123 | chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT | | ||
124 | chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT | | ||
125 | chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT; | ||
126 | max8997_write_reg(chip->client, | ||
127 | MAX8997_HAPTIC_REG_DRVCONF, value); | ||
128 | |||
129 | switch (chip->internal_mode_pattern) { | ||
130 | case 0: | ||
131 | value = chip->pattern_cycle << 4; | ||
132 | max8997_write_reg(chip->client, | ||
133 | MAX8997_HAPTIC_REG_CYCLECONF1, value); | ||
134 | value = chip->pattern_signal_period; | ||
135 | max8997_write_reg(chip->client, | ||
136 | MAX8997_HAPTIC_REG_SIGCONF1, value); | ||
137 | break; | ||
138 | |||
139 | case 1: | ||
140 | value = chip->pattern_cycle; | ||
141 | max8997_write_reg(chip->client, | ||
142 | MAX8997_HAPTIC_REG_CYCLECONF1, value); | ||
143 | value = chip->pattern_signal_period; | ||
144 | max8997_write_reg(chip->client, | ||
145 | MAX8997_HAPTIC_REG_SIGCONF2, value); | ||
146 | break; | ||
147 | |||
148 | case 2: | ||
149 | value = chip->pattern_cycle << 4; | ||
150 | max8997_write_reg(chip->client, | ||
151 | MAX8997_HAPTIC_REG_CYCLECONF2, value); | ||
152 | value = chip->pattern_signal_period; | ||
153 | max8997_write_reg(chip->client, | ||
154 | MAX8997_HAPTIC_REG_SIGCONF3, value); | ||
155 | break; | ||
156 | |||
157 | case 3: | ||
158 | value = chip->pattern_cycle; | ||
159 | max8997_write_reg(chip->client, | ||
160 | MAX8997_HAPTIC_REG_CYCLECONF2, value); | ||
161 | value = chip->pattern_signal_period; | ||
162 | max8997_write_reg(chip->client, | ||
163 | MAX8997_HAPTIC_REG_SIGCONF4, value); | ||
164 | break; | ||
165 | |||
166 | default: | ||
167 | break; | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static void max8997_haptic_enable(struct max8997_haptic *chip) | ||
173 | { | ||
174 | int error; | ||
175 | |||
176 | mutex_lock(&chip->mutex); | ||
177 | |||
178 | error = max8997_haptic_set_duty_cycle(chip); | ||
179 | if (error) { | ||
180 | dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error); | ||
181 | goto out; | ||
182 | } | ||
183 | |||
184 | if (!chip->enabled) { | ||
185 | chip->enabled = true; | ||
186 | regulator_enable(chip->regulator); | ||
187 | max8997_haptic_configure(chip); | ||
188 | if (chip->mode == MAX8997_EXTERNAL_MODE) | ||
189 | pwm_enable(chip->pwm); | ||
190 | } | ||
191 | |||
192 | out: | ||
193 | mutex_unlock(&chip->mutex); | ||
194 | } | ||
195 | |||
196 | static void max8997_haptic_disable(struct max8997_haptic *chip) | ||
197 | { | ||
198 | mutex_lock(&chip->mutex); | ||
199 | |||
200 | if (chip->enabled) { | ||
201 | chip->enabled = false; | ||
202 | max8997_haptic_configure(chip); | ||
203 | if (chip->mode == MAX8997_EXTERNAL_MODE) | ||
204 | pwm_disable(chip->pwm); | ||
205 | regulator_disable(chip->regulator); | ||
206 | } | ||
207 | |||
208 | mutex_unlock(&chip->mutex); | ||
209 | } | ||
210 | |||
211 | static void max8997_haptic_play_effect_work(struct work_struct *work) | ||
212 | { | ||
213 | struct max8997_haptic *chip = | ||
214 | container_of(work, struct max8997_haptic, work); | ||
215 | |||
216 | if (chip->level) | ||
217 | max8997_haptic_enable(chip); | ||
218 | else | ||
219 | max8997_haptic_disable(chip); | ||
220 | } | ||
221 | |||
222 | static int max8997_haptic_play_effect(struct input_dev *dev, void *data, | ||
223 | struct ff_effect *effect) | ||
224 | { | ||
225 | struct max8997_haptic *chip = input_get_drvdata(dev); | ||
226 | |||
227 | chip->level = effect->u.rumble.strong_magnitude; | ||
228 | if (!chip->level) | ||
229 | chip->level = effect->u.rumble.weak_magnitude; | ||
230 | |||
231 | schedule_work(&chip->work); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static void max8997_haptic_close(struct input_dev *dev) | ||
237 | { | ||
238 | struct max8997_haptic *chip = input_get_drvdata(dev); | ||
239 | |||
240 | cancel_work_sync(&chip->work); | ||
241 | max8997_haptic_disable(chip); | ||
242 | } | ||
243 | |||
244 | static int __devinit max8997_haptic_probe(struct platform_device *pdev) | ||
245 | { | ||
246 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
247 | const struct max8997_platform_data *pdata = | ||
248 | dev_get_platdata(iodev->dev); | ||
249 | const struct max8997_haptic_platform_data *haptic_pdata = | ||
250 | pdata->haptic_pdata; | ||
251 | struct max8997_haptic *chip; | ||
252 | struct input_dev *input_dev; | ||
253 | int error; | ||
254 | |||
255 | if (!haptic_pdata) { | ||
256 | dev_err(&pdev->dev, "no haptic platform data\n"); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); | ||
261 | input_dev = input_allocate_device(); | ||
262 | if (!chip || !input_dev) { | ||
263 | dev_err(&pdev->dev, "unable to allocate memory\n"); | ||
264 | error = -ENOMEM; | ||
265 | goto err_free_mem; | ||
266 | } | ||
267 | |||
268 | INIT_WORK(&chip->work, max8997_haptic_play_effect_work); | ||
269 | mutex_init(&chip->mutex); | ||
270 | |||
271 | chip->client = iodev->haptic; | ||
272 | chip->dev = &pdev->dev; | ||
273 | chip->input_dev = input_dev; | ||
274 | chip->pwm_period = haptic_pdata->pwm_period; | ||
275 | chip->type = haptic_pdata->type; | ||
276 | chip->mode = haptic_pdata->mode; | ||
277 | chip->pwm_divisor = haptic_pdata->pwm_divisor; | ||
278 | |||
279 | switch (chip->mode) { | ||
280 | case MAX8997_INTERNAL_MODE: | ||
281 | chip->internal_mode_pattern = | ||
282 | haptic_pdata->internal_mode_pattern; | ||
283 | chip->pattern_cycle = haptic_pdata->pattern_cycle; | ||
284 | chip->pattern_signal_period = | ||
285 | haptic_pdata->pattern_signal_period; | ||
286 | break; | ||
287 | |||
288 | case MAX8997_EXTERNAL_MODE: | ||
289 | chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, | ||
290 | "max8997-haptic"); | ||
291 | if (IS_ERR(chip->pwm)) { | ||
292 | error = PTR_ERR(chip->pwm); | ||
293 | dev_err(&pdev->dev, | ||
294 | "unable to request PWM for haptic, error: %d\n", | ||
295 | error); | ||
296 | goto err_free_mem; | ||
297 | } | ||
298 | break; | ||
299 | |||
300 | default: | ||
301 | dev_err(&pdev->dev, | ||
302 | "Invalid chip mode specified (%d)\n", chip->mode); | ||
303 | error = -EINVAL; | ||
304 | goto err_free_mem; | ||
305 | } | ||
306 | |||
307 | chip->regulator = regulator_get(&pdev->dev, "inmotor"); | ||
308 | if (IS_ERR(chip->regulator)) { | ||
309 | error = PTR_ERR(chip->regulator); | ||
310 | dev_err(&pdev->dev, | ||
311 | "unable to get regulator, error: %d\n", | ||
312 | error); | ||
313 | goto err_free_pwm; | ||
314 | } | ||
315 | |||
316 | input_dev->name = "max8997-haptic"; | ||
317 | input_dev->id.version = 1; | ||
318 | input_dev->dev.parent = &pdev->dev; | ||
319 | input_dev->close = max8997_haptic_close; | ||
320 | input_set_drvdata(input_dev, chip); | ||
321 | input_set_capability(input_dev, EV_FF, FF_RUMBLE); | ||
322 | |||
323 | error = input_ff_create_memless(input_dev, NULL, | ||
324 | max8997_haptic_play_effect); | ||
325 | if (error) { | ||
326 | dev_err(&pdev->dev, | ||
327 | "unable to create FF device, error: %d\n", | ||
328 | error); | ||
329 | goto err_put_regulator; | ||
330 | } | ||
331 | |||
332 | error = input_register_device(input_dev); | ||
333 | if (error) { | ||
334 | dev_err(&pdev->dev, | ||
335 | "unable to register input device, error: %d\n", | ||
336 | error); | ||
337 | goto err_destroy_ff; | ||
338 | } | ||
339 | |||
340 | platform_set_drvdata(pdev, chip); | ||
341 | return 0; | ||
342 | |||
343 | err_destroy_ff: | ||
344 | input_ff_destroy(input_dev); | ||
345 | err_put_regulator: | ||
346 | regulator_put(chip->regulator); | ||
347 | err_free_pwm: | ||
348 | if (chip->mode == MAX8997_EXTERNAL_MODE) | ||
349 | pwm_free(chip->pwm); | ||
350 | err_free_mem: | ||
351 | input_free_device(input_dev); | ||
352 | kfree(chip); | ||
353 | |||
354 | return error; | ||
355 | } | ||
356 | |||
357 | static int __devexit max8997_haptic_remove(struct platform_device *pdev) | ||
358 | { | ||
359 | struct max8997_haptic *chip = platform_get_drvdata(pdev); | ||
360 | |||
361 | input_unregister_device(chip->input_dev); | ||
362 | regulator_put(chip->regulator); | ||
363 | |||
364 | if (chip->mode == MAX8997_EXTERNAL_MODE) | ||
365 | pwm_free(chip->pwm); | ||
366 | |||
367 | kfree(chip); | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | #ifdef CONFIG_PM_SLEEP | ||
373 | static int max8997_haptic_suspend(struct device *dev) | ||
374 | { | ||
375 | struct platform_device *pdev = to_platform_device(dev); | ||
376 | struct max8997_haptic *chip = platform_get_drvdata(pdev); | ||
377 | |||
378 | max8997_haptic_disable(chip); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | #endif | ||
383 | |||
384 | static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL); | ||
385 | |||
386 | static const struct platform_device_id max8997_haptic_id[] = { | ||
387 | { "max8997-haptic", 0 }, | ||
388 | { }, | ||
389 | }; | ||
390 | MODULE_DEVICE_TABLE(i2c, max8997_haptic_id); | ||
391 | |||
392 | static struct platform_driver max8997_haptic_driver = { | ||
393 | .driver = { | ||
394 | .name = "max8997-haptic", | ||
395 | .owner = THIS_MODULE, | ||
396 | .pm = &max8997_haptic_pm_ops, | ||
397 | }, | ||
398 | .probe = max8997_haptic_probe, | ||
399 | .remove = __devexit_p(max8997_haptic_remove), | ||
400 | .id_table = max8997_haptic_id, | ||
401 | }; | ||
402 | module_platform_driver(max8997_haptic_driver); | ||
403 | |||
404 | MODULE_ALIAS("platform:max8997-haptic"); | ||
405 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); | ||
406 | MODULE_DESCRIPTION("max8997_haptic driver"); | ||
407 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 4d60080bb5d5..873ebced544e 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c | |||
@@ -247,17 +247,7 @@ static struct i2c_driver mma8450_driver = { | |||
247 | .id_table = mma8450_id, | 247 | .id_table = mma8450_id, |
248 | }; | 248 | }; |
249 | 249 | ||
250 | static int __init mma8450_init(void) | 250 | module_i2c_driver(mma8450_driver); |
251 | { | ||
252 | return i2c_add_driver(&mma8450_driver); | ||
253 | } | ||
254 | module_init(mma8450_init); | ||
255 | |||
256 | static void __exit mma8450_exit(void) | ||
257 | { | ||
258 | i2c_del_driver(&mma8450_driver); | ||
259 | } | ||
260 | module_exit(mma8450_exit); | ||
261 | 251 | ||
262 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | 252 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
263 | MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver"); | 253 | MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver"); |
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index 208d1a1cc7f3..5403c571b6a5 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c | |||
@@ -475,17 +475,7 @@ static struct i2c_driver mpu3050_i2c_driver = { | |||
475 | .id_table = mpu3050_ids, | 475 | .id_table = mpu3050_ids, |
476 | }; | 476 | }; |
477 | 477 | ||
478 | static int __init mpu3050_init(void) | 478 | module_i2c_driver(mpu3050_i2c_driver); |
479 | { | ||
480 | return i2c_add_driver(&mpu3050_i2c_driver); | ||
481 | } | ||
482 | module_init(mpu3050_init); | ||
483 | |||
484 | static void __exit mpu3050_exit(void) | ||
485 | { | ||
486 | i2c_del_driver(&mpu3050_i2c_driver); | ||
487 | } | ||
488 | module_exit(mpu3050_exit); | ||
489 | 479 | ||
490 | MODULE_AUTHOR("Wistron Corp."); | 480 | MODULE_AUTHOR("Wistron Corp."); |
491 | MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver"); | 481 | MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver"); |
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 08be1a355956..544c6635abe9 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c | |||
@@ -216,17 +216,7 @@ static struct i2c_driver pcf8574_kp_driver = { | |||
216 | .id_table = pcf8574_kp_id, | 216 | .id_table = pcf8574_kp_id, |
217 | }; | 217 | }; |
218 | 218 | ||
219 | static int __init pcf8574_kp_init(void) | 219 | module_i2c_driver(pcf8574_kp_driver); |
220 | { | ||
221 | return i2c_add_driver(&pcf8574_kp_driver); | ||
222 | } | ||
223 | module_init(pcf8574_kp_init); | ||
224 | |||
225 | static void __exit pcf8574_kp_exit(void) | ||
226 | { | ||
227 | i2c_del_driver(&pcf8574_kp_driver); | ||
228 | } | ||
229 | module_exit(pcf8574_kp_exit); | ||
230 | 220 | ||
231 | MODULE_AUTHOR("Michael Hennerich"); | 221 | MODULE_AUTHOR("Michael Hennerich"); |
232 | MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574"); | 222 | MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574"); |
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index f45947190e4f..538f7049ec64 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c | |||
@@ -441,18 +441,7 @@ static struct usb_driver powermate_driver = { | |||
441 | .id_table = powermate_devices, | 441 | .id_table = powermate_devices, |
442 | }; | 442 | }; |
443 | 443 | ||
444 | static int __init powermate_init(void) | 444 | module_usb_driver(powermate_driver); |
445 | { | ||
446 | return usb_register(&powermate_driver); | ||
447 | } | ||
448 | |||
449 | static void __exit powermate_cleanup(void) | ||
450 | { | ||
451 | usb_deregister(&powermate_driver); | ||
452 | } | ||
453 | |||
454 | module_init(powermate_init); | ||
455 | module_exit(powermate_cleanup); | ||
456 | 445 | ||
457 | MODULE_AUTHOR( "William R Sowerbutts" ); | 446 | MODULE_AUTHOR( "William R Sowerbutts" ); |
458 | MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); | 447 | MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 52b419348983..e2bdfd4bea70 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -48,7 +48,7 @@ MODULE_DESCRIPTION("Wistron laptop button driver"); | |||
48 | MODULE_LICENSE("GPL v2"); | 48 | MODULE_LICENSE("GPL v2"); |
49 | MODULE_VERSION("0.3"); | 49 | MODULE_VERSION("0.3"); |
50 | 50 | ||
51 | static int force; /* = 0; */ | 51 | static bool force; /* = 0; */ |
52 | module_param(force, bool, 0); | 52 | module_param(force, bool, 0); |
53 | MODULE_PARM_DESC(force, "Load even if computer is not in database"); | 53 | MODULE_PARM_DESC(force, "Load even if computer is not in database"); |
54 | 54 | ||
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index ad2e51c04db8..02ca8680ea5b 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c | |||
@@ -361,15 +361,12 @@ static const struct xenbus_device_id xenkbd_ids[] = { | |||
361 | { "" } | 361 | { "" } |
362 | }; | 362 | }; |
363 | 363 | ||
364 | static struct xenbus_driver xenkbd_driver = { | 364 | static DEFINE_XENBUS_DRIVER(xenkbd, , |
365 | .name = "vkbd", | ||
366 | .owner = THIS_MODULE, | ||
367 | .ids = xenkbd_ids, | ||
368 | .probe = xenkbd_probe, | 365 | .probe = xenkbd_probe, |
369 | .remove = xenkbd_remove, | 366 | .remove = xenkbd_remove, |
370 | .resume = xenkbd_resume, | 367 | .resume = xenkbd_resume, |
371 | .otherend_changed = xenkbd_backend_changed, | 368 | .otherend_changed = xenkbd_backend_changed, |
372 | }; | 369 | ); |
373 | 370 | ||
374 | static int __init xenkbd_init(void) | 371 | static int __init xenkbd_init(void) |
375 | { | 372 | { |
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 41201c6b5e68..f4776e7f8c15 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c | |||
@@ -988,22 +988,7 @@ static struct usb_driver yealink_driver = { | |||
988 | .id_table = usb_table, | 988 | .id_table = usb_table, |
989 | }; | 989 | }; |
990 | 990 | ||
991 | static int __init yealink_dev_init(void) | 991 | module_usb_driver(yealink_driver); |
992 | { | ||
993 | int ret = usb_register(&yealink_driver); | ||
994 | if (ret == 0) | ||
995 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
996 | DRIVER_DESC "\n"); | ||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | static void __exit yealink_dev_exit(void) | ||
1001 | { | ||
1002 | usb_deregister(&yealink_driver); | ||
1003 | } | ||
1004 | |||
1005 | module_init(yealink_dev_init); | ||
1006 | module_exit(yealink_dev_exit); | ||
1007 | 992 | ||
1008 | MODULE_DEVICE_TABLE (usb, usb_table); | 993 | MODULE_DEVICE_TABLE (usb, usb_table); |
1009 | 994 | ||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 9c1e6ee83531..9b8db821d5f0 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -322,4 +322,21 @@ config MOUSE_SYNAPTICS_I2C | |||
322 | To compile this driver as a module, choose M here: the | 322 | To compile this driver as a module, choose M here: the |
323 | module will be called synaptics_i2c. | 323 | module will be called synaptics_i2c. |
324 | 324 | ||
325 | config MOUSE_SYNAPTICS_USB | ||
326 | tristate "Synaptics USB device support" | ||
327 | depends on USB_ARCH_HAS_HCD | ||
328 | select USB | ||
329 | help | ||
330 | Say Y here if you want to use a Synaptics USB touchpad or pointing | ||
331 | stick. | ||
332 | |||
333 | While these devices emulate an USB mouse by default and can be used | ||
334 | with standard usbhid driver, this driver, together with its X.Org | ||
335 | counterpart, allows you to fully utilize capabilities of the device. | ||
336 | More information can be found at: | ||
337 | <http://jan-steinhoff.de/linux/synaptics-usb.html> | ||
338 | |||
339 | To compile this driver as a module, choose M here: the | ||
340 | module will be called synaptics_usb. | ||
341 | |||
325 | endif | 342 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 570c84a4a654..4718effeb8d9 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o | |||
18 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 18 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
19 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | 19 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o |
20 | obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o | 20 | obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o |
21 | obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o | ||
21 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 22 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
22 | 23 | ||
23 | psmouse-objs := psmouse-base.o synaptics.o | 24 | psmouse-objs := psmouse-base.o synaptics.o |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index b77f9991278e..0acbc7d50d05 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -938,15 +938,4 @@ static struct usb_driver atp_driver = { | |||
938 | .id_table = atp_table, | 938 | .id_table = atp_table, |
939 | }; | 939 | }; |
940 | 940 | ||
941 | static int __init atp_init(void) | 941 | module_usb_driver(atp_driver); |
942 | { | ||
943 | return usb_register(&atp_driver); | ||
944 | } | ||
945 | |||
946 | static void __exit atp_exit(void) | ||
947 | { | ||
948 | usb_deregister(&atp_driver); | ||
949 | } | ||
950 | |||
951 | module_init(atp_init); | ||
952 | module_exit(atp_exit); | ||
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 913e9fa4c810..f9e2758b9f46 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -433,6 +433,7 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
433 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | 433 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); |
434 | __set_bit(BTN_LEFT, input_dev->keybit); | 434 | __set_bit(BTN_LEFT, input_dev->keybit); |
435 | 435 | ||
436 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
436 | if (cfg->caps & HAS_INTEGRATED_BUTTON) | 437 | if (cfg->caps & HAS_INTEGRATED_BUTTON) |
437 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | 438 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); |
438 | 439 | ||
@@ -943,16 +944,4 @@ static struct usb_driver bcm5974_driver = { | |||
943 | .supports_autosuspend = 1, | 944 | .supports_autosuspend = 1, |
944 | }; | 945 | }; |
945 | 946 | ||
946 | static int __init bcm5974_init(void) | 947 | module_usb_driver(bcm5974_driver); |
947 | { | ||
948 | return usb_register(&bcm5974_driver); | ||
949 | } | ||
950 | |||
951 | static void __exit bcm5974_exit(void) | ||
952 | { | ||
953 | usb_deregister(&bcm5974_driver); | ||
954 | } | ||
955 | |||
956 | module_init(bcm5974_init); | ||
957 | module_exit(bcm5974_exit); | ||
958 | |||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 1c5d521de600..575f880727fe 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -640,7 +640,6 @@ static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) | |||
640 | 640 | ||
641 | static int hgpk_force_recalibrate(struct psmouse *psmouse) | 641 | static int hgpk_force_recalibrate(struct psmouse *psmouse) |
642 | { | 642 | { |
643 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
644 | struct hgpk_data *priv = psmouse->private; | 643 | struct hgpk_data *priv = psmouse->private; |
645 | int err; | 644 | int err; |
646 | 645 | ||
@@ -669,12 +668,9 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) | |||
669 | * we don't have a good way to deal with it. The 2s window stuff | 668 | * we don't have a good way to deal with it. The 2s window stuff |
670 | * (below) is our best option for now. | 669 | * (below) is our best option for now. |
671 | */ | 670 | */ |
672 | 671 | if (psmouse_activate(psmouse)) | |
673 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | ||
674 | return -1; | 672 | return -1; |
675 | 673 | ||
676 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
677 | |||
678 | if (tpdebug) | 674 | if (tpdebug) |
679 | psmouse_dbg(psmouse, "touchpad reactivated\n"); | 675 | psmouse_dbg(psmouse, "touchpad reactivated\n"); |
680 | 676 | ||
@@ -733,8 +729,7 @@ static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable) | |||
733 | } | 729 | } |
734 | 730 | ||
735 | /* should be all set, enable the touchpad */ | 731 | /* should be all set, enable the touchpad */ |
736 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 732 | psmouse_activate(psmouse); |
737 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
738 | psmouse_dbg(psmouse, "Touchpad powered up.\n"); | 733 | psmouse_dbg(psmouse, "Touchpad powered up.\n"); |
739 | } else { | 734 | } else { |
740 | psmouse_dbg(psmouse, "Powering off touchpad.\n"); | 735 | psmouse_dbg(psmouse, "Powering off touchpad.\n"); |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index de7e8bc17b1f..22fe2547e169 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -60,7 +60,7 @@ static unsigned int psmouse_rate = 100; | |||
60 | module_param_named(rate, psmouse_rate, uint, 0644); | 60 | module_param_named(rate, psmouse_rate, uint, 0644); |
61 | MODULE_PARM_DESC(rate, "Report rate, in reports per second."); | 61 | MODULE_PARM_DESC(rate, "Report rate, in reports per second."); |
62 | 62 | ||
63 | static unsigned int psmouse_smartscroll = 1; | 63 | static bool psmouse_smartscroll = 1; |
64 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); | 64 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
65 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); | 65 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); |
66 | 66 | ||
@@ -1092,28 +1092,33 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
1092 | * psmouse_activate() enables the mouse so that we get motion reports from it. | 1092 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
1093 | */ | 1093 | */ |
1094 | 1094 | ||
1095 | static void psmouse_activate(struct psmouse *psmouse) | 1095 | int psmouse_activate(struct psmouse *psmouse) |
1096 | { | 1096 | { |
1097 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | 1097 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
1098 | psmouse_warn(psmouse, "Failed to enable mouse on %s\n", | 1098 | psmouse_warn(psmouse, "Failed to enable mouse on %s\n", |
1099 | psmouse->ps2dev.serio->phys); | 1099 | psmouse->ps2dev.serio->phys); |
1100 | return -1; | ||
1101 | } | ||
1100 | 1102 | ||
1101 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 1103 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
1104 | return 0; | ||
1102 | } | 1105 | } |
1103 | 1106 | ||
1104 | |||
1105 | /* | 1107 | /* |
1106 | * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion | 1108 | * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion |
1107 | * reports from it unless we explicitly request it. | 1109 | * reports from it unless we explicitly request it. |
1108 | */ | 1110 | */ |
1109 | 1111 | ||
1110 | static void psmouse_deactivate(struct psmouse *psmouse) | 1112 | int psmouse_deactivate(struct psmouse *psmouse) |
1111 | { | 1113 | { |
1112 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | 1114 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) { |
1113 | psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n", | 1115 | psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n", |
1114 | psmouse->ps2dev.serio->phys); | 1116 | psmouse->ps2dev.serio->phys); |
1117 | return -1; | ||
1118 | } | ||
1115 | 1119 | ||
1116 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1120 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
1121 | return 0; | ||
1117 | } | 1122 | } |
1118 | 1123 | ||
1119 | 1124 | ||
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 6a417092d010..fe1df231ba4c 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -105,6 +105,8 @@ int psmouse_reset(struct psmouse *psmouse); | |||
105 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state); | 105 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state); |
106 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); | 106 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); |
107 | psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse); | 107 | psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse); |
108 | int psmouse_activate(struct psmouse *psmouse); | ||
109 | int psmouse_deactivate(struct psmouse *psmouse); | ||
108 | 110 | ||
109 | struct psmouse_attribute { | 111 | struct psmouse_attribute { |
110 | struct device_attribute dattr; | 112 | struct device_attribute dattr; |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index e36847de7617..2a77a52d2e62 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
@@ -90,8 +90,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
90 | * to do that for writes because sysfs set helper does this for | 90 | * to do that for writes because sysfs set helper does this for |
91 | * us. | 91 | * us. |
92 | */ | 92 | */ |
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 93 | psmouse_deactivate(psmouse); |
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
95 | 94 | ||
96 | ps2_begin_command(ps2dev); | 95 | ps2_begin_command(ps2dev); |
97 | 96 | ||
@@ -128,8 +127,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
128 | 127 | ||
129 | out: | 128 | out: |
130 | ps2_end_command(ps2dev); | 129 | ps2_end_command(ps2dev); |
131 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 130 | psmouse_activate(psmouse); |
132 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
133 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | 131 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", |
134 | reg_addr, *reg_val, rc); | 132 | reg_addr, *reg_val, rc); |
135 | return rc; | 133 | return rc; |
@@ -213,8 +211,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
213 | unsigned char param[3]; | 211 | unsigned char param[3]; |
214 | int rc = -1; | 212 | int rc = -1; |
215 | 213 | ||
216 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 214 | psmouse_deactivate(psmouse); |
217 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
218 | 215 | ||
219 | ps2_begin_command(ps2dev); | 216 | ps2_begin_command(ps2dev); |
220 | 217 | ||
@@ -239,8 +236,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
239 | 236 | ||
240 | out: | 237 | out: |
241 | ps2_end_command(ps2dev); | 238 | ps2_end_command(ps2dev); |
242 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 239 | psmouse_activate(psmouse); |
243 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
244 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | 240 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", |
245 | *reg_val, rc); | 241 | *reg_val, rc); |
246 | return rc; | 242 | return rc; |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 4b755cb5b38c..f14675702c0f 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -185,17 +185,17 @@ | |||
185 | #define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) | 185 | #define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) |
186 | 186 | ||
187 | /* Control touchpad's No Deceleration option */ | 187 | /* Control touchpad's No Deceleration option */ |
188 | static int no_decel = 1; | 188 | static bool no_decel = 1; |
189 | module_param(no_decel, bool, 0644); | 189 | module_param(no_decel, bool, 0644); |
190 | MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); | 190 | MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); |
191 | 191 | ||
192 | /* Control touchpad's Reduced Reporting option */ | 192 | /* Control touchpad's Reduced Reporting option */ |
193 | static int reduce_report; | 193 | static bool reduce_report; |
194 | module_param(reduce_report, bool, 0644); | 194 | module_param(reduce_report, bool, 0644); |
195 | MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); | 195 | MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); |
196 | 196 | ||
197 | /* Control touchpad's No Filter option */ | 197 | /* Control touchpad's No Filter option */ |
198 | static int no_filter; | 198 | static bool no_filter; |
199 | module_param(no_filter, bool, 0644); | 199 | module_param(no_filter, bool, 0644); |
200 | MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | 200 | MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); |
201 | 201 | ||
@@ -672,18 +672,7 @@ static struct i2c_driver synaptics_i2c_driver = { | |||
672 | .id_table = synaptics_i2c_id_table, | 672 | .id_table = synaptics_i2c_id_table, |
673 | }; | 673 | }; |
674 | 674 | ||
675 | static int __init synaptics_i2c_init(void) | 675 | module_i2c_driver(synaptics_i2c_driver); |
676 | { | ||
677 | return i2c_add_driver(&synaptics_i2c_driver); | ||
678 | } | ||
679 | |||
680 | static void __exit synaptics_i2c_exit(void) | ||
681 | { | ||
682 | i2c_del_driver(&synaptics_i2c_driver); | ||
683 | } | ||
684 | |||
685 | module_init(synaptics_i2c_init); | ||
686 | module_exit(synaptics_i2c_exit); | ||
687 | 676 | ||
688 | MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); | 677 | MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); |
689 | MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); | 678 | MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); |
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c new file mode 100644 index 000000000000..3c5eaaa5d154 --- /dev/null +++ b/drivers/input/mouse/synaptics_usb.c | |||
@@ -0,0 +1,557 @@ | |||
1 | /* | ||
2 | * USB Synaptics device driver | ||
3 | * | ||
4 | * Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk) | ||
5 | * Copyright (c) 2003 Ron Lee (ron@debian.org) | ||
6 | * cPad driver for kernel 2.4 | ||
7 | * | ||
8 | * Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de) | ||
9 | * Copyright (c) 2004 Ron Lee (ron@debian.org) | ||
10 | * rewritten for kernel 2.6 | ||
11 | * | ||
12 | * cPad display character device part is not included. It can be found at | ||
13 | * http://jan-steinhoff.de/linux/synaptics-usb.html | ||
14 | * | ||
15 | * Bases on: usb_skeleton.c v2.2 by Greg Kroah-Hartman | ||
16 | * drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik | ||
17 | * drivers/input/mouse/synaptics.c by Peter Osterlund | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the Free | ||
21 | * Software Foundation; either version 2 of the License, or (at your option) | ||
22 | * any later version. | ||
23 | * | ||
24 | * Trademarks are the property of their respective owners. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * There are three different types of Synaptics USB devices: Touchpads, | ||
29 | * touchsticks (or trackpoints), and touchscreens. Touchpads are well supported | ||
30 | * by this driver, touchstick support has not been tested much yet, and | ||
31 | * touchscreens have not been tested at all. | ||
32 | * | ||
33 | * Up to three alternate settings are possible: | ||
34 | * setting 0: one int endpoint for relative movement (used by usbhid.ko) | ||
35 | * setting 1: one int endpoint for absolute finger position | ||
36 | * setting 2 (cPad only): one int endpoint for absolute finger position and | ||
37 | * two bulk endpoints for the display (in/out) | ||
38 | * This driver uses setting 1. | ||
39 | */ | ||
40 | |||
41 | #include <linux/kernel.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/moduleparam.h> | ||
46 | #include <linux/usb.h> | ||
47 | #include <linux/input.h> | ||
48 | #include <linux/usb/input.h> | ||
49 | |||
50 | #define USB_VENDOR_ID_SYNAPTICS 0x06cb | ||
51 | #define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 /* Synaptics USB TouchPad */ | ||
52 | #define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 /* Integrated USB TouchPad */ | ||
53 | #define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 /* Synaptics cPad */ | ||
54 | #define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 /* Synaptics TouchScreen */ | ||
55 | #define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 /* Synaptics USB Styk */ | ||
56 | #define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 /* Synaptics USB WheelPad */ | ||
57 | #define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 /* Composite USB TouchPad */ | ||
58 | #define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 /* Wireless TouchPad */ | ||
59 | #define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 /* DisplayPad */ | ||
60 | |||
61 | #define SYNUSB_TOUCHPAD (1 << 0) | ||
62 | #define SYNUSB_STICK (1 << 1) | ||
63 | #define SYNUSB_TOUCHSCREEN (1 << 2) | ||
64 | #define SYNUSB_AUXDISPLAY (1 << 3) /* For cPad */ | ||
65 | #define SYNUSB_COMBO (1 << 4) /* Composite device (TP + stick) */ | ||
66 | #define SYNUSB_IO_ALWAYS (1 << 5) | ||
67 | |||
68 | #define USB_DEVICE_SYNAPTICS(prod, kind) \ | ||
69 | USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, \ | ||
70 | USB_DEVICE_ID_SYNAPTICS_##prod), \ | ||
71 | .driver_info = (kind), | ||
72 | |||
73 | #define SYNUSB_RECV_SIZE 8 | ||
74 | |||
75 | #define XMIN_NOMINAL 1472 | ||
76 | #define XMAX_NOMINAL 5472 | ||
77 | #define YMIN_NOMINAL 1408 | ||
78 | #define YMAX_NOMINAL 4448 | ||
79 | |||
80 | struct synusb { | ||
81 | struct usb_device *udev; | ||
82 | struct usb_interface *intf; | ||
83 | struct urb *urb; | ||
84 | unsigned char *data; | ||
85 | |||
86 | /* input device related data structures */ | ||
87 | struct input_dev *input; | ||
88 | char name[128]; | ||
89 | char phys[64]; | ||
90 | |||
91 | /* characteristics of the device */ | ||
92 | unsigned long flags; | ||
93 | }; | ||
94 | |||
95 | static void synusb_report_buttons(struct synusb *synusb) | ||
96 | { | ||
97 | struct input_dev *input_dev = synusb->input; | ||
98 | |||
99 | input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04); | ||
100 | input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01); | ||
101 | input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02); | ||
102 | } | ||
103 | |||
104 | static void synusb_report_stick(struct synusb *synusb) | ||
105 | { | ||
106 | struct input_dev *input_dev = synusb->input; | ||
107 | int x, y; | ||
108 | unsigned int pressure; | ||
109 | |||
110 | pressure = synusb->data[6]; | ||
111 | x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7; | ||
112 | y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7; | ||
113 | |||
114 | if (pressure > 0) { | ||
115 | input_report_rel(input_dev, REL_X, x); | ||
116 | input_report_rel(input_dev, REL_Y, -y); | ||
117 | } | ||
118 | |||
119 | input_report_abs(input_dev, ABS_PRESSURE, pressure); | ||
120 | |||
121 | synusb_report_buttons(synusb); | ||
122 | |||
123 | input_sync(input_dev); | ||
124 | } | ||
125 | |||
126 | static void synusb_report_touchpad(struct synusb *synusb) | ||
127 | { | ||
128 | struct input_dev *input_dev = synusb->input; | ||
129 | unsigned int num_fingers, tool_width; | ||
130 | unsigned int x, y; | ||
131 | unsigned int pressure, w; | ||
132 | |||
133 | pressure = synusb->data[6]; | ||
134 | x = be16_to_cpup((__be16 *)&synusb->data[2]); | ||
135 | y = be16_to_cpup((__be16 *)&synusb->data[4]); | ||
136 | w = synusb->data[0] & 0x0f; | ||
137 | |||
138 | if (pressure > 0) { | ||
139 | num_fingers = 1; | ||
140 | tool_width = 5; | ||
141 | switch (w) { | ||
142 | case 0 ... 1: | ||
143 | num_fingers = 2 + w; | ||
144 | break; | ||
145 | |||
146 | case 2: /* pen, pretend its a finger */ | ||
147 | break; | ||
148 | |||
149 | case 4 ... 15: | ||
150 | tool_width = w; | ||
151 | break; | ||
152 | } | ||
153 | } else { | ||
154 | num_fingers = 0; | ||
155 | tool_width = 0; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Post events | ||
160 | * BTN_TOUCH has to be first as mousedev relies on it when doing | ||
161 | * absolute -> relative conversion | ||
162 | */ | ||
163 | |||
164 | if (pressure > 30) | ||
165 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
166 | if (pressure < 25) | ||
167 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
168 | |||
169 | if (num_fingers > 0) { | ||
170 | input_report_abs(input_dev, ABS_X, x); | ||
171 | input_report_abs(input_dev, ABS_Y, | ||
172 | YMAX_NOMINAL + YMIN_NOMINAL - y); | ||
173 | } | ||
174 | |||
175 | input_report_abs(input_dev, ABS_PRESSURE, pressure); | ||
176 | input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width); | ||
177 | |||
178 | input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1); | ||
179 | input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); | ||
180 | input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); | ||
181 | |||
182 | synusb_report_buttons(synusb); | ||
183 | if (synusb->flags & SYNUSB_AUXDISPLAY) | ||
184 | input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08); | ||
185 | |||
186 | input_sync(input_dev); | ||
187 | } | ||
188 | |||
189 | static void synusb_irq(struct urb *urb) | ||
190 | { | ||
191 | struct synusb *synusb = urb->context; | ||
192 | int error; | ||
193 | |||
194 | /* Check our status in case we need to bail out early. */ | ||
195 | switch (urb->status) { | ||
196 | case 0: | ||
197 | usb_mark_last_busy(synusb->udev); | ||
198 | break; | ||
199 | |||
200 | /* Device went away so don't keep trying to read from it. */ | ||
201 | case -ECONNRESET: | ||
202 | case -ENOENT: | ||
203 | case -ESHUTDOWN: | ||
204 | return; | ||
205 | |||
206 | default: | ||
207 | goto resubmit; | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | if (synusb->flags & SYNUSB_STICK) | ||
212 | synusb_report_stick(synusb); | ||
213 | else | ||
214 | synusb_report_touchpad(synusb); | ||
215 | |||
216 | resubmit: | ||
217 | error = usb_submit_urb(urb, GFP_ATOMIC); | ||
218 | if (error && error != -EPERM) | ||
219 | dev_err(&synusb->intf->dev, | ||
220 | "%s - usb_submit_urb failed with result: %d", | ||
221 | __func__, error); | ||
222 | } | ||
223 | |||
224 | static struct usb_endpoint_descriptor * | ||
225 | synusb_get_in_endpoint(struct usb_host_interface *iface) | ||
226 | { | ||
227 | |||
228 | struct usb_endpoint_descriptor *endpoint; | ||
229 | int i; | ||
230 | |||
231 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { | ||
232 | endpoint = &iface->endpoint[i].desc; | ||
233 | |||
234 | if (usb_endpoint_is_int_in(endpoint)) { | ||
235 | /* we found our interrupt in endpoint */ | ||
236 | return endpoint; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | return NULL; | ||
241 | } | ||
242 | |||
243 | static int synusb_open(struct input_dev *dev) | ||
244 | { | ||
245 | struct synusb *synusb = input_get_drvdata(dev); | ||
246 | int retval; | ||
247 | |||
248 | retval = usb_autopm_get_interface(synusb->intf); | ||
249 | if (retval) { | ||
250 | dev_err(&synusb->intf->dev, | ||
251 | "%s - usb_autopm_get_interface failed, error: %d\n", | ||
252 | __func__, retval); | ||
253 | return retval; | ||
254 | } | ||
255 | |||
256 | retval = usb_submit_urb(synusb->urb, GFP_KERNEL); | ||
257 | if (retval) { | ||
258 | dev_err(&synusb->intf->dev, | ||
259 | "%s - usb_submit_urb failed, error: %d\n", | ||
260 | __func__, retval); | ||
261 | retval = -EIO; | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | synusb->intf->needs_remote_wakeup = 1; | ||
266 | |||
267 | out: | ||
268 | usb_autopm_put_interface(synusb->intf); | ||
269 | return retval; | ||
270 | } | ||
271 | |||
272 | static void synusb_close(struct input_dev *dev) | ||
273 | { | ||
274 | struct synusb *synusb = input_get_drvdata(dev); | ||
275 | int autopm_error; | ||
276 | |||
277 | autopm_error = usb_autopm_get_interface(synusb->intf); | ||
278 | |||
279 | usb_kill_urb(synusb->urb); | ||
280 | synusb->intf->needs_remote_wakeup = 0; | ||
281 | |||
282 | if (!autopm_error) | ||
283 | usb_autopm_put_interface(synusb->intf); | ||
284 | } | ||
285 | |||
286 | static int synusb_probe(struct usb_interface *intf, | ||
287 | const struct usb_device_id *id) | ||
288 | { | ||
289 | struct usb_device *udev = interface_to_usbdev(intf); | ||
290 | struct usb_endpoint_descriptor *ep; | ||
291 | struct synusb *synusb; | ||
292 | struct input_dev *input_dev; | ||
293 | unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber; | ||
294 | unsigned int altsetting = min(intf->num_altsetting, 1U); | ||
295 | int error; | ||
296 | |||
297 | error = usb_set_interface(udev, intf_num, altsetting); | ||
298 | if (error) { | ||
299 | dev_err(&udev->dev, | ||
300 | "Can not set alternate setting to %i, error: %i", | ||
301 | altsetting, error); | ||
302 | return error; | ||
303 | } | ||
304 | |||
305 | ep = synusb_get_in_endpoint(intf->cur_altsetting); | ||
306 | if (!ep) | ||
307 | return -ENODEV; | ||
308 | |||
309 | synusb = kzalloc(sizeof(*synusb), GFP_KERNEL); | ||
310 | input_dev = input_allocate_device(); | ||
311 | if (!synusb || !input_dev) { | ||
312 | error = -ENOMEM; | ||
313 | goto err_free_mem; | ||
314 | } | ||
315 | |||
316 | synusb->udev = udev; | ||
317 | synusb->intf = intf; | ||
318 | synusb->input = input_dev; | ||
319 | |||
320 | synusb->flags = id->driver_info; | ||
321 | if (synusb->flags & SYNUSB_COMBO) { | ||
322 | /* | ||
323 | * This is a combo device, we need to set proper | ||
324 | * capability, depending on the interface. | ||
325 | */ | ||
326 | synusb->flags |= intf_num == 1 ? | ||
327 | SYNUSB_STICK : SYNUSB_TOUCHPAD; | ||
328 | } | ||
329 | |||
330 | synusb->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
331 | if (!synusb->urb) { | ||
332 | error = -ENOMEM; | ||
333 | goto err_free_mem; | ||
334 | } | ||
335 | |||
336 | synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL, | ||
337 | &synusb->urb->transfer_dma); | ||
338 | if (!synusb->data) { | ||
339 | error = -ENOMEM; | ||
340 | goto err_free_urb; | ||
341 | } | ||
342 | |||
343 | usb_fill_int_urb(synusb->urb, udev, | ||
344 | usb_rcvintpipe(udev, ep->bEndpointAddress), | ||
345 | synusb->data, SYNUSB_RECV_SIZE, | ||
346 | synusb_irq, synusb, | ||
347 | ep->bInterval); | ||
348 | synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
349 | |||
350 | if (udev->manufacturer) | ||
351 | strlcpy(synusb->name, udev->manufacturer, | ||
352 | sizeof(synusb->name)); | ||
353 | |||
354 | if (udev->product) { | ||
355 | if (udev->manufacturer) | ||
356 | strlcat(synusb->name, " ", sizeof(synusb->name)); | ||
357 | strlcat(synusb->name, udev->product, sizeof(synusb->name)); | ||
358 | } | ||
359 | |||
360 | if (!strlen(synusb->name)) | ||
361 | snprintf(synusb->name, sizeof(synusb->name), | ||
362 | "USB Synaptics Device %04x:%04x", | ||
363 | le16_to_cpu(udev->descriptor.idVendor), | ||
364 | le16_to_cpu(udev->descriptor.idProduct)); | ||
365 | |||
366 | if (synusb->flags & SYNUSB_STICK) | ||
367 | strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); | ||
368 | |||
369 | usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); | ||
370 | strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); | ||
371 | |||
372 | input_dev->name = synusb->name; | ||
373 | input_dev->phys = synusb->phys; | ||
374 | usb_to_input_id(udev, &input_dev->id); | ||
375 | input_dev->dev.parent = &synusb->intf->dev; | ||
376 | |||
377 | if (!(synusb->flags & SYNUSB_IO_ALWAYS)) { | ||
378 | input_dev->open = synusb_open; | ||
379 | input_dev->close = synusb_close; | ||
380 | } | ||
381 | |||
382 | input_set_drvdata(input_dev, synusb); | ||
383 | |||
384 | __set_bit(EV_ABS, input_dev->evbit); | ||
385 | __set_bit(EV_KEY, input_dev->evbit); | ||
386 | |||
387 | if (synusb->flags & SYNUSB_STICK) { | ||
388 | __set_bit(EV_REL, input_dev->evbit); | ||
389 | __set_bit(REL_X, input_dev->relbit); | ||
390 | __set_bit(REL_Y, input_dev->relbit); | ||
391 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); | ||
392 | } else { | ||
393 | input_set_abs_params(input_dev, ABS_X, | ||
394 | XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); | ||
395 | input_set_abs_params(input_dev, ABS_Y, | ||
396 | YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); | ||
397 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); | ||
398 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | ||
399 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
400 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
401 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
402 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
403 | } | ||
404 | |||
405 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
406 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
407 | __set_bit(BTN_MIDDLE, input_dev->keybit); | ||
408 | |||
409 | usb_set_intfdata(intf, synusb); | ||
410 | |||
411 | if (synusb->flags & SYNUSB_IO_ALWAYS) { | ||
412 | error = synusb_open(input_dev); | ||
413 | if (error) | ||
414 | goto err_free_dma; | ||
415 | } | ||
416 | |||
417 | error = input_register_device(input_dev); | ||
418 | if (error) { | ||
419 | dev_err(&udev->dev, | ||
420 | "Failed to register input device, error %d\n", | ||
421 | error); | ||
422 | goto err_stop_io; | ||
423 | } | ||
424 | |||
425 | return 0; | ||
426 | |||
427 | err_stop_io: | ||
428 | if (synusb->flags & SYNUSB_IO_ALWAYS) | ||
429 | synusb_close(synusb->input); | ||
430 | err_free_dma: | ||
431 | usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, | ||
432 | synusb->urb->transfer_dma); | ||
433 | err_free_urb: | ||
434 | usb_free_urb(synusb->urb); | ||
435 | err_free_mem: | ||
436 | input_free_device(input_dev); | ||
437 | kfree(synusb); | ||
438 | usb_set_intfdata(intf, NULL); | ||
439 | |||
440 | return error; | ||
441 | } | ||
442 | |||
443 | static void synusb_disconnect(struct usb_interface *intf) | ||
444 | { | ||
445 | struct synusb *synusb = usb_get_intfdata(intf); | ||
446 | struct usb_device *udev = interface_to_usbdev(intf); | ||
447 | |||
448 | if (synusb->flags & SYNUSB_IO_ALWAYS) | ||
449 | synusb_close(synusb->input); | ||
450 | |||
451 | input_unregister_device(synusb->input); | ||
452 | |||
453 | usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, | ||
454 | synusb->urb->transfer_dma); | ||
455 | usb_free_urb(synusb->urb); | ||
456 | kfree(synusb); | ||
457 | |||
458 | usb_set_intfdata(intf, NULL); | ||
459 | } | ||
460 | |||
461 | static int synusb_suspend(struct usb_interface *intf, pm_message_t message) | ||
462 | { | ||
463 | struct synusb *synusb = usb_get_intfdata(intf); | ||
464 | struct input_dev *input_dev = synusb->input; | ||
465 | |||
466 | mutex_lock(&input_dev->mutex); | ||
467 | usb_kill_urb(synusb->urb); | ||
468 | mutex_unlock(&input_dev->mutex); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int synusb_resume(struct usb_interface *intf) | ||
474 | { | ||
475 | struct synusb *synusb = usb_get_intfdata(intf); | ||
476 | struct input_dev *input_dev = synusb->input; | ||
477 | int retval = 0; | ||
478 | |||
479 | mutex_lock(&input_dev->mutex); | ||
480 | |||
481 | if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && | ||
482 | usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { | ||
483 | retval = -EIO; | ||
484 | } | ||
485 | |||
486 | mutex_unlock(&input_dev->mutex); | ||
487 | |||
488 | return retval; | ||
489 | } | ||
490 | |||
491 | static int synusb_pre_reset(struct usb_interface *intf) | ||
492 | { | ||
493 | struct synusb *synusb = usb_get_intfdata(intf); | ||
494 | struct input_dev *input_dev = synusb->input; | ||
495 | |||
496 | mutex_lock(&input_dev->mutex); | ||
497 | usb_kill_urb(synusb->urb); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int synusb_post_reset(struct usb_interface *intf) | ||
503 | { | ||
504 | struct synusb *synusb = usb_get_intfdata(intf); | ||
505 | struct input_dev *input_dev = synusb->input; | ||
506 | int retval = 0; | ||
507 | |||
508 | if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && | ||
509 | usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { | ||
510 | retval = -EIO; | ||
511 | } | ||
512 | |||
513 | mutex_unlock(&input_dev->mutex); | ||
514 | |||
515 | return retval; | ||
516 | } | ||
517 | |||
518 | static int synusb_reset_resume(struct usb_interface *intf) | ||
519 | { | ||
520 | return synusb_resume(intf); | ||
521 | } | ||
522 | |||
523 | static struct usb_device_id synusb_idtable[] = { | ||
524 | { USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) }, | ||
525 | { USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) }, | ||
526 | { USB_DEVICE_SYNAPTICS(CPAD, | ||
527 | SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) }, | ||
528 | { USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) }, | ||
529 | { USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) }, | ||
530 | { USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) }, | ||
531 | { USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) }, | ||
532 | { USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) }, | ||
533 | { USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) }, | ||
534 | { } | ||
535 | }; | ||
536 | MODULE_DEVICE_TABLE(usb, synusb_idtable); | ||
537 | |||
538 | static struct usb_driver synusb_driver = { | ||
539 | .name = "synaptics_usb", | ||
540 | .probe = synusb_probe, | ||
541 | .disconnect = synusb_disconnect, | ||
542 | .id_table = synusb_idtable, | ||
543 | .suspend = synusb_suspend, | ||
544 | .resume = synusb_resume, | ||
545 | .pre_reset = synusb_pre_reset, | ||
546 | .post_reset = synusb_post_reset, | ||
547 | .reset_resume = synusb_reset_resume, | ||
548 | .supports_autosuspend = 1, | ||
549 | }; | ||
550 | |||
551 | module_usb_driver(synusb_driver); | ||
552 | |||
553 | MODULE_AUTHOR("Rob Miller <rob@inpharmatica.co.uk>, " | ||
554 | "Ron Lee <ron@debian.org>, " | ||
555 | "Jan Steinhoff <cpad@jan-steinhoff.de>"); | ||
556 | MODULE_DESCRIPTION("Synaptics USB device driver"); | ||
557 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c new file mode 100644 index 000000000000..061493d57682 --- /dev/null +++ b/drivers/input/of_keymap.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Helpers for open firmware matrix keyboard bindings | ||
3 | * | ||
4 | * Copyright (C) 2012 Google, Inc | ||
5 | * | ||
6 | * Author: | ||
7 | * Olof Johansson <olof@lixom.net> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/input.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/input/matrix_keypad.h> | ||
25 | #include <linux/export.h> | ||
26 | #include <linux/gfp.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | struct matrix_keymap_data * | ||
30 | matrix_keyboard_of_fill_keymap(struct device_node *np, | ||
31 | const char *propname) | ||
32 | { | ||
33 | struct matrix_keymap_data *kd; | ||
34 | u32 *keymap; | ||
35 | int proplen, i; | ||
36 | const __be32 *prop; | ||
37 | |||
38 | if (!np) | ||
39 | return NULL; | ||
40 | |||
41 | if (!propname) | ||
42 | propname = "linux,keymap"; | ||
43 | |||
44 | prop = of_get_property(np, propname, &proplen); | ||
45 | if (!prop) | ||
46 | return NULL; | ||
47 | |||
48 | if (proplen % sizeof(u32)) { | ||
49 | pr_warn("Malformed keymap property %s in %s\n", | ||
50 | propname, np->full_name); | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | kd = kzalloc(sizeof(*kd), GFP_KERNEL); | ||
55 | if (!kd) | ||
56 | return NULL; | ||
57 | |||
58 | kd->keymap = keymap = kzalloc(proplen, GFP_KERNEL); | ||
59 | if (!kd->keymap) { | ||
60 | kfree(kd); | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | kd->keymap_size = proplen / sizeof(u32); | ||
65 | |||
66 | for (i = 0; i < kd->keymap_size; i++) { | ||
67 | u32 tmp = be32_to_cpup(prop + i); | ||
68 | int key_code, row, col; | ||
69 | |||
70 | row = (tmp >> 24) & 0xff; | ||
71 | col = (tmp >> 16) & 0xff; | ||
72 | key_code = tmp & 0xffff; | ||
73 | keymap[i] = KEY(row, col, key_code); | ||
74 | } | ||
75 | |||
76 | return kd; | ||
77 | } | ||
78 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_fill_keymap); | ||
79 | |||
80 | void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd) | ||
81 | { | ||
82 | if (kd) { | ||
83 | kfree(kd->keymap); | ||
84 | kfree(kd); | ||
85 | } | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_free_keymap); | ||
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 35864c6130bb..cc11f4efe119 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c | |||
@@ -180,8 +180,6 @@ static const struct of_device_id altera_ps2_match[] = { | |||
180 | {}, | 180 | {}, |
181 | }; | 181 | }; |
182 | MODULE_DEVICE_TABLE(of, altera_ps2_match); | 182 | MODULE_DEVICE_TABLE(of, altera_ps2_match); |
183 | #else /* CONFIG_OF */ | ||
184 | #define altera_ps2_match NULL | ||
185 | #endif /* CONFIG_OF */ | 183 | #endif /* CONFIG_OF */ |
186 | 184 | ||
187 | /* | 185 | /* |
@@ -193,7 +191,7 @@ static struct platform_driver altera_ps2_driver = { | |||
193 | .driver = { | 191 | .driver = { |
194 | .name = DRV_NAME, | 192 | .name = DRV_NAME, |
195 | .owner = THIS_MODULE, | 193 | .owner = THIS_MODULE, |
196 | .of_match_table = altera_ps2_match, | 194 | .of_match_table = of_match_ptr(altera_ps2_match), |
197 | }, | 195 | }, |
198 | }; | 196 | }; |
199 | module_platform_driver(altera_ps2_driver); | 197 | module_platform_driver(altera_ps2_driver); |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 12abc50508e5..8407d5b0ced8 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
@@ -195,6 +195,8 @@ static struct amba_id amba_kmi_idtable[] = { | |||
195 | { 0, 0 } | 195 | { 0, 0 } |
196 | }; | 196 | }; |
197 | 197 | ||
198 | MODULE_DEVICE_TABLE(amba, amba_kmi_idtable); | ||
199 | |||
198 | static struct amba_driver ambakmi_driver = { | 200 | static struct amba_driver ambakmi_driver = { |
199 | .drv = { | 201 | .drv = { |
200 | .name = "kmi-pl050", | 202 | .name = "kmi-pl050", |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 95280f9207e1..36e799c31f5e 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
@@ -98,9 +98,9 @@ struct psif { | |||
98 | struct serio *io; | 98 | struct serio *io; |
99 | void __iomem *regs; | 99 | void __iomem *regs; |
100 | unsigned int irq; | 100 | unsigned int irq; |
101 | unsigned int open; | ||
102 | /* Prevent concurrent writes to PSIF THR. */ | 101 | /* Prevent concurrent writes to PSIF THR. */ |
103 | spinlock_t lock; | 102 | spinlock_t lock; |
103 | bool open; | ||
104 | }; | 104 | }; |
105 | 105 | ||
106 | static irqreturn_t psif_interrupt(int irq, void *_ptr) | 106 | static irqreturn_t psif_interrupt(int irq, void *_ptr) |
@@ -164,7 +164,7 @@ static int psif_open(struct serio *io) | |||
164 | psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN)); | 164 | psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN)); |
165 | psif_writel(psif, IER, PSIF_BIT(RXRDY)); | 165 | psif_writel(psif, IER, PSIF_BIT(RXRDY)); |
166 | 166 | ||
167 | psif->open = 1; | 167 | psif->open = true; |
168 | out: | 168 | out: |
169 | return retval; | 169 | return retval; |
170 | } | 170 | } |
@@ -173,7 +173,7 @@ static void psif_close(struct serio *io) | |||
173 | { | 173 | { |
174 | struct psif *psif = io->port_data; | 174 | struct psif *psif = io->port_data; |
175 | 175 | ||
176 | psif->open = 0; | 176 | psif->open = false; |
177 | 177 | ||
178 | psif_writel(psif, IDR, ~0UL); | 178 | psif_writel(psif, IDR, ~0UL); |
179 | psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS)); | 179 | psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS)); |
@@ -319,9 +319,10 @@ static int __exit psif_remove(struct platform_device *pdev) | |||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | #ifdef CONFIG_PM | 322 | #ifdef CONFIG_PM_SLEEP |
323 | static int psif_suspend(struct platform_device *pdev, pm_message_t state) | 323 | static int psif_suspend(struct device *dev) |
324 | { | 324 | { |
325 | struct platform_device *pdev = to_platform_device(dev); | ||
325 | struct psif *psif = platform_get_drvdata(pdev); | 326 | struct psif *psif = platform_get_drvdata(pdev); |
326 | 327 | ||
327 | if (psif->open) { | 328 | if (psif->open) { |
@@ -332,8 +333,9 @@ static int psif_suspend(struct platform_device *pdev, pm_message_t state) | |||
332 | return 0; | 333 | return 0; |
333 | } | 334 | } |
334 | 335 | ||
335 | static int psif_resume(struct platform_device *pdev) | 336 | static int psif_resume(struct device *dev) |
336 | { | 337 | { |
338 | struct platform_device *pdev = to_platform_device(dev); | ||
337 | struct psif *psif = platform_get_drvdata(pdev); | 339 | struct psif *psif = platform_get_drvdata(pdev); |
338 | 340 | ||
339 | if (psif->open) { | 341 | if (psif->open) { |
@@ -344,19 +346,17 @@ static int psif_resume(struct platform_device *pdev) | |||
344 | 346 | ||
345 | return 0; | 347 | return 0; |
346 | } | 348 | } |
347 | #else | ||
348 | #define psif_suspend NULL | ||
349 | #define psif_resume NULL | ||
350 | #endif | 349 | #endif |
351 | 350 | ||
351 | static SIMPLE_DEV_PM_OPS(psif_pm_ops, psif_suspend, psif_resume); | ||
352 | |||
352 | static struct platform_driver psif_driver = { | 353 | static struct platform_driver psif_driver = { |
353 | .remove = __exit_p(psif_remove), | 354 | .remove = __exit_p(psif_remove), |
354 | .driver = { | 355 | .driver = { |
355 | .name = "atmel_psif", | 356 | .name = "atmel_psif", |
356 | .owner = THIS_MODULE, | 357 | .owner = THIS_MODULE, |
358 | .pm = &psif_pm_ops, | ||
357 | }, | 359 | }, |
358 | .suspend = psif_suspend, | ||
359 | .resume = psif_resume, | ||
360 | }; | 360 | }; |
361 | 361 | ||
362 | static int __init psif_init(void) | 362 | static int __init psif_init(void) |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 979c443bf1ef..be3316073ae7 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -105,7 +105,7 @@ EXPORT_SYMBOL(__hp_sdc_enqueue_transaction); | |||
105 | EXPORT_SYMBOL(hp_sdc_enqueue_transaction); | 105 | EXPORT_SYMBOL(hp_sdc_enqueue_transaction); |
106 | EXPORT_SYMBOL(hp_sdc_dequeue_transaction); | 106 | EXPORT_SYMBOL(hp_sdc_dequeue_transaction); |
107 | 107 | ||
108 | static unsigned int hp_sdc_disabled; | 108 | static bool hp_sdc_disabled; |
109 | module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0); | 109 | module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0); |
110 | MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver."); | 110 | MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver."); |
111 | 111 | ||
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 5eb84b3b67fb..0c0df7f73802 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c | |||
@@ -44,26 +44,31 @@ | |||
44 | #include <asm/irq.h> | 44 | #include <asm/irq.h> |
45 | #include <asm/q40ints.h> | 45 | #include <asm/q40ints.h> |
46 | 46 | ||
47 | #define DRV_NAME "q40kbd" | ||
48 | |||
47 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 49 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
48 | MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); | 50 | MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); |
49 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | MODULE_ALIAS("platform:" DRV_NAME); | ||
50 | 53 | ||
51 | static DEFINE_SPINLOCK(q40kbd_lock); | 54 | struct q40kbd { |
52 | static struct serio *q40kbd_port; | 55 | struct serio *port; |
53 | static struct platform_device *q40kbd_device; | 56 | spinlock_t lock; |
57 | }; | ||
54 | 58 | ||
55 | static irqreturn_t q40kbd_interrupt(int irq, void *dev_id) | 59 | static irqreturn_t q40kbd_interrupt(int irq, void *dev_id) |
56 | { | 60 | { |
61 | struct q40kbd *q40kbd = dev_id; | ||
57 | unsigned long flags; | 62 | unsigned long flags; |
58 | 63 | ||
59 | spin_lock_irqsave(&q40kbd_lock, flags); | 64 | spin_lock_irqsave(&q40kbd->lock, flags); |
60 | 65 | ||
61 | if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)) | 66 | if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)) |
62 | serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0); | 67 | serio_interrupt(q40kbd->port, master_inb(KEYCODE_REG), 0); |
63 | 68 | ||
64 | master_outb(-1, KEYBOARD_UNLOCK_REG); | 69 | master_outb(-1, KEYBOARD_UNLOCK_REG); |
65 | 70 | ||
66 | spin_unlock_irqrestore(&q40kbd_lock, flags); | 71 | spin_unlock_irqrestore(&q40kbd->lock, flags); |
67 | 72 | ||
68 | return IRQ_HANDLED; | 73 | return IRQ_HANDLED; |
69 | } | 74 | } |
@@ -72,17 +77,23 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id) | |||
72 | * q40kbd_flush() flushes all data that may be in the keyboard buffers | 77 | * q40kbd_flush() flushes all data that may be in the keyboard buffers |
73 | */ | 78 | */ |
74 | 79 | ||
75 | static void q40kbd_flush(void) | 80 | static void q40kbd_flush(struct q40kbd *q40kbd) |
76 | { | 81 | { |
77 | int maxread = 100; | 82 | int maxread = 100; |
78 | unsigned long flags; | 83 | unsigned long flags; |
79 | 84 | ||
80 | spin_lock_irqsave(&q40kbd_lock, flags); | 85 | spin_lock_irqsave(&q40kbd->lock, flags); |
81 | 86 | ||
82 | while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) | 87 | while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) |
83 | master_inb(KEYCODE_REG); | 88 | master_inb(KEYCODE_REG); |
84 | 89 | ||
85 | spin_unlock_irqrestore(&q40kbd_lock, flags); | 90 | spin_unlock_irqrestore(&q40kbd->lock, flags); |
91 | } | ||
92 | |||
93 | static void q40kbd_stop(void) | ||
94 | { | ||
95 | master_outb(0, KEY_IRQ_ENABLE_REG); | ||
96 | master_outb(-1, KEYBOARD_UNLOCK_REG); | ||
86 | } | 97 | } |
87 | 98 | ||
88 | /* | 99 | /* |
@@ -92,12 +103,9 @@ static void q40kbd_flush(void) | |||
92 | 103 | ||
93 | static int q40kbd_open(struct serio *port) | 104 | static int q40kbd_open(struct serio *port) |
94 | { | 105 | { |
95 | q40kbd_flush(); | 106 | struct q40kbd *q40kbd = port->port_data; |
96 | 107 | ||
97 | if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { | 108 | q40kbd_flush(q40kbd); |
98 | printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); | ||
99 | return -EBUSY; | ||
100 | } | ||
101 | 109 | ||
102 | /* off we go */ | 110 | /* off we go */ |
103 | master_outb(-1, KEYBOARD_UNLOCK_REG); | 111 | master_outb(-1, KEYBOARD_UNLOCK_REG); |
@@ -108,36 +116,72 @@ static int q40kbd_open(struct serio *port) | |||
108 | 116 | ||
109 | static void q40kbd_close(struct serio *port) | 117 | static void q40kbd_close(struct serio *port) |
110 | { | 118 | { |
111 | master_outb(0, KEY_IRQ_ENABLE_REG); | 119 | struct q40kbd *q40kbd = port->port_data; |
112 | master_outb(-1, KEYBOARD_UNLOCK_REG); | ||
113 | free_irq(Q40_IRQ_KEYBOARD, NULL); | ||
114 | 120 | ||
115 | q40kbd_flush(); | 121 | q40kbd_stop(); |
122 | q40kbd_flush(q40kbd); | ||
116 | } | 123 | } |
117 | 124 | ||
118 | static int __devinit q40kbd_probe(struct platform_device *dev) | 125 | static int __devinit q40kbd_probe(struct platform_device *pdev) |
119 | { | 126 | { |
120 | q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL); | 127 | struct q40kbd *q40kbd; |
121 | if (!q40kbd_port) | 128 | struct serio *port; |
122 | return -ENOMEM; | 129 | int error; |
123 | 130 | ||
124 | q40kbd_port->id.type = SERIO_8042; | 131 | q40kbd = kzalloc(sizeof(struct q40kbd), GFP_KERNEL); |
125 | q40kbd_port->open = q40kbd_open; | 132 | port = kzalloc(sizeof(struct serio), GFP_KERNEL); |
126 | q40kbd_port->close = q40kbd_close; | 133 | if (!q40kbd || !port) { |
127 | q40kbd_port->dev.parent = &dev->dev; | 134 | error = -ENOMEM; |
128 | strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name)); | 135 | goto err_free_mem; |
129 | strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys)); | 136 | } |
130 | 137 | ||
131 | serio_register_port(q40kbd_port); | 138 | q40kbd->port = port; |
139 | spin_lock_init(&q40kbd->lock); | ||
140 | |||
141 | port->id.type = SERIO_8042; | ||
142 | port->open = q40kbd_open; | ||
143 | port->close = q40kbd_close; | ||
144 | port->port_data = q40kbd; | ||
145 | port->dev.parent = &pdev->dev; | ||
146 | strlcpy(port->name, "Q40 Kbd Port", sizeof(port->name)); | ||
147 | strlcpy(port->phys, "Q40", sizeof(port->phys)); | ||
148 | |||
149 | q40kbd_stop(); | ||
150 | |||
151 | error = request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, | ||
152 | DRV_NAME, q40kbd); | ||
153 | if (error) { | ||
154 | dev_err(&pdev->dev, "Can't get irq %d.\n", Q40_IRQ_KEYBOARD); | ||
155 | goto err_free_mem; | ||
156 | } | ||
157 | |||
158 | serio_register_port(q40kbd->port); | ||
159 | |||
160 | platform_set_drvdata(pdev, q40kbd); | ||
132 | printk(KERN_INFO "serio: Q40 kbd registered\n"); | 161 | printk(KERN_INFO "serio: Q40 kbd registered\n"); |
133 | 162 | ||
134 | return 0; | 163 | return 0; |
164 | |||
165 | err_free_mem: | ||
166 | kfree(port); | ||
167 | kfree(q40kbd); | ||
168 | return error; | ||
135 | } | 169 | } |
136 | 170 | ||
137 | static int __devexit q40kbd_remove(struct platform_device *dev) | 171 | static int __devexit q40kbd_remove(struct platform_device *pdev) |
138 | { | 172 | { |
139 | serio_unregister_port(q40kbd_port); | 173 | struct q40kbd *q40kbd = platform_get_drvdata(pdev); |
140 | 174 | ||
175 | /* | ||
176 | * q40kbd_close() will be called as part of unregistering | ||
177 | * and will ensure that IRQ is turned off, so it is safe | ||
178 | * to unregister port first and free IRQ later. | ||
179 | */ | ||
180 | serio_unregister_port(q40kbd->port); | ||
181 | free_irq(Q40_IRQ_KEYBOARD, q40kbd); | ||
182 | kfree(q40kbd); | ||
183 | |||
184 | platform_set_drvdata(pdev, NULL); | ||
141 | return 0; | 185 | return 0; |
142 | } | 186 | } |
143 | 187 | ||
@@ -146,41 +190,16 @@ static struct platform_driver q40kbd_driver = { | |||
146 | .name = "q40kbd", | 190 | .name = "q40kbd", |
147 | .owner = THIS_MODULE, | 191 | .owner = THIS_MODULE, |
148 | }, | 192 | }, |
149 | .probe = q40kbd_probe, | ||
150 | .remove = __devexit_p(q40kbd_remove), | 193 | .remove = __devexit_p(q40kbd_remove), |
151 | }; | 194 | }; |
152 | 195 | ||
153 | static int __init q40kbd_init(void) | 196 | static int __init q40kbd_init(void) |
154 | { | 197 | { |
155 | int error; | 198 | return platform_driver_probe(&q40kbd_driver, q40kbd_probe); |
156 | |||
157 | if (!MACH_IS_Q40) | ||
158 | return -ENODEV; | ||
159 | |||
160 | error = platform_driver_register(&q40kbd_driver); | ||
161 | if (error) | ||
162 | return error; | ||
163 | |||
164 | q40kbd_device = platform_device_alloc("q40kbd", -1); | ||
165 | if (!q40kbd_device) | ||
166 | goto err_unregister_driver; | ||
167 | |||
168 | error = platform_device_add(q40kbd_device); | ||
169 | if (error) | ||
170 | goto err_free_device; | ||
171 | |||
172 | return 0; | ||
173 | |||
174 | err_free_device: | ||
175 | platform_device_put(q40kbd_device); | ||
176 | err_unregister_driver: | ||
177 | platform_driver_unregister(&q40kbd_driver); | ||
178 | return error; | ||
179 | } | 199 | } |
180 | 200 | ||
181 | static void __exit q40kbd_exit(void) | 201 | static void __exit q40kbd_exit(void) |
182 | { | 202 | { |
183 | platform_device_unregister(q40kbd_device); | ||
184 | platform_driver_unregister(&q40kbd_driver); | 203 | platform_driver_unregister(&q40kbd_driver); |
185 | } | 204 | } |
186 | 205 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 127c391deced..d96d4c2a76a9 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -253,7 +253,7 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | /* Get IRQ for the device */ | 255 | /* Get IRQ for the device */ |
256 | if (of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq) == NO_IRQ) { | 256 | if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) { |
257 | dev_err(dev, "no IRQ found\n"); | 257 | dev_err(dev, "no IRQ found\n"); |
258 | return -ENODEV; | 258 | return -ENODEV; |
259 | } | 259 | } |
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index d94f7e9aa997..f8b0b1df9138 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c | |||
@@ -269,19 +269,4 @@ static struct usb_driver usb_acecad_driver = { | |||
269 | .id_table = usb_acecad_id_table, | 269 | .id_table = usb_acecad_id_table, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int __init usb_acecad_init(void) | 272 | module_usb_driver(usb_acecad_driver); |
273 | { | ||
274 | int result = usb_register(&usb_acecad_driver); | ||
275 | if (result == 0) | ||
276 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
277 | DRIVER_DESC "\n"); | ||
278 | return result; | ||
279 | } | ||
280 | |||
281 | static void __exit usb_acecad_exit(void) | ||
282 | { | ||
283 | usb_deregister(&usb_acecad_driver); | ||
284 | } | ||
285 | |||
286 | module_init(usb_acecad_init); | ||
287 | module_exit(usb_acecad_exit); | ||
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 85bace2c8fe8..205d16aab441 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -1923,21 +1923,7 @@ static struct usb_driver aiptek_driver = { | |||
1923 | .id_table = aiptek_ids, | 1923 | .id_table = aiptek_ids, |
1924 | }; | 1924 | }; |
1925 | 1925 | ||
1926 | static int __init aiptek_init(void) | 1926 | module_usb_driver(aiptek_driver); |
1927 | { | ||
1928 | int result = usb_register(&aiptek_driver); | ||
1929 | if (result == 0) { | ||
1930 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
1931 | DRIVER_DESC "\n"); | ||
1932 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_AUTHOR "\n"); | ||
1933 | } | ||
1934 | return result; | ||
1935 | } | ||
1936 | |||
1937 | static void __exit aiptek_exit(void) | ||
1938 | { | ||
1939 | usb_deregister(&aiptek_driver); | ||
1940 | } | ||
1941 | 1927 | ||
1942 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1928 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1943 | MODULE_DESCRIPTION(DRIVER_DESC); | 1929 | MODULE_DESCRIPTION(DRIVER_DESC); |
@@ -1947,6 +1933,3 @@ module_param(programmableDelay, int, 0); | |||
1947 | MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); | 1933 | MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); |
1948 | module_param(jitterDelay, int, 0); | 1934 | module_param(jitterDelay, int, 0); |
1949 | MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); | 1935 | MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); |
1950 | |||
1951 | module_init(aiptek_init); | ||
1952 | module_exit(aiptek_exit); | ||
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 8ea6afe2e992..89a297801dce 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c | |||
@@ -1022,33 +1022,7 @@ static struct usb_driver gtco_driverinfo_table = { | |||
1022 | .disconnect = gtco_disconnect, | 1022 | .disconnect = gtco_disconnect, |
1023 | }; | 1023 | }; |
1024 | 1024 | ||
1025 | /* | 1025 | module_usb_driver(gtco_driverinfo_table); |
1026 | * Register this module with the USB subsystem | ||
1027 | */ | ||
1028 | static int __init gtco_init(void) | ||
1029 | { | ||
1030 | int error; | ||
1031 | |||
1032 | error = usb_register(>co_driverinfo_table); | ||
1033 | if (error) { | ||
1034 | err("usb_register() failed rc=0x%x", error); | ||
1035 | return error; | ||
1036 | } | ||
1037 | |||
1038 | printk("GTCO usb driver version: %s", GTCO_VERSION); | ||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | /* | ||
1043 | * Deregister this module with the USB subsystem | ||
1044 | */ | ||
1045 | static void __exit gtco_exit(void) | ||
1046 | { | ||
1047 | usb_deregister(>co_driverinfo_table); | ||
1048 | } | ||
1049 | |||
1050 | module_init(gtco_init); | ||
1051 | module_exit(gtco_exit); | ||
1052 | 1026 | ||
1053 | MODULE_DESCRIPTION("GTCO digitizer USB driver"); | 1027 | MODULE_DESCRIPTION("GTCO digitizer USB driver"); |
1054 | MODULE_LICENSE("GPL"); | 1028 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index 6504b627b234..b2db3cfe3084 100644 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c | |||
@@ -432,15 +432,4 @@ static struct usb_driver hanwang_driver = { | |||
432 | .id_table = hanwang_ids, | 432 | .id_table = hanwang_ids, |
433 | }; | 433 | }; |
434 | 434 | ||
435 | static int __init hanwang_init(void) | 435 | module_usb_driver(hanwang_driver); |
436 | { | ||
437 | return usb_register(&hanwang_driver); | ||
438 | } | ||
439 | |||
440 | static void __exit hanwang_exit(void) | ||
441 | { | ||
442 | usb_deregister(&hanwang_driver); | ||
443 | } | ||
444 | |||
445 | module_init(hanwang_init); | ||
446 | module_exit(hanwang_exit); | ||
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 290f4e57b589..85a5b40333ac 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c | |||
@@ -198,22 +198,4 @@ static struct usb_driver kbtab_driver = { | |||
198 | .id_table = kbtab_ids, | 198 | .id_table = kbtab_ids, |
199 | }; | 199 | }; |
200 | 200 | ||
201 | static int __init kbtab_init(void) | 201 | module_usb_driver(kbtab_driver); |
202 | { | ||
203 | int retval; | ||
204 | retval = usb_register(&kbtab_driver); | ||
205 | if (retval) | ||
206 | goto out; | ||
207 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
208 | DRIVER_DESC "\n"); | ||
209 | out: | ||
210 | return retval; | ||
211 | } | ||
212 | |||
213 | static void __exit kbtab_exit(void) | ||
214 | { | ||
215 | usb_deregister(&kbtab_driver); | ||
216 | } | ||
217 | |||
218 | module_init(kbtab_init); | ||
219 | module_exit(kbtab_exit); | ||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b59058998417..ca28066dc81e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -176,7 +176,7 @@ static int wacom_parse_logical_collection(unsigned char *report, | |||
176 | 176 | ||
177 | /* Logical collection is only used by 3rd gen Bamboo Touch */ | 177 | /* Logical collection is only used by 3rd gen Bamboo Touch */ |
178 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; | 178 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; |
179 | features->device_type = BTN_TOOL_DOUBLETAP; | 179 | features->device_type = BTN_TOOL_FINGER; |
180 | 180 | ||
181 | /* | 181 | /* |
182 | * Stylus and Touch have same active area | 182 | * Stylus and Touch have same active area |
@@ -286,12 +286,10 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
286 | if (features->type == TABLETPC2FG) { | 286 | if (features->type == TABLETPC2FG) { |
287 | /* need to reset back */ | 287 | /* need to reset back */ |
288 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 288 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
289 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
290 | } | 289 | } |
291 | if (features->type == BAMBOO_PT) { | 290 | if (features->type == BAMBOO_PT) { |
292 | /* need to reset back */ | 291 | /* need to reset back */ |
293 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | 292 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
294 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
295 | features->x_phy = | 293 | features->x_phy = |
296 | get_unaligned_le16(&report[i + 5]); | 294 | get_unaligned_le16(&report[i + 5]); |
297 | features->x_max = | 295 | features->x_max = |
@@ -325,7 +323,6 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
325 | if (features->type == TABLETPC2FG) { | 323 | if (features->type == TABLETPC2FG) { |
326 | /* need to reset back */ | 324 | /* need to reset back */ |
327 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 325 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
328 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
329 | features->y_max = | 326 | features->y_max = |
330 | get_unaligned_le16(&report[i + 3]); | 327 | get_unaligned_le16(&report[i + 3]); |
331 | features->y_phy = | 328 | features->y_phy = |
@@ -334,7 +331,6 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
334 | } else if (features->type == BAMBOO_PT) { | 331 | } else if (features->type == BAMBOO_PT) { |
335 | /* need to reset back */ | 332 | /* need to reset back */ |
336 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | 333 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
337 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
338 | features->y_phy = | 334 | features->y_phy = |
339 | get_unaligned_le16(&report[i + 3]); | 335 | get_unaligned_le16(&report[i + 3]); |
340 | features->y_max = | 336 | features->y_max = |
@@ -1000,21 +996,4 @@ static struct usb_driver wacom_driver = { | |||
1000 | .supports_autosuspend = 1, | 996 | .supports_autosuspend = 1, |
1001 | }; | 997 | }; |
1002 | 998 | ||
1003 | static int __init wacom_init(void) | 999 | module_usb_driver(wacom_driver); |
1004 | { | ||
1005 | int result; | ||
1006 | |||
1007 | result = usb_register(&wacom_driver); | ||
1008 | if (result == 0) | ||
1009 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
1010 | DRIVER_DESC "\n"); | ||
1011 | return result; | ||
1012 | } | ||
1013 | |||
1014 | static void __exit wacom_exit(void) | ||
1015 | { | ||
1016 | usb_deregister(&wacom_driver); | ||
1017 | } | ||
1018 | |||
1019 | module_init(wacom_init); | ||
1020 | module_exit(wacom_exit); | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index cd3ed29e0801..89a96427faa0 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -832,12 +832,24 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
832 | 832 | ||
833 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 833 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
834 | 834 | ||
835 | if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG) | 835 | switch (len) { |
836 | return wacom_tpc_single_touch(wacom, len); | 836 | case WACOM_PKGLEN_TPC1FG: |
837 | else if (data[0] == WACOM_REPORT_TPC2FG) | 837 | return wacom_tpc_single_touch(wacom, len); |
838 | return wacom_tpc_mt_touch(wacom); | 838 | |
839 | else if (data[0] == WACOM_REPORT_PENABLED) | 839 | case WACOM_PKGLEN_TPC2FG: |
840 | return wacom_tpc_pen(wacom); | 840 | return wacom_tpc_mt_touch(wacom); |
841 | |||
842 | default: | ||
843 | switch (data[0]) { | ||
844 | case WACOM_REPORT_TPC1FG: | ||
845 | case WACOM_REPORT_TPCHID: | ||
846 | case WACOM_REPORT_TPCST: | ||
847 | return wacom_tpc_single_touch(wacom, len); | ||
848 | |||
849 | case WACOM_REPORT_PENABLED: | ||
850 | return wacom_tpc_pen(wacom); | ||
851 | } | ||
852 | } | ||
841 | 853 | ||
842 | return 0; | 854 | return 0; |
843 | } | 855 | } |
@@ -1317,7 +1329,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1317 | break; | 1329 | break; |
1318 | 1330 | ||
1319 | case TABLETPC2FG: | 1331 | case TABLETPC2FG: |
1320 | if (features->device_type == BTN_TOOL_DOUBLETAP) { | 1332 | if (features->device_type == BTN_TOOL_FINGER) { |
1321 | 1333 | ||
1322 | input_mt_init_slots(input_dev, 2); | 1334 | input_mt_init_slots(input_dev, 2); |
1323 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, | 1335 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, |
@@ -1366,7 +1378,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1366 | 1378 | ||
1367 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 1379 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
1368 | 1380 | ||
1369 | if (features->device_type == BTN_TOOL_DOUBLETAP) { | 1381 | if (features->device_type == BTN_TOOL_FINGER) { |
1370 | __set_bit(BTN_LEFT, input_dev->keybit); | 1382 | __set_bit(BTN_LEFT, input_dev->keybit); |
1371 | __set_bit(BTN_FORWARD, input_dev->keybit); | 1383 | __set_bit(BTN_FORWARD, input_dev->keybit); |
1372 | __set_bit(BTN_BACK, input_dev->keybit); | 1384 | __set_bit(BTN_BACK, input_dev->keybit); |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 050acaefee7d..4f0ba21b0196 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -39,6 +39,8 @@ | |||
39 | #define WACOM_REPORT_INTUOSPAD 12 | 39 | #define WACOM_REPORT_INTUOSPAD 12 |
40 | #define WACOM_REPORT_TPC1FG 6 | 40 | #define WACOM_REPORT_TPC1FG 6 |
41 | #define WACOM_REPORT_TPC2FG 13 | 41 | #define WACOM_REPORT_TPC2FG 13 |
42 | #define WACOM_REPORT_TPCHID 15 | ||
43 | #define WACOM_REPORT_TPCST 16 | ||
42 | 44 | ||
43 | /* device quirks */ | 45 | /* device quirks */ |
44 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 | 46 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 4af2a18eb3ba..97b31a0e0525 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110 | |||
139 | tristate "cy8ctmg110 touchscreen" | 139 | tristate "cy8ctmg110 touchscreen" |
140 | depends on I2C | 140 | depends on I2C |
141 | depends on GPIOLIB | 141 | depends on GPIOLIB |
142 | |||
143 | help | 142 | help |
144 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on | 143 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on |
145 | an AAVA device. | 144 | an AAVA device. |
@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110 | |||
149 | To compile this driver as a module, choose M here: the | 148 | To compile this driver as a module, choose M here: the |
150 | module will be called cy8ctmg110_ts. | 149 | module will be called cy8ctmg110_ts. |
151 | 150 | ||
151 | config TOUCHSCREEN_CYTTSP_CORE | ||
152 | tristate "Cypress TTSP touchscreen" | ||
153 | help | ||
154 | Say Y here if you have a touchscreen using controller from | ||
155 | the Cypress TrueTouch(tm) Standard Product family connected | ||
156 | to your system. You will also need to select appropriate | ||
157 | bus connection below. | ||
158 | |||
159 | If unsure, say N. | ||
160 | |||
161 | To compile this driver as a module, choose M here: the | ||
162 | module will be called cyttsp_core. | ||
163 | |||
164 | config TOUCHSCREEN_CYTTSP_I2C | ||
165 | tristate "support I2C bus connection" | ||
166 | depends on TOUCHSCREEN_CYTTSP_CORE && I2C | ||
167 | help | ||
168 | Say Y here if the touchscreen is connected via I2C bus. | ||
169 | |||
170 | To compile this driver as a module, choose M here: the | ||
171 | module will be called cyttsp_i2c. | ||
172 | |||
173 | config TOUCHSCREEN_CYTTSP_SPI | ||
174 | tristate "support SPI bus connection" | ||
175 | depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER | ||
176 | help | ||
177 | Say Y here if the touchscreen is connected via SPI bus. | ||
178 | |||
179 | To compile this driver as a module, choose M here: the | ||
180 | module will be called cyttsp_spi. | ||
181 | |||
152 | config TOUCHSCREEN_DA9034 | 182 | config TOUCHSCREEN_DA9034 |
153 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 183 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
154 | depends on PMIC_DA903X | 184 | depends on PMIC_DA903X |
@@ -213,6 +243,21 @@ config TOUCHSCREEN_FUJITSU | |||
213 | To compile this driver as a module, choose M here: the | 243 | To compile this driver as a module, choose M here: the |
214 | module will be called fujitsu-ts. | 244 | module will be called fujitsu-ts. |
215 | 245 | ||
246 | config TOUCHSCREEN_ILI210X | ||
247 | tristate "Ilitek ILI210X based touchscreen" | ||
248 | depends on I2C | ||
249 | help | ||
250 | Say Y here if you have a ILI210X based touchscreen | ||
251 | controller. This driver supports models ILI2102, | ||
252 | ILI2102s, ILI2103, ILI2103s and ILI2105. | ||
253 | Such kind of chipsets can be found in Amazon Kindle Fire | ||
254 | touchscreens. | ||
255 | |||
256 | If unsure, say N. | ||
257 | |||
258 | To compile this driver as a module, choose M here: the | ||
259 | module will be called ili210x. | ||
260 | |||
216 | config TOUCHSCREEN_S3C2410 | 261 | config TOUCHSCREEN_S3C2410 |
217 | tristate "Samsung S3C2410/generic touchscreen input driver" | 262 | tristate "Samsung S3C2410/generic touchscreen input driver" |
218 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS | 263 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS |
@@ -430,6 +475,18 @@ config TOUCHSCREEN_TOUCHWIN | |||
430 | To compile this driver as a module, choose M here: the | 475 | To compile this driver as a module, choose M here: the |
431 | module will be called touchwin. | 476 | module will be called touchwin. |
432 | 477 | ||
478 | config TOUCHSCREEN_TI_TSCADC | ||
479 | tristate "TI Touchscreen Interface" | ||
480 | depends on ARCH_OMAP2PLUS | ||
481 | help | ||
482 | Say Y here if you have 4/5/8 wire touchscreen controller | ||
483 | to be connected to the ADC controller on your TI AM335x SoC. | ||
484 | |||
485 | If unsure, say N. | ||
486 | |||
487 | To compile this driver as a module, choose M here: the | ||
488 | module will be called ti_tscadc. | ||
489 | |||
433 | config TOUCHSCREEN_ATMEL_TSADCC | 490 | config TOUCHSCREEN_ATMEL_TSADCC |
434 | tristate "Atmel Touchscreen Interface" | 491 | tristate "Atmel Touchscreen Interface" |
435 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 | 492 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
@@ -577,6 +634,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
577 | - JASTEC USB Touch Controller/DigiTech DTR-02U | 634 | - JASTEC USB Touch Controller/DigiTech DTR-02U |
578 | - Zytronic controllers | 635 | - Zytronic controllers |
579 | - Elo TouchSystems 2700 IntelliTouch | 636 | - Elo TouchSystems 2700 IntelliTouch |
637 | - EasyTouch USB Touch Controller from Data Modul | ||
580 | 638 | ||
581 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 639 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
582 | a usage description and the required user-space stuff. | 640 | a usage description and the required user-space stuff. |
@@ -681,6 +739,14 @@ config TOUCHSCREEN_USB_NEXIO | |||
681 | bool "NEXIO/iNexio device support" if EXPERT | 739 | bool "NEXIO/iNexio device support" if EXPERT |
682 | depends on TOUCHSCREEN_USB_COMPOSITE | 740 | depends on TOUCHSCREEN_USB_COMPOSITE |
683 | 741 | ||
742 | config TOUCHSCREEN_USB_EASYTOUCH | ||
743 | default y | ||
744 | bool "EasyTouch USB Touch controller device support" if EMBEDDED | ||
745 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
746 | help | ||
747 | Say Y here if you have a EasyTouch USB Touch controller device support. | ||
748 | If unsure, say N. | ||
749 | |||
684 | config TOUCHSCREEN_TOUCHIT213 | 750 | config TOUCHSCREEN_TOUCHIT213 |
685 | tristate "Sahara TouchIT-213 touchscreen" | 751 | tristate "Sahara TouchIT-213 touchscreen" |
686 | select SERIO | 752 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 496091e88460..3d5cf8cbf89c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | |||
16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
17 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o |
18 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 18 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | ||
22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o | ||
23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o | ||
21 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | 24 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o |
22 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 25 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
23 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 26 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
@@ -26,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | |||
26 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 29 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
27 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o | 30 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o |
28 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 31 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
32 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | ||
29 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 33 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
30 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 34 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
31 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o | 35 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o |
@@ -45,6 +49,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o | |||
45 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 49 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
46 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | 50 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o |
47 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 51 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
52 | obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o | ||
48 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 53 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
49 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 54 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
50 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 55 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 42ae7a232f63..2c7692108e6c 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -612,10 +612,10 @@ static struct attribute *ad7877_attributes[] = { | |||
612 | NULL | 612 | NULL |
613 | }; | 613 | }; |
614 | 614 | ||
615 | static mode_t ad7877_attr_is_visible(struct kobject *kobj, | 615 | static umode_t ad7877_attr_is_visible(struct kobject *kobj, |
616 | struct attribute *attr, int n) | 616 | struct attribute *attr, int n) |
617 | { | 617 | { |
618 | mode_t mode = attr->mode; | 618 | umode_t mode = attr->mode; |
619 | 619 | ||
620 | if (attr == &dev_attr_aux3.attr) { | 620 | if (attr == &dev_attr_aux3.attr) { |
621 | if (gpio3) | 621 | if (gpio3) |
@@ -860,17 +860,7 @@ static struct spi_driver ad7877_driver = { | |||
860 | .remove = __devexit_p(ad7877_remove), | 860 | .remove = __devexit_p(ad7877_remove), |
861 | }; | 861 | }; |
862 | 862 | ||
863 | static int __init ad7877_init(void) | 863 | module_spi_driver(ad7877_driver); |
864 | { | ||
865 | return spi_register_driver(&ad7877_driver); | ||
866 | } | ||
867 | module_init(ad7877_init); | ||
868 | |||
869 | static void __exit ad7877_exit(void) | ||
870 | { | ||
871 | spi_unregister_driver(&ad7877_driver); | ||
872 | } | ||
873 | module_exit(ad7877_exit); | ||
874 | 864 | ||
875 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 865 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
876 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); | 866 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 0dac6712f42b..3054354d0dd3 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
@@ -102,17 +102,7 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
102 | .id_table = ad7879_id, | 102 | .id_table = ad7879_id, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static int __init ad7879_i2c_init(void) | 105 | module_i2c_driver(ad7879_i2c_driver); |
106 | { | ||
107 | return i2c_add_driver(&ad7879_i2c_driver); | ||
108 | } | ||
109 | module_init(ad7879_i2c_init); | ||
110 | |||
111 | static void __exit ad7879_i2c_exit(void) | ||
112 | { | ||
113 | i2c_del_driver(&ad7879_i2c_driver); | ||
114 | } | ||
115 | module_exit(ad7879_i2c_exit); | ||
116 | 106 | ||
117 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 107 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
118 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); | 108 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); |
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 9b2e1c2b1971..db49abf056ba 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c | |||
@@ -157,17 +157,7 @@ static struct spi_driver ad7879_spi_driver = { | |||
157 | .remove = __devexit_p(ad7879_spi_remove), | 157 | .remove = __devexit_p(ad7879_spi_remove), |
158 | }; | 158 | }; |
159 | 159 | ||
160 | static int __init ad7879_spi_init(void) | 160 | module_spi_driver(ad7879_spi_driver); |
161 | { | ||
162 | return spi_register_driver(&ad7879_spi_driver); | ||
163 | } | ||
164 | module_init(ad7879_spi_init); | ||
165 | |||
166 | static void __exit ad7879_spi_exit(void) | ||
167 | { | ||
168 | spi_unregister_driver(&ad7879_spi_driver); | ||
169 | } | ||
170 | module_exit(ad7879_spi_exit); | ||
171 | 161 | ||
172 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 162 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
173 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); | 163 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 23fd90185659..f02028ec3db6 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -1433,17 +1433,7 @@ static struct spi_driver ads7846_driver = { | |||
1433 | .remove = __devexit_p(ads7846_remove), | 1433 | .remove = __devexit_p(ads7846_remove), |
1434 | }; | 1434 | }; |
1435 | 1435 | ||
1436 | static int __init ads7846_init(void) | 1436 | module_spi_driver(ads7846_driver); |
1437 | { | ||
1438 | return spi_register_driver(&ads7846_driver); | ||
1439 | } | ||
1440 | module_init(ads7846_init); | ||
1441 | |||
1442 | static void __exit ads7846_exit(void) | ||
1443 | { | ||
1444 | spi_unregister_driver(&ads7846_driver); | ||
1445 | } | ||
1446 | module_exit(ads7846_exit); | ||
1447 | 1437 | ||
1448 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); | 1438 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); |
1449 | MODULE_LICENSE("GPL"); | 1439 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 8034cbb20f74..c5c2dbb93869 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
@@ -392,9 +392,10 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev) | |||
392 | return 0; | 392 | return 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | #ifdef CONFIG_PM | 395 | #ifdef CONFIG_PM_SLEEP |
396 | static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) | 396 | static int atmel_wm97xx_suspend(struct *dev) |
397 | { | 397 | { |
398 | struct platform_device *pdev = to_platform_device(dev); | ||
398 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 399 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
399 | 400 | ||
400 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | 401 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); |
@@ -404,8 +405,9 @@ static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) | |||
404 | return 0; | 405 | return 0; |
405 | } | 406 | } |
406 | 407 | ||
407 | static int atmel_wm97xx_resume(struct platform_device *pdev) | 408 | static int atmel_wm97xx_resume(struct device *dev) |
408 | { | 409 | { |
410 | struct platform_device *pdev = to_platform_device(dev); | ||
409 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 411 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
410 | struct wm97xx *wm = atmel_wm97xx->wm; | 412 | struct wm97xx *wm = atmel_wm97xx->wm; |
411 | 413 | ||
@@ -416,18 +418,18 @@ static int atmel_wm97xx_resume(struct platform_device *pdev) | |||
416 | 418 | ||
417 | return 0; | 419 | return 0; |
418 | } | 420 | } |
419 | #else | ||
420 | #define atmel_wm97xx_suspend NULL | ||
421 | #define atmel_wm97xx_resume NULL | ||
422 | #endif | 421 | #endif |
423 | 422 | ||
423 | static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops, | ||
424 | atmel_wm97xx_suspend, atmel_wm97xx_resume); | ||
425 | |||
424 | static struct platform_driver atmel_wm97xx_driver = { | 426 | static struct platform_driver atmel_wm97xx_driver = { |
425 | .remove = __exit_p(atmel_wm97xx_remove), | 427 | .remove = __exit_p(atmel_wm97xx_remove), |
426 | .driver = { | 428 | .driver = { |
427 | .name = "wm97xx-touch", | 429 | .name = "wm97xx-touch", |
430 | .owner = THIS_MODULE, | ||
431 | .pm = &atmel_wm97xx_pm_ops, | ||
428 | }, | 432 | }, |
429 | .suspend = atmel_wm97xx_suspend, | ||
430 | .resume = atmel_wm97xx_resume, | ||
431 | }; | 433 | }; |
432 | 434 | ||
433 | static int __init atmel_wm97xx_init(void) | 435 | static int __init atmel_wm97xx_init(void) |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index a596c2775d1a..19d4ea65ea01 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -1267,18 +1267,7 @@ static struct i2c_driver mxt_driver = { | |||
1267 | .id_table = mxt_id, | 1267 | .id_table = mxt_id, |
1268 | }; | 1268 | }; |
1269 | 1269 | ||
1270 | static int __init mxt_init(void) | 1270 | module_i2c_driver(mxt_driver); |
1271 | { | ||
1272 | return i2c_add_driver(&mxt_driver); | ||
1273 | } | ||
1274 | |||
1275 | static void __exit mxt_exit(void) | ||
1276 | { | ||
1277 | i2c_del_driver(&mxt_driver); | ||
1278 | } | ||
1279 | |||
1280 | module_init(mxt_init); | ||
1281 | module_exit(mxt_exit); | ||
1282 | 1271 | ||
1283 | /* Module information */ | 1272 | /* Module information */ |
1284 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 1273 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 94fb9fbb08a9..c7047b6bb020 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c | |||
@@ -635,17 +635,7 @@ static struct i2c_driver auo_pixcir_driver = { | |||
635 | .id_table = auo_pixcir_idtable, | 635 | .id_table = auo_pixcir_idtable, |
636 | }; | 636 | }; |
637 | 637 | ||
638 | static int __init auo_pixcir_init(void) | 638 | module_i2c_driver(auo_pixcir_driver); |
639 | { | ||
640 | return i2c_add_driver(&auo_pixcir_driver); | ||
641 | } | ||
642 | module_init(auo_pixcir_init); | ||
643 | |||
644 | static void __exit auo_pixcir_exit(void) | ||
645 | { | ||
646 | i2c_del_driver(&auo_pixcir_driver); | ||
647 | } | ||
648 | module_exit(auo_pixcir_exit); | ||
649 | 639 | ||
650 | MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); | 640 | MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); |
651 | MODULE_LICENSE("GPL v2"); | 641 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 902c7214e887..f2d03c06c2da 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c | |||
@@ -652,30 +652,7 @@ static struct i2c_driver bu21013_driver = { | |||
652 | .id_table = bu21013_id, | 652 | .id_table = bu21013_id, |
653 | }; | 653 | }; |
654 | 654 | ||
655 | /** | 655 | module_i2c_driver(bu21013_driver); |
656 | * bu21013_init() - initializes the bu21013 touchscreen driver | ||
657 | * | ||
658 | * This function used to initializes the bu21013 | ||
659 | * touchscreen driver and returns integer. | ||
660 | */ | ||
661 | static int __init bu21013_init(void) | ||
662 | { | ||
663 | return i2c_add_driver(&bu21013_driver); | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * bu21013_exit() - de-initializes the bu21013 touchscreen driver | ||
668 | * | ||
669 | * This function uses to de-initializes the bu21013 | ||
670 | * touchscreen driver and returns none. | ||
671 | */ | ||
672 | static void __exit bu21013_exit(void) | ||
673 | { | ||
674 | i2c_del_driver(&bu21013_driver); | ||
675 | } | ||
676 | |||
677 | module_init(bu21013_init); | ||
678 | module_exit(bu21013_exit); | ||
679 | 656 | ||
680 | MODULE_LICENSE("GPL v2"); | 657 | MODULE_LICENSE("GPL v2"); |
681 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); | 658 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); |
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d8815c5d54ad..237753ad1031 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
@@ -350,18 +350,7 @@ static struct i2c_driver cy8ctmg110_driver = { | |||
350 | .remove = __devexit_p(cy8ctmg110_remove), | 350 | .remove = __devexit_p(cy8ctmg110_remove), |
351 | }; | 351 | }; |
352 | 352 | ||
353 | static int __init cy8ctmg110_init(void) | 353 | module_i2c_driver(cy8ctmg110_driver); |
354 | { | ||
355 | return i2c_add_driver(&cy8ctmg110_driver); | ||
356 | } | ||
357 | |||
358 | static void __exit cy8ctmg110_exit(void) | ||
359 | { | ||
360 | i2c_del_driver(&cy8ctmg110_driver); | ||
361 | } | ||
362 | |||
363 | module_init(cy8ctmg110_init); | ||
364 | module_exit(cy8ctmg110_exit); | ||
365 | 354 | ||
366 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); | 355 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); |
367 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); | 356 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c new file mode 100644 index 000000000000..f030d9ec795d --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_core.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* | ||
2 | * Core Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
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 along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/input.h> | ||
32 | #include <linux/input/mt.h> | ||
33 | #include <linux/gpio.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #include "cyttsp_core.h" | ||
38 | |||
39 | /* Bootloader number of command keys */ | ||
40 | #define CY_NUM_BL_KEYS 8 | ||
41 | |||
42 | /* helpers */ | ||
43 | #define GET_NUM_TOUCHES(x) ((x) & 0x0F) | ||
44 | #define IS_LARGE_AREA(x) (((x) & 0x10) >> 4) | ||
45 | #define IS_BAD_PKT(x) ((x) & 0x20) | ||
46 | #define IS_VALID_APP(x) ((x) & 0x01) | ||
47 | #define IS_OPERATIONAL_ERR(x) ((x) & 0x3F) | ||
48 | #define GET_HSTMODE(reg) (((reg) & 0x70) >> 4) | ||
49 | #define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4) | ||
50 | |||
51 | #define CY_REG_BASE 0x00 | ||
52 | #define CY_REG_ACT_DIST 0x1E | ||
53 | #define CY_REG_ACT_INTRVL 0x1D | ||
54 | #define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1) | ||
55 | #define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1) | ||
56 | #define CY_MAXZ 255 | ||
57 | #define CY_DELAY_DFLT 20 /* ms */ | ||
58 | #define CY_DELAY_MAX 500 | ||
59 | #define CY_ACT_DIST_DFLT 0xF8 | ||
60 | #define CY_HNDSHK_BIT 0x80 | ||
61 | /* device mode bits */ | ||
62 | #define CY_OPERATE_MODE 0x00 | ||
63 | #define CY_SYSINFO_MODE 0x10 | ||
64 | /* power mode select bits */ | ||
65 | #define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */ | ||
66 | #define CY_DEEP_SLEEP_MODE 0x02 | ||
67 | #define CY_LOW_POWER_MODE 0x04 | ||
68 | |||
69 | /* Slots management */ | ||
70 | #define CY_MAX_FINGER 4 | ||
71 | #define CY_MAX_ID 16 | ||
72 | |||
73 | static const u8 bl_command[] = { | ||
74 | 0x00, /* file offset */ | ||
75 | 0xFF, /* command */ | ||
76 | 0xA5, /* exit bootloader command */ | ||
77 | 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */ | ||
78 | }; | ||
79 | |||
80 | static int ttsp_read_block_data(struct cyttsp *ts, u8 command, | ||
81 | u8 length, void *buf) | ||
82 | { | ||
83 | int error; | ||
84 | int tries; | ||
85 | |||
86 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
87 | error = ts->bus_ops->read(ts, command, length, buf); | ||
88 | if (!error) | ||
89 | return 0; | ||
90 | |||
91 | msleep(CY_DELAY_DFLT); | ||
92 | } | ||
93 | |||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | static int ttsp_write_block_data(struct cyttsp *ts, u8 command, | ||
98 | u8 length, void *buf) | ||
99 | { | ||
100 | int error; | ||
101 | int tries; | ||
102 | |||
103 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
104 | error = ts->bus_ops->write(ts, command, length, buf); | ||
105 | if (!error) | ||
106 | return 0; | ||
107 | |||
108 | msleep(CY_DELAY_DFLT); | ||
109 | } | ||
110 | |||
111 | return -EIO; | ||
112 | } | ||
113 | |||
114 | static int ttsp_send_command(struct cyttsp *ts, u8 cmd) | ||
115 | { | ||
116 | return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd); | ||
117 | } | ||
118 | |||
119 | static int cyttsp_load_bl_regs(struct cyttsp *ts) | ||
120 | { | ||
121 | memset(&ts->bl_data, 0, sizeof(ts->bl_data)); | ||
122 | ts->bl_data.bl_status = 0x10; | ||
123 | |||
124 | return ttsp_read_block_data(ts, CY_REG_BASE, | ||
125 | sizeof(ts->bl_data), &ts->bl_data); | ||
126 | } | ||
127 | |||
128 | static int cyttsp_exit_bl_mode(struct cyttsp *ts) | ||
129 | { | ||
130 | int error; | ||
131 | u8 bl_cmd[sizeof(bl_command)]; | ||
132 | |||
133 | memcpy(bl_cmd, bl_command, sizeof(bl_command)); | ||
134 | if (ts->pdata->bl_keys) | ||
135 | memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], | ||
136 | ts->pdata->bl_keys, sizeof(bl_command)); | ||
137 | |||
138 | error = ttsp_write_block_data(ts, CY_REG_BASE, | ||
139 | sizeof(bl_cmd), bl_cmd); | ||
140 | if (error) | ||
141 | return error; | ||
142 | |||
143 | /* wait for TTSP Device to complete the operation */ | ||
144 | msleep(CY_DELAY_DFLT); | ||
145 | |||
146 | error = cyttsp_load_bl_regs(ts); | ||
147 | if (error) | ||
148 | return error; | ||
149 | |||
150 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status)) | ||
151 | return -EIO; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int cyttsp_set_operational_mode(struct cyttsp *ts) | ||
157 | { | ||
158 | int error; | ||
159 | |||
160 | error = ttsp_send_command(ts, CY_OPERATE_MODE); | ||
161 | if (error) | ||
162 | return error; | ||
163 | |||
164 | /* wait for TTSP Device to complete switch to Operational mode */ | ||
165 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
166 | sizeof(ts->xy_data), &ts->xy_data); | ||
167 | if (error) | ||
168 | return error; | ||
169 | |||
170 | return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0; | ||
171 | } | ||
172 | |||
173 | static int cyttsp_set_sysinfo_mode(struct cyttsp *ts) | ||
174 | { | ||
175 | int error; | ||
176 | |||
177 | memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data)); | ||
178 | |||
179 | /* switch to sysinfo mode */ | ||
180 | error = ttsp_send_command(ts, CY_SYSINFO_MODE); | ||
181 | if (error) | ||
182 | return error; | ||
183 | |||
184 | /* read sysinfo registers */ | ||
185 | msleep(CY_DELAY_DFLT); | ||
186 | error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data), | ||
187 | &ts->sysinfo_data); | ||
188 | if (error) | ||
189 | return error; | ||
190 | |||
191 | if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl) | ||
192 | return -EIO; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) | ||
198 | { | ||
199 | int retval = 0; | ||
200 | |||
201 | if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || | ||
202 | ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || | ||
203 | ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { | ||
204 | |||
205 | u8 intrvl_ray[] = { | ||
206 | ts->pdata->act_intrvl, | ||
207 | ts->pdata->tch_tmout, | ||
208 | ts->pdata->lp_intrvl | ||
209 | }; | ||
210 | |||
211 | /* set intrvl registers */ | ||
212 | retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL, | ||
213 | sizeof(intrvl_ray), intrvl_ray); | ||
214 | msleep(CY_DELAY_DFLT); | ||
215 | } | ||
216 | |||
217 | return retval; | ||
218 | } | ||
219 | |||
220 | static int cyttsp_soft_reset(struct cyttsp *ts) | ||
221 | { | ||
222 | unsigned long timeout; | ||
223 | int retval; | ||
224 | |||
225 | /* wait for interrupt to set ready completion */ | ||
226 | INIT_COMPLETION(ts->bl_ready); | ||
227 | ts->state = CY_BL_STATE; | ||
228 | |||
229 | enable_irq(ts->irq); | ||
230 | |||
231 | retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE); | ||
232 | if (retval) | ||
233 | goto out; | ||
234 | |||
235 | timeout = wait_for_completion_timeout(&ts->bl_ready, | ||
236 | msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX)); | ||
237 | retval = timeout ? 0 : -EIO; | ||
238 | |||
239 | out: | ||
240 | ts->state = CY_IDLE_STATE; | ||
241 | disable_irq(ts->irq); | ||
242 | return retval; | ||
243 | } | ||
244 | |||
245 | static int cyttsp_act_dist_setup(struct cyttsp *ts) | ||
246 | { | ||
247 | u8 act_dist_setup = ts->pdata->act_dist; | ||
248 | |||
249 | /* Init gesture; active distance setup */ | ||
250 | return ttsp_write_block_data(ts, CY_REG_ACT_DIST, | ||
251 | sizeof(act_dist_setup), &act_dist_setup); | ||
252 | } | ||
253 | |||
254 | static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids) | ||
255 | { | ||
256 | ids[0] = xy_data->touch12_id >> 4; | ||
257 | ids[1] = xy_data->touch12_id & 0xF; | ||
258 | ids[2] = xy_data->touch34_id >> 4; | ||
259 | ids[3] = xy_data->touch34_id & 0xF; | ||
260 | } | ||
261 | |||
262 | static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data, | ||
263 | int idx) | ||
264 | { | ||
265 | switch (idx) { | ||
266 | case 0: | ||
267 | return &xy_data->tch1; | ||
268 | case 1: | ||
269 | return &xy_data->tch2; | ||
270 | case 2: | ||
271 | return &xy_data->tch3; | ||
272 | case 3: | ||
273 | return &xy_data->tch4; | ||
274 | default: | ||
275 | return NULL; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | static void cyttsp_report_tchdata(struct cyttsp *ts) | ||
280 | { | ||
281 | struct cyttsp_xydata *xy_data = &ts->xy_data; | ||
282 | struct input_dev *input = ts->input; | ||
283 | int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat); | ||
284 | const struct cyttsp_tch *tch; | ||
285 | int ids[CY_MAX_ID]; | ||
286 | int i; | ||
287 | DECLARE_BITMAP(used, CY_MAX_ID); | ||
288 | |||
289 | if (IS_LARGE_AREA(xy_data->tt_stat) == 1) { | ||
290 | /* terminate all active tracks */ | ||
291 | num_tch = 0; | ||
292 | dev_dbg(ts->dev, "%s: Large area detected\n", __func__); | ||
293 | } else if (num_tch > CY_MAX_FINGER) { | ||
294 | /* terminate all active tracks */ | ||
295 | num_tch = 0; | ||
296 | dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__); | ||
297 | } else if (IS_BAD_PKT(xy_data->tt_mode)) { | ||
298 | /* terminate all active tracks */ | ||
299 | num_tch = 0; | ||
300 | dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__); | ||
301 | } | ||
302 | |||
303 | cyttsp_extract_track_ids(xy_data, ids); | ||
304 | |||
305 | bitmap_zero(used, CY_MAX_ID); | ||
306 | |||
307 | for (i = 0; i < num_tch; i++) { | ||
308 | tch = cyttsp_get_tch(xy_data, i); | ||
309 | |||
310 | input_mt_slot(input, ids[i]); | ||
311 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | ||
312 | input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x)); | ||
313 | input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y)); | ||
314 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z); | ||
315 | |||
316 | __set_bit(ids[i], used); | ||
317 | } | ||
318 | |||
319 | for (i = 0; i < CY_MAX_ID; i++) { | ||
320 | if (test_bit(i, used)) | ||
321 | continue; | ||
322 | |||
323 | input_mt_slot(input, i); | ||
324 | input_mt_report_slot_state(input, MT_TOOL_FINGER, false); | ||
325 | } | ||
326 | |||
327 | input_sync(input); | ||
328 | } | ||
329 | |||
330 | static irqreturn_t cyttsp_irq(int irq, void *handle) | ||
331 | { | ||
332 | struct cyttsp *ts = handle; | ||
333 | int error; | ||
334 | |||
335 | if (unlikely(ts->state == CY_BL_STATE)) { | ||
336 | complete(&ts->bl_ready); | ||
337 | goto out; | ||
338 | } | ||
339 | |||
340 | /* Get touch data from CYTTSP device */ | ||
341 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
342 | sizeof(struct cyttsp_xydata), &ts->xy_data); | ||
343 | if (error) | ||
344 | goto out; | ||
345 | |||
346 | /* provide flow control handshake */ | ||
347 | if (ts->pdata->use_hndshk) { | ||
348 | error = ttsp_send_command(ts, | ||
349 | ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); | ||
350 | if (error) | ||
351 | goto out; | ||
352 | } | ||
353 | |||
354 | if (unlikely(ts->state == CY_IDLE_STATE)) | ||
355 | goto out; | ||
356 | |||
357 | if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) { | ||
358 | /* | ||
359 | * TTSP device has reset back to bootloader mode. | ||
360 | * Restore to operational mode. | ||
361 | */ | ||
362 | error = cyttsp_exit_bl_mode(ts); | ||
363 | if (error) { | ||
364 | dev_err(ts->dev, | ||
365 | "Could not return to operational mode, err: %d\n", | ||
366 | error); | ||
367 | ts->state = CY_IDLE_STATE; | ||
368 | } | ||
369 | } else { | ||
370 | cyttsp_report_tchdata(ts); | ||
371 | } | ||
372 | |||
373 | out: | ||
374 | return IRQ_HANDLED; | ||
375 | } | ||
376 | |||
377 | static int cyttsp_power_on(struct cyttsp *ts) | ||
378 | { | ||
379 | int error; | ||
380 | |||
381 | error = cyttsp_soft_reset(ts); | ||
382 | if (error) | ||
383 | return error; | ||
384 | |||
385 | error = cyttsp_load_bl_regs(ts); | ||
386 | if (error) | ||
387 | return error; | ||
388 | |||
389 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) && | ||
390 | IS_VALID_APP(ts->bl_data.bl_status)) { | ||
391 | error = cyttsp_exit_bl_mode(ts); | ||
392 | if (error) | ||
393 | return error; | ||
394 | } | ||
395 | |||
396 | if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE || | ||
397 | IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) { | ||
398 | return -ENODEV; | ||
399 | } | ||
400 | |||
401 | error = cyttsp_set_sysinfo_mode(ts); | ||
402 | if (error) | ||
403 | return error; | ||
404 | |||
405 | error = cyttsp_set_sysinfo_regs(ts); | ||
406 | if (error) | ||
407 | return error; | ||
408 | |||
409 | error = cyttsp_set_operational_mode(ts); | ||
410 | if (error) | ||
411 | return error; | ||
412 | |||
413 | /* init active distance */ | ||
414 | error = cyttsp_act_dist_setup(ts); | ||
415 | if (error) | ||
416 | return error; | ||
417 | |||
418 | ts->state = CY_ACTIVE_STATE; | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int cyttsp_enable(struct cyttsp *ts) | ||
424 | { | ||
425 | int error; | ||
426 | |||
427 | /* | ||
428 | * The device firmware can wake on an I2C or SPI memory slave | ||
429 | * address match. So just reading a register is sufficient to | ||
430 | * wake up the device. The first read attempt will fail but it | ||
431 | * will wake it up making the second read attempt successful. | ||
432 | */ | ||
433 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
434 | sizeof(ts->xy_data), &ts->xy_data); | ||
435 | if (error) | ||
436 | return error; | ||
437 | |||
438 | if (GET_HSTMODE(ts->xy_data.hst_mode)) | ||
439 | return -EIO; | ||
440 | |||
441 | enable_irq(ts->irq); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int cyttsp_disable(struct cyttsp *ts) | ||
447 | { | ||
448 | int error; | ||
449 | |||
450 | error = ttsp_send_command(ts, CY_LOW_POWER_MODE); | ||
451 | if (error) | ||
452 | return error; | ||
453 | |||
454 | disable_irq(ts->irq); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | #ifdef CONFIG_PM_SLEEP | ||
460 | static int cyttsp_suspend(struct device *dev) | ||
461 | { | ||
462 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
463 | int retval = 0; | ||
464 | |||
465 | mutex_lock(&ts->input->mutex); | ||
466 | |||
467 | if (ts->input->users) { | ||
468 | retval = cyttsp_disable(ts); | ||
469 | if (retval == 0) | ||
470 | ts->suspended = true; | ||
471 | } | ||
472 | |||
473 | mutex_unlock(&ts->input->mutex); | ||
474 | |||
475 | return retval; | ||
476 | } | ||
477 | |||
478 | static int cyttsp_resume(struct device *dev) | ||
479 | { | ||
480 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
481 | |||
482 | mutex_lock(&ts->input->mutex); | ||
483 | |||
484 | if (ts->input->users) | ||
485 | cyttsp_enable(ts); | ||
486 | |||
487 | ts->suspended = false; | ||
488 | |||
489 | mutex_unlock(&ts->input->mutex); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | #endif | ||
495 | |||
496 | SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); | ||
497 | EXPORT_SYMBOL_GPL(cyttsp_pm_ops); | ||
498 | |||
499 | static int cyttsp_open(struct input_dev *dev) | ||
500 | { | ||
501 | struct cyttsp *ts = input_get_drvdata(dev); | ||
502 | int retval = 0; | ||
503 | |||
504 | if (!ts->suspended) | ||
505 | retval = cyttsp_enable(ts); | ||
506 | |||
507 | return retval; | ||
508 | } | ||
509 | |||
510 | static void cyttsp_close(struct input_dev *dev) | ||
511 | { | ||
512 | struct cyttsp *ts = input_get_drvdata(dev); | ||
513 | |||
514 | if (!ts->suspended) | ||
515 | cyttsp_disable(ts); | ||
516 | } | ||
517 | |||
518 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
519 | struct device *dev, int irq, size_t xfer_buf_size) | ||
520 | { | ||
521 | const struct cyttsp_platform_data *pdata = dev->platform_data; | ||
522 | struct cyttsp *ts; | ||
523 | struct input_dev *input_dev; | ||
524 | int error; | ||
525 | |||
526 | if (!pdata || !pdata->name || irq <= 0) { | ||
527 | error = -EINVAL; | ||
528 | goto err_out; | ||
529 | } | ||
530 | |||
531 | ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); | ||
532 | input_dev = input_allocate_device(); | ||
533 | if (!ts || !input_dev) { | ||
534 | error = -ENOMEM; | ||
535 | goto err_free_mem; | ||
536 | } | ||
537 | |||
538 | ts->dev = dev; | ||
539 | ts->input = input_dev; | ||
540 | ts->pdata = dev->platform_data; | ||
541 | ts->bus_ops = bus_ops; | ||
542 | ts->irq = irq; | ||
543 | |||
544 | init_completion(&ts->bl_ready); | ||
545 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); | ||
546 | |||
547 | if (pdata->init) { | ||
548 | error = pdata->init(); | ||
549 | if (error) { | ||
550 | dev_err(ts->dev, "platform init failed, err: %d\n", | ||
551 | error); | ||
552 | goto err_free_mem; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | input_dev->name = pdata->name; | ||
557 | input_dev->phys = ts->phys; | ||
558 | input_dev->id.bustype = bus_ops->bustype; | ||
559 | input_dev->dev.parent = ts->dev; | ||
560 | |||
561 | input_dev->open = cyttsp_open; | ||
562 | input_dev->close = cyttsp_close; | ||
563 | |||
564 | input_set_drvdata(input_dev, ts); | ||
565 | |||
566 | __set_bit(EV_ABS, input_dev->evbit); | ||
567 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
568 | 0, pdata->maxx, 0, 0); | ||
569 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
570 | 0, pdata->maxy, 0, 0); | ||
571 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
572 | 0, CY_MAXZ, 0, 0); | ||
573 | |||
574 | input_mt_init_slots(input_dev, CY_MAX_ID); | ||
575 | |||
576 | error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, | ||
577 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
578 | pdata->name, ts); | ||
579 | if (error) { | ||
580 | dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", | ||
581 | ts->irq, error); | ||
582 | goto err_platform_exit; | ||
583 | } | ||
584 | |||
585 | disable_irq(ts->irq); | ||
586 | |||
587 | error = cyttsp_power_on(ts); | ||
588 | if (error) | ||
589 | goto err_free_irq; | ||
590 | |||
591 | error = input_register_device(input_dev); | ||
592 | if (error) { | ||
593 | dev_err(ts->dev, "failed to register input device: %d\n", | ||
594 | error); | ||
595 | goto err_free_irq; | ||
596 | } | ||
597 | |||
598 | return ts; | ||
599 | |||
600 | err_free_irq: | ||
601 | free_irq(ts->irq, ts); | ||
602 | err_platform_exit: | ||
603 | if (pdata->exit) | ||
604 | pdata->exit(); | ||
605 | err_free_mem: | ||
606 | input_free_device(input_dev); | ||
607 | kfree(ts); | ||
608 | err_out: | ||
609 | return ERR_PTR(error); | ||
610 | } | ||
611 | EXPORT_SYMBOL_GPL(cyttsp_probe); | ||
612 | |||
613 | void cyttsp_remove(struct cyttsp *ts) | ||
614 | { | ||
615 | free_irq(ts->irq, ts); | ||
616 | input_unregister_device(ts->input); | ||
617 | if (ts->pdata->exit) | ||
618 | ts->pdata->exit(); | ||
619 | kfree(ts); | ||
620 | } | ||
621 | EXPORT_SYMBOL_GPL(cyttsp_remove); | ||
622 | |||
623 | MODULE_LICENSE("GPL"); | ||
624 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); | ||
625 | MODULE_AUTHOR("Cypress"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h new file mode 100644 index 000000000000..1aa3c6967e70 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_core.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * Header file for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
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 along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | |||
31 | #ifndef __CYTTSP_CORE_H__ | ||
32 | #define __CYTTSP_CORE_H__ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/module.h> | ||
37 | #include <linux/types.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/input/cyttsp.h> | ||
40 | |||
41 | #define CY_NUM_RETRY 16 /* max number of retries for read ops */ | ||
42 | |||
43 | struct cyttsp_tch { | ||
44 | __be16 x, y; | ||
45 | u8 z; | ||
46 | } __packed; | ||
47 | |||
48 | /* TrueTouch Standard Product Gen3 interface definition */ | ||
49 | struct cyttsp_xydata { | ||
50 | u8 hst_mode; | ||
51 | u8 tt_mode; | ||
52 | u8 tt_stat; | ||
53 | struct cyttsp_tch tch1; | ||
54 | u8 touch12_id; | ||
55 | struct cyttsp_tch tch2; | ||
56 | u8 gest_cnt; | ||
57 | u8 gest_id; | ||
58 | struct cyttsp_tch tch3; | ||
59 | u8 touch34_id; | ||
60 | struct cyttsp_tch tch4; | ||
61 | u8 tt_undef[3]; | ||
62 | u8 act_dist; | ||
63 | u8 tt_reserved; | ||
64 | } __packed; | ||
65 | |||
66 | |||
67 | /* TTSP System Information interface definition */ | ||
68 | struct cyttsp_sysinfo_data { | ||
69 | u8 hst_mode; | ||
70 | u8 mfg_cmd; | ||
71 | u8 mfg_stat; | ||
72 | u8 cid[3]; | ||
73 | u8 tt_undef1; | ||
74 | u8 uid[8]; | ||
75 | u8 bl_verh; | ||
76 | u8 bl_verl; | ||
77 | u8 tts_verh; | ||
78 | u8 tts_verl; | ||
79 | u8 app_idh; | ||
80 | u8 app_idl; | ||
81 | u8 app_verh; | ||
82 | u8 app_verl; | ||
83 | u8 tt_undef[5]; | ||
84 | u8 scn_typ; | ||
85 | u8 act_intrvl; | ||
86 | u8 tch_tmout; | ||
87 | u8 lp_intrvl; | ||
88 | }; | ||
89 | |||
90 | /* TTSP Bootloader Register Map interface definition */ | ||
91 | #define CY_BL_CHKSUM_OK 0x01 | ||
92 | struct cyttsp_bootloader_data { | ||
93 | u8 bl_file; | ||
94 | u8 bl_status; | ||
95 | u8 bl_error; | ||
96 | u8 blver_hi; | ||
97 | u8 blver_lo; | ||
98 | u8 bld_blver_hi; | ||
99 | u8 bld_blver_lo; | ||
100 | u8 ttspver_hi; | ||
101 | u8 ttspver_lo; | ||
102 | u8 appid_hi; | ||
103 | u8 appid_lo; | ||
104 | u8 appver_hi; | ||
105 | u8 appver_lo; | ||
106 | u8 cid_0; | ||
107 | u8 cid_1; | ||
108 | u8 cid_2; | ||
109 | }; | ||
110 | |||
111 | struct cyttsp; | ||
112 | |||
113 | struct cyttsp_bus_ops { | ||
114 | u16 bustype; | ||
115 | int (*write)(struct cyttsp *ts, | ||
116 | u8 addr, u8 length, const void *values); | ||
117 | int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values); | ||
118 | }; | ||
119 | |||
120 | enum cyttsp_state { | ||
121 | CY_IDLE_STATE, | ||
122 | CY_ACTIVE_STATE, | ||
123 | CY_BL_STATE, | ||
124 | }; | ||
125 | |||
126 | struct cyttsp { | ||
127 | struct device *dev; | ||
128 | int irq; | ||
129 | struct input_dev *input; | ||
130 | char phys[32]; | ||
131 | const struct cyttsp_platform_data *pdata; | ||
132 | const struct cyttsp_bus_ops *bus_ops; | ||
133 | struct cyttsp_bootloader_data bl_data; | ||
134 | struct cyttsp_sysinfo_data sysinfo_data; | ||
135 | struct cyttsp_xydata xy_data; | ||
136 | struct completion bl_ready; | ||
137 | enum cyttsp_state state; | ||
138 | bool suspended; | ||
139 | |||
140 | u8 xfer_buf[] ____cacheline_aligned; | ||
141 | }; | ||
142 | |||
143 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
144 | struct device *dev, int irq, size_t xfer_buf_size); | ||
145 | void cyttsp_remove(struct cyttsp *ts); | ||
146 | |||
147 | extern const struct dev_pm_ops cyttsp_pm_ops; | ||
148 | |||
149 | #endif /* __CYTTSP_CORE_H__ */ | ||
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c new file mode 100644 index 000000000000..2af1d0c52bcd --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_i2c.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
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 along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cyttsp_core.h" | ||
31 | |||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/input.h> | ||
34 | |||
35 | #define CY_I2C_DATA_SIZE 128 | ||
36 | |||
37 | static int cyttsp_i2c_read_block_data(struct cyttsp *ts, | ||
38 | u8 addr, u8 length, void *values) | ||
39 | { | ||
40 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
41 | struct i2c_msg msgs[] = { | ||
42 | { | ||
43 | .addr = client->addr, | ||
44 | .flags = 0, | ||
45 | .len = 1, | ||
46 | .buf = &addr, | ||
47 | }, | ||
48 | { | ||
49 | .addr = client->addr, | ||
50 | .flags = I2C_M_RD, | ||
51 | .len = length, | ||
52 | .buf = values, | ||
53 | }, | ||
54 | }; | ||
55 | int retval; | ||
56 | |||
57 | retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
58 | if (retval < 0) | ||
59 | return retval; | ||
60 | |||
61 | return retval != ARRAY_SIZE(msgs) ? -EIO : 0; | ||
62 | } | ||
63 | |||
64 | static int cyttsp_i2c_write_block_data(struct cyttsp *ts, | ||
65 | u8 addr, u8 length, const void *values) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
68 | int retval; | ||
69 | |||
70 | ts->xfer_buf[0] = addr; | ||
71 | memcpy(&ts->xfer_buf[1], values, length); | ||
72 | |||
73 | retval = i2c_master_send(client, ts->xfer_buf, length + 1); | ||
74 | |||
75 | return retval < 0 ? retval : 0; | ||
76 | } | ||
77 | |||
78 | static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { | ||
79 | .bustype = BUS_I2C, | ||
80 | .write = cyttsp_i2c_write_block_data, | ||
81 | .read = cyttsp_i2c_read_block_data, | ||
82 | }; | ||
83 | |||
84 | static int __devinit cyttsp_i2c_probe(struct i2c_client *client, | ||
85 | const struct i2c_device_id *id) | ||
86 | { | ||
87 | struct cyttsp *ts; | ||
88 | |||
89 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
90 | dev_err(&client->dev, "I2C functionality not Supported\n"); | ||
91 | return -EIO; | ||
92 | } | ||
93 | |||
94 | ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq, | ||
95 | CY_I2C_DATA_SIZE); | ||
96 | |||
97 | if (IS_ERR(ts)) | ||
98 | return PTR_ERR(ts); | ||
99 | |||
100 | i2c_set_clientdata(client, ts); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int __devexit cyttsp_i2c_remove(struct i2c_client *client) | ||
106 | { | ||
107 | struct cyttsp *ts = i2c_get_clientdata(client); | ||
108 | |||
109 | cyttsp_remove(ts); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static const struct i2c_device_id cyttsp_i2c_id[] = { | ||
115 | { CY_I2C_NAME, 0 }, | ||
116 | { } | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); | ||
119 | |||
120 | static struct i2c_driver cyttsp_i2c_driver = { | ||
121 | .driver = { | ||
122 | .name = CY_I2C_NAME, | ||
123 | .owner = THIS_MODULE, | ||
124 | .pm = &cyttsp_pm_ops, | ||
125 | }, | ||
126 | .probe = cyttsp_i2c_probe, | ||
127 | .remove = __devexit_p(cyttsp_i2c_remove), | ||
128 | .id_table = cyttsp_i2c_id, | ||
129 | }; | ||
130 | |||
131 | module_i2c_driver(cyttsp_i2c_driver); | ||
132 | |||
133 | MODULE_LICENSE("GPL"); | ||
134 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); | ||
135 | MODULE_AUTHOR("Cypress"); | ||
136 | MODULE_ALIAS("i2c:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c new file mode 100644 index 000000000000..9f263410407b --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_spi.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
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 along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cyttsp_core.h" | ||
31 | |||
32 | #include <linux/delay.h> | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/spi/spi.h> | ||
35 | |||
36 | #define CY_SPI_WR_OP 0x00 /* r/~w */ | ||
37 | #define CY_SPI_RD_OP 0x01 | ||
38 | #define CY_SPI_CMD_BYTES 4 | ||
39 | #define CY_SPI_SYNC_BYTE 2 | ||
40 | #define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */ | ||
41 | #define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */ | ||
42 | #define CY_SPI_DATA_SIZE 128 | ||
43 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) | ||
44 | #define CY_SPI_BITS_PER_WORD 8 | ||
45 | |||
46 | static int cyttsp_spi_xfer(struct cyttsp *ts, | ||
47 | u8 op, u8 reg, u8 *buf, int length) | ||
48 | { | ||
49 | struct spi_device *spi = to_spi_device(ts->dev); | ||
50 | struct spi_message msg; | ||
51 | struct spi_transfer xfer[2]; | ||
52 | u8 *wr_buf = &ts->xfer_buf[0]; | ||
53 | u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE]; | ||
54 | int retval; | ||
55 | int i; | ||
56 | |||
57 | if (length > CY_SPI_DATA_SIZE) { | ||
58 | dev_err(ts->dev, "%s: length %d is too big.\n", | ||
59 | __func__, length); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
64 | memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
65 | |||
66 | wr_buf[0] = 0x00; /* header byte 0 */ | ||
67 | wr_buf[1] = 0xFF; /* header byte 1 */ | ||
68 | wr_buf[2] = reg; /* reg index */ | ||
69 | wr_buf[3] = op; /* r/~w */ | ||
70 | if (op == CY_SPI_WR_OP) | ||
71 | memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); | ||
72 | |||
73 | memset(xfer, 0, sizeof(xfer)); | ||
74 | spi_message_init(&msg); | ||
75 | |||
76 | /* | ||
77 | We set both TX and RX buffers because Cypress TTSP | ||
78 | requires full duplex operation. | ||
79 | */ | ||
80 | xfer[0].tx_buf = wr_buf; | ||
81 | xfer[0].rx_buf = rd_buf; | ||
82 | switch (op) { | ||
83 | case CY_SPI_WR_OP: | ||
84 | xfer[0].len = length + CY_SPI_CMD_BYTES; | ||
85 | spi_message_add_tail(&xfer[0], &msg); | ||
86 | break; | ||
87 | |||
88 | case CY_SPI_RD_OP: | ||
89 | xfer[0].len = CY_SPI_CMD_BYTES; | ||
90 | spi_message_add_tail(&xfer[0], &msg); | ||
91 | |||
92 | xfer[1].rx_buf = buf; | ||
93 | xfer[1].len = length; | ||
94 | spi_message_add_tail(&xfer[1], &msg); | ||
95 | break; | ||
96 | |||
97 | default: | ||
98 | dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | retval = spi_sync(spi, &msg); | ||
103 | if (retval < 0) { | ||
104 | dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n", | ||
105 | __func__, retval, xfer[1].len, op); | ||
106 | |||
107 | /* | ||
108 | * do not return here since was a bad ACK sequence | ||
109 | * let the following ACK check handle any errors and | ||
110 | * allow silent retries | ||
111 | */ | ||
112 | } | ||
113 | |||
114 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 || | ||
115 | rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) { | ||
116 | |||
117 | dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op); | ||
118 | |||
119 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) | ||
120 | dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n", | ||
121 | __func__, i, rd_buf[i]); | ||
122 | for (i = 0; i < length; i++) | ||
123 | dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n", | ||
124 | __func__, i, buf[i]); | ||
125 | |||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int cyttsp_spi_read_block_data(struct cyttsp *ts, | ||
133 | u8 addr, u8 length, void *data) | ||
134 | { | ||
135 | return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length); | ||
136 | } | ||
137 | |||
138 | static int cyttsp_spi_write_block_data(struct cyttsp *ts, | ||
139 | u8 addr, u8 length, const void *data) | ||
140 | { | ||
141 | return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length); | ||
142 | } | ||
143 | |||
144 | static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { | ||
145 | .bustype = BUS_SPI, | ||
146 | .write = cyttsp_spi_write_block_data, | ||
147 | .read = cyttsp_spi_read_block_data, | ||
148 | }; | ||
149 | |||
150 | static int __devinit cyttsp_spi_probe(struct spi_device *spi) | ||
151 | { | ||
152 | struct cyttsp *ts; | ||
153 | int error; | ||
154 | |||
155 | /* Set up SPI*/ | ||
156 | spi->bits_per_word = CY_SPI_BITS_PER_WORD; | ||
157 | spi->mode = SPI_MODE_0; | ||
158 | error = spi_setup(spi); | ||
159 | if (error < 0) { | ||
160 | dev_err(&spi->dev, "%s: SPI setup error %d\n", | ||
161 | __func__, error); | ||
162 | return error; | ||
163 | } | ||
164 | |||
165 | ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, | ||
166 | CY_SPI_DATA_BUF_SIZE * 2); | ||
167 | if (IS_ERR(ts)) | ||
168 | return PTR_ERR(ts); | ||
169 | |||
170 | spi_set_drvdata(spi, ts); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int __devexit cyttsp_spi_remove(struct spi_device *spi) | ||
176 | { | ||
177 | struct cyttsp *ts = spi_get_drvdata(spi); | ||
178 | |||
179 | cyttsp_remove(ts); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static struct spi_driver cyttsp_spi_driver = { | ||
185 | .driver = { | ||
186 | .name = CY_SPI_NAME, | ||
187 | .owner = THIS_MODULE, | ||
188 | .pm = &cyttsp_pm_ops, | ||
189 | }, | ||
190 | .probe = cyttsp_spi_probe, | ||
191 | .remove = __devexit_p(cyttsp_spi_remove), | ||
192 | }; | ||
193 | |||
194 | module_spi_driver(cyttsp_spi_driver); | ||
195 | |||
196 | MODULE_ALIAS("spi:cyttsp"); | ||
197 | MODULE_LICENSE("GPL"); | ||
198 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); | ||
199 | MODULE_AUTHOR("Cypress"); | ||
200 | MODULE_ALIAS("spi:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 7f8f538a9806..503c7096ed36 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -35,11 +35,11 @@ | |||
35 | #include <linux/input/eeti_ts.h> | 35 | #include <linux/input/eeti_ts.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | 37 | ||
38 | static int flip_x; | 38 | static bool flip_x; |
39 | module_param(flip_x, bool, 0644); | 39 | module_param(flip_x, bool, 0644); |
40 | MODULE_PARM_DESC(flip_x, "flip x coordinate"); | 40 | MODULE_PARM_DESC(flip_x, "flip x coordinate"); |
41 | 41 | ||
42 | static int flip_y; | 42 | static bool flip_y; |
43 | module_param(flip_y, bool, 0644); | 43 | module_param(flip_y, bool, 0644); |
44 | MODULE_PARM_DESC(flip_y, "flip y coordinate"); | 44 | MODULE_PARM_DESC(flip_y, "flip y coordinate"); |
45 | 45 | ||
@@ -320,20 +320,8 @@ static struct i2c_driver eeti_ts_driver = { | |||
320 | .id_table = eeti_ts_id, | 320 | .id_table = eeti_ts_id, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static int __init eeti_ts_init(void) | 323 | module_i2c_driver(eeti_ts_driver); |
324 | { | ||
325 | return i2c_add_driver(&eeti_ts_driver); | ||
326 | } | ||
327 | |||
328 | static void __exit eeti_ts_exit(void) | ||
329 | { | ||
330 | i2c_del_driver(&eeti_ts_driver); | ||
331 | } | ||
332 | 324 | ||
333 | MODULE_DESCRIPTION("EETI Touchscreen driver"); | 325 | MODULE_DESCRIPTION("EETI Touchscreen driver"); |
334 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 326 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
335 | MODULE_LICENSE("GPL"); | 327 | MODULE_LICENSE("GPL"); |
336 | |||
337 | module_init(eeti_ts_init); | ||
338 | module_exit(eeti_ts_exit); | ||
339 | |||
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index eadcc2e83c77..70524dd34f42 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c | |||
@@ -285,18 +285,7 @@ static struct i2c_driver egalax_ts_driver = { | |||
285 | .remove = __devexit_p(egalax_ts_remove), | 285 | .remove = __devexit_p(egalax_ts_remove), |
286 | }; | 286 | }; |
287 | 287 | ||
288 | static int __init egalax_ts_init(void) | 288 | module_i2c_driver(egalax_ts_driver); |
289 | { | ||
290 | return i2c_add_driver(&egalax_ts_driver); | ||
291 | } | ||
292 | |||
293 | static void __exit egalax_ts_exit(void) | ||
294 | { | ||
295 | i2c_del_driver(&egalax_ts_driver); | ||
296 | } | ||
297 | |||
298 | module_init(egalax_ts_init); | ||
299 | module_exit(egalax_ts_exit); | ||
300 | 289 | ||
301 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | 290 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
302 | MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller"); | 291 | MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller"); |
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index 639a6044183d..85cf9bee8018 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c | |||
@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void) | |||
93 | hp680_ts_dev->phys = "hp680_ts/input0"; | 93 | hp680_ts_dev->phys = "hp680_ts/input0"; |
94 | 94 | ||
95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, | 95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, |
96 | 0, MODNAME, 0) < 0) { | 96 | 0, MODNAME, NULL) < 0) { |
97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", | 97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", |
98 | HP680_TS_IRQ); | 98 | HP680_TS_IRQ); |
99 | err = -EBUSY; | 99 | err = -EBUSY; |
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 81e338623944..d13143b68b3e 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c | |||
@@ -40,10 +40,10 @@ MODULE_LICENSE("GPL"); | |||
40 | #define X_AXIS_MAX 2040 | 40 | #define X_AXIS_MAX 2040 |
41 | #define Y_AXIS_MAX 2040 | 41 | #define Y_AXIS_MAX 2040 |
42 | 42 | ||
43 | static int invert_x; | 43 | static bool invert_x; |
44 | module_param(invert_x, bool, 0644); | 44 | module_param(invert_x, bool, 0644); |
45 | MODULE_PARM_DESC(invert_x, "If set, X axis is inverted"); | 45 | MODULE_PARM_DESC(invert_x, "If set, X axis is inverted"); |
46 | static int invert_y; | 46 | static bool invert_y; |
47 | module_param(invert_y, bool, 0644); | 47 | module_param(invert_y, bool, 0644); |
48 | MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted"); | 48 | MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted"); |
49 | 49 | ||
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c new file mode 100644 index 000000000000..c0044175a921 --- /dev/null +++ b/drivers/input/touchscreen/ili210x.c | |||
@@ -0,0 +1,360 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/i2c.h> | ||
3 | #include <linux/interrupt.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/input.h> | ||
6 | #include <linux/input/mt.h> | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/workqueue.h> | ||
9 | #include <linux/input/ili210x.h> | ||
10 | |||
11 | #define MAX_TOUCHES 2 | ||
12 | #define DEFAULT_POLL_PERIOD 20 | ||
13 | |||
14 | /* Touchscreen commands */ | ||
15 | #define REG_TOUCHDATA 0x10 | ||
16 | #define REG_PANEL_INFO 0x20 | ||
17 | #define REG_FIRMWARE_VERSION 0x40 | ||
18 | #define REG_CALIBRATE 0xcc | ||
19 | |||
20 | struct finger { | ||
21 | u8 x_low; | ||
22 | u8 x_high; | ||
23 | u8 y_low; | ||
24 | u8 y_high; | ||
25 | } __packed; | ||
26 | |||
27 | struct touchdata { | ||
28 | u8 status; | ||
29 | struct finger finger[MAX_TOUCHES]; | ||
30 | } __packed; | ||
31 | |||
32 | struct panel_info { | ||
33 | struct finger finger_max; | ||
34 | u8 xchannel_num; | ||
35 | u8 ychannel_num; | ||
36 | } __packed; | ||
37 | |||
38 | struct firmware_version { | ||
39 | u8 id; | ||
40 | u8 major; | ||
41 | u8 minor; | ||
42 | } __packed; | ||
43 | |||
44 | struct ili210x { | ||
45 | struct i2c_client *client; | ||
46 | struct input_dev *input; | ||
47 | bool (*get_pendown_state)(void); | ||
48 | unsigned int poll_period; | ||
49 | struct delayed_work dwork; | ||
50 | }; | ||
51 | |||
52 | static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, | ||
53 | size_t len) | ||
54 | { | ||
55 | struct i2c_msg msg[2] = { | ||
56 | { | ||
57 | .addr = client->addr, | ||
58 | .flags = 0, | ||
59 | .len = 1, | ||
60 | .buf = ®, | ||
61 | }, | ||
62 | { | ||
63 | .addr = client->addr, | ||
64 | .flags = I2C_M_RD, | ||
65 | .len = len, | ||
66 | .buf = buf, | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | if (i2c_transfer(client->adapter, msg, 2) != 2) { | ||
71 | dev_err(&client->dev, "i2c transfer failed\n"); | ||
72 | return -EIO; | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static void ili210x_report_events(struct input_dev *input, | ||
79 | const struct touchdata *touchdata) | ||
80 | { | ||
81 | int i; | ||
82 | bool touch; | ||
83 | unsigned int x, y; | ||
84 | const struct finger *finger; | ||
85 | |||
86 | for (i = 0; i < MAX_TOUCHES; i++) { | ||
87 | input_mt_slot(input, i); | ||
88 | |||
89 | finger = &touchdata->finger[i]; | ||
90 | |||
91 | touch = touchdata->status & (1 << i); | ||
92 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
93 | if (touch) { | ||
94 | x = finger->x_low | (finger->x_high << 8); | ||
95 | y = finger->y_low | (finger->y_high << 8); | ||
96 | |||
97 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
98 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | input_mt_report_pointer_emulation(input, false); | ||
103 | input_sync(input); | ||
104 | } | ||
105 | |||
106 | static bool get_pendown_state(const struct ili210x *priv) | ||
107 | { | ||
108 | bool state = false; | ||
109 | |||
110 | if (priv->get_pendown_state) | ||
111 | state = priv->get_pendown_state(); | ||
112 | |||
113 | return state; | ||
114 | } | ||
115 | |||
116 | static void ili210x_work(struct work_struct *work) | ||
117 | { | ||
118 | struct ili210x *priv = container_of(work, struct ili210x, | ||
119 | dwork.work); | ||
120 | struct i2c_client *client = priv->client; | ||
121 | struct touchdata touchdata; | ||
122 | int error; | ||
123 | |||
124 | error = ili210x_read_reg(client, REG_TOUCHDATA, | ||
125 | &touchdata, sizeof(touchdata)); | ||
126 | if (error) { | ||
127 | dev_err(&client->dev, | ||
128 | "Unable to get touchdata, err = %d\n", error); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | ili210x_report_events(priv->input, &touchdata); | ||
133 | |||
134 | if ((touchdata.status & 0xf3) || get_pendown_state(priv)) | ||
135 | schedule_delayed_work(&priv->dwork, | ||
136 | msecs_to_jiffies(priv->poll_period)); | ||
137 | } | ||
138 | |||
139 | static irqreturn_t ili210x_irq(int irq, void *irq_data) | ||
140 | { | ||
141 | struct ili210x *priv = irq_data; | ||
142 | |||
143 | schedule_delayed_work(&priv->dwork, 0); | ||
144 | |||
145 | return IRQ_HANDLED; | ||
146 | } | ||
147 | |||
148 | static ssize_t ili210x_calibrate(struct device *dev, | ||
149 | struct device_attribute *attr, | ||
150 | const char *buf, size_t count) | ||
151 | { | ||
152 | struct i2c_client *client = to_i2c_client(dev); | ||
153 | struct ili210x *priv = i2c_get_clientdata(client); | ||
154 | unsigned long calibrate; | ||
155 | int rc; | ||
156 | u8 cmd = REG_CALIBRATE; | ||
157 | |||
158 | if (kstrtoul(buf, 10, &calibrate)) | ||
159 | return -EINVAL; | ||
160 | |||
161 | if (calibrate > 1) | ||
162 | return -EINVAL; | ||
163 | |||
164 | if (calibrate) { | ||
165 | rc = i2c_master_send(priv->client, &cmd, sizeof(cmd)); | ||
166 | if (rc != sizeof(cmd)) | ||
167 | return -EIO; | ||
168 | } | ||
169 | |||
170 | return count; | ||
171 | } | ||
172 | static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate); | ||
173 | |||
174 | static struct attribute *ili210x_attributes[] = { | ||
175 | &dev_attr_calibrate.attr, | ||
176 | NULL, | ||
177 | }; | ||
178 | |||
179 | static const struct attribute_group ili210x_attr_group = { | ||
180 | .attrs = ili210x_attributes, | ||
181 | }; | ||
182 | |||
183 | static int __devinit ili210x_i2c_probe(struct i2c_client *client, | ||
184 | const struct i2c_device_id *id) | ||
185 | { | ||
186 | struct device *dev = &client->dev; | ||
187 | const struct ili210x_platform_data *pdata = dev->platform_data; | ||
188 | struct ili210x *priv; | ||
189 | struct input_dev *input; | ||
190 | struct panel_info panel; | ||
191 | struct firmware_version firmware; | ||
192 | int xmax, ymax; | ||
193 | int error; | ||
194 | |||
195 | dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); | ||
196 | |||
197 | if (!pdata) { | ||
198 | dev_err(dev, "No platform data!\n"); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | |||
202 | if (client->irq <= 0) { | ||
203 | dev_err(dev, "No IRQ!\n"); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | /* Get firmware version */ | ||
208 | error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, | ||
209 | &firmware, sizeof(firmware)); | ||
210 | if (error) { | ||
211 | dev_err(dev, "Failed to get firmware version, err: %d\n", | ||
212 | error); | ||
213 | return error; | ||
214 | } | ||
215 | |||
216 | /* get panel info */ | ||
217 | error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel)); | ||
218 | if (error) { | ||
219 | dev_err(dev, "Failed to get panel informations, err: %d\n", | ||
220 | error); | ||
221 | return error; | ||
222 | } | ||
223 | |||
224 | xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8); | ||
225 | ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8); | ||
226 | |||
227 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
228 | input = input_allocate_device(); | ||
229 | if (!priv || !input) { | ||
230 | error = -ENOMEM; | ||
231 | goto err_free_mem; | ||
232 | } | ||
233 | |||
234 | priv->client = client; | ||
235 | priv->input = input; | ||
236 | priv->get_pendown_state = pdata->get_pendown_state; | ||
237 | priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD; | ||
238 | INIT_DELAYED_WORK(&priv->dwork, ili210x_work); | ||
239 | |||
240 | /* Setup input device */ | ||
241 | input->name = "ILI210x Touchscreen"; | ||
242 | input->id.bustype = BUS_I2C; | ||
243 | input->dev.parent = dev; | ||
244 | |||
245 | __set_bit(EV_SYN, input->evbit); | ||
246 | __set_bit(EV_KEY, input->evbit); | ||
247 | __set_bit(EV_ABS, input->evbit); | ||
248 | __set_bit(BTN_TOUCH, input->keybit); | ||
249 | |||
250 | /* Single touch */ | ||
251 | input_set_abs_params(input, ABS_X, 0, xmax, 0, 0); | ||
252 | input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0); | ||
253 | |||
254 | /* Multi touch */ | ||
255 | input_mt_init_slots(input, MAX_TOUCHES); | ||
256 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0); | ||
257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0); | ||
258 | |||
259 | input_set_drvdata(input, priv); | ||
260 | i2c_set_clientdata(client, priv); | ||
261 | |||
262 | error = request_irq(client->irq, ili210x_irq, pdata->irq_flags, | ||
263 | client->name, priv); | ||
264 | if (error) { | ||
265 | dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", | ||
266 | error); | ||
267 | goto err_free_mem; | ||
268 | } | ||
269 | |||
270 | error = sysfs_create_group(&dev->kobj, &ili210x_attr_group); | ||
271 | if (error) { | ||
272 | dev_err(dev, "Unable to create sysfs attributes, err: %d\n", | ||
273 | error); | ||
274 | goto err_free_irq; | ||
275 | } | ||
276 | |||
277 | error = input_register_device(priv->input); | ||
278 | if (error) { | ||
279 | dev_err(dev, "Cannot regiser input device, err: %d\n", error); | ||
280 | goto err_remove_sysfs; | ||
281 | } | ||
282 | |||
283 | device_init_wakeup(&client->dev, 1); | ||
284 | |||
285 | dev_dbg(dev, | ||
286 | "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", | ||
287 | client->irq, firmware.id, firmware.major, firmware.minor); | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | err_remove_sysfs: | ||
292 | sysfs_remove_group(&dev->kobj, &ili210x_attr_group); | ||
293 | err_free_irq: | ||
294 | free_irq(client->irq, priv); | ||
295 | err_free_mem: | ||
296 | input_free_device(input); | ||
297 | kfree(priv); | ||
298 | return error; | ||
299 | } | ||
300 | |||
301 | static int __devexit ili210x_i2c_remove(struct i2c_client *client) | ||
302 | { | ||
303 | struct ili210x *priv = i2c_get_clientdata(client); | ||
304 | |||
305 | sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group); | ||
306 | free_irq(priv->client->irq, priv); | ||
307 | cancel_delayed_work_sync(&priv->dwork); | ||
308 | input_unregister_device(priv->input); | ||
309 | kfree(priv); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #ifdef CONFIG_PM_SLEEP | ||
315 | static int ili210x_i2c_suspend(struct device *dev) | ||
316 | { | ||
317 | struct i2c_client *client = to_i2c_client(dev); | ||
318 | |||
319 | if (device_may_wakeup(&client->dev)) | ||
320 | enable_irq_wake(client->irq); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int ili210x_i2c_resume(struct device *dev) | ||
326 | { | ||
327 | struct i2c_client *client = to_i2c_client(dev); | ||
328 | |||
329 | if (device_may_wakeup(&client->dev)) | ||
330 | disable_irq_wake(client->irq); | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | #endif | ||
335 | |||
336 | static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, | ||
337 | ili210x_i2c_suspend, ili210x_i2c_resume); | ||
338 | |||
339 | static const struct i2c_device_id ili210x_i2c_id[] = { | ||
340 | { "ili210x", 0 }, | ||
341 | { } | ||
342 | }; | ||
343 | MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); | ||
344 | |||
345 | static struct i2c_driver ili210x_ts_driver = { | ||
346 | .driver = { | ||
347 | .name = "ili210x_i2c", | ||
348 | .owner = THIS_MODULE, | ||
349 | .pm = &ili210x_i2c_pm, | ||
350 | }, | ||
351 | .id_table = ili210x_i2c_id, | ||
352 | .probe = ili210x_i2c_probe, | ||
353 | .remove = __devexit_p(ili210x_i2c_remove), | ||
354 | }; | ||
355 | |||
356 | module_i2c_driver(ili210x_ts_driver); | ||
357 | |||
358 | MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>"); | ||
359 | MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver"); | ||
360 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 4627fe55b401..4eab50b856d7 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c | |||
@@ -255,18 +255,7 @@ static struct i2c_driver max11801_ts_driver = { | |||
255 | .remove = __devexit_p(max11801_ts_remove), | 255 | .remove = __devexit_p(max11801_ts_remove), |
256 | }; | 256 | }; |
257 | 257 | ||
258 | static int __init max11801_ts_init(void) | 258 | module_i2c_driver(max11801_ts_driver); |
259 | { | ||
260 | return i2c_add_driver(&max11801_ts_driver); | ||
261 | } | ||
262 | |||
263 | static void __exit max11801_ts_exit(void) | ||
264 | { | ||
265 | i2c_del_driver(&max11801_ts_driver); | ||
266 | } | ||
267 | |||
268 | module_init(max11801_ts_init); | ||
269 | module_exit(max11801_ts_exit); | ||
270 | 259 | ||
271 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); | 260 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); |
272 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); | 261 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); |
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 2d84c80ceb66..b528511861ce 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -302,18 +302,7 @@ static struct i2c_driver mcs5000_ts_driver = { | |||
302 | .id_table = mcs5000_ts_id, | 302 | .id_table = mcs5000_ts_id, |
303 | }; | 303 | }; |
304 | 304 | ||
305 | static int __init mcs5000_ts_init(void) | 305 | module_i2c_driver(mcs5000_ts_driver); |
306 | { | ||
307 | return i2c_add_driver(&mcs5000_ts_driver); | ||
308 | } | ||
309 | |||
310 | static void __exit mcs5000_ts_exit(void) | ||
311 | { | ||
312 | i2c_del_driver(&mcs5000_ts_driver); | ||
313 | } | ||
314 | |||
315 | module_init(mcs5000_ts_init); | ||
316 | module_exit(mcs5000_ts_exit); | ||
317 | 306 | ||
318 | /* Module information */ | 307 | /* Module information */ |
319 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 308 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 5226194aa78e..c038db93e2c3 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
@@ -242,19 +242,8 @@ static struct i2c_driver migor_ts_driver = { | |||
242 | .id_table = migor_ts_id, | 242 | .id_table = migor_ts_id, |
243 | }; | 243 | }; |
244 | 244 | ||
245 | static int __init migor_ts_init(void) | 245 | module_i2c_driver(migor_ts_driver); |
246 | { | ||
247 | return i2c_add_driver(&migor_ts_driver); | ||
248 | } | ||
249 | |||
250 | static void __exit migor_ts_exit(void) | ||
251 | { | ||
252 | i2c_del_driver(&migor_ts_driver); | ||
253 | } | ||
254 | 246 | ||
255 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); | 247 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); |
256 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | 248 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); |
257 | MODULE_LICENSE("GPL"); | 249 | MODULE_LICENSE("GPL"); |
258 | |||
259 | module_init(migor_ts_init); | ||
260 | module_exit(migor_ts_exit); | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index d5ac09a1ee56..72f6ba3a4709 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
@@ -222,17 +222,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = { | |||
222 | .id_table = pixcir_i2c_ts_id, | 222 | .id_table = pixcir_i2c_ts_id, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static int __init pixcir_i2c_ts_init(void) | 225 | module_i2c_driver(pixcir_i2c_ts_driver); |
226 | { | ||
227 | return i2c_add_driver(&pixcir_i2c_ts_driver); | ||
228 | } | ||
229 | module_init(pixcir_i2c_ts_init); | ||
230 | |||
231 | static void __exit pixcir_i2c_ts_exit(void) | ||
232 | { | ||
233 | i2c_del_driver(&pixcir_i2c_ts_driver); | ||
234 | } | ||
235 | module_exit(pixcir_i2c_ts_exit); | ||
236 | 226 | ||
237 | MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); | 227 | MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); |
238 | MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); | 228 | MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 4ab371358b33..cbbf71b22696 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/pm_qos.h> | ||
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <linux/types.h> | 28 | #include <linux/types.h> |
28 | 29 | ||
@@ -46,6 +47,7 @@ struct st1232_ts_data { | |||
46 | struct i2c_client *client; | 47 | struct i2c_client *client; |
47 | struct input_dev *input_dev; | 48 | struct input_dev *input_dev; |
48 | struct st1232_ts_finger finger[MAX_FINGERS]; | 49 | struct st1232_ts_finger finger[MAX_FINGERS]; |
50 | struct dev_pm_qos_request low_latency_req; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static int st1232_ts_read_data(struct st1232_ts_data *ts) | 53 | static int st1232_ts_read_data(struct st1232_ts_data *ts) |
@@ -118,8 +120,17 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | |||
118 | } | 120 | } |
119 | 121 | ||
120 | /* SYN_MT_REPORT only if no contact */ | 122 | /* SYN_MT_REPORT only if no contact */ |
121 | if (!count) | 123 | if (!count) { |
122 | input_mt_sync(input_dev); | 124 | input_mt_sync(input_dev); |
125 | if (ts->low_latency_req.dev) { | ||
126 | dev_pm_qos_remove_request(&ts->low_latency_req); | ||
127 | ts->low_latency_req.dev = NULL; | ||
128 | } | ||
129 | } else if (!ts->low_latency_req.dev) { | ||
130 | /* First contact, request 100 us latency. */ | ||
131 | dev_pm_qos_add_ancestor_request(&ts->client->dev, | ||
132 | &ts->low_latency_req, 100); | ||
133 | } | ||
123 | 134 | ||
124 | /* SYN_REPORT */ | 135 | /* SYN_REPORT */ |
125 | input_sync(input_dev); | 136 | input_sync(input_dev); |
@@ -257,17 +268,7 @@ static struct i2c_driver st1232_ts_driver = { | |||
257 | }, | 268 | }, |
258 | }; | 269 | }; |
259 | 270 | ||
260 | static int __init st1232_ts_init(void) | 271 | module_i2c_driver(st1232_ts_driver); |
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 | ||
272 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | 273 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); |
273 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); | 274 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); |
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c new file mode 100644 index 000000000000..d229c741d544 --- /dev/null +++ b/drivers/input/touchscreen/ti_tscadc.c | |||
@@ -0,0 +1,486 @@ | |||
1 | /* | ||
2 | * TI Touch Screen driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/input/ti_tscadc.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #define REG_IRQEOI 0x020 | ||
31 | #define REG_RAWIRQSTATUS 0x024 | ||
32 | #define REG_IRQSTATUS 0x028 | ||
33 | #define REG_IRQENABLE 0x02C | ||
34 | #define REG_IRQWAKEUP 0x034 | ||
35 | #define REG_CTRL 0x040 | ||
36 | #define REG_ADCFSM 0x044 | ||
37 | #define REG_CLKDIV 0x04C | ||
38 | #define REG_SE 0x054 | ||
39 | #define REG_IDLECONFIG 0x058 | ||
40 | #define REG_CHARGECONFIG 0x05C | ||
41 | #define REG_CHARGEDELAY 0x060 | ||
42 | #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) | ||
43 | #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) | ||
44 | #define REG_STEPCONFIG13 0x0C4 | ||
45 | #define REG_STEPDELAY13 0x0C8 | ||
46 | #define REG_STEPCONFIG14 0x0CC | ||
47 | #define REG_STEPDELAY14 0x0D0 | ||
48 | #define REG_FIFO0CNT 0xE4 | ||
49 | #define REG_FIFO1THR 0xF4 | ||
50 | #define REG_FIFO0 0x100 | ||
51 | #define REG_FIFO1 0x200 | ||
52 | |||
53 | /* Register Bitfields */ | ||
54 | #define IRQWKUP_ENB BIT(0) | ||
55 | #define STPENB_STEPENB 0x7FFF | ||
56 | #define IRQENB_FIFO1THRES BIT(5) | ||
57 | #define IRQENB_PENUP BIT(9) | ||
58 | #define STEPCONFIG_MODE_HWSYNC 0x2 | ||
59 | #define STEPCONFIG_SAMPLES_AVG (1 << 4) | ||
60 | #define STEPCONFIG_XPP (1 << 5) | ||
61 | #define STEPCONFIG_XNN (1 << 6) | ||
62 | #define STEPCONFIG_YPP (1 << 7) | ||
63 | #define STEPCONFIG_YNN (1 << 8) | ||
64 | #define STEPCONFIG_XNP (1 << 9) | ||
65 | #define STEPCONFIG_YPN (1 << 10) | ||
66 | #define STEPCONFIG_INM (1 << 18) | ||
67 | #define STEPCONFIG_INP (1 << 20) | ||
68 | #define STEPCONFIG_INP_5 (1 << 21) | ||
69 | #define STEPCONFIG_FIFO1 (1 << 26) | ||
70 | #define STEPCONFIG_OPENDLY 0xff | ||
71 | #define STEPCONFIG_Z1 (3 << 19) | ||
72 | #define STEPIDLE_INP (1 << 22) | ||
73 | #define STEPCHARGE_RFP (1 << 12) | ||
74 | #define STEPCHARGE_INM (1 << 15) | ||
75 | #define STEPCHARGE_INP (1 << 19) | ||
76 | #define STEPCHARGE_RFM (1 << 23) | ||
77 | #define STEPCHARGE_DELAY 0x1 | ||
78 | #define CNTRLREG_TSCSSENB (1 << 0) | ||
79 | #define CNTRLREG_STEPID (1 << 1) | ||
80 | #define CNTRLREG_STEPCONFIGWRT (1 << 2) | ||
81 | #define CNTRLREG_4WIRE (1 << 5) | ||
82 | #define CNTRLREG_5WIRE (1 << 6) | ||
83 | #define CNTRLREG_8WIRE (3 << 5) | ||
84 | #define CNTRLREG_TSCENB (1 << 7) | ||
85 | #define ADCFSM_STEPID 0x10 | ||
86 | |||
87 | #define SEQ_SETTLE 275 | ||
88 | #define ADC_CLK 3000000 | ||
89 | #define MAX_12BIT ((1 << 12) - 1) | ||
90 | #define TSCADC_DELTA_X 15 | ||
91 | #define TSCADC_DELTA_Y 15 | ||
92 | |||
93 | struct tscadc { | ||
94 | struct input_dev *input; | ||
95 | struct clk *tsc_ick; | ||
96 | void __iomem *tsc_base; | ||
97 | unsigned int irq; | ||
98 | unsigned int wires; | ||
99 | unsigned int x_plate_resistance; | ||
100 | bool pen_down; | ||
101 | }; | ||
102 | |||
103 | static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg) | ||
104 | { | ||
105 | return readl(ts->tsc_base + reg); | ||
106 | } | ||
107 | |||
108 | static void tscadc_writel(struct tscadc *tsc, unsigned int reg, | ||
109 | unsigned int val) | ||
110 | { | ||
111 | writel(val, tsc->tsc_base + reg); | ||
112 | } | ||
113 | |||
114 | static void tscadc_step_config(struct tscadc *ts_dev) | ||
115 | { | ||
116 | unsigned int config; | ||
117 | int i; | ||
118 | |||
119 | /* Configure the Step registers */ | ||
120 | |||
121 | config = STEPCONFIG_MODE_HWSYNC | | ||
122 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP; | ||
123 | switch (ts_dev->wires) { | ||
124 | case 4: | ||
125 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
126 | break; | ||
127 | case 5: | ||
128 | config |= STEPCONFIG_YNN | | ||
129 | STEPCONFIG_INP_5 | STEPCONFIG_XNN | | ||
130 | STEPCONFIG_YPP; | ||
131 | break; | ||
132 | case 8: | ||
133 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | for (i = 1; i < 7; i++) { | ||
138 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
139 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
140 | } | ||
141 | |||
142 | config = 0; | ||
143 | config = STEPCONFIG_MODE_HWSYNC | | ||
144 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN | | ||
145 | STEPCONFIG_INM | STEPCONFIG_FIFO1; | ||
146 | switch (ts_dev->wires) { | ||
147 | case 4: | ||
148 | config |= STEPCONFIG_YPP; | ||
149 | break; | ||
150 | case 5: | ||
151 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 | | ||
152 | STEPCONFIG_XNP | STEPCONFIG_YPN; | ||
153 | break; | ||
154 | case 8: | ||
155 | config |= STEPCONFIG_YPP; | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | for (i = 7; i < 13; i++) { | ||
160 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
161 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
162 | } | ||
163 | |||
164 | config = 0; | ||
165 | /* Charge step configuration */ | ||
166 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | ||
167 | STEPCHARGE_RFP | STEPCHARGE_RFM | | ||
168 | STEPCHARGE_INM | STEPCHARGE_INP; | ||
169 | |||
170 | tscadc_writel(ts_dev, REG_CHARGECONFIG, config); | ||
171 | tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY); | ||
172 | |||
173 | config = 0; | ||
174 | /* Configure to calculate pressure */ | ||
175 | config = STEPCONFIG_MODE_HWSYNC | | ||
176 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP | | ||
177 | STEPCONFIG_XNN | STEPCONFIG_INM; | ||
178 | tscadc_writel(ts_dev, REG_STEPCONFIG13, config); | ||
179 | tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY); | ||
180 | |||
181 | config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1; | ||
182 | tscadc_writel(ts_dev, REG_STEPCONFIG14, config); | ||
183 | tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY); | ||
184 | |||
185 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
186 | } | ||
187 | |||
188 | static void tscadc_idle_config(struct tscadc *ts_config) | ||
189 | { | ||
190 | unsigned int idleconfig; | ||
191 | |||
192 | idleconfig = STEPCONFIG_YNN | | ||
193 | STEPCONFIG_INM | | ||
194 | STEPCONFIG_YPN | STEPIDLE_INP; | ||
195 | tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig); | ||
196 | } | ||
197 | |||
198 | static void tscadc_read_coordinates(struct tscadc *ts_dev, | ||
199 | unsigned int *x, unsigned int *y) | ||
200 | { | ||
201 | unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT); | ||
202 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | ||
203 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | ||
204 | unsigned int read, diff; | ||
205 | unsigned int i; | ||
206 | |||
207 | /* | ||
208 | * Delta filter is used to remove large variations in sampled | ||
209 | * values from ADC. The filter tries to predict where the next | ||
210 | * coordinate could be. This is done by taking a previous | ||
211 | * coordinate and subtracting it form current one. Further the | ||
212 | * algorithm compares the difference with that of a present value, | ||
213 | * if true the value is reported to the sub system. | ||
214 | */ | ||
215 | for (i = 0; i < fifocount - 1; i++) { | ||
216 | read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
217 | diff = abs(read - prev_val_x); | ||
218 | if (diff < prev_diff_x) { | ||
219 | prev_diff_x = diff; | ||
220 | *x = read; | ||
221 | } | ||
222 | prev_val_x = read; | ||
223 | |||
224 | read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
225 | diff = abs(read - prev_val_y); | ||
226 | if (diff < prev_diff_y) { | ||
227 | prev_diff_y = diff; | ||
228 | *y = read; | ||
229 | } | ||
230 | prev_val_y = read; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static irqreturn_t tscadc_irq(int irq, void *dev) | ||
235 | { | ||
236 | struct tscadc *ts_dev = dev; | ||
237 | struct input_dev *input_dev = ts_dev->input; | ||
238 | unsigned int status, irqclr = 0; | ||
239 | unsigned int x = 0, y = 0; | ||
240 | unsigned int z1, z2, z; | ||
241 | unsigned int fsm; | ||
242 | |||
243 | status = tscadc_readl(ts_dev, REG_IRQSTATUS); | ||
244 | if (status & IRQENB_FIFO1THRES) { | ||
245 | tscadc_read_coordinates(ts_dev, &x, &y); | ||
246 | |||
247 | z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
248 | z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
249 | |||
250 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | ||
251 | /* | ||
252 | * Calculate pressure using formula | ||
253 | * Resistance(touch) = x plate resistance * | ||
254 | * x postion/4096 * ((z2 / z1) - 1) | ||
255 | */ | ||
256 | z = z2 - z1; | ||
257 | z *= x; | ||
258 | z *= ts_dev->x_plate_resistance; | ||
259 | z /= z1; | ||
260 | z = (z + 2047) >> 12; | ||
261 | |||
262 | if (z <= MAX_12BIT) { | ||
263 | input_report_abs(input_dev, ABS_X, x); | ||
264 | input_report_abs(input_dev, ABS_Y, y); | ||
265 | input_report_abs(input_dev, ABS_PRESSURE, z); | ||
266 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
267 | input_sync(input_dev); | ||
268 | } | ||
269 | } | ||
270 | irqclr |= IRQENB_FIFO1THRES; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Time for sequencer to settle, to read | ||
275 | * correct state of the sequencer. | ||
276 | */ | ||
277 | udelay(SEQ_SETTLE); | ||
278 | |||
279 | status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS); | ||
280 | if (status & IRQENB_PENUP) { | ||
281 | /* Pen up event */ | ||
282 | fsm = tscadc_readl(ts_dev, REG_ADCFSM); | ||
283 | if (fsm == ADCFSM_STEPID) { | ||
284 | ts_dev->pen_down = false; | ||
285 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
286 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
287 | input_sync(input_dev); | ||
288 | } else { | ||
289 | ts_dev->pen_down = true; | ||
290 | } | ||
291 | irqclr |= IRQENB_PENUP; | ||
292 | } | ||
293 | |||
294 | tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
295 | /* check pending interrupts */ | ||
296 | tscadc_writel(ts_dev, REG_IRQEOI, 0x0); | ||
297 | |||
298 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
299 | return IRQ_HANDLED; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * The functions for inserting/removing driver as a module. | ||
304 | */ | ||
305 | |||
306 | static int __devinit tscadc_probe(struct platform_device *pdev) | ||
307 | { | ||
308 | const struct tsc_data *pdata = pdev->dev.platform_data; | ||
309 | struct resource *res; | ||
310 | struct tscadc *ts_dev; | ||
311 | struct input_dev *input_dev; | ||
312 | struct clk *clk; | ||
313 | int err; | ||
314 | int clk_value, ctrl, irq; | ||
315 | |||
316 | if (!pdata) { | ||
317 | dev_err(&pdev->dev, "missing platform data.\n"); | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
322 | if (!res) { | ||
323 | dev_err(&pdev->dev, "no memory resource defined.\n"); | ||
324 | return -EINVAL; | ||
325 | } | ||
326 | |||
327 | irq = platform_get_irq(pdev, 0); | ||
328 | if (irq < 0) { | ||
329 | dev_err(&pdev->dev, "no irq ID is specified.\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | /* Allocate memory for device */ | ||
334 | ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL); | ||
335 | input_dev = input_allocate_device(); | ||
336 | if (!ts_dev || !input_dev) { | ||
337 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | ||
338 | err = -ENOMEM; | ||
339 | goto err_free_mem; | ||
340 | } | ||
341 | |||
342 | ts_dev->input = input_dev; | ||
343 | ts_dev->irq = irq; | ||
344 | ts_dev->wires = pdata->wires; | ||
345 | ts_dev->x_plate_resistance = pdata->x_plate_resistance; | ||
346 | |||
347 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
348 | if (!res) { | ||
349 | dev_err(&pdev->dev, "failed to reserve registers.\n"); | ||
350 | err = -EBUSY; | ||
351 | goto err_free_mem; | ||
352 | } | ||
353 | |||
354 | ts_dev->tsc_base = ioremap(res->start, resource_size(res)); | ||
355 | if (!ts_dev->tsc_base) { | ||
356 | dev_err(&pdev->dev, "failed to map registers.\n"); | ||
357 | err = -ENOMEM; | ||
358 | goto err_release_mem_region; | ||
359 | } | ||
360 | |||
361 | err = request_irq(ts_dev->irq, tscadc_irq, | ||
362 | 0, pdev->dev.driver->name, ts_dev); | ||
363 | if (err) { | ||
364 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | ||
365 | goto err_unmap_regs; | ||
366 | } | ||
367 | |||
368 | ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick"); | ||
369 | if (IS_ERR(ts_dev->tsc_ick)) { | ||
370 | dev_err(&pdev->dev, "failed to get TSC ick\n"); | ||
371 | goto err_free_irq; | ||
372 | } | ||
373 | clk_enable(ts_dev->tsc_ick); | ||
374 | |||
375 | clk = clk_get(&pdev->dev, "adc_tsc_fck"); | ||
376 | if (IS_ERR(clk)) { | ||
377 | dev_err(&pdev->dev, "failed to get TSC fck\n"); | ||
378 | err = PTR_ERR(clk); | ||
379 | goto err_disable_clk; | ||
380 | } | ||
381 | |||
382 | clk_value = clk_get_rate(clk) / ADC_CLK; | ||
383 | clk_put(clk); | ||
384 | |||
385 | if (clk_value < 7) { | ||
386 | dev_err(&pdev->dev, "clock input less than min clock requirement\n"); | ||
387 | goto err_disable_clk; | ||
388 | } | ||
389 | /* CLKDIV needs to be configured to the value minus 1 */ | ||
390 | tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1); | ||
391 | |||
392 | /* Enable wake-up of the SoC using touchscreen */ | ||
393 | tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); | ||
394 | |||
395 | ctrl = CNTRLREG_STEPCONFIGWRT | | ||
396 | CNTRLREG_TSCENB | | ||
397 | CNTRLREG_STEPID; | ||
398 | switch (ts_dev->wires) { | ||
399 | case 4: | ||
400 | ctrl |= CNTRLREG_4WIRE; | ||
401 | break; | ||
402 | case 5: | ||
403 | ctrl |= CNTRLREG_5WIRE; | ||
404 | break; | ||
405 | case 8: | ||
406 | ctrl |= CNTRLREG_8WIRE; | ||
407 | break; | ||
408 | } | ||
409 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
410 | |||
411 | tscadc_idle_config(ts_dev); | ||
412 | tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); | ||
413 | tscadc_step_config(ts_dev); | ||
414 | tscadc_writel(ts_dev, REG_FIFO1THR, 6); | ||
415 | |||
416 | ctrl |= CNTRLREG_TSCSSENB; | ||
417 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
418 | |||
419 | input_dev->name = "ti-tsc-adc"; | ||
420 | input_dev->dev.parent = &pdev->dev; | ||
421 | |||
422 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
423 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
424 | |||
425 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
426 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
427 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | ||
428 | |||
429 | /* register to the input system */ | ||
430 | err = input_register_device(input_dev); | ||
431 | if (err) | ||
432 | goto err_disable_clk; | ||
433 | |||
434 | platform_set_drvdata(pdev, ts_dev); | ||
435 | return 0; | ||
436 | |||
437 | err_disable_clk: | ||
438 | clk_disable(ts_dev->tsc_ick); | ||
439 | clk_put(ts_dev->tsc_ick); | ||
440 | err_free_irq: | ||
441 | free_irq(ts_dev->irq, ts_dev); | ||
442 | err_unmap_regs: | ||
443 | iounmap(ts_dev->tsc_base); | ||
444 | err_release_mem_region: | ||
445 | release_mem_region(res->start, resource_size(res)); | ||
446 | err_free_mem: | ||
447 | input_free_device(input_dev); | ||
448 | kfree(ts_dev); | ||
449 | return err; | ||
450 | } | ||
451 | |||
452 | static int __devexit tscadc_remove(struct platform_device *pdev) | ||
453 | { | ||
454 | struct tscadc *ts_dev = platform_get_drvdata(pdev); | ||
455 | struct resource *res; | ||
456 | |||
457 | free_irq(ts_dev->irq, ts_dev); | ||
458 | |||
459 | input_unregister_device(ts_dev->input); | ||
460 | |||
461 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
462 | iounmap(ts_dev->tsc_base); | ||
463 | release_mem_region(res->start, resource_size(res)); | ||
464 | |||
465 | clk_disable(ts_dev->tsc_ick); | ||
466 | clk_put(ts_dev->tsc_ick); | ||
467 | |||
468 | kfree(ts_dev); | ||
469 | |||
470 | platform_set_drvdata(pdev, NULL); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static struct platform_driver ti_tsc_driver = { | ||
475 | .probe = tscadc_probe, | ||
476 | .remove = __devexit_p(tscadc_remove), | ||
477 | .driver = { | ||
478 | .name = "tsc", | ||
479 | .owner = THIS_MODULE, | ||
480 | }, | ||
481 | }; | ||
482 | module_platform_driver(ti_tsc_driver); | ||
483 | |||
484 | MODULE_DESCRIPTION("TI touchscreen controller driver"); | ||
485 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | ||
486 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index cbf0ff322676..b6adeaee9cc5 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
@@ -450,13 +450,13 @@ static struct attribute *tsc2005_attrs[] = { | |||
450 | NULL | 450 | NULL |
451 | }; | 451 | }; |
452 | 452 | ||
453 | static mode_t tsc2005_attr_is_visible(struct kobject *kobj, | 453 | static umode_t tsc2005_attr_is_visible(struct kobject *kobj, |
454 | struct attribute *attr, int n) | 454 | struct attribute *attr, int n) |
455 | { | 455 | { |
456 | struct device *dev = container_of(kobj, struct device, kobj); | 456 | struct device *dev = container_of(kobj, struct device, kobj); |
457 | struct spi_device *spi = to_spi_device(dev); | 457 | struct spi_device *spi = to_spi_device(dev); |
458 | struct tsc2005 *ts = spi_get_drvdata(spi); | 458 | struct tsc2005 *ts = spi_get_drvdata(spi); |
459 | mode_t mode = attr->mode; | 459 | umode_t mode = attr->mode; |
460 | 460 | ||
461 | if (attr == &dev_attr_selftest.attr) { | 461 | if (attr == &dev_attr_selftest.attr) { |
462 | if (!ts->set_reset) | 462 | if (!ts->set_reset) |
@@ -747,17 +747,7 @@ static struct spi_driver tsc2005_driver = { | |||
747 | .remove = __devexit_p(tsc2005_remove), | 747 | .remove = __devexit_p(tsc2005_remove), |
748 | }; | 748 | }; |
749 | 749 | ||
750 | static int __init tsc2005_init(void) | 750 | module_spi_driver(tsc2005_driver); |
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 | 751 | ||
762 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); | 752 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); |
763 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); | 753 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 1f674cb6c55b..1473d2382afd 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -399,18 +399,7 @@ static struct i2c_driver tsc2007_driver = { | |||
399 | .remove = __devexit_p(tsc2007_remove), | 399 | .remove = __devexit_p(tsc2007_remove), |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static int __init tsc2007_init(void) | 402 | module_i2c_driver(tsc2007_driver); |
403 | { | ||
404 | return i2c_add_driver(&tsc2007_driver); | ||
405 | } | ||
406 | |||
407 | static void __exit tsc2007_exit(void) | ||
408 | { | ||
409 | i2c_del_driver(&tsc2007_driver); | ||
410 | } | ||
411 | |||
412 | module_init(tsc2007_init); | ||
413 | module_exit(tsc2007_exit); | ||
414 | 403 | ||
415 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); | 404 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); |
416 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); | 405 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index d2b57536feea..46e83ad53f43 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define UCB1400_TS_POLL_PERIOD 10 /* ms */ | 31 | #define UCB1400_TS_POLL_PERIOD 10 /* ms */ |
32 | 32 | ||
33 | static int adcsync; | 33 | static bool adcsync; |
34 | static int ts_delay = 55; /* us */ | 34 | static int ts_delay = 55; /* us */ |
35 | static int ts_delay_pressure; /* us */ | 35 | static int ts_delay_pressure; /* us */ |
36 | 36 | ||
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 9dbd8b4d9a6e..22cd96f58c99 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * - Zytronic capacitive touchscreen | 17 | * - Zytronic capacitive touchscreen |
18 | * - NEXIO/iNexio | 18 | * - NEXIO/iNexio |
19 | * - Elo TouchSystems 2700 IntelliTouch | 19 | * - Elo TouchSystems 2700 IntelliTouch |
20 | * - EasyTouch USB Dual/Multi touch controller from Data Modul | ||
20 | * | 21 | * |
21 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 22 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
22 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 23 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -60,11 +61,11 @@ | |||
60 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" | 61 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" |
61 | #define DRIVER_DESC "USB Touchscreen Driver" | 62 | #define DRIVER_DESC "USB Touchscreen Driver" |
62 | 63 | ||
63 | static int swap_xy; | 64 | static bool swap_xy; |
64 | module_param(swap_xy, bool, 0644); | 65 | module_param(swap_xy, bool, 0644); |
65 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 66 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); |
66 | 67 | ||
67 | static int hwcalib_xy; | 68 | static bool hwcalib_xy; |
68 | module_param(hwcalib_xy, bool, 0644); | 69 | module_param(hwcalib_xy, bool, 0644); |
69 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | 70 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); |
70 | 71 | ||
@@ -140,6 +141,7 @@ enum { | |||
140 | DEVTYPE_TC45USB, | 141 | DEVTYPE_TC45USB, |
141 | DEVTYPE_NEXIO, | 142 | DEVTYPE_NEXIO, |
142 | DEVTYPE_ELO, | 143 | DEVTYPE_ELO, |
144 | DEVTYPE_ETOUCH, | ||
143 | }; | 145 | }; |
144 | 146 | ||
145 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 147 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
@@ -245,6 +247,10 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
245 | {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, | 247 | {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, |
246 | #endif | 248 | #endif |
247 | 249 | ||
250 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
251 | {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, | ||
252 | #endif | ||
253 | |||
248 | {} | 254 | {} |
249 | }; | 255 | }; |
250 | 256 | ||
@@ -326,6 +332,51 @@ static int egalax_get_pkt_len(unsigned char *buf, int len) | |||
326 | } | 332 | } |
327 | #endif | 333 | #endif |
328 | 334 | ||
335 | /***************************************************************************** | ||
336 | * EasyTouch part | ||
337 | */ | ||
338 | |||
339 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
340 | |||
341 | #ifndef MULTI_PACKET | ||
342 | #define MULTI_PACKET | ||
343 | #endif | ||
344 | |||
345 | #define ETOUCH_PKT_TYPE_MASK 0xFE | ||
346 | #define ETOUCH_PKT_TYPE_REPT 0x80 | ||
347 | #define ETOUCH_PKT_TYPE_REPT2 0xB0 | ||
348 | #define ETOUCH_PKT_TYPE_DIAG 0x0A | ||
349 | |||
350 | static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
351 | { | ||
352 | if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && | ||
353 | (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) | ||
354 | return 0; | ||
355 | |||
356 | dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); | ||
357 | dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); | ||
358 | dev->touch = pkt[0] & 0x01; | ||
359 | |||
360 | return 1; | ||
361 | } | ||
362 | |||
363 | static int etouch_get_pkt_len(unsigned char *buf, int len) | ||
364 | { | ||
365 | switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { | ||
366 | case ETOUCH_PKT_TYPE_REPT: | ||
367 | case ETOUCH_PKT_TYPE_REPT2: | ||
368 | return 5; | ||
369 | |||
370 | case ETOUCH_PKT_TYPE_DIAG: | ||
371 | if (len < 2) | ||
372 | return -1; | ||
373 | |||
374 | return buf[1] + 2; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | #endif | ||
329 | 380 | ||
330 | /***************************************************************************** | 381 | /***************************************************************************** |
331 | * PanJit Part | 382 | * PanJit Part |
@@ -1175,6 +1226,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1175 | .exit = nexio_exit, | 1226 | .exit = nexio_exit, |
1176 | }, | 1227 | }, |
1177 | #endif | 1228 | #endif |
1229 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
1230 | [DEVTYPE_ETOUCH] = { | ||
1231 | .min_xc = 0x0, | ||
1232 | .max_xc = 0x07ff, | ||
1233 | .min_yc = 0x0, | ||
1234 | .max_yc = 0x07ff, | ||
1235 | .rept_size = 16, | ||
1236 | .process_pkt = usbtouch_process_multi, | ||
1237 | .get_pkt_len = etouch_get_pkt_len, | ||
1238 | .read_data = etouch_read_data, | ||
1239 | }, | ||
1240 | #endif | ||
1178 | }; | 1241 | }; |
1179 | 1242 | ||
1180 | 1243 | ||
@@ -1616,18 +1679,7 @@ static struct usb_driver usbtouch_driver = { | |||
1616 | .supports_autosuspend = 1, | 1679 | .supports_autosuspend = 1, |
1617 | }; | 1680 | }; |
1618 | 1681 | ||
1619 | static int __init usbtouch_init(void) | 1682 | module_usb_driver(usbtouch_driver); |
1620 | { | ||
1621 | return usb_register(&usbtouch_driver); | ||
1622 | } | ||
1623 | |||
1624 | static void __exit usbtouch_cleanup(void) | ||
1625 | { | ||
1626 | usb_deregister(&usbtouch_driver); | ||
1627 | } | ||
1628 | |||
1629 | module_init(usbtouch_init); | ||
1630 | module_exit(usbtouch_cleanup); | ||
1631 | 1683 | ||
1632 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1684 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1633 | MODULE_DESCRIPTION(DRIVER_DESC); | 1685 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index add6e3b2802f..bf0869a7a78e 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/gpio.h> | ||
25 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
@@ -192,8 +193,8 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev) | |||
192 | else | 193 | else |
193 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); | 194 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); |
194 | 195 | ||
195 | wm->pen_irq = IRQ_GPIO(gpio_touch_irq); | 196 | wm->pen_irq = gpio_to_irq(gpio_touch_irq); |
196 | irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); | 197 | irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); |
197 | 198 | ||
198 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 199 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
199 | WM97XX_GPIO_POL_HIGH, | 200 | WM97XX_GPIO_POL_HIGH, |