aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c121
1 files changed, 40 insertions, 81 deletions
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 2f33a0167644..56dc35c94bb1 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -25,18 +25,16 @@ MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>");
25MODULE_DESCRIPTION(DRIVER_DESC); 25MODULE_DESCRIPTION(DRIVER_DESC);
26MODULE_LICENSE("GPL"); 26MODULE_LICENSE("GPL");
27 27
28/*
29 * Definitions & global arrays.
30 */
31
32#define W8001_MAX_LENGTH 11 28#define W8001_MAX_LENGTH 11
33#define W8001_PACKET_LEN 11 29#define W8001_LEAD_MASK 0x80
34#define W8001_LEAD_MASK 0x80 30#define W8001_LEAD_BYTE 0x80
35#define W8001_LEAD_BYTE 0x80 31#define W8001_TAB_MASK 0x40
36#define W8001_TAB_MASK 0x40 32#define W8001_TAB_BYTE 0x40
37#define W8001_TAB_BYTE 0x40
38 33
39#define W8001_QUERY_PACKET 0x20 34#define W8001_QUERY_PACKET 0x20
35
36#define W8001_CMD_START '1'
37#define W8001_CMD_QUERY '*'
40 38
41struct w8001_coord { 39struct w8001_coord {
42 u8 rdy; 40 u8 rdy;
@@ -57,18 +55,19 @@ struct w8001_coord {
57struct w8001 { 55struct w8001 {
58 struct input_dev *dev; 56 struct input_dev *dev;
59 struct serio *serio; 57 struct serio *serio;
60 struct mutex cmd_mutex;
61 struct completion cmd_done; 58 struct completion cmd_done;
62 int id; 59 int id;
63 int idx; 60 int idx;
64 unsigned char expected_packet; 61 unsigned char response_type;
62 unsigned char response[W8001_MAX_LENGTH];
65 unsigned char data[W8001_MAX_LENGTH]; 63 unsigned char data[W8001_MAX_LENGTH];
66 unsigned char response[W8001_PACKET_LEN];
67 char phys[32]; 64 char phys[32];
68}; 65};
69 66
70static int parse_data(u8 *data, struct w8001_coord *coord) 67static void parse_data(u8 *data, struct w8001_coord *coord)
71{ 68{
69 memset(coord, 0, sizeof(*coord));
70
72 coord->rdy = data[0] & 0x20; 71 coord->rdy = data[0] & 0x20;
73 coord->tsw = data[0] & 0x01; 72 coord->tsw = data[0] & 0x01;
74 coord->f1 = data[0] & 0x02; 73 coord->f1 = data[0] & 0x02;
@@ -87,15 +86,15 @@ static int parse_data(u8 *data, struct w8001_coord *coord)
87 86
88 coord->tilt_x = data[7] & 0x7F; 87 coord->tilt_x = data[7] & 0x7F;
89 coord->tilt_y = data[8] & 0x7F; 88 coord->tilt_y = data[8] & 0x7F;
90
91 return 0;
92} 89}
93 90
94static void w8001_process_data(struct w8001 *w8001, unsigned char data) 91static irqreturn_t w8001_interrupt(struct serio *serio,
92 unsigned char data, unsigned int flags)
95{ 93{
94 struct w8001 *w8001 = serio_get_drvdata(serio);
96 struct input_dev *dev = w8001->dev; 95 struct input_dev *dev = w8001->dev;
97 u8 tmp;
98 struct w8001_coord coord; 96 struct w8001_coord coord;
97 unsigned char tmp;
99 98
100 w8001->data[w8001->idx] = data; 99 w8001->data[w8001->idx] = data;
101 switch (w8001->idx++) { 100 switch (w8001->idx++) {
@@ -105,12 +104,13 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data)
105 w8001->idx = 0; 104 w8001->idx = 0;
106 } 105 }
107 break; 106 break;
107
108 case 8: 108 case 8:
109 tmp = w8001->data[0] & W8001_TAB_MASK; 109 tmp = w8001->data[0] & W8001_TAB_MASK;
110 if (unlikely(tmp == W8001_TAB_BYTE)) 110 if (unlikely(tmp == W8001_TAB_BYTE))
111 break; 111 break;
112
112 w8001->idx = 0; 113 w8001->idx = 0;
113 memset(&coord, 0, sizeof(coord));
114 parse_data(w8001->data, &coord); 114 parse_data(w8001->data, &coord);
115 input_report_abs(dev, ABS_X, coord.x); 115 input_report_abs(dev, ABS_X, coord.x);
116 input_report_abs(dev, ABS_Y, coord.y); 116 input_report_abs(dev, ABS_Y, coord.y);
@@ -118,86 +118,48 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data)
118 input_report_key(dev, BTN_TOUCH, coord.tsw); 118 input_report_key(dev, BTN_TOUCH, coord.tsw);
119 input_sync(dev); 119 input_sync(dev);
120 break; 120 break;
121
121 case 10: 122 case 10:
122 w8001->idx = 0; 123 w8001->idx = 0;
123 memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN); 124 memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH);
124 w8001->expected_packet = W8001_QUERY_PACKET; 125 w8001->response_type = W8001_QUERY_PACKET;
125 complete(&w8001->cmd_done); 126 complete(&w8001->cmd_done);
126 break; 127 break;
127 } 128 }
128}
129
130
131static irqreturn_t w8001_interrupt(struct serio *serio,
132 unsigned char data, unsigned int flags)
133{
134 struct w8001 *w8001 = serio_get_drvdata(serio);
135
136 w8001_process_data(w8001, data);
137 129
138 return IRQ_HANDLED; 130 return IRQ_HANDLED;
139} 131}
140 132
141static int w8001_async_command(struct w8001 *w8001, unsigned char *packet, 133static int w8001_command(struct w8001 *w8001, unsigned char command,
142 int len) 134 bool wait_response)
143{
144 int rc = -1;
145 int i;
146
147 mutex_lock(&w8001->cmd_mutex);
148
149 for (i = 0; i < len; i++) {
150 if (serio_write(w8001->serio, packet[i]))
151 goto out;
152 }
153 rc = 0;
154
155out:
156 mutex_unlock(&w8001->cmd_mutex);
157 return rc;
158}
159
160static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len)
161{ 135{
162 int rc = -1; 136 int rc;
163 int i;
164 137
165 mutex_lock(&w8001->cmd_mutex); 138 w8001->response_type = 0;
166
167 serio_pause_rx(w8001->serio);
168 init_completion(&w8001->cmd_done); 139 init_completion(&w8001->cmd_done);
169 serio_continue_rx(w8001->serio);
170
171 for (i = 0; i < len; i++) {
172 if (serio_write(w8001->serio, packet[i]))
173 goto out;
174 }
175 140
176 wait_for_completion_timeout(&w8001->cmd_done, HZ); 141 rc = serio_write(w8001->serio, command);
142 if (rc == 0 && wait_response) {
177 143
178 if (w8001->expected_packet == W8001_QUERY_PACKET) { 144 wait_for_completion_timeout(&w8001->cmd_done, HZ);
179 /* We are back in reporting mode, the query was ACKed */ 145 if (w8001->response_type != W8001_QUERY_PACKET)
180 memcpy(packet, w8001->response, W8001_PACKET_LEN); 146 rc = -EIO;
181 rc = 0;
182 } 147 }
183 148
184out:
185 mutex_unlock(&w8001->cmd_mutex);
186 return rc; 149 return rc;
187} 150}
188 151
189static int w8001_setup(struct w8001 *w8001) 152static int w8001_setup(struct w8001 *w8001)
190{ 153{
191 struct w8001_coord coord;
192 struct input_dev *dev = w8001->dev; 154 struct input_dev *dev = w8001->dev;
193 unsigned char start[1] = { '1' }; 155 struct w8001_coord coord;
194 unsigned char query[11] = { '*' }; 156 int error;
195 157
196 if (w8001_command(w8001, query, 1)) 158 error = w8001_command(w8001, W8001_CMD_QUERY, true);
197 return -1; 159 if (error)
160 return error;
198 161
199 memset(&coord, 0, sizeof(coord)); 162 parse_data(w8001->response, &coord);
200 parse_data(query, &coord);
201 163
202 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); 164 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
203 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); 165 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
@@ -205,10 +167,7 @@ static int w8001_setup(struct w8001 *w8001)
205 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); 167 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
206 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); 168 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
207 169
208 if (w8001_async_command(w8001, start, 1)) 170 return w8001_command(w8001, W8001_CMD_START, false);
209 return -1;
210
211 return 0;
212} 171}
213 172
214/* 173/*
@@ -249,7 +208,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
249 w8001->serio = serio; 208 w8001->serio = serio;
250 w8001->id = serio->id.id; 209 w8001->id = serio->id.id;
251 w8001->dev = input_dev; 210 w8001->dev = input_dev;
252 mutex_init(&w8001->cmd_mutex);
253 init_completion(&w8001->cmd_done); 211 init_completion(&w8001->cmd_done);
254 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); 212 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
255 213
@@ -269,7 +227,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
269 if (err) 227 if (err)
270 goto fail2; 228 goto fail2;
271 229
272 if (w8001_setup(w8001)) 230 err = w8001_setup(w8001);
231 if (err)
273 goto fail3; 232 goto fail3;
274 233
275 err = input_register_device(w8001->dev); 234 err = input_register_device(w8001->dev);