diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 12:16:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 12:16:07 -0400 |
commit | d638d4990bfb99998420e78e8fd4607bca5cf8d0 (patch) | |
tree | 8f09b50e65a32403ae0348c2768bc466a9c8b764 /drivers/input/touchscreen | |
parent | 8c6b065b792061c2e471d530127f2348fd9d243d (diff) | |
parent | 5a6eb676d3bc4d7a6feab200a92437b62ad298da (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: appletouch - improve powersaving for Geyser3 devices
Input: lifebook - fix an oops on Panasonic CF-18
Input: document intended meaning of KEY_SWITCHVIDEOMODE
Input: switch to using seq_list_xxx helpers
Input: i8042 - give more trust to PNP data on i386
Input: add driver for Fujitsu serial touchscreens
Input: ads7846 - re-check pendown status before reporting events
Input: ads7846 - introduce sample settling delay
Input: xpad - add support for leds on xbox 360 pad
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 13 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 80 | ||||
-rw-r--r-- | drivers/input/touchscreen/fujitsu_ts.c | 189 |
4 files changed, 282 insertions, 1 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 69371779806a..f929fcdbae2e 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -54,6 +54,19 @@ config TOUCHSCREEN_CORGI | |||
54 | To compile this driver as a module, choose M here: the | 54 | To compile this driver as a module, choose M here: the |
55 | module will be called corgi_ts. | 55 | module will be called corgi_ts. |
56 | 56 | ||
57 | config TOUCHSCREEN_FUJITSU | ||
58 | tristate "Fujitsu serial touchscreen" | ||
59 | select SERIO | ||
60 | help | ||
61 | Say Y here if you have the Fujitsu touchscreen (such as one | ||
62 | installed in Lifebook P series laptop) connected to your | ||
63 | system. | ||
64 | |||
65 | If unsure, say N. | ||
66 | |||
67 | To compile this driver as a module, choose M here: the | ||
68 | module will be called fujitsu-ts. | ||
69 | |||
57 | config TOUCHSCREEN_GUNZE | 70 | config TOUCHSCREEN_GUNZE |
58 | tristate "Gunze AHL-51S touchscreen" | 71 | tristate "Gunze AHL-51S touchscreen" |
59 | select SERIO | 72 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 2f86d6ad06d3..5de8933c4993 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | |||
9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
11 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 11 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
12 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | ||
12 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 13 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
13 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 14 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
14 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | 15 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 1c9069cd3bae..96581d08774f 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -95,7 +95,7 @@ struct ads7846 { | |||
95 | u16 dummy; /* for the pwrdown read */ | 95 | u16 dummy; /* for the pwrdown read */ |
96 | struct ts_event tc; | 96 | struct ts_event tc; |
97 | 97 | ||
98 | struct spi_transfer xfer[10]; | 98 | struct spi_transfer xfer[18]; |
99 | struct spi_message msg[5]; | 99 | struct spi_message msg[5]; |
100 | struct spi_message *last_msg; | 100 | struct spi_message *last_msg; |
101 | int msg_idx; | 101 | int msg_idx; |
@@ -107,6 +107,8 @@ struct ads7846 { | |||
107 | u16 debounce_tol; | 107 | u16 debounce_tol; |
108 | u16 debounce_rep; | 108 | u16 debounce_rep; |
109 | 109 | ||
110 | u16 penirq_recheck_delay_usecs; | ||
111 | |||
110 | spinlock_t lock; | 112 | spinlock_t lock; |
111 | struct hrtimer timer; | 113 | struct hrtimer timer; |
112 | unsigned pendown:1; /* P: lock */ | 114 | unsigned pendown:1; /* P: lock */ |
@@ -553,6 +555,15 @@ static void ads7846_rx(void *ads) | |||
553 | return; | 555 | return; |
554 | } | 556 | } |
555 | 557 | ||
558 | /* Maybe check the pendown state before reporting. This discards | ||
559 | * false readings when the pen is lifted. | ||
560 | */ | ||
561 | if (ts->penirq_recheck_delay_usecs) { | ||
562 | udelay(ts->penirq_recheck_delay_usecs); | ||
563 | if (!ts->get_pendown_state()) | ||
564 | Rt = 0; | ||
565 | } | ||
566 | |||
556 | /* NOTE: We can't rely on the pressure to determine the pen down | 567 | /* NOTE: We can't rely on the pressure to determine the pen down |
557 | * state, even this controller has a pressure sensor. The pressure | 568 | * state, even this controller has a pressure sensor. The pressure |
558 | * value can fluctuate for quite a while after lifting the pen and | 569 | * value can fluctuate for quite a while after lifting the pen and |
@@ -896,6 +907,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
896 | ts->filter = ads7846_no_filter; | 907 | ts->filter = ads7846_no_filter; |
897 | ts->get_pendown_state = pdata->get_pendown_state; | 908 | ts->get_pendown_state = pdata->get_pendown_state; |
898 | 909 | ||
910 | if (pdata->penirq_recheck_delay_usecs) | ||
911 | ts->penirq_recheck_delay_usecs = | ||
912 | pdata->penirq_recheck_delay_usecs; | ||
913 | |||
899 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); | 914 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); |
900 | 915 | ||
901 | input_dev->name = "ADS784x Touchscreen"; | 916 | input_dev->name = "ADS784x Touchscreen"; |
@@ -936,6 +951,24 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
936 | x->len = 2; | 951 | x->len = 2; |
937 | spi_message_add_tail(x, m); | 952 | spi_message_add_tail(x, m); |
938 | 953 | ||
954 | /* the first sample after switching drivers can be low quality; | ||
955 | * optionally discard it, using a second one after the signals | ||
956 | * have had enough time to stabilize. | ||
957 | */ | ||
958 | if (pdata->settle_delay_usecs) { | ||
959 | x->delay_usecs = pdata->settle_delay_usecs; | ||
960 | |||
961 | x++; | ||
962 | x->tx_buf = &ts->read_y; | ||
963 | x->len = 1; | ||
964 | spi_message_add_tail(x, m); | ||
965 | |||
966 | x++; | ||
967 | x->rx_buf = &ts->tc.y; | ||
968 | x->len = 2; | ||
969 | spi_message_add_tail(x, m); | ||
970 | } | ||
971 | |||
939 | m->complete = ads7846_rx_val; | 972 | m->complete = ads7846_rx_val; |
940 | m->context = ts; | 973 | m->context = ts; |
941 | 974 | ||
@@ -954,6 +987,21 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
954 | x->len = 2; | 987 | x->len = 2; |
955 | spi_message_add_tail(x, m); | 988 | spi_message_add_tail(x, m); |
956 | 989 | ||
990 | /* ... maybe discard first sample ... */ | ||
991 | if (pdata->settle_delay_usecs) { | ||
992 | x->delay_usecs = pdata->settle_delay_usecs; | ||
993 | |||
994 | x++; | ||
995 | x->tx_buf = &ts->read_x; | ||
996 | x->len = 1; | ||
997 | spi_message_add_tail(x, m); | ||
998 | |||
999 | x++; | ||
1000 | x->rx_buf = &ts->tc.x; | ||
1001 | x->len = 2; | ||
1002 | spi_message_add_tail(x, m); | ||
1003 | } | ||
1004 | |||
957 | m->complete = ads7846_rx_val; | 1005 | m->complete = ads7846_rx_val; |
958 | m->context = ts; | 1006 | m->context = ts; |
959 | 1007 | ||
@@ -973,6 +1021,21 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
973 | x->len = 2; | 1021 | x->len = 2; |
974 | spi_message_add_tail(x, m); | 1022 | spi_message_add_tail(x, m); |
975 | 1023 | ||
1024 | /* ... maybe discard first sample ... */ | ||
1025 | if (pdata->settle_delay_usecs) { | ||
1026 | x->delay_usecs = pdata->settle_delay_usecs; | ||
1027 | |||
1028 | x++; | ||
1029 | x->tx_buf = &ts->read_z1; | ||
1030 | x->len = 1; | ||
1031 | spi_message_add_tail(x, m); | ||
1032 | |||
1033 | x++; | ||
1034 | x->rx_buf = &ts->tc.z1; | ||
1035 | x->len = 2; | ||
1036 | spi_message_add_tail(x, m); | ||
1037 | } | ||
1038 | |||
976 | m->complete = ads7846_rx_val; | 1039 | m->complete = ads7846_rx_val; |
977 | m->context = ts; | 1040 | m->context = ts; |
978 | 1041 | ||
@@ -990,6 +1053,21 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
990 | x->len = 2; | 1053 | x->len = 2; |
991 | spi_message_add_tail(x, m); | 1054 | spi_message_add_tail(x, m); |
992 | 1055 | ||
1056 | /* ... maybe discard first sample ... */ | ||
1057 | if (pdata->settle_delay_usecs) { | ||
1058 | x->delay_usecs = pdata->settle_delay_usecs; | ||
1059 | |||
1060 | x++; | ||
1061 | x->tx_buf = &ts->read_z2; | ||
1062 | x->len = 1; | ||
1063 | spi_message_add_tail(x, m); | ||
1064 | |||
1065 | x++; | ||
1066 | x->rx_buf = &ts->tc.z2; | ||
1067 | x->len = 2; | ||
1068 | spi_message_add_tail(x, m); | ||
1069 | } | ||
1070 | |||
993 | m->complete = ads7846_rx_val; | 1071 | m->complete = ads7846_rx_val; |
994 | m->context = ts; | 1072 | m->context = ts; |
995 | } | 1073 | } |
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c new file mode 100644 index 000000000000..daf7a4afc935 --- /dev/null +++ b/drivers/input/touchscreen/fujitsu_ts.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * Fujitsu serial touchscreen driver | ||
3 | * | ||
4 | * Copyright (c) Dmitry Torokhov <dtor@mail.ru> | ||
5 | */ | ||
6 | |||
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 version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/serio.h> | ||
19 | #include <linux/init.h> | ||
20 | |||
21 | #define DRIVER_DESC "Fujitsu serial touchscreen driver" | ||
22 | |||
23 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | ||
24 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
25 | MODULE_LICENSE("GPL"); | ||
26 | |||
27 | #define FUJITSU_LENGTH 5 | ||
28 | |||
29 | /* | ||
30 | * Per-touchscreen data. | ||
31 | */ | ||
32 | struct fujitsu { | ||
33 | struct input_dev *dev; | ||
34 | struct serio *serio; | ||
35 | int idx; | ||
36 | unsigned char data[FUJITSU_LENGTH]; | ||
37 | char phys[32]; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Decode serial data (5 bytes per packet) | ||
42 | * First byte | ||
43 | * 1 C 0 0 R S S S | ||
44 | * Where C is 1 while in calibration mode (which we don't use) | ||
45 | * R is 1 when no coordinate corection was done. | ||
46 | * S are button state | ||
47 | */ | ||
48 | static irqreturn_t fujitsu_interrupt(struct serio *serio, | ||
49 | unsigned char data, unsigned int flags) | ||
50 | { | ||
51 | struct fujitsu *fujitsu = serio_get_drvdata(serio); | ||
52 | struct input_dev *dev = fujitsu->dev; | ||
53 | |||
54 | if (fujitsu->idx == 0) { | ||
55 | /* resync skip until start of frame */ | ||
56 | if ((data & 0xf0) != 0x80) | ||
57 | return IRQ_HANDLED; | ||
58 | } else { | ||
59 | /* resync skip garbage */ | ||
60 | if (data & 0x80) { | ||
61 | fujitsu->idx = 0; | ||
62 | return IRQ_HANDLED; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | fujitsu->data[fujitsu->idx++] = data; | ||
67 | if (fujitsu->idx == FUJITSU_LENGTH) { | ||
68 | input_report_abs(dev, ABS_X, | ||
69 | (fujitsu->data[2] << 7) | fujitsu->data[1]); | ||
70 | input_report_abs(dev, ABS_Y, | ||
71 | (fujitsu->data[4] << 7) | fujitsu->data[3]); | ||
72 | input_report_key(dev, BTN_TOUCH, | ||
73 | (fujitsu->data[0] & 0x03) != 2); | ||
74 | input_sync(dev); | ||
75 | fujitsu->idx = 0; | ||
76 | } | ||
77 | |||
78 | return IRQ_HANDLED; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * fujitsu_disconnect() is the opposite of fujitsu_connect() | ||
83 | */ | ||
84 | static void fujitsu_disconnect(struct serio *serio) | ||
85 | { | ||
86 | struct fujitsu *fujitsu = serio_get_drvdata(serio); | ||
87 | |||
88 | input_get_device(fujitsu->dev); | ||
89 | input_unregister_device(fujitsu->dev); | ||
90 | serio_close(serio); | ||
91 | serio_set_drvdata(serio, NULL); | ||
92 | input_put_device(fujitsu->dev); | ||
93 | kfree(fujitsu); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * fujitsu_connect() is the routine that is called when someone adds a | ||
98 | * new serio device that supports the Fujitsu protocol and registers it | ||
99 | * as input device. | ||
100 | */ | ||
101 | static int fujitsu_connect(struct serio *serio, struct serio_driver *drv) | ||
102 | { | ||
103 | struct fujitsu *fujitsu; | ||
104 | struct input_dev *input_dev; | ||
105 | int err; | ||
106 | |||
107 | fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL); | ||
108 | input_dev = input_allocate_device(); | ||
109 | if (!fujitsu || !input_dev) { | ||
110 | err = -ENOMEM; | ||
111 | goto fail1; | ||
112 | } | ||
113 | |||
114 | fujitsu->serio = serio; | ||
115 | fujitsu->dev = input_dev; | ||
116 | snprintf(fujitsu->phys, sizeof(fujitsu->phys), | ||
117 | "%s/input0", serio->phys); | ||
118 | |||
119 | input_dev->name = "Fujitsu Serial Touchscreen"; | ||
120 | input_dev->phys = fujitsu->phys; | ||
121 | input_dev->id.bustype = BUS_RS232; | ||
122 | input_dev->id.vendor = SERIO_FUJITSU; | ||
123 | input_dev->id.product = 0; | ||
124 | input_dev->id.version = 0x0100; | ||
125 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
126 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
127 | |||
128 | input_set_abs_params(input_dev, ABS_X, 0, 4096, 0, 0); | ||
129 | input_set_abs_params(input_dev, ABS_Y, 0, 4096, 0, 0); | ||
130 | serio_set_drvdata(serio, fujitsu); | ||
131 | |||
132 | err = serio_open(serio, drv); | ||
133 | if (err) | ||
134 | goto fail2; | ||
135 | |||
136 | err = input_register_device(fujitsu->dev); | ||
137 | if (err) | ||
138 | goto fail3; | ||
139 | |||
140 | return 0; | ||
141 | |||
142 | fail3: | ||
143 | serio_close(serio); | ||
144 | fail2: | ||
145 | serio_set_drvdata(serio, NULL); | ||
146 | fail1: | ||
147 | input_free_device(input_dev); | ||
148 | kfree(fujitsu); | ||
149 | return err; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * The serio driver structure. | ||
154 | */ | ||
155 | static struct serio_device_id fujitsu_serio_ids[] = { | ||
156 | { | ||
157 | .type = SERIO_RS232, | ||
158 | .proto = SERIO_FUJITSU, | ||
159 | .id = SERIO_ANY, | ||
160 | .extra = SERIO_ANY, | ||
161 | }, | ||
162 | { 0 } | ||
163 | }; | ||
164 | |||
165 | MODULE_DEVICE_TABLE(serio, fujitsu_serio_ids); | ||
166 | |||
167 | static struct serio_driver fujitsu_drv = { | ||
168 | .driver = { | ||
169 | .name = "fujitsu_ts", | ||
170 | }, | ||
171 | .description = DRIVER_DESC, | ||
172 | .id_table = fujitsu_serio_ids, | ||
173 | .interrupt = fujitsu_interrupt, | ||
174 | .connect = fujitsu_connect, | ||
175 | .disconnect = fujitsu_disconnect, | ||
176 | }; | ||
177 | |||
178 | static int __init fujitsu_init(void) | ||
179 | { | ||
180 | return serio_register_driver(&fujitsu_drv); | ||
181 | } | ||
182 | |||
183 | static void __exit fujitsu_exit(void) | ||
184 | { | ||
185 | serio_unregister_driver(&fujitsu_drv); | ||
186 | } | ||
187 | |||
188 | module_init(fujitsu_init); | ||
189 | module_exit(fujitsu_exit); | ||