This source file includes following definitions.
- poll_delay
- wm9712_phy_init
- wm9712_dig_enable
- wm9712_aux_prepare
- wm9712_dig_restore
- is_pden
- wm9712_poll_sample
- wm9712_poll_coord
- wm9712_poll_touch
- wm9712_acc_enable
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/kernel.h>
15 #include <linux/input.h>
16 #include <linux/delay.h>
17 #include <linux/bitops.h>
18 #include <linux/wm97xx.h>
19
20 #define TS_NAME "wm97xx"
21 #define WM9712_VERSION "1.00"
22 #define DEFAULT_PRESSURE 0xb0c0
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 static int rpu = 8;
38 module_param(rpu, int, 0);
39 MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
40
41
42
43
44
45
46
47
48
49
50
51 static int pil;
52 module_param(pil, int, 0);
53 MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
54
55
56
57
58
59
60 static int pressure = DEFAULT_PRESSURE & 0xfff;
61 module_param(pressure, int, 0);
62 MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
63
64
65
66
67
68
69
70
71
72
73
74
75
76 static int delay = 3;
77 module_param(delay, int, 0);
78 MODULE_PARM_DESC(delay, "Set adc sample delay.");
79
80
81
82
83
84
85 static int five_wire;
86 module_param(five_wire, int, 0);
87 MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 static int mask;
103 module_param(mask, int, 0);
104 MODULE_PARM_DESC(mask, "Set adc mask function.");
105
106
107
108
109
110
111
112 static int coord;
113 module_param(coord, int, 0);
114 MODULE_PARM_DESC(coord, "Polling coordinate mode");
115
116
117
118
119 static const int delay_table[] = {
120 21,
121 42,
122 84,
123 167,
124 333,
125 667,
126 1000,
127 1333,
128 2000,
129 2667,
130 3333,
131 4000,
132 4667,
133 5333,
134 6000,
135 0
136 };
137
138
139
140
141
142
143 static inline void poll_delay(int d)
144 {
145 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
146 }
147
148
149
150
151 static void wm9712_phy_init(struct wm97xx *wm)
152 {
153 u16 dig1 = 0;
154 u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
155
156
157 if (rpu) {
158 dig2 &= 0xffc0;
159 dig2 |= WM9712_RPU(rpu);
160 dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms\n",
161 64000 / rpu);
162 }
163
164
165 if (five_wire) {
166 dig2 |= WM9712_45W;
167 dev_dbg(wm->dev, "setting 5-wire touchscreen mode.\n");
168
169 if (pil) {
170 dev_warn(wm->dev, "pressure measurement is not "
171 "supported in 5-wire mode\n");
172 pil = 0;
173 }
174 }
175
176
177 if (pil == 2) {
178 dig2 |= WM9712_PIL;
179 dev_dbg(wm->dev,
180 "setting pressure measurement current to 400uA.\n");
181 } else if (pil)
182 dev_dbg(wm->dev,
183 "setting pressure measurement current to 200uA.\n");
184 if (!pil)
185 pressure = 0;
186
187
188 if (delay < 0 || delay > 15) {
189 dev_dbg(wm->dev, "supplied delay out of range.\n");
190 delay = 4;
191 }
192 dig1 &= 0xff0f;
193 dig1 |= WM97XX_DELAY(delay);
194 dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.\n",
195 delay_table[delay]);
196
197
198 dig2 |= ((mask & 0x3) << 6);
199 if (mask) {
200 u16 reg;
201
202 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
203 wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
204 reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
205 wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
206 }
207
208
209 if (coord)
210 dig2 |= WM9712_WAIT;
211
212 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
213 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
214 }
215
216 static void wm9712_dig_enable(struct wm97xx *wm, int enable)
217 {
218 u16 dig2 = wm->dig[2];
219
220 if (enable) {
221 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
222 dig2 | WM97XX_PRP_DET_DIG);
223 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
224 } else
225 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
226 dig2 & ~WM97XX_PRP_DET_DIG);
227 }
228
229 static void wm9712_aux_prepare(struct wm97xx *wm)
230 {
231 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
232 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
233 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
234 }
235
236 static void wm9712_dig_restore(struct wm97xx *wm)
237 {
238 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
239 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
240 }
241
242 static inline int is_pden(struct wm97xx *wm)
243 {
244 return wm->dig[2] & WM9712_PDEN;
245 }
246
247
248
249
250 static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
251 {
252 int timeout = 5 * delay;
253 bool wants_pen = adcsel & WM97XX_PEN_DOWN;
254
255 if (wants_pen && !wm->pen_probably_down) {
256 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
257 if (!(data & WM97XX_PEN_DOWN))
258 return RC_PENUP;
259 wm->pen_probably_down = 1;
260 }
261
262
263 if (wm->mach_ops && wm->mach_ops->pre_sample)
264 wm->mach_ops->pre_sample(adcsel);
265 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
266 | WM97XX_POLL | WM97XX_DELAY(delay));
267
268
269 poll_delay(delay);
270
271
272 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
273 && timeout) {
274 udelay(AC97_LINK_FRAME);
275 timeout--;
276 }
277
278 if (timeout <= 0) {
279
280 if (is_pden(wm))
281 wm->pen_probably_down = 0;
282 else
283 dev_dbg(wm->dev, "adc sample timeout\n");
284 return RC_PENUP;
285 }
286
287 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
288 if (wm->mach_ops && wm->mach_ops->post_sample)
289 wm->mach_ops->post_sample(adcsel);
290
291
292 if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
293 dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x\n",
294 adcsel & WM97XX_ADCSEL_MASK,
295 *sample & WM97XX_ADCSEL_MASK);
296 return RC_AGAIN;
297 }
298
299 if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
300
301 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
302 if (!(*sample & WM97XX_PEN_DOWN)) {
303 wm->pen_probably_down = 0;
304 return RC_PENUP;
305 }
306 }
307
308 return RC_VALID;
309 }
310
311
312
313
314 static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
315 {
316 int timeout = 5 * delay;
317
318 if (!wm->pen_probably_down) {
319 u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
320 if (!(data_rd & WM97XX_PEN_DOWN))
321 return RC_PENUP;
322 wm->pen_probably_down = 1;
323 }
324
325
326 if (wm->mach_ops && wm->mach_ops->pre_sample)
327 wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
328
329 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
330 WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
331
332
333 poll_delay(delay);
334 data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
335
336 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
337 && timeout) {
338 udelay(AC97_LINK_FRAME);
339 timeout--;
340 }
341
342 if (timeout <= 0) {
343
344 if (is_pden(wm))
345 wm->pen_probably_down = 0;
346 else
347 dev_dbg(wm->dev, "adc sample timeout\n");
348 return RC_PENUP;
349 }
350
351
352 data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
353 if (pil)
354 data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
355 else
356 data->p = DEFAULT_PRESSURE;
357
358 if (wm->mach_ops && wm->mach_ops->post_sample)
359 wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
360
361
362 if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
363 goto err;
364 if (pil && !(data->p & WM97XX_ADCSEL_PRES))
365 goto err;
366
367 if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
368 wm->pen_probably_down = 0;
369 return RC_PENUP;
370 }
371 return RC_VALID;
372 err:
373 return 0;
374 }
375
376
377
378
379 static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
380 {
381 int rc;
382
383 if (coord) {
384 rc = wm9712_poll_coord(wm, data);
385 if (rc != RC_VALID)
386 return rc;
387 } else {
388 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
389 &data->x);
390 if (rc != RC_VALID)
391 return rc;
392
393 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
394 &data->y);
395 if (rc != RC_VALID)
396 return rc;
397
398 if (pil && !five_wire) {
399 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
400 &data->p);
401 if (rc != RC_VALID)
402 return rc;
403 } else
404 data->p = DEFAULT_PRESSURE;
405 }
406 return RC_VALID;
407 }
408
409
410
411
412
413 static int wm9712_acc_enable(struct wm97xx *wm, int enable)
414 {
415 u16 dig1, dig2;
416 int ret = 0;
417
418 dig1 = wm->dig[1];
419 dig2 = wm->dig[2];
420
421 if (enable) {
422
423 if (wm->mach_ops->acc_startup) {
424 ret = wm->mach_ops->acc_startup(wm);
425 if (ret < 0)
426 return ret;
427 }
428 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
429 WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
430 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
431 WM97XX_DELAY(delay) |
432 WM97XX_SLT(wm->acc_slot) |
433 WM97XX_RATE(wm->acc_rate);
434 if (pil)
435 dig1 |= WM97XX_ADCSEL_PRES;
436 dig2 |= WM9712_PDEN;
437 } else {
438 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
439 dig2 &= ~WM9712_PDEN;
440 if (wm->mach_ops->acc_shutdown)
441 wm->mach_ops->acc_shutdown(wm);
442 }
443
444 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
445 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
446
447 return 0;
448 }
449
450 struct wm97xx_codec_drv wm9712_codec = {
451 .id = WM9712_ID2,
452 .name = "wm9712",
453 .poll_sample = wm9712_poll_sample,
454 .poll_touch = wm9712_poll_touch,
455 .acc_enable = wm9712_acc_enable,
456 .phy_init = wm9712_phy_init,
457 .dig_enable = wm9712_dig_enable,
458 .dig_restore = wm9712_dig_restore,
459 .aux_prepare = wm9712_aux_prepare,
460 };
461 EXPORT_SYMBOL_GPL(wm9712_codec);
462
463
464 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
465 MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
466 MODULE_LICENSE("GPL");