merge of '7393275c6ccce67cadeb49d4afb3459e56edf8a9'
[vuplus_openembedded] / packages / linux / linux-rp-2.6.24 / tosa / 0033-Add-chip-driver-for-WM9713-touchscreen.patch
1 From 05b2a361eedb5461e902c73ebc6e30f9916b3a8a Mon Sep 17 00:00:00 2001
2 From: Mark Brown <broonie@opensource.wolfsonmicro.com>
3 Date: Sat, 26 Jan 2008 21:14:19 +0300
4 Subject: [PATCH 33/64] Add chip driver for WM9713 touchscreen
5
6 Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
7 Signed-off-by: Graeme Gregory <gg@opensource.wolfsonmicro.com>
8 Signed-off-by: Mike Arthur <mike.arthur@wolfsonmicro.com>
9 Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
10 Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
11 Cc: Stanley Cai <stanley.cai@intel.com>
12 Cc: Rodolfo Giometti <giometti@enneenne.com>
13 Cc: Russell King <rmk@arm.linux.org.uk>
14 Cc: Marc Kleine-Budde <mkl@pengutronix.de>
15 Cc: Ian Molton <spyro@f2s.com>
16 Cc: Vince Sanders <vince@kyllikki.org>
17 Cc: Andrew Zabolotny <zap@homelink.ru>
18 ---
19  drivers/input/touchscreen/wm9713.c |  459 ++++++++++++++++++++++++++++++++++++
20  1 files changed, 459 insertions(+), 0 deletions(-)
21  create mode 100644 drivers/input/touchscreen/wm9713.c
22
23 diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
24 new file mode 100644
25 index 0000000..5067e59
26 --- /dev/null
27 +++ b/drivers/input/touchscreen/wm9713.c
28 @@ -0,0 +1,459 @@
29 +/*
30 + * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
31 + *
32 + * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
33 + * Author: Liam Girdwood
34 + *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
35 + * Parts Copyright : Ian Molton <spyro@f2s.com>
36 + *                   Andrew Zabolotny <zap@homelink.ru>
37 + *                   Russell King <rmk@arm.linux.org.uk>
38 + *
39 + *  This program is free software; you can redistribute  it and/or modify it
40 + *  under  the terms of  the GNU General  Public License as published by the
41 + *  Free Software Foundation;  either version 2 of the  License, or (at your
42 + *  option) any later version.
43 + *
44 + */
45 +
46 +#include <linux/module.h>
47 +#include <linux/moduleparam.h>
48 +#include <linux/version.h>
49 +#include <linux/kernel.h>
50 +#include <linux/input.h>
51 +#include <linux/delay.h>
52 +#include <linux/bitops.h>
53 +#include <linux/wm97xx.h>
54 +
55 +#define TS_NAME                        "wm97xx"
56 +#define WM9713_VERSION         "0.53"
57 +#define DEFAULT_PRESSURE       0xb0c0
58 +
59 +/*
60 + * Module parameters
61 + */
62 +
63 +/*
64 + * Set internal pull up for pen detect.
65 + *
66 + * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
67 + * i.e. pull up resistance = 64k Ohms / rpu.
68 + *
69 + * Adjust this value if you are having problems with pen detect not
70 + * detecting any down event.
71 + */
72 +static int rpu = 8;
73 +module_param(rpu, int, 0);
74 +MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
75 +
76 +/*
77 + * Set current used for pressure measurement.
78 + *
79 + * Set pil = 2 to use 400uA
80 + *     pil = 1 to use 200uA and
81 + *     pil = 0 to disable pressure measurement.
82 + *
83 + * This is used to increase the range of values returned by the adc
84 + * when measureing touchpanel pressure.
85 + */
86 +static int pil;
87 +module_param(pil, int, 0);
88 +MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
89 +
90 +/*
91 + * Set threshold for pressure measurement.
92 + *
93 + * Pen down pressure below threshold is ignored.
94 + */
95 +static int pressure = DEFAULT_PRESSURE & 0xfff;
96 +module_param(pressure, int, 0);
97 +MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
98 +
99 +/*
100 + * Set adc sample delay.
101 + *
102 + * For accurate touchpanel measurements, some settling time may be
103 + * required between the switch matrix applying a voltage across the
104 + * touchpanel plate and the ADC sampling the signal.
105 + *
106 + * This delay can be set by setting delay = n, where n is the array
107 + * position of the delay in the array delay_table below.
108 + * Long delays > 1ms are supported for completeness, but are not
109 + * recommended.
110 + */
111 +static int delay = 4;
112 +module_param(delay, int, 0);
113 +MODULE_PARM_DESC(delay, "Set adc sample delay.");
114 +
115 +/*
116 + * Set adc mask function.
117 + *
118 + * Sources of glitch noise, such as signals driving an LCD display, may feed
119 + * through to the touch screen plates and affect measurement accuracy. In
120 + * order to minimise this, a signal may be applied to the MASK pin to delay or
121 + * synchronise the sampling.
122 + *
123 + * 0 = No delay or sync
124 + * 1 = High on pin stops conversions
125 + * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
126 + * 3 = Edge triggered, edge on pin starts conversion after delay param
127 + */
128 +static int mask;
129 +module_param(mask, int, 0);
130 +MODULE_PARM_DESC(mask, "Set adc mask function.");
131 +
132 +/*
133 + * Coordinate Polling Enable.
134 + *
135 + * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
136 + * for every poll.
137 + */
138 +static int coord;
139 +module_param(coord, int, 0);
140 +MODULE_PARM_DESC(coord, "Polling coordinate mode");
141 +
142 +/*
143 + * ADC sample delay times in uS
144 + */
145 +static const int delay_table[] = {
146 +       21,    /* 1 AC97 Link frames */
147 +       42,    /* 2 */
148 +       84,    /* 4 */
149 +       167,   /* 8 */
150 +       333,   /* 16 */
151 +       667,   /* 32 */
152 +       1000,  /* 48 */
153 +       1333,  /* 64 */
154 +       2000,  /* 96 */
155 +       2667,  /* 128 */
156 +       3333,  /* 160 */
157 +       4000,  /* 192 */
158 +       4667,  /* 224 */
159 +       5333,  /* 256 */
160 +       6000,  /* 288 */
161 +       0      /* No delay, switch matrix always on */
162 +};
163 +
164 +/*
165 + * Delay after issuing a POLL command.
166 + *
167 + * The delay is 3 AC97 link frames + the touchpanel settling delay
168 + */
169 +static inline void poll_delay(int d)
170 +{
171 +       udelay(3 * AC97_LINK_FRAME + delay_table[d]);
172 +}
173 +
174 +/*
175 + * set up the physical settings of the WM9713
176 + */
177 +static void wm9713_phy_init(struct wm97xx *wm)
178 +{
179 +       u16 dig1 = 0, dig2, dig3;
180 +
181 +       /* default values */
182 +       dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
183 +       dig3 = WM9712_RPU(1);
184 +
185 +       /* rpu */
186 +       if (rpu) {
187 +               dig3 &= 0xffc0;
188 +               dig3 |= WM9712_RPU(rpu);
189 +               dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
190 +                        64000 / rpu);
191 +       }
192 +
193 +       /* touchpanel pressure */
194 +       if (pil == 2) {
195 +               dig3 |= WM9712_PIL;
196 +               dev_info(wm->dev,
197 +                        "setting pressure measurement current to 400uA.");
198 +       } else if (pil)
199 +               dev_info(wm->dev,
200 +                        "setting pressure measurement current to 200uA.");
201 +       if (!pil)
202 +               pressure = 0;
203 +
204 +       /* sample settling delay */
205 +       if (delay < 0 || delay > 15) {
206 +               dev_info(wm->dev, "supplied delay out of range.");
207 +               delay = 4;
208 +               dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
209 +                        delay_table[delay]);
210 +       }
211 +       dig2 &= 0xff0f;
212 +       dig2 |= WM97XX_DELAY(delay);
213 +
214 +       /* mask */
215 +       dig3 |= ((mask & 0x3) << 4);
216 +       if (coord)
217 +               dig3 |= WM9713_WAIT;
218 +
219 +       wm->misc = wm97xx_reg_read(wm, 0x5a);
220 +
221 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
222 +       wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
223 +       wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
224 +       wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
225 +}
226 +
227 +static void wm9713_dig_enable(struct wm97xx *wm, int enable)
228 +{
229 +       u16 val;
230 +
231 +       if (enable) {
232 +               val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
233 +               wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
234 +               wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
235 +                                WM97XX_PRP_DET_DIG);
236 +               wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
237 +       } else {
238 +               wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
239 +                                       ~WM97XX_PRP_DET_DIG);
240 +               val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
241 +               wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
242 +       }
243 +}
244 +
245 +static void wm9713_dig_restore(struct wm97xx *wm)
246 +{
247 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
248 +       wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
249 +       wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
250 +}
251 +
252 +static void wm9713_aux_prepare(struct wm97xx *wm)
253 +{
254 +       memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
255 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
256 +       wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
257 +       wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
258 +}
259 +
260 +static inline int is_pden(struct wm97xx *wm)
261 +{
262 +       return wm->dig[2] & WM9713_PDEN;
263 +}
264 +
265 +/*
266 + * Read a sample from the WM9713 adc in polling mode.
267 + */
268 +static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
269 +{
270 +       u16 dig1;
271 +       int timeout = 5 * delay;
272 +
273 +       if (!wm->pen_probably_down) {
274 +               u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
275 +               if (!(data & WM97XX_PEN_DOWN))
276 +                       return RC_PENUP;
277 +               wm->pen_probably_down = 1;
278 +       }
279 +
280 +       /* set up digitiser */
281 +       if (adcsel & 0x8000)
282 +               adcsel = 1 << ((adcsel & 0x7fff) + 3);
283 +
284 +       dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
285 +       dig1 &= ~WM9713_ADCSEL_MASK;
286 +
287 +       if (wm->mach_ops && wm->mach_ops->pre_sample)
288 +               wm->mach_ops->pre_sample(adcsel);
289 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
290 +
291 +       /* wait 3 AC97 time slots + delay for conversion */
292 +       poll_delay(delay);
293 +
294 +       /* wait for POLL to go low */
295 +       while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
296 +               timeout) {
297 +               udelay(AC97_LINK_FRAME);
298 +               timeout--;
299 +       }
300 +
301 +       if (timeout <= 0) {
302 +               /* If PDEN is set, we can get a timeout when pen goes up */
303 +               if (is_pden(wm))
304 +                       wm->pen_probably_down = 0;
305 +               else
306 +                       dev_dbg(wm->dev, "adc sample timeout");
307 +               return RC_PENUP;
308 +       }
309 +
310 +       *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
311 +       if (wm->mach_ops && wm->mach_ops->post_sample)
312 +               wm->mach_ops->post_sample(adcsel);
313 +
314 +       /* check we have correct sample */
315 +       if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
316 +               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
317 +                       *sample & WM97XX_ADCSRC_MASK);
318 +               return RC_PENUP;
319 +       }
320 +
321 +       if (!(*sample & WM97XX_PEN_DOWN)) {
322 +               wm->pen_probably_down = 0;
323 +               return RC_PENUP;
324 +       }
325 +
326 +       return RC_VALID;
327 +}
328 +
329 +/*
330 + * Read a coordinate from the WM9713 adc in polling mode.
331 + */
332 +static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
333 +{
334 +       u16 dig1;
335 +       int timeout = 5 * delay;
336 +
337 +       if (!wm->pen_probably_down) {
338 +               u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
339 +               if (!(data & WM97XX_PEN_DOWN))
340 +                       return RC_PENUP;
341 +               wm->pen_probably_down = 1;
342 +       }
343 +
344 +       /* set up digitiser */
345 +       dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
346 +       dig1 &= ~WM9713_ADCSEL_MASK;
347 +       if (pil)
348 +               dig1 |= WM97XX_ADCSEL_PRES;
349 +
350 +       if (wm->mach_ops && wm->mach_ops->pre_sample)
351 +               wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
352 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1,
353 +                        dig1 | WM9713_POLL | WM9713_COO);
354 +
355 +       /* wait 3 AC97 time slots + delay for conversion */
356 +       poll_delay(delay);
357 +       data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
358 +       /* wait for POLL to go low */
359 +       while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL)
360 +              && timeout) {
361 +               udelay(AC97_LINK_FRAME);
362 +               timeout--;
363 +       }
364 +
365 +       if (timeout <= 0) {
366 +               /* If PDEN is set, we can get a timeout when pen goes up */
367 +               if (is_pden(wm))
368 +                       wm->pen_probably_down = 0;
369 +               else
370 +                       dev_dbg(wm->dev, "adc sample timeout");
371 +               return RC_PENUP;
372 +       }
373 +
374 +       /* read back data */
375 +       data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
376 +       if (pil)
377 +               data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
378 +       else
379 +               data->p = DEFAULT_PRESSURE;
380 +
381 +       if (wm->mach_ops && wm->mach_ops->post_sample)
382 +               wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
383 +
384 +       /* check we have correct sample */
385 +       if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
386 +               goto err;
387 +       if (pil && !(data->p & WM97XX_ADCSEL_PRES))
388 +               goto err;
389 +
390 +       if (!(data->x & WM97XX_PEN_DOWN)) {
391 +               wm->pen_probably_down = 0;
392 +               return RC_PENUP;
393 +       }
394 +       return RC_VALID;
395 +err:
396 +       return RC_PENUP;
397 +}
398 +
399 +/*
400 + * Sample the WM9713 touchscreen in polling mode
401 + */
402 +static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
403 +{
404 +       int rc;
405 +
406 +       if (coord) {
407 +               rc = wm9713_poll_coord(wm, data);
408 +               if (rc != RC_VALID)
409 +                       return rc;
410 +       } else {
411 +               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
412 +               if (rc != RC_VALID)
413 +                       return rc;
414 +               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
415 +               if (rc != RC_VALID)
416 +                       return rc;
417 +               if (pil) {
418 +                       rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
419 +                                               &data->p);
420 +                       if (rc != RC_VALID)
421 +                               return rc;
422 +               } else
423 +                       data->p = DEFAULT_PRESSURE;
424 +       }
425 +       return RC_VALID;
426 +}
427 +
428 +/*
429 + * Enable WM9713 continuous mode, i.e. touch data is streamed across
430 + * an AC97 slot
431 + */
432 +static int wm9713_acc_enable(struct wm97xx *wm, int enable)
433 +{
434 +       u16 dig1, dig2, dig3;
435 +       int ret = 0;
436 +
437 +       dig1 = wm->dig[0];
438 +       dig2 = wm->dig[1];
439 +       dig3 = wm->dig[2];
440 +
441 +       if (enable) {
442 +               /* continous mode */
443 +               if (wm->mach_ops->acc_startup &&
444 +                       (ret = wm->mach_ops->acc_startup(wm)) < 0)
445 +                       return ret;
446 +
447 +               dig1 &= ~WM9713_ADCSEL_MASK;
448 +               dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X |
449 +                       WM9713_ADCSEL_Y;
450 +               if (pil)
451 +                       dig1 |= WM9713_ADCSEL_PRES;
452 +               dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK  |
453 +                       WM97XX_CM_RATE_MASK);
454 +               dig2 |= WM97XX_SLEN | WM97XX_DELAY(delay) |
455 +               WM97XX_SLT(wm->acc_slot) | WM97XX_RATE(wm->acc_rate);
456 +               dig3 |= WM9713_PDEN;
457 +       } else {
458 +               dig1 &= ~(WM9713_CTC | WM9713_COO);
459 +               dig2 &= ~WM97XX_SLEN;
460 +               dig3 &= ~WM9713_PDEN;
461 +               if (wm->mach_ops->acc_shutdown)
462 +                       wm->mach_ops->acc_shutdown(wm);
463 +       }
464 +
465 +       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
466 +       wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
467 +       wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
468 +       return ret;
469 +}
470 +
471 +struct wm97xx_codec_drv wm9713_codec = {
472 +       .id =   WM9713_ID2,
473 +       .name = "wm9713",
474 +       .poll_sample = wm9713_poll_sample,
475 +       .poll_touch = wm9713_poll_touch,
476 +       .acc_enable = wm9713_acc_enable,
477 +       .phy_init = wm9713_phy_init,
478 +       .dig_enable = wm9713_dig_enable,
479 +       .dig_restore = wm9713_dig_restore,
480 +       .aux_prepare = wm9713_aux_prepare,
481 +};
482 +EXPORT_SYMBOL_GPL(wm9713_codec);
483 +
484 +/* Module information */
485 +MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
486 +MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
487 +MODULE_LICENSE("GPL");
488 -- 
489 1.5.3.8
490