summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch2899
1 files changed, 2899 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch b/meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch
new file mode 100644
index 0000000000..c918c5daff
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch
@@ -0,0 +1,2899 @@
1Index: linux-2.6.17/drivers/input/touchscreen/Kconfig
2===================================================================
3--- linux-2.6.17.orig/drivers/input/touchscreen/Kconfig 2006-09-19 20:35:35.060495500 +0200
4+++ linux-2.6.17/drivers/input/touchscreen/Kconfig 2006-09-19 20:36:47.965051750 +0200
5@@ -121,4 +121,57 @@ config TOUCHSCREEN_TSC2101
6 To compile this driver as a module, choose M here: the
7 module will be called ads7846_ts.
8
9+config TOUCHSCREEN_WM97XX
10+ tristate "Support for WM97xx AC97 touchscreen controllers"
11+ depends SND_AC97_BUS
12+
13+choice
14+ prompt "WM97xx codec type"
15+
16+config TOUCHSCREEN_WM9705
17+ bool "WM9705 Touchscreen interface support"
18+ depends on TOUCHSCREEN_WM97XX
19+ help
20+ Say Y here if you have the wm9705 touchscreen.
21+
22+ If unsure, say N.
23+
24+ To compile this driver as a module, choose M here: the
25+ module will be called wm9705.
26+
27+config TOUCHSCREEN_WM9712
28+ bool "WM9712 Touchscreen interface support"
29+ depends on TOUCHSCREEN_WM97XX
30+ help
31+ Say Y here if you have the wm9712 touchscreen.
32+
33+ If unsure, say N.
34+
35+ To compile this driver as a module, choose M here: the
36+ module will be called wm9712.
37+
38+config TOUCHSCREEN_WM9713
39+ bool "WM9713 Touchscreen interface support"
40+ depends on TOUCHSCREEN_WM97XX
41+ help
42+ Say Y here if you have the wm9713 touchscreen.
43+
44+ If unsure, say N.
45+
46+ To compile this driver as a module, choose M here: the
47+ module will be called wm9713.
48+
49+endchoice
50+
51+config TOUCHSCREEN_WM97XX_PXA
52+ tristate "WM97xx PXA accelerated touch"
53+ depends on TOUCHSCREEN_WM97XX && ARCH_PXA
54+ help
55+ Say Y here for continuous mode touch on the PXA
56+
57+ If unsure, say N
58+
59+ To compile this driver as a module, choose M here: the
60+ module will be called pxa-wm97xx
61+
62 endif
63Index: linux-2.6.17/drivers/input/touchscreen/Makefile
64===================================================================
65--- linux-2.6.17.orig/drivers/input/touchscreen/Makefile 2006-09-19 20:35:35.072496250 +0200
66+++ linux-2.6.17/drivers/input/touchscreen/Makefile 2006-09-19 20:37:40.540337500 +0200
67@@ -4,6 +4,8 @@
68
69 # Each configuration option enables a list of files.
70
71+wm97xx-ts-objs := wm97xx-core.o
72+
73 obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
74 obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
75 obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
76@@ -13,3 +15,16 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtou
77 obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
78 obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
79 obj-$(CONFIG_TOUCHSCREEN_TSC2101) += tsc2101_ts.o
80+obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
81+obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA) += pxa-wm97xx.o
82+
83+ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y)
84+wm97xx-ts-objs += wm9713.o
85+endif
86+
87+ifeq ($(CONFIG_TOUCHSCREEN_WM9712),y)
88+wm97xx-ts-objs += wm9712.o
89+endif
90+ifeq ($(CONFIG_TOUCHSCREEN_WM9705),y)
91+wm97xx-ts-objs += wm9705.o
92+endif
93Index: linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c
94===================================================================
95--- /dev/null 1970-01-01 00:00:00.000000000 +0000
96+++ linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c 2006-09-19 20:36:47.965051750 +0200
97@@ -0,0 +1,289 @@
98+/*
99+ * pxa-wm97xx.c -- pxa-wm97xx Continuous Touch screen driver for
100+ * Wolfson WM97xx AC97 Codecs.
101+ *
102+ * Copyright 2004 Wolfson Microelectronics PLC.
103+ * Author: Liam Girdwood
104+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
105+ * Parts Copyright : Ian Molton <spyro@f2s.com>
106+ * Andrew Zabolotny <zap@homelink.ru>
107+ *
108+ * This program is free software; you can redistribute it and/or modify it
109+ * under the terms of the GNU General Public License as published by the
110+ * Free Software Foundation; either version 2 of the License, or (at your
111+ * option) any later version.
112+ *
113+ * Notes:
114+ * This is a wm97xx extended touch driver to capture touch
115+ * data in a continuous manner on the Intel XScale archictecture
116+ *
117+ * Features:
118+ * - codecs supported:- WM9705, WM9712, WM9713
119+ * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
120+ *
121+ * Revision history
122+ * 18th Aug 2004 Initial version.
123+ * 26th Jul 2005 Improved continous read back and added FIFO flushing.
124+ * 06th Sep 2005 Mike Arthur <linux@wolfsonmicro.com>
125+ * Moved to using the wm97xx bus
126+ *
127+ */
128+
129+#include <linux/module.h>
130+#include <linux/moduleparam.h>
131+#include <linux/version.h>
132+#include <linux/kernel.h>
133+#include <linux/init.h>
134+#include <linux/delay.h>
135+#include <linux/irq.h>
136+#include <linux/wm97xx.h>
137+#include <asm/io.h>
138+#include <asm/arch/pxa-regs.h>
139+
140+#define VERSION "0.13"
141+
142+struct continuous {
143+ u16 id; /* codec id */
144+ u8 code; /* continuous code */
145+ u8 reads; /* number of coord reads per read cycle */
146+ u32 speed; /* number of coords per second */
147+};
148+
149+#define WM_READS(sp) ((sp / HZ) + 1)
150+
151+static const struct continuous cinfo[] = {
152+ {WM9705_ID2, 0, WM_READS(94), 94},
153+ {WM9705_ID2, 1, WM_READS(188), 188},
154+ {WM9705_ID2, 2, WM_READS(375), 375},
155+ {WM9705_ID2, 3, WM_READS(750), 750},
156+ {WM9712_ID2, 0, WM_READS(94), 94},
157+ {WM9712_ID2, 1, WM_READS(188), 188},
158+ {WM9712_ID2, 2, WM_READS(375), 375},
159+ {WM9712_ID2, 3, WM_READS(750), 750},
160+ {WM9713_ID2, 0, WM_READS(94), 94},
161+ {WM9713_ID2, 1, WM_READS(120), 120},
162+ {WM9713_ID2, 2, WM_READS(154), 154},
163+ {WM9713_ID2, 3, WM_READS(188), 188},
164+};
165+
166+/* continuous speed index */
167+static int sp_idx = 0;
168+static u16 last = 0, tries = 0;
169+
170+/*
171+ * Pen sampling frequency (Hz) in continuous mode.
172+ */
173+static int cont_rate = 200;
174+module_param(cont_rate, int, 0);
175+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
176+
177+/*
178+ * Pen down detection.
179+ *
180+ * This driver can either poll or use an interrupt to indicate a pen down
181+ * event. If the irq request fails then it will fall back to polling mode.
182+ */
183+static int pen_int = 1;
184+module_param(pen_int, int, 0);
185+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
186+
187+/*
188+ * Pressure readback.
189+ *
190+ * Set to 1 to read back pen down pressure
191+ */
192+static int pressure = 0;
193+module_param(pressure, int, 0);
194+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
195+
196+/*
197+ * AC97 touch data slot.
198+ *
199+ * Touch screen readback data ac97 slot
200+ */
201+static int ac97_touch_slot = 5;
202+module_param(ac97_touch_slot, int, 0);
203+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
204+
205+
206+/* flush AC97 slot 5 FIFO on pxa machines */
207+#ifdef CONFIG_PXA27x
208+void wm97xx_acc_pen_up (struct wm97xx* wm)
209+{
210+ set_current_state(TASK_INTERRUPTIBLE);
211+ schedule_timeout(1);
212+
213+ while (MISR & (1 << 2))
214+ MODR;
215+}
216+#else
217+void wm97xx_acc_pen_up (struct wm97xx* wm)
218+{
219+ int count = 16;
220+ set_current_state(TASK_INTERRUPTIBLE);
221+ schedule_timeout(1);
222+
223+ while (count < 16) {
224+ MODR;
225+ count--;
226+ }
227+}
228+#endif
229+
230+int wm97xx_acc_pen_down (struct wm97xx* wm)
231+{
232+ u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
233+ int reads = 0;
234+
235+ /* data is never immediately available after pen down irq */
236+ set_current_state(TASK_INTERRUPTIBLE);
237+ schedule_timeout(1);
238+
239+ if (tries > 5){
240+ tries = 0;
241+ return RC_PENUP;
242+ }
243+
244+ x = MODR;
245+ if (x == last) {
246+ tries++;
247+ return RC_AGAIN;
248+ }
249+ last = x;
250+ do {
251+ if (reads)
252+ x= MODR;
253+ y= MODR;
254+ if (pressure)
255+ p = MODR;
256+
257+ /* are samples valid */
258+ if ((x & 0x7000) != WM97XX_ADCSEL_X ||
259+ (y & 0x7000) != WM97XX_ADCSEL_Y ||
260+ (p & 0x7000) != WM97XX_ADCSEL_PRES)
261+ goto up;
262+
263+ /* coordinate is good */
264+ tries = 0;
265+ //printk("x %x y %x p %x\n", x,y,p);
266+ input_report_abs (wm->input_dev, ABS_X, x & 0xfff);
267+ input_report_abs (wm->input_dev, ABS_Y, y & 0xfff);
268+ input_report_abs (wm->input_dev, ABS_PRESSURE, p & 0xfff);
269+ input_sync (wm->input_dev);
270+ reads++;
271+ } while (reads < cinfo[sp_idx].reads);
272+up:
273+ return RC_PENDOWN | RC_AGAIN;
274+}
275+
276+int wm97xx_acc_startup(struct wm97xx* wm)
277+{
278+ int idx = 0;
279+
280+ /* check we have a codec */
281+ if (wm->ac97 == NULL)
282+ return -ENODEV;
283+
284+ /* Go you big red fire engine */
285+ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
286+ if (wm->id != cinfo[idx].id)
287+ continue;
288+ sp_idx = idx;
289+ if (cont_rate <= cinfo[idx].speed)
290+ break;
291+ }
292+ wm->acc_rate = cinfo[sp_idx].code;
293+ wm->acc_slot = ac97_touch_slot;
294+ printk(KERN_INFO "pxa2xx accelerated touchscreen driver, %d samples (sec)\n",
295+ cinfo[sp_idx].speed);
296+
297+ /* codec specific irq config */
298+ if (pen_int) {
299+ switch (wm->id) {
300+ case WM9705_ID2:
301+ wm->pen_irq = IRQ_GPIO(4);
302+ set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
303+ break;
304+ case WM9712_ID2:
305+ case WM9713_ID2:
306+ /* enable pen down interrupt */
307+ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
308+ wm->pen_irq = MAINSTONE_AC97_IRQ;
309+ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
310+ WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, WM97XX_GPIO_WAKE);
311+ wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
312+ WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE);
313+ break;
314+ default:
315+ printk(KERN_WARNING "pen down irq not supported on this device\n");
316+ pen_int = 0;
317+ break;
318+ }
319+ }
320+
321+ return 0;
322+}
323+
324+void wm97xx_acc_shutdown(struct wm97xx* wm)
325+{
326+ /* codec specific deconfig */
327+ if (pen_int) {
328+ switch (wm->id & 0xffff) {
329+ case WM9705_ID2:
330+ wm->pen_irq = 0;
331+ break;
332+ case WM9712_ID2:
333+ case WM9713_ID2:
334+ /* disable interrupt */
335+ wm->pen_irq = 0;
336+ break;
337+ }
338+ }
339+}
340+
341+static struct wm97xx_mach_ops pxa_mach_ops = {
342+ .acc_enabled = 1,
343+ .acc_pen_up = wm97xx_acc_pen_up,
344+ .acc_pen_down = wm97xx_acc_pen_down,
345+ .acc_startup = wm97xx_acc_startup,
346+ .acc_shutdown = wm97xx_acc_shutdown,
347+};
348+
349+int pxa_wm97xx_probe(struct device *dev)
350+{
351+ struct wm97xx *wm = dev->driver_data;
352+ return wm97xx_register_mach_ops (wm, &pxa_mach_ops);
353+}
354+
355+int pxa_wm97xx_remove(struct device *dev)
356+{
357+ struct wm97xx *wm = dev->driver_data;
358+ wm97xx_unregister_mach_ops (wm);
359+ return 0;
360+}
361+
362+static struct device_driver pxa_wm97xx_driver = {
363+ .name = "wm97xx-touchscreen",
364+ .bus = &wm97xx_bus_type,
365+ .owner = THIS_MODULE,
366+ .probe = pxa_wm97xx_probe,
367+ .remove = pxa_wm97xx_remove
368+};
369+
370+static int __init pxa_wm97xx_init(void)
371+{
372+ return driver_register(&pxa_wm97xx_driver);
373+}
374+
375+static void __exit pxa_wm97xx_exit(void)
376+{
377+ driver_unregister(&pxa_wm97xx_driver);
378+}
379+
380+module_init(pxa_wm97xx_init);
381+module_exit(pxa_wm97xx_exit);
382+
383+/* Module information */
384+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
385+MODULE_DESCRIPTION("wm97xx continuous touch driver for pxa2xx");
386+MODULE_LICENSE("GPL");
387Index: linux-2.6.17/drivers/input/touchscreen/wm9705.c
388===================================================================
389--- /dev/null 1970-01-01 00:00:00.000000000 +0000
390+++ linux-2.6.17/drivers/input/touchscreen/wm9705.c 2006-09-19 20:36:47.969052000 +0200
391@@ -0,0 +1,360 @@
392+/*
393+ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
394+ *
395+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
396+ * Author: Liam Girdwood
397+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
398+ * Parts Copyright : Ian Molton <spyro@f2s.com>
399+ * Andrew Zabolotny <zap@homelink.ru>
400+ * Russell King <rmk@arm.linux.org.uk>
401+ *
402+ * This program is free software; you can redistribute it and/or modify it
403+ * under the terms of the GNU General Public License as published by the
404+ * Free Software Foundation; either version 2 of the License, or (at your
405+ * option) any later version.
406+ *
407+ * Revision history
408+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com>
409+ * Added pre and post sample calls.
410+ *
411+ */
412+
413+#include <linux/module.h>
414+#include <linux/moduleparam.h>
415+#include <linux/version.h>
416+#include <linux/kernel.h>
417+#include <linux/input.h>
418+#include <linux/delay.h>
419+#include <linux/bitops.h>
420+#include <linux/wm97xx.h>
421+
422+#define TS_NAME "wm97xx"
423+#define WM9705_VERSION "0.62"
424+#define DEFAULT_PRESSURE 0xb0c0
425+
426+/*
427+ * Debug
428+ */
429+#if 0
430+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
431+#else
432+#define dbg(format, arg...)
433+#endif
434+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
435+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
436+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
437+
438+/*
439+ * Module parameters
440+ */
441+
442+/*
443+ * Set current used for pressure measurement.
444+ *
445+ * Set pil = 2 to use 400uA
446+ * pil = 1 to use 200uA and
447+ * pil = 0 to disable pressure measurement.
448+ *
449+ * This is used to increase the range of values returned by the adc
450+ * when measureing touchpanel pressure.
451+ */
452+static int pil = 0;
453+module_param(pil, int, 0);
454+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
455+
456+/*
457+ * Set threshold for pressure measurement.
458+ *
459+ * Pen down pressure below threshold is ignored.
460+ */
461+static int pressure = DEFAULT_PRESSURE & 0xfff;
462+module_param(pressure, int, 0);
463+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
464+
465+/*
466+ * Set adc sample delay.
467+ *
468+ * For accurate touchpanel measurements, some settling time may be
469+ * required between the switch matrix applying a voltage across the
470+ * touchpanel plate and the ADC sampling the signal.
471+ *
472+ * This delay can be set by setting delay = n, where n is the array
473+ * position of the delay in the array delay_table below.
474+ * Long delays > 1ms are supported for completeness, but are not
475+ * recommended.
476+ */
477+static int delay = 4;
478+module_param(delay, int, 0);
479+MODULE_PARM_DESC(delay, "Set adc sample delay.");
480+
481+/*
482+ * Pen detect comparator threshold.
483+ *
484+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
485+ * i.e. 1 = Vmid/15 threshold
486+ * 15 = Vmid/1 threshold
487+ *
488+ * Adjust this value if you are having problems with pen detect not
489+ * detecting any down events.
490+ */
491+static int pdd = 8;
492+module_param(pdd, int, 0);
493+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
494+
495+/*
496+ * Set adc mask function.
497+ *
498+ * Sources of glitch noise, such as signals driving an LCD display, may feed
499+ * through to the touch screen plates and affect measurement accuracy. In
500+ * order to minimise this, a signal may be applied to the MASK pin to delay or
501+ * synchronise the sampling.
502+ *
503+ * 0 = No delay or sync
504+ * 1 = High on pin stops conversions
505+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
506+ * 3 = Edge triggered, edge on pin starts conversion after delay param
507+ */
508+static int mask = 0;
509+module_param(mask, int, 0);
510+MODULE_PARM_DESC(mask, "Set adc mask function.");
511+
512+/*
513+ * ADC sample delay times in uS
514+ */
515+static const int delay_table[] = {
516+ 21, // 1 AC97 Link frames
517+ 42, // 2
518+ 84, // 4
519+ 167, // 8
520+ 333, // 16
521+ 667, // 32
522+ 1000, // 48
523+ 1333, // 64
524+ 2000, // 96
525+ 2667, // 128
526+ 3333, // 160
527+ 4000, // 192
528+ 4667, // 224
529+ 5333, // 256
530+ 6000, // 288
531+ 0 // No delay, switch matrix always on
532+};
533+
534+/*
535+ * Delay after issuing a POLL command.
536+ *
537+ * The delay is 3 AC97 link frames + the touchpanel settling delay
538+ */
539+static inline void poll_delay(int d)
540+{
541+ udelay (3 * AC97_LINK_FRAME + delay_table [d]);
542+}
543+
544+/*
545+ * set up the physical settings of the WM9705
546+ */
547+static void init_wm9705_phy(struct wm97xx* wm)
548+{
549+ u16 dig1 = 0, dig2 = WM97XX_RPR;
550+
551+ /*
552+ * mute VIDEO and AUX as they share X and Y touchscreen
553+ * inputs on the WM9705
554+ */
555+ wm97xx_reg_write(wm, AC97_AUX, 0x8000);
556+ wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
557+
558+ /* touchpanel pressure current*/
559+ if (pil == 2) {
560+ dig2 |= WM9705_PIL;
561+ dbg("setting pressure measurement current to 400uA.");
562+ } else if (pil)
563+ dbg("setting pressure measurement current to 200uA.");
564+ if(!pil)
565+ pressure = 0;
566+
567+ /* polling mode sample settling delay */
568+ if (delay!=4) {
569+ if (delay < 0 || delay > 15) {
570+ dbg("supplied delay out of range.");
571+ delay = 4;
572+ }
573+ }
574+ dig1 &= 0xff0f;
575+ dig1 |= WM97XX_DELAY(delay);
576+ dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
577+
578+ /* WM9705 pdd */
579+ dig2 |= (pdd & 0x000f);
580+ dbg("setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
581+
582+ /* mask */
583+ dig2 |= ((mask & 0x3) << 4);
584+
585+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
586+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
587+}
588+
589+static int wm9705_digitiser_ioctl(struct wm97xx* wm, int cmd)
590+{
591+ switch(cmd) {
592+ case WM97XX_DIG_START:
593+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] | WM97XX_PRP_DET_DIG);
594+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
595+ break;
596+ case WM97XX_DIG_STOP:
597+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
598+ break;
599+ case WM97XX_AUX_PREPARE:
600+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
601+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
602+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
603+ break;
604+ case WM97XX_DIG_RESTORE:
605+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
606+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
607+ break;
608+ case WM97XX_PHY_INIT:
609+ init_wm9705_phy(wm);
610+ break;
611+ default:
612+ return -EINVAL;
613+ }
614+ return 0;
615+}
616+
617+static inline int is_pden (struct wm97xx* wm)
618+{
619+ return wm->dig[2] & WM9705_PDEN;
620+}
621+
622+/*
623+ * Read a sample from the WM9705 adc in polling mode.
624+ */
625+static int wm9705_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
626+{
627+ int timeout = 5 * delay;
628+
629+ if (!wm->pen_probably_down) {
630+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
631+ if (!(data & WM97XX_PEN_DOWN))
632+ return RC_PENUP;
633+ wm->pen_probably_down = 1;
634+ }
635+
636+ /* set up digitiser */
637+ if (adcsel & 0x8000)
638+ adcsel = ((adcsel & 0x7fff) + 3) << 12;
639+
640+ if (wm->mach_ops && wm->mach_ops->pre_sample)
641+ wm->mach_ops->pre_sample(adcsel);
642+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
643+
644+ /* wait 3 AC97 time slots + delay for conversion */
645+ poll_delay (delay);
646+
647+ /* wait for POLL to go low */
648+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
649+ udelay(AC97_LINK_FRAME);
650+ timeout--;
651+ }
652+
653+ if (timeout <= 0) {
654+ /* If PDEN is set, we can get a timeout when pen goes up */
655+ if (is_pden(wm))
656+ wm->pen_probably_down = 0;
657+ else
658+ dbg ("adc sample timeout");
659+ return RC_PENUP;
660+ }
661+
662+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
663+ if (wm->mach_ops && wm->mach_ops->post_sample)
664+ wm->mach_ops->post_sample(adcsel);
665+
666+ /* check we have correct sample */
667+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
668+ dbg ("adc wrong sample, read %x got %x", adcsel,
669+ *sample & WM97XX_ADCSEL_MASK);
670+ return RC_PENUP;
671+ }
672+
673+ if (!(*sample & WM97XX_PEN_DOWN)) {
674+ wm->pen_probably_down = 0;
675+ return RC_PENUP;
676+ }
677+
678+ return RC_VALID;
679+}
680+
681+/*
682+ * Sample the WM9705 touchscreen in polling mode
683+ */
684+static int wm9705_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
685+{
686+ int rc;
687+
688+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
689+ return rc;
690+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
691+ return rc;
692+ if (pil) {
693+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
694+ return rc;
695+ } else
696+ data->p = DEFAULT_PRESSURE;
697+
698+ return RC_VALID;
699+}
700+
701+/*
702+ * Enable WM9705 continuous mode, i.e. touch data is streamed across an AC97 slot
703+ */
704+static int wm9705_acc_enable (struct wm97xx* wm, int enable)
705+{
706+ u16 dig1, dig2;
707+ int ret = 0;
708+
709+ dig1 = wm->dig[1];
710+ dig2 = wm->dig[2];
711+
712+ if (enable) {
713+ /* continous mode */
714+ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
715+ return ret;
716+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
717+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
718+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
719+ WM97XX_DELAY (delay) |
720+ WM97XX_SLT (wm->acc_slot) |
721+ WM97XX_RATE (wm->acc_rate);
722+ if (pil)
723+ dig1 |= WM97XX_ADCSEL_PRES;
724+ dig2 |= WM9705_PDEN;
725+ } else {
726+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
727+ dig2 &= ~WM9705_PDEN;
728+ if (wm->mach_ops->acc_shutdown)
729+ wm->mach_ops->acc_shutdown(wm);
730+ }
731+
732+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
733+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
734+ return ret;
735+}
736+
737+struct wm97xx_codec_drv wm97xx_codec = {
738+ .id = WM9705_ID2,
739+ .name = "wm9705",
740+ .poll_sample = wm9705_poll_sample,
741+ .poll_touch = wm9705_poll_touch,
742+ .acc_enable = wm9705_acc_enable,
743+ .digitiser_ioctl = wm9705_digitiser_ioctl,
744+};
745+
746+EXPORT_SYMBOL_GPL(wm97xx_codec);
747+
748+/* Module information */
749+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
750+MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
751+MODULE_LICENSE("GPL");
752Index: linux-2.6.17/drivers/input/touchscreen/wm9712.c
753===================================================================
754--- /dev/null 1970-01-01 00:00:00.000000000 +0000
755+++ linux-2.6.17/drivers/input/touchscreen/wm9712.c 2006-09-19 20:36:47.969052000 +0200
756@@ -0,0 +1,464 @@
757+/*
758+ * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
759+ *
760+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
761+ * Author: Liam Girdwood
762+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
763+ * Parts Copyright : Ian Molton <spyro@f2s.com>
764+ * Andrew Zabolotny <zap@homelink.ru>
765+ * Russell King <rmk@arm.linux.org.uk>
766+ *
767+ * This program is free software; you can redistribute it and/or modify it
768+ * under the terms of the GNU General Public License as published by the
769+ * Free Software Foundation; either version 2 of the License, or (at your
770+ * option) any later version.
771+ *
772+ * Revision history
773+ * 4th Jul 2005 Initial version.
774+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com>
775+ * Added pre and post sample calls.
776+ *
777+ */
778+
779+#include <linux/module.h>
780+#include <linux/moduleparam.h>
781+#include <linux/version.h>
782+#include <linux/kernel.h>
783+#include <linux/input.h>
784+#include <linux/delay.h>
785+#include <linux/bitops.h>
786+#include <linux/wm97xx.h>
787+
788+#define TS_NAME "wm97xx"
789+#define WM9712_VERSION "0.61"
790+#define DEFAULT_PRESSURE 0xb0c0
791+
792+/*
793+ * Debug
794+ */
795+#if 0
796+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
797+#else
798+#define dbg(format, arg...)
799+#endif
800+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
801+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
802+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
803+
804+/*
805+ * Module parameters
806+ */
807+
808+/*
809+ * Set internal pull up for pen detect.
810+ *
811+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
812+ * i.e. pull up resistance = 64k Ohms / rpu.
813+ *
814+ * Adjust this value if you are having problems with pen detect not
815+ * detecting any down event.
816+ */
817+static int rpu = 3;
818+module_param(rpu, int, 0);
819+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
820+
821+/*
822+ * Set current used for pressure measurement.
823+ *
824+ * Set pil = 2 to use 400uA
825+ * pil = 1 to use 200uA and
826+ * pil = 0 to disable pressure measurement.
827+ *
828+ * This is used to increase the range of values returned by the adc
829+ * when measureing touchpanel pressure.
830+ */
831+static int pil = 0;
832+module_param(pil, int, 0);
833+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
834+
835+/*
836+ * Set threshold for pressure measurement.
837+ *
838+ * Pen down pressure below threshold is ignored.
839+ */
840+static int pressure = DEFAULT_PRESSURE & 0xfff;
841+module_param(pressure, int, 0);
842+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
843+
844+/*
845+ * Set adc sample delay.
846+ *
847+ * For accurate touchpanel measurements, some settling time may be
848+ * required between the switch matrix applying a voltage across the
849+ * touchpanel plate and the ADC sampling the signal.
850+ *
851+ * This delay can be set by setting delay = n, where n is the array
852+ * position of the delay in the array delay_table below.
853+ * Long delays > 1ms are supported for completeness, but are not
854+ * recommended.
855+ */
856+static int delay = 3;
857+module_param(delay, int, 0);
858+MODULE_PARM_DESC(delay, "Set adc sample delay.");
859+
860+/*
861+ * Set five_wire = 1 to use a 5 wire touchscreen.
862+ *
863+ * NOTE: Five wire mode does not allow for readback of pressure.
864+ */
865+static int five_wire;
866+module_param(five_wire, int, 0);
867+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
868+
869+/*
870+ * Set adc mask function.
871+ *
872+ * Sources of glitch noise, such as signals driving an LCD display, may feed
873+ * through to the touch screen plates and affect measurement accuracy. In
874+ * order to minimise this, a signal may be applied to the MASK pin to delay or
875+ * synchronise the sampling.
876+ *
877+ * 0 = No delay or sync
878+ * 1 = High on pin stops conversions
879+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
880+ * 3 = Edge triggered, edge on pin starts conversion after delay param
881+ */
882+static int mask = 0;
883+module_param(mask, int, 0);
884+MODULE_PARM_DESC(mask, "Set adc mask function.");
885+
886+/*
887+ * Coordinate Polling Enable.
888+ *
889+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
890+ * for every poll.
891+ */
892+static int coord = 0;
893+module_param(coord, int, 0);
894+MODULE_PARM_DESC(coord, "Polling coordinate mode");
895+
896+/*
897+ * ADC sample delay times in uS
898+ */
899+static const int delay_table[] = {
900+ 21, // 1 AC97 Link frames
901+ 42, // 2
902+ 84, // 4
903+ 167, // 8
904+ 333, // 16
905+ 667, // 32
906+ 1000, // 48
907+ 1333, // 64
908+ 2000, // 96
909+ 2667, // 128
910+ 3333, // 160
911+ 4000, // 192
912+ 4667, // 224
913+ 5333, // 256
914+ 6000, // 288
915+ 0 // No delay, switch matrix always on
916+};
917+
918+/*
919+ * Delay after issuing a POLL command.
920+ *
921+ * The delay is 3 AC97 link frames + the touchpanel settling delay
922+ */
923+static inline void poll_delay(int d)
924+{
925+ udelay (3 * AC97_LINK_FRAME + delay_table [d]);
926+}
927+
928+/*
929+ * set up the physical settings of the WM9712
930+ */
931+static void init_wm9712_phy(struct wm97xx* wm)
932+{
933+ u16 dig1 = 0;
934+ u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
935+
936+ /* WM9712 rpu */
937+ if (rpu) {
938+ dig2 &= 0xffc0;
939+ dig2 |= WM9712_RPU(rpu);
940+ dbg("setting pen detect pull-up to %d Ohms",64000 / rpu);
941+ }
942+
943+ /* touchpanel pressure current*/
944+ if (pil == 2) {
945+ dig2 |= WM9712_PIL;
946+ dbg("setting pressure measurement current to 400uA.");
947+ } else if (pil)
948+ dbg("setting pressure measurement current to 200uA.");
949+ if(!pil)
950+ pressure = 0;
951+
952+ /* WM9712 five wire */
953+ if (five_wire) {
954+ dig2 |= WM9712_45W;
955+ dbg("setting 5-wire touchscreen mode.");
956+ }
957+
958+ /* polling mode sample settling delay */
959+ if (delay < 0 || delay > 15) {
960+ dbg("supplied delay out of range.");
961+ delay = 4;
962+ }
963+ dig1 &= 0xff0f;
964+ dig1 |= WM97XX_DELAY(delay);
965+ dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
966+
967+ /* mask */
968+ dig2 |= ((mask & 0x3) << 6);
969+ if (mask) {
970+ u16 reg;
971+ /* Set GPIO4 as Mask Pin*/
972+ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
973+ wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
974+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
975+ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
976+ }
977+
978+ /* wait - coord mode */
979+ if(coord)
980+ dig2 |= WM9712_WAIT;
981+
982+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
983+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
984+}
985+
986+static int wm9712_digitiser_ioctl(struct wm97xx* wm, int cmd)
987+{
988+ u16 dig2 = wm->dig[2];
989+
990+ switch(cmd) {
991+ case WM97XX_DIG_START:
992+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 | WM97XX_PRP_DET_DIG);
993+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
994+ break;
995+ case WM97XX_DIG_STOP:
996+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 & ~WM97XX_PRP_DET_DIG);
997+ break;
998+ case WM97XX_AUX_PREPARE:
999+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
1000+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
1001+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
1002+ break;
1003+ case WM97XX_DIG_RESTORE:
1004+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
1005+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
1006+ break;
1007+ case WM97XX_PHY_INIT:
1008+ init_wm9712_phy(wm);
1009+ break;
1010+ default:
1011+ return -EINVAL;
1012+ }
1013+ return 0;
1014+}
1015+
1016+static inline int is_pden (struct wm97xx* wm)
1017+{
1018+ return wm->dig[2] & WM9712_PDEN;
1019+}
1020+
1021+/*
1022+ * Read a sample from the WM9712 adc in polling mode.
1023+ */
1024+static int wm9712_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
1025+{
1026+ int timeout = 5 * delay;
1027+
1028+ if (!wm->pen_probably_down) {
1029+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1030+ if (!(data & WM97XX_PEN_DOWN))
1031+ return RC_PENUP;
1032+ wm->pen_probably_down = 1;
1033+ }
1034+
1035+ /* set up digitiser */
1036+ if (adcsel & 0x8000)
1037+ adcsel = ((adcsel & 0x7fff) + 3) << 12;
1038+
1039+ if (wm->mach_ops && wm->mach_ops->pre_sample)
1040+ wm->mach_ops->pre_sample(adcsel);
1041+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
1042+
1043+ /* wait 3 AC97 time slots + delay for conversion */
1044+ poll_delay (delay);
1045+
1046+ /* wait for POLL to go low */
1047+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
1048+ udelay(AC97_LINK_FRAME);
1049+ timeout--;
1050+ }
1051+
1052+ if (timeout <= 0) {
1053+ /* If PDEN is set, we can get a timeout when pen goes up */
1054+ if (is_pden(wm))
1055+ wm->pen_probably_down = 0;
1056+ else
1057+ dbg ("adc sample timeout");
1058+ return RC_PENUP;
1059+ }
1060+
1061+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1062+ if (wm->mach_ops && wm->mach_ops->post_sample)
1063+ wm->mach_ops->post_sample(adcsel);
1064+
1065+ /* check we have correct sample */
1066+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
1067+ dbg ("adc wrong sample, read %x got %x", adcsel,
1068+ *sample & WM97XX_ADCSEL_MASK);
1069+ return RC_PENUP;
1070+ }
1071+
1072+ if (!(*sample & WM97XX_PEN_DOWN)) {
1073+ wm->pen_probably_down = 0;
1074+ return RC_PENUP;
1075+ }
1076+
1077+ return RC_VALID;
1078+}
1079+
1080+/*
1081+ * Read a coord from the WM9712 adc in polling mode.
1082+ */
1083+static int wm9712_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
1084+{
1085+ int timeout = 5 * delay;
1086+
1087+ if (!wm->pen_probably_down) {
1088+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1089+ if (!(data & WM97XX_PEN_DOWN))
1090+ return RC_PENUP;
1091+ wm->pen_probably_down = 1;
1092+ }
1093+
1094+ /* set up digitiser */
1095+ if (wm->mach_ops && wm->mach_ops->pre_sample)
1096+ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
1097+
1098+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
1099+ WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
1100+
1101+ /* wait 3 AC97 time slots + delay for conversion and read x */
1102+ poll_delay(delay);
1103+ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1104+ /* wait for POLL to go low */
1105+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
1106+ udelay(AC97_LINK_FRAME);
1107+ timeout--;
1108+ }
1109+
1110+ if (timeout <= 0) {
1111+ /* If PDEN is set, we can get a timeout when pen goes up */
1112+ if (is_pden(wm))
1113+ wm->pen_probably_down = 0;
1114+ else
1115+ dbg ("adc sample timeout");
1116+ return RC_PENUP;
1117+ }
1118+
1119+ /* read back y data */
1120+ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1121+ if (pil)
1122+ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1123+ else
1124+ data->p = DEFAULT_PRESSURE;
1125+
1126+ if (wm->mach_ops && wm->mach_ops->post_sample)
1127+ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
1128+
1129+ /* check we have correct sample */
1130+ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
1131+ goto err;
1132+ if(pil && !(data->p & WM97XX_ADCSEL_PRES))
1133+ goto err;
1134+
1135+ if (!(data->x & WM97XX_PEN_DOWN)) {
1136+ wm->pen_probably_down = 0;
1137+ return RC_PENUP;
1138+ }
1139+ return RC_VALID;
1140+err:
1141+ return RC_PENUP;
1142+}
1143+
1144+/*
1145+ * Sample the WM9712 touchscreen in polling mode
1146+ */
1147+static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
1148+{
1149+ int rc;
1150+
1151+ if(coord) {
1152+ if((rc = wm9712_poll_coord(wm, data)) != RC_VALID)
1153+ return rc;
1154+ } else {
1155+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
1156+ return rc;
1157+
1158+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
1159+ return rc;
1160+
1161+ if (pil && !five_wire) {
1162+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
1163+ return rc;
1164+ } else
1165+ data->p = DEFAULT_PRESSURE;
1166+ }
1167+ return RC_VALID;
1168+}
1169+
1170+/*
1171+ * Enable WM9712 continuous mode, i.e. touch data is streamed across an AC97 slot
1172+ */
1173+static int wm9712_acc_enable (struct wm97xx* wm, int enable)
1174+{
1175+ u16 dig1, dig2;
1176+ int ret = 0;
1177+
1178+ dig1 = wm->dig[1];
1179+ dig2 = wm->dig[2];
1180+
1181+ if (enable) {
1182+ /* continous mode */
1183+ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
1184+ return ret;
1185+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
1186+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
1187+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
1188+ WM97XX_DELAY (delay) |
1189+ WM97XX_SLT (wm->acc_slot) |
1190+ WM97XX_RATE (wm->acc_rate);
1191+ if (pil)
1192+ dig1 |= WM97XX_ADCSEL_PRES;
1193+ dig2 |= WM9712_PDEN;
1194+ } else {
1195+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
1196+ dig2 &= ~WM9712_PDEN;
1197+ if (wm->mach_ops->acc_shutdown)
1198+ wm->mach_ops->acc_shutdown(wm);
1199+ }
1200+
1201+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
1202+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
1203+ return 0;
1204+}
1205+
1206+struct wm97xx_codec_drv wm97xx_codec = {
1207+ .id = WM9712_ID2,
1208+ .name = "wm9712",
1209+ .poll_sample = wm9712_poll_sample,
1210+ .poll_touch = wm9712_poll_touch,
1211+ .acc_enable = wm9712_acc_enable,
1212+ .digitiser_ioctl = wm9712_digitiser_ioctl,
1213+};
1214+
1215+EXPORT_SYMBOL_GPL(wm97xx_codec);
1216+
1217+/* Module information */
1218+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1219+MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
1220+MODULE_LICENSE("GPL");
1221Index: linux-2.6.17/drivers/input/touchscreen/wm9713.c
1222===================================================================
1223--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1224+++ linux-2.6.17/drivers/input/touchscreen/wm9713.c 2006-09-19 20:36:47.969052000 +0200
1225@@ -0,0 +1,461 @@
1226+/*
1227+ * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
1228+ *
1229+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
1230+ * Author: Liam Girdwood
1231+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
1232+ * Parts Copyright : Ian Molton <spyro@f2s.com>
1233+ * Andrew Zabolotny <zap@homelink.ru>
1234+ * Russell King <rmk@arm.linux.org.uk>
1235+ *
1236+ * This program is free software; you can redistribute it and/or modify it
1237+ * under the terms of the GNU General Public License as published by the
1238+ * Free Software Foundation; either version 2 of the License, or (at your
1239+ * option) any later version.
1240+ *
1241+ * Revision history
1242+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com>
1243+ * Added pre and post sample calls.
1244+ *
1245+ */
1246+
1247+#include <linux/module.h>
1248+#include <linux/moduleparam.h>
1249+#include <linux/version.h>
1250+#include <linux/kernel.h>
1251+#include <linux/input.h>
1252+#include <linux/delay.h>
1253+#include <linux/bitops.h>
1254+#include <linux/wm97xx.h>
1255+
1256+#define TS_NAME "wm97xx"
1257+#define WM9713_VERSION "0.53"
1258+#define DEFAULT_PRESSURE 0xb0c0
1259+
1260+/*
1261+ * Debug
1262+ */
1263+#if 0
1264+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
1265+#else
1266+#define dbg(format, arg...)
1267+#endif
1268+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
1269+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
1270+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
1271+
1272+/*
1273+ * Module parameters
1274+ */
1275+
1276+/*
1277+ * Set internal pull up for pen detect.
1278+ *
1279+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
1280+ * i.e. pull up resistance = 64k Ohms / rpu.
1281+ *
1282+ * Adjust this value if you are having problems with pen detect not
1283+ * detecting any down event.
1284+ */
1285+static int rpu = 1;
1286+module_param(rpu, int, 0);
1287+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
1288+
1289+/*
1290+ * Set current used for pressure measurement.
1291+ *
1292+ * Set pil = 2 to use 400uA
1293+ * pil = 1 to use 200uA and
1294+ * pil = 0 to disable pressure measurement.
1295+ *
1296+ * This is used to increase the range of values returned by the adc
1297+ * when measureing touchpanel pressure.
1298+ */
1299+static int pil = 0;
1300+module_param(pil, int, 0);
1301+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
1302+
1303+/*
1304+ * Set threshold for pressure measurement.
1305+ *
1306+ * Pen down pressure below threshold is ignored.
1307+ */
1308+static int pressure = DEFAULT_PRESSURE & 0xfff;
1309+module_param(pressure, int, 0);
1310+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
1311+
1312+/*
1313+ * Set adc sample delay.
1314+ *
1315+ * For accurate touchpanel measurements, some settling time may be
1316+ * required between the switch matrix applying a voltage across the
1317+ * touchpanel plate and the ADC sampling the signal.
1318+ *
1319+ * This delay can be set by setting delay = n, where n is the array
1320+ * position of the delay in the array delay_table below.
1321+ * Long delays > 1ms are supported for completeness, but are not
1322+ * recommended.
1323+ */
1324+static int delay = 4;
1325+module_param(delay, int, 0);
1326+MODULE_PARM_DESC(delay, "Set adc sample delay.");
1327+
1328+/*
1329+ * Set adc mask function.
1330+ *
1331+ * Sources of glitch noise, such as signals driving an LCD display, may feed
1332+ * through to the touch screen plates and affect measurement accuracy. In
1333+ * order to minimise this, a signal may be applied to the MASK pin to delay or
1334+ * synchronise the sampling.
1335+ *
1336+ * 0 = No delay or sync
1337+ * 1 = High on pin stops conversions
1338+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
1339+ * 3 = Edge triggered, edge on pin starts conversion after delay param
1340+ */
1341+static int mask = 0;
1342+module_param(mask, int, 0);
1343+MODULE_PARM_DESC(mask, "Set adc mask function.");
1344+
1345+/*
1346+ * Coordinate Polling Enable.
1347+ *
1348+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
1349+ * for every poll.
1350+ */
1351+static int coord = 1;
1352+module_param(coord, int, 0);
1353+MODULE_PARM_DESC(coord, "Polling coordinate mode");
1354+
1355+/*
1356+ * ADC sample delay times in uS
1357+ */
1358+static const int delay_table[] = {
1359+ 21, // 1 AC97 Link frames
1360+ 42, // 2
1361+ 84, // 4
1362+ 167, // 8
1363+ 333, // 16
1364+ 667, // 32
1365+ 1000, // 48
1366+ 1333, // 64
1367+ 2000, // 96
1368+ 2667, // 128
1369+ 3333, // 160
1370+ 4000, // 192
1371+ 4667, // 224
1372+ 5333, // 256
1373+ 6000, // 288
1374+ 0 // No delay, switch matrix always on
1375+};
1376+
1377+/*
1378+ * Delay after issuing a POLL command.
1379+ *
1380+ * The delay is 3 AC97 link frames + the touchpanel settling delay
1381+ */
1382+static inline void poll_delay(int d)
1383+{
1384+ udelay (3 * AC97_LINK_FRAME + delay_table [d]);
1385+}
1386+
1387+/*
1388+ * set up the physical settings of the WM9713
1389+ */
1390+static void init_wm9713_phy(struct wm97xx* wm)
1391+{
1392+ u16 dig1 = 0, dig2, dig3;
1393+
1394+ /* default values */
1395+ dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
1396+ dig3= WM9712_RPU(1);
1397+
1398+ /* rpu */
1399+ if (rpu) {
1400+ dig3 &= 0xffc0;
1401+ dig3 |= WM9712_RPU(rpu);
1402+ info("setting pen detect pull-up to %d Ohms",64000 / rpu);
1403+ }
1404+
1405+ /* touchpanel pressure */
1406+ if (pil == 2) {
1407+ dig3 |= WM9712_PIL;
1408+ info("setting pressure measurement current to 400uA.");
1409+ } else if (pil)
1410+ info ("setting pressure measurement current to 200uA.");
1411+ if(!pil)
1412+ pressure = 0;
1413+
1414+ /* sample settling delay */
1415+ if (delay < 0 || delay > 15) {
1416+ info ("supplied delay out of range.");
1417+ delay = 4;
1418+ info("setting adc sample delay to %d u Secs.", delay_table[delay]);
1419+ }
1420+ dig2 &= 0xff0f;
1421+ dig2 |= WM97XX_DELAY(delay);
1422+
1423+ /* mask */
1424+ dig3 |= ((mask & 0x3) << 4);
1425+ if(coord)
1426+ dig3 |= WM9713_WAIT;
1427+
1428+ wm->misc = wm97xx_reg_read(wm, 0x5a);
1429+
1430+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
1431+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
1432+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
1433+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
1434+}
1435+
1436+static int wm9713_digitiser_ioctl(struct wm97xx* wm, int cmd)
1437+{
1438+ u16 val = 0;
1439+
1440+ switch(cmd){
1441+ case WM97XX_DIG_START:
1442+ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
1443+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
1444+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] | WM97XX_PRP_DET_DIG);
1445+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
1446+ break;
1447+ case WM97XX_DIG_STOP:
1448+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
1449+ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
1450+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
1451+ break;
1452+ case WM97XX_AUX_PREPARE:
1453+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
1454+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
1455+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
1456+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
1457+ break;
1458+ case WM97XX_DIG_RESTORE:
1459+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
1460+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
1461+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
1462+ break;
1463+ case WM97XX_PHY_INIT:
1464+ init_wm9713_phy(wm);
1465+ break;
1466+ default:
1467+ return -EINVAL;
1468+ }
1469+ return 0;
1470+}
1471+
1472+static inline int is_pden (struct wm97xx* wm)
1473+{
1474+ return wm->dig[2] & WM9713_PDEN;
1475+}
1476+
1477+/*
1478+ * Read a sample from the WM9713 adc in polling mode.
1479+ */
1480+static int wm9713_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
1481+{
1482+ u16 dig1;
1483+ int timeout = 5 * delay;
1484+
1485+ if (!wm->pen_probably_down) {
1486+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1487+ if (!(data & WM97XX_PEN_DOWN))
1488+ return RC_PENUP;
1489+ wm->pen_probably_down = 1;
1490+ }
1491+
1492+ /* set up digitiser */
1493+ if (adcsel & 0x8000)
1494+ adcsel = 1 << ((adcsel & 0x7fff) + 3);
1495+
1496+ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
1497+ dig1 &= ~WM9713_ADCSEL_MASK;
1498+
1499+ if (wm->mach_ops && wm->mach_ops->pre_sample)
1500+ wm->mach_ops->pre_sample(adcsel);
1501+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel |WM9713_POLL);
1502+
1503+ /* wait 3 AC97 time slots + delay for conversion */
1504+ poll_delay(delay);
1505+
1506+ /* wait for POLL to go low */
1507+ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
1508+ udelay(AC97_LINK_FRAME);
1509+ timeout--;
1510+ }
1511+
1512+ if (timeout <= 0) {
1513+ /* If PDEN is set, we can get a timeout when pen goes up */
1514+ if (is_pden(wm))
1515+ wm->pen_probably_down = 0;
1516+ else
1517+ dbg ("adc sample timeout");
1518+ return RC_PENUP;
1519+ }
1520+
1521+ *sample =wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1522+ if (wm->mach_ops && wm->mach_ops->post_sample)
1523+ wm->mach_ops->post_sample(adcsel);
1524+
1525+ /* check we have correct sample */
1526+ if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
1527+ dbg ("adc wrong sample, read %x got %x", adcsel,
1528+ *sample & WM97XX_ADCSRC_MASK);
1529+ return RC_PENUP;
1530+ }
1531+
1532+ if (!(*sample & WM97XX_PEN_DOWN)) {
1533+ wm->pen_probably_down = 0;
1534+ return RC_PENUP;
1535+ }
1536+
1537+ return RC_VALID;
1538+}
1539+
1540+/*
1541+ * Read a coordinate from the WM9713 adc in polling mode.
1542+ */
1543+static int wm9713_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
1544+{
1545+ u16 dig1;
1546+ int timeout = 5 * delay;
1547+
1548+ if (!wm->pen_probably_down) {
1549+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1550+ if (!(data & WM97XX_PEN_DOWN))
1551+ return RC_PENUP;
1552+ wm->pen_probably_down = 1;
1553+ }
1554+
1555+ /* set up digitiser */
1556+ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
1557+ dig1 &= ~WM9713_ADCSEL_MASK;
1558+ if(pil)
1559+ dig1 |= WM97XX_ADCSEL_PRES;
1560+
1561+ if (wm->mach_ops && wm->mach_ops->pre_sample)
1562+ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
1563+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL | WM9713_COO);
1564+
1565+ /* wait 3 AC97 time slots + delay for conversion */
1566+ poll_delay(delay);
1567+ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1568+ /* wait for POLL to go low */
1569+ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
1570+ udelay(AC97_LINK_FRAME);
1571+ timeout--;
1572+ }
1573+
1574+ if (timeout <= 0) {
1575+ /* If PDEN is set, we can get a timeout when pen goes up */
1576+ if (is_pden(wm))
1577+ wm->pen_probably_down = 0;
1578+ else
1579+ dbg ("adc sample timeout");
1580+ return RC_PENUP;
1581+ }
1582+
1583+ /* read back data */
1584+ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1585+ if (pil)
1586+ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
1587+ else
1588+ data->p = DEFAULT_PRESSURE;
1589+
1590+ if (wm->mach_ops && wm->mach_ops->post_sample)
1591+ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
1592+
1593+ /* check we have correct sample */
1594+ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
1595+ goto err;
1596+ if(pil && !(data->p & WM97XX_ADCSEL_PRES))
1597+ goto err;
1598+
1599+ if (!(data->x & WM97XX_PEN_DOWN)) {
1600+ wm->pen_probably_down = 0;
1601+ return RC_PENUP;
1602+ }
1603+ return RC_VALID;
1604+err:
1605+ return RC_PENUP;
1606+}
1607+
1608+/*
1609+ * Sample the WM9713 touchscreen in polling mode
1610+ */
1611+static int wm9713_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
1612+{
1613+ int rc;
1614+
1615+ if(coord) {
1616+ if((rc = wm9713_poll_coord(wm, data)) != RC_VALID)
1617+ return rc;
1618+ } else {
1619+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x)) != RC_VALID)
1620+ return rc;
1621+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y)) != RC_VALID)
1622+ return rc;
1623+ if (pil) {
1624+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, &data->p)) != RC_VALID)
1625+ return rc;
1626+ } else
1627+ data->p = DEFAULT_PRESSURE;
1628+ }
1629+ return RC_VALID;
1630+}
1631+
1632+/*
1633+ * Enable WM9713 continuous mode, i.e. touch data is streamed across an AC97 slot
1634+ */
1635+static int wm9713_acc_enable (struct wm97xx* wm, int enable)
1636+{
1637+ u16 dig1, dig2, dig3;
1638+ int ret = 0;
1639+
1640+ dig1 = wm->dig[0];
1641+ dig2 = wm->dig[1];
1642+ dig3 = wm->dig[2];
1643+
1644+ if (enable) {
1645+ /* continous mode */
1646+ if (wm->mach_ops->acc_startup &&
1647+ (ret = wm->mach_ops->acc_startup(wm)) < 0)
1648+ return ret;
1649+
1650+ dig1 &= ~WM9713_ADCSEL_MASK;
1651+ dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X | WM9713_ADCSEL_Y;
1652+ if (pil)
1653+ dig1 |= WM9713_ADCSEL_PRES;
1654+ dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK | WM97XX_CM_RATE_MASK);
1655+ dig2 |= WM97XX_SLEN | WM97XX_DELAY (delay) |
1656+ WM97XX_SLT (wm->acc_slot) | WM97XX_RATE (wm->acc_rate);
1657+ dig3 |= WM9713_PDEN;
1658+ } else {
1659+ dig1 &= ~(WM9713_CTC | WM9713_COO);
1660+ dig2 &= ~WM97XX_SLEN;
1661+ dig3 &= ~WM9713_PDEN;
1662+ if (wm->mach_ops->acc_shutdown)
1663+ wm->mach_ops->acc_shutdown(wm);
1664+ }
1665+
1666+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
1667+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
1668+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
1669+ return ret;
1670+}
1671+
1672+struct wm97xx_codec_drv wm97xx_codec = {
1673+ .id = WM9713_ID2,
1674+ .name = "wm9713",
1675+ .poll_sample = wm9713_poll_sample,
1676+ .poll_touch = wm9713_poll_touch,
1677+ .acc_enable = wm9713_acc_enable,
1678+ .digitiser_ioctl = wm9713_digitiser_ioctl,
1679+};
1680+
1681+EXPORT_SYMBOL_GPL(wm97xx_codec);
1682+
1683+/* Module information */
1684+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1685+MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
1686+MODULE_LICENSE("GPL");
1687Index: linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c
1688===================================================================
1689--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1690+++ linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c 2006-09-19 20:36:47.969052000 +0200
1691@@ -0,0 +1,912 @@
1692+/*
1693+ * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
1694+ * and WM9713 AC97 Codecs.
1695+ *
1696+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
1697+ * Author: Liam Girdwood
1698+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
1699+ * Parts Copyright : Ian Molton <spyro@f2s.com>
1700+ * Andrew Zabolotny <zap@homelink.ru>
1701+ * Russell King <rmk@arm.linux.org.uk>
1702+ *
1703+ * This program is free software; you can redistribute it and/or modify it
1704+ * under the terms of the GNU General Public License as published by the
1705+ * Free Software Foundation; either version 2 of the License, or (at your
1706+ * option) any later version.
1707+ *
1708+ * Notes:
1709+ *
1710+ * Features:
1711+ * - supports WM9705, WM9712, WM9713
1712+ * - polling mode
1713+ * - continuous mode (arch-dependent)
1714+ * - adjustable rpu/dpp settings
1715+ * - adjustable pressure current
1716+ * - adjustable sample settle delay
1717+ * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
1718+ * - pen down detection
1719+ * - battery monitor
1720+ * - sample AUX adc's
1721+ * - power management
1722+ * - codec GPIO
1723+ * - codec event notification
1724+ * Todo
1725+ * - Support for async sampling control for noisy LCD's.
1726+ *
1727+ * Revision history
1728+ * 7th May 2003 Initial version.
1729+ * 6th June 2003 Added non module support and AC97 registration.
1730+ * 18th June 2003 Added AUX adc sampling.
1731+ * 23rd June 2003 Did some minimal reformatting, fixed a couple of
1732+ * codec_mutexing bugs and noted a race to fix.
1733+ * 24th June 2003 Added power management and fixed race condition.
1734+ * 10th July 2003 Changed to a misc device.
1735+ * 31st July 2003 Moved TS_EVENT and TS_CAL to wm97xx.h
1736+ * 8th Aug 2003 Added option for read() calling wm97xx_sample_touch()
1737+ * because some ac97_read/ac_97_write call schedule()
1738+ * 7th Nov 2003 Added Input touch event interface, stanley.cai@intel.com
1739+ * 13th Nov 2003 Removed h3600 touch interface, added interrupt based
1740+ * pen down notification and implemented continous mode
1741+ * on XScale arch.
1742+ * 16th Nov 2003 Ian Molton <spyro@f2s.com>
1743+ * Modified so that it suits the new 2.6 driver model.
1744+ * 25th Jan 2004 Andrew Zabolotny <zap@homelink.ru>
1745+ * Implemented IRQ-driven pen down detection, implemented
1746+ * the private API meant to be exposed to platform-specific
1747+ * drivers, reorganized the driver so that it supports
1748+ * an arbitrary number of devices.
1749+ * 1st Feb 2004 Moved continuous mode handling to a separate
1750+ * architecture-dependent file. For now only PXA
1751+ * built-in AC97 controller is supported (pxa-ac97-wm97xx.c).
1752+ * 11th Feb 2004 Reduced CPU usage by keeping a cached copy of both
1753+ * digitizer registers instead of reading them every time.
1754+ * A reorganization of the whole code for better
1755+ * error handling.
1756+ * 17th Apr 2004 Added BMON support.
1757+ * 17th Nov 2004 Added codec GPIO, codec event handling (real and virtual
1758+ * GPIOs) and 2.6 power management.
1759+ * 29th Nov 2004 Added WM9713 support.
1760+ * 4th Jul 2005 Moved codec specific code out to seperate files.
1761+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com>
1762+ * Added bus interface.
1763+ */
1764+
1765+#include <linux/module.h>
1766+#include <linux/moduleparam.h>
1767+#include <linux/version.h>
1768+#include <linux/kernel.h>
1769+#include <linux/init.h>
1770+#include <linux/delay.h>
1771+#include <linux/string.h>
1772+#include <linux/proc_fs.h>
1773+#include <linux/pm.h>
1774+#include <linux/interrupt.h>
1775+#include <linux/bitops.h>
1776+#include <linux/workqueue.h>
1777+#include <linux/device.h>
1778+#include <linux/wm97xx.h>
1779+#include <asm/uaccess.h>
1780+#include <asm/io.h>
1781+
1782+#define TS_NAME "wm97xx"
1783+#define WM_CORE_VERSION "0.63"
1784+#define DEFAULT_PRESSURE 0xb0c0
1785+
1786+/*
1787+ * WM97xx - enable/disable AUX ADC sysfs
1788+ */
1789+static int aux_sys = 1;
1790+module_param(aux_sys, int, 0);
1791+MODULE_PARM_DESC(aux_sys, "enable AUX ADC sysfs entries");
1792+
1793+/*
1794+ * WM97xx - enable/disable codec status sysfs
1795+ */
1796+static int status_sys = 1;
1797+module_param(status_sys, int, 0);
1798+MODULE_PARM_DESC(status_sys, "enable codec status sysfs entries");
1799+
1800+/*
1801+ * Touchscreen absolute values
1802+ *
1803+ * These parameters are used to help the input layer discard out of
1804+ * range readings and reduce jitter etc.
1805+ *
1806+ * o min, max:- indicate the min and max values your touch screen returns
1807+ * o fuzz:- use a higher number to reduce jitter
1808+ *
1809+ * The default values correspond to Mainstone II in QVGA mode
1810+ *
1811+ * Please read
1812+ * Documentation/input/input-programming.txt for more details.
1813+ */
1814+
1815+static int abs_x[3] = {350,3900,5};
1816+module_param_array(abs_x, int, NULL, 0);
1817+MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
1818+
1819+static int abs_y[3] = {320,3750,40};
1820+module_param_array(abs_y, int, NULL, 0);
1821+MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
1822+
1823+static int abs_p[3] = {0,150,4};
1824+module_param_array(abs_p, int, NULL, 0);
1825+MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
1826+
1827+/*
1828+ * Debug
1829+ */
1830+#if 0
1831+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
1832+#else
1833+#define dbg(format, arg...)
1834+#endif
1835+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
1836+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
1837+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
1838+
1839+/* codec AC97 IO access */
1840+int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
1841+{
1842+ if (wm->ac97)
1843+ return wm->ac97->bus->ops->read(wm->ac97, reg);
1844+ else
1845+ return -1;
1846+}
1847+
1848+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
1849+{
1850+ /* cache digitiser registers */
1851+ if(reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
1852+ wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
1853+
1854+ /* cache gpio regs */
1855+ if(reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
1856+ wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
1857+
1858+ /* wm9713 irq reg */
1859+ if(reg == 0x5a)
1860+ wm->misc = val;
1861+
1862+ if (wm->ac97)
1863+ wm->ac97->bus->ops->write(wm->ac97, reg, val);
1864+}
1865+
1866+
1867+/**
1868+ * wm97xx_read_aux_adc - Read the aux adc.
1869+ * @wm: wm97xx device.
1870+ * @adcsel: codec ADC to be read
1871+ *
1872+ * Reads the selected AUX ADC.
1873+ */
1874+
1875+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
1876+{
1877+ int power_adc = 0, auxval;
1878+ u16 power = 0;
1879+
1880+ /* get codec */
1881+ mutex_lock(&wm->codec_mutex);
1882+
1883+ /* When the touchscreen is not in use, we may have to power up the AUX ADC
1884+ * before we can use sample the AUX inputs->
1885+ */
1886+ if (wm->id == WM9713_ID2 &&
1887+ (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
1888+ power_adc = 1;
1889+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
1890+ }
1891+
1892+ /* Prepare the codec for AUX reading */
1893+ wm->codec->digitiser_ioctl(wm, WM97XX_AUX_PREPARE);
1894+
1895+ /* Turn polling mode on to read AUX ADC */
1896+ wm->pen_probably_down = 1;
1897+ wm->codec->poll_sample(wm, adcsel, &auxval);
1898+
1899+ if (power_adc)
1900+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
1901+
1902+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_RESTORE);
1903+
1904+ wm->pen_probably_down = 0;
1905+
1906+ mutex_unlock(&wm->codec_mutex);
1907+ return auxval & 0xfff;
1908+}
1909+
1910+#define WM97XX_AUX_ATTR(name,input) \
1911+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
1912+{ \
1913+ struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \
1914+ return sprintf(buf, "%d\n", wm97xx_read_aux_adc(wm, input)); \
1915+} \
1916+static DEVICE_ATTR(name, 0444, name##_show, NULL)
1917+
1918+WM97XX_AUX_ATTR(aux1, WM97XX_AUX_ID1);
1919+WM97XX_AUX_ATTR(aux2, WM97XX_AUX_ID2);
1920+WM97XX_AUX_ATTR(aux3, WM97XX_AUX_ID3);
1921+WM97XX_AUX_ATTR(aux4, WM97XX_AUX_ID4);
1922+
1923+#define WM97XX_STATUS_ATTR(name) \
1924+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
1925+{ \
1926+ struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \
1927+ return sprintf(buf, "%d\n", wm97xx_reg_read(wm, AC97_GPIO_STATUS)); \
1928+} \
1929+static DEVICE_ATTR(name, 0444, name##_show, NULL)
1930+
1931+WM97XX_STATUS_ATTR(gpio);
1932+
1933+static int wm97xx_sys_add(struct device *dev)
1934+{
1935+ if (aux_sys) {
1936+ device_create_file(dev, &dev_attr_aux1);
1937+ device_create_file(dev, &dev_attr_aux2);
1938+ device_create_file(dev, &dev_attr_aux3);
1939+ device_create_file(dev, &dev_attr_aux4);
1940+ }
1941+ if (status_sys)
1942+ device_create_file(dev, &dev_attr_gpio);
1943+ return 0;
1944+}
1945+
1946+static void wm97xx_sys_remove(struct device *dev)
1947+{
1948+ if (status_sys)
1949+ device_remove_file(dev, &dev_attr_gpio);
1950+ if (aux_sys) {
1951+ device_remove_file(dev, &dev_attr_aux1);
1952+ device_remove_file(dev, &dev_attr_aux2);
1953+ device_remove_file(dev, &dev_attr_aux3);
1954+ device_remove_file(dev, &dev_attr_aux4);
1955+ }
1956+}
1957+
1958+/**
1959+ * wm97xx_get_gpio - Get the status of a codec GPIO.
1960+ * @wm: wm97xx device.
1961+ * @gpio: gpio
1962+ *
1963+ * Get the status of a codec GPIO pin
1964+ */
1965+
1966+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
1967+{
1968+ u16 status;
1969+ wm97xx_gpio_status_t ret;
1970+
1971+ mutex_lock(&wm->codec_mutex);
1972+ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
1973+
1974+ if (status & gpio)
1975+ ret = WM97XX_GPIO_HIGH;
1976+ else
1977+ ret = WM97XX_GPIO_LOW;
1978+
1979+ mutex_unlock(&wm->codec_mutex);
1980+ return ret;
1981+}
1982+
1983+/**
1984+ * wm97xx_set_gpio - Set the status of a codec GPIO.
1985+ * @wm: wm97xx device.
1986+ * @gpio: gpio
1987+ *
1988+ *
1989+ * Set the status of a codec GPIO pin
1990+ */
1991+
1992+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
1993+ wm97xx_gpio_status_t status)
1994+{
1995+ u16 reg;
1996+
1997+ mutex_lock(&wm->codec_mutex);
1998+ reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
1999+
2000+ if (status & WM97XX_GPIO_HIGH)
2001+ reg |= gpio;
2002+ else
2003+ reg &= ~gpio;
2004+
2005+ if (wm->id == WM9712_ID2)
2006+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
2007+ else
2008+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
2009+ mutex_unlock(&wm->codec_mutex);
2010+}
2011+
2012+/*
2013+ * Codec GPIO pin configuration, this set's pin direction, polarity,
2014+ * stickyness and wake up.
2015+ */
2016+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir,
2017+ wm97xx_gpio_pol_t pol, wm97xx_gpio_sticky_t sticky,
2018+ wm97xx_gpio_wake_t wake)
2019+{
2020+ u16 reg;
2021+
2022+ mutex_lock(&wm->codec_mutex);
2023+ reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
2024+
2025+ if (pol == WM97XX_GPIO_POL_HIGH)
2026+ reg |= gpio;
2027+ else
2028+ reg &= ~gpio;
2029+
2030+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
2031+ reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
2032+
2033+ if (sticky == WM97XX_GPIO_STICKY)
2034+ reg |= gpio;
2035+ else
2036+ reg &= ~gpio;
2037+
2038+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
2039+ reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
2040+
2041+ if (wake == WM97XX_GPIO_WAKE)
2042+ reg |= gpio;
2043+ else
2044+ reg &= ~gpio;
2045+
2046+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
2047+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
2048+
2049+ if (dir == WM97XX_GPIO_IN)
2050+ reg |= gpio;
2051+ else
2052+ reg &= ~gpio;
2053+
2054+ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
2055+ mutex_unlock(&wm->codec_mutex);
2056+}
2057+
2058+/*
2059+ * Handle a pen down interrupt.
2060+ */
2061+static void wm97xx_pen_irq_worker(void *ptr)
2062+{
2063+ struct wm97xx *wm = (struct wm97xx *) ptr;
2064+
2065+ /* do we need to enable the touch panel reader */
2066+ if (wm->id == WM9705_ID2) {
2067+ if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN)
2068+ wm->pen_is_down = 1;
2069+ else
2070+ wm->pen_is_down = 0;
2071+ wake_up_interruptible(&wm->pen_irq_wait);
2072+ } else {
2073+ u16 status, pol;
2074+ mutex_lock(&wm->codec_mutex);
2075+ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
2076+ pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
2077+
2078+ if (WM97XX_GPIO_13 & pol & status) {
2079+ wm->pen_is_down = 1;
2080+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol & ~WM97XX_GPIO_13);
2081+ } else {
2082+ wm->pen_is_down = 0;
2083+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol | WM97XX_GPIO_13);
2084+ }
2085+
2086+ if (wm->id == WM9712_ID2)
2087+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & ~WM97XX_GPIO_13) << 1);
2088+ else
2089+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, status & ~WM97XX_GPIO_13);
2090+ mutex_unlock(&wm->codec_mutex);
2091+ wake_up_interruptible(&wm->pen_irq_wait);
2092+ }
2093+
2094+ if (!wm->pen_is_down && wm->mach_ops && wm->mach_ops->acc_enabled)
2095+ wm->mach_ops->acc_pen_up(wm);
2096+ enable_irq(wm->pen_irq);
2097+}
2098+
2099+/*
2100+ * Codec PENDOWN irq handler
2101+ *
2102+ * We have to disable the codec interrupt in the handler because it can
2103+ * take upto 1ms to clear the interrupt source. The interrupt is then enabled
2104+ * again in the slow handler when the source has been cleared.
2105+ */
2106+static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id,
2107+ struct pt_regs *regs)
2108+{
2109+ struct wm97xx *wm = (struct wm97xx *) dev_id;
2110+ disable_irq(wm->pen_irq);
2111+ queue_work(wm->pen_irq_workq, &wm->pen_event_work);
2112+ return IRQ_HANDLED;
2113+}
2114+
2115+/*
2116+ * initialise pen IRQ handler and workqueue
2117+ */
2118+static int wm97xx_init_pen_irq(struct wm97xx *wm)
2119+{
2120+ u16 reg;
2121+
2122+ INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker, wm);
2123+ if ((wm->pen_irq_workq =
2124+ create_singlethread_workqueue("kwm97pen")) == NULL) {
2125+ err("could not create pen irq work queue");
2126+ wm->pen_irq = 0;
2127+ return -EINVAL;
2128+ }
2129+
2130+ if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) {
2131+ err("could not register codec pen down interrupt, will poll for pen down");
2132+ destroy_workqueue(wm->pen_irq_workq);
2133+ wm->pen_irq = 0;
2134+ return -EINVAL;
2135+ }
2136+
2137+ /* enable PEN down on wm9712/13 */
2138+ if (wm->id != WM9705_ID2) {
2139+ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
2140+ wm97xx_reg_write(wm, AC97_MISC_AFE, reg & 0xfffb);
2141+ reg = wm97xx_reg_read(wm, 0x5a);
2142+ wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
2143+ }
2144+
2145+ return 0;
2146+}
2147+
2148+/* Private struct for communication between struct wm97xx_tshread
2149+ * and wm97xx_read_samples */
2150+struct ts_state {
2151+ int sleep_time;
2152+ int min_sleep_time;
2153+};
2154+
2155+static int wm97xx_read_samples(struct wm97xx *wm, struct ts_state *state)
2156+{
2157+ struct wm97xx_data data;
2158+ int rc;
2159+
2160+ mutex_lock(&wm->codec_mutex);
2161+
2162+ if (wm->mach_ops && wm->mach_ops->acc_enabled)
2163+ rc = wm->mach_ops->acc_pen_down(wm);
2164+ else
2165+ rc = wm->codec->poll_touch(wm, &data);
2166+
2167+ if (rc & RC_PENUP) {
2168+ if (wm->pen_is_down) {
2169+ wm->pen_is_down = 0;
2170+ dbg("pen up");
2171+ input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
2172+ input_sync(wm->input_dev);
2173+ } else if (!(rc & RC_AGAIN)) {
2174+ /* We need high frequency updates only while pen is down,
2175+ * the user never will be able to touch screen faster than
2176+ * a few times per second... On the other hand, when the
2177+ * user is actively working with the touchscreen we don't
2178+ * want to lose the quick response. So we will slowly
2179+ * increase sleep time after the pen is up and quicky
2180+ * restore it to ~one task switch when pen is down again.
2181+ */
2182+ if (state->sleep_time < HZ / 10)
2183+ state->sleep_time++;
2184+ }
2185+
2186+ } else if (rc & RC_VALID) {
2187+ dbg("pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
2188+ data.x >> 12, data.x & 0xfff, data.y >> 12,
2189+ data.y & 0xfff, data.p >> 12, data.p & 0xfff);
2190+ input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
2191+ input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
2192+ input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
2193+ input_sync(wm->input_dev);
2194+ wm->pen_is_down = 1;
2195+ state->sleep_time = state->min_sleep_time;
2196+ } else if (rc & RC_PENDOWN) {
2197+ dbg("pen down");
2198+ wm->pen_is_down = 1;
2199+ state->sleep_time = state->min_sleep_time;
2200+ }
2201+
2202+ mutex_unlock(&wm->codec_mutex);
2203+ return rc;
2204+}
2205+
2206+/*
2207+* The touchscreen sample reader thread.
2208+*/
2209+static int wm97xx_ts_read(void *data)
2210+{
2211+ int rc;
2212+ struct ts_state state;
2213+ struct wm97xx *wm = (struct wm97xx *) data;
2214+
2215+ /* set up thread context */
2216+ wm->ts_task = current;
2217+ daemonize("kwm97xxts");
2218+
2219+ if (wm->codec == NULL) {
2220+ wm->ts_task = NULL;
2221+ printk(KERN_ERR "codec is NULL, bailing\n");
2222+ }
2223+
2224+ complete(&wm->ts_init);
2225+ wm->pen_is_down = 0;
2226+ state.min_sleep_time = HZ >= 100 ? HZ / 100 : 1;
2227+ if (state.min_sleep_time < 1)
2228+ state.min_sleep_time = 1;
2229+ state.sleep_time = state.min_sleep_time;
2230+
2231+ /* touch reader loop */
2232+ while (wm->ts_task) {
2233+ do {
2234+ try_to_freeze();
2235+ rc = wm97xx_read_samples(wm, &state);
2236+ } while (rc & RC_AGAIN);
2237+ if (!wm->pen_is_down && wm->pen_irq) {
2238+ /* Nice, we don't have to poll for pen down event */
2239+ wait_event_interruptible(wm->pen_irq_wait, wm->pen_is_down);
2240+ } else {
2241+ set_task_state(current, TASK_INTERRUPTIBLE);
2242+ schedule_timeout(state.sleep_time);
2243+ }
2244+ }
2245+ complete_and_exit(&wm->ts_exit, 0);
2246+}
2247+
2248+/**
2249+ * wm97xx_ts_input_open - Open the touch screen input device.
2250+ * @idev: Input device to be opened.
2251+ *
2252+ * Called by the input sub system to open a wm97xx touchscreen device.
2253+ * Starts the touchscreen thread and touch digitiser.
2254+ */
2255+static int wm97xx_ts_input_open(struct input_dev *idev)
2256+{
2257+ int ret = 0;
2258+ struct wm97xx *wm = (struct wm97xx *) idev->private;
2259+
2260+ mutex_lock(&wm->codec_mutex);
2261+ /* first time opened ? */
2262+ if (wm->ts_use_count++ == 0) {
2263+ /* start touchscreen thread */
2264+ init_completion(&wm->ts_init);
2265+ init_completion(&wm->ts_exit);
2266+ ret = kernel_thread(wm97xx_ts_read, wm, CLONE_KERNEL);
2267+
2268+ if (ret >= 0) {
2269+ wait_for_completion(&wm->ts_init);
2270+ if (wm->ts_task == NULL)
2271+ ret = -EINVAL;
2272+ } else {
2273+ mutex_unlock(&wm->codec_mutex);
2274+ return ret;
2275+ }
2276+
2277+ /* start digitiser */
2278+ if (wm->mach_ops && wm->mach_ops->acc_enabled)
2279+ wm->codec->acc_enable(wm, 1);
2280+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_START);
2281+
2282+ /* init pen down/up irq handling */
2283+ if (wm->pen_irq) {
2284+ wm97xx_init_pen_irq(wm);
2285+
2286+ if (wm->pen_irq == 0) {
2287+ /* we failed to get an irq for pen down events,
2288+ * so we resort to polling. kickstart the reader */
2289+ wm->pen_is_down = 1;
2290+ wake_up_interruptible(&wm->pen_irq_wait);
2291+ }
2292+ }
2293+ }
2294+
2295+ mutex_unlock(&wm->codec_mutex);
2296+ return 0;
2297+}
2298+
2299+/**
2300+ * wm97xx_ts_input_close - Close the touch screen input device.
2301+ * @idev: Input device to be closed.
2302+ *
2303+ * Called by the input sub system to close a wm97xx touchscreen device.
2304+ * Kills the touchscreen thread and stops the touch digitiser.
2305+ */
2306+
2307+static void wm97xx_ts_input_close(struct input_dev *idev)
2308+{
2309+ struct wm97xx *wm = (struct wm97xx *) idev->private;
2310+
2311+ mutex_lock(&wm->codec_mutex);
2312+ if (--wm->ts_use_count == 0) {
2313+ /* destroy workqueues and free irqs */
2314+ if (wm->pen_irq) {
2315+ free_irq(wm->pen_irq, wm);
2316+ destroy_workqueue(wm->pen_irq_workq);
2317+ }
2318+
2319+ /* kill thread */
2320+ if (wm->ts_task) {
2321+ wm->ts_task = NULL;
2322+ wm->pen_is_down = 1;
2323+ wake_up_interruptible(&wm->pen_irq_wait);
2324+ wait_for_completion(&wm->ts_exit);
2325+ wm->pen_is_down = 0;
2326+ }
2327+
2328+ /* stop digitiser */
2329+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_STOP);
2330+ if (wm->mach_ops && wm->mach_ops->acc_enabled)
2331+ wm->codec->acc_enable(wm, 0);
2332+ }
2333+ mutex_unlock(&wm->codec_mutex);
2334+}
2335+
2336+static int wm97xx_bus_match(struct device *dev, struct device_driver *drv)
2337+{
2338+ return !(strcmp(dev->bus_id,drv->name));
2339+}
2340+
2341+/*
2342+ * The AC97 audio driver will do all the Codec suspend and resume
2343+ * tasks. This is just for anything machine specific or extra.
2344+ */
2345+static int wm97xx_bus_suspend(struct device *dev, pm_message_t state)
2346+{
2347+ int ret = 0;
2348+
2349+ if (dev->driver && dev->driver->suspend)
2350+ ret = dev->driver->suspend(dev, state);
2351+
2352+ return ret;
2353+}
2354+
2355+static int wm97xx_bus_resume(struct device *dev)
2356+{
2357+ int ret = 0;
2358+
2359+ if (dev->driver && dev->driver->resume)
2360+ ret = dev->driver->resume(dev);
2361+
2362+ return ret;
2363+}
2364+
2365+struct bus_type wm97xx_bus_type = {
2366+ .name = "wm97xx",
2367+ .match = wm97xx_bus_match,
2368+ .suspend = wm97xx_bus_suspend,
2369+ .resume = wm97xx_bus_resume,
2370+};
2371+
2372+static void wm97xx_release(struct device *dev)
2373+{
2374+ kfree(dev);
2375+}
2376+
2377+static int wm97xx_probe(struct device *dev)
2378+{
2379+ struct wm97xx* wm;
2380+ int ret = 0, id = 0;
2381+
2382+ if (!(wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL)))
2383+ return -ENOMEM;
2384+ mutex_init(&wm->codec_mutex);
2385+
2386+ init_waitqueue_head(&wm->pen_irq_wait);
2387+ wm->dev = dev;
2388+ dev->driver_data = wm;
2389+ wm->ac97 = to_ac97_t(dev);
2390+
2391+ /* check that we have a supported codec */
2392+ if ((id = wm97xx_reg_read(wm, AC97_VENDOR_ID1)) != WM97XX_ID1) {
2393+ err("could not find a wm97xx, found a %x instead\n", id);
2394+ kfree(wm);
2395+ return -ENODEV;
2396+ }
2397+
2398+ wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
2399+ if(wm->id != wm97xx_codec.id) {
2400+ err("could not find a the selected codec, please build for wm97%2x", wm->id & 0xff);
2401+ kfree(wm);
2402+ return -ENODEV;
2403+ }
2404+
2405+ if((wm->input_dev = input_allocate_device()) == NULL) {
2406+ kfree(wm);
2407+ return -ENOMEM;
2408+ }
2409+
2410+ /* set up touch configuration */
2411+ info("detected a wm97%2x codec", wm->id & 0xff);
2412+ wm->input_dev->name = "wm97xx touchscreen";
2413+ wm->input_dev->open = wm97xx_ts_input_open;
2414+ wm->input_dev->close = wm97xx_ts_input_close;
2415+ set_bit(EV_ABS, wm->input_dev->evbit);
2416+ set_bit(ABS_X, wm->input_dev->absbit);
2417+ set_bit(ABS_Y, wm->input_dev->absbit);
2418+ set_bit(ABS_PRESSURE, wm->input_dev->absbit);
2419+ wm->input_dev->absmax[ABS_X] = abs_x[1];
2420+ wm->input_dev->absmax[ABS_Y] = abs_y[1];
2421+ wm->input_dev->absmax[ABS_PRESSURE] = abs_p[1];
2422+ wm->input_dev->absmin[ABS_X] = abs_x[0];
2423+ wm->input_dev->absmin[ABS_Y] = abs_y[0];
2424+ wm->input_dev->absmin[ABS_PRESSURE] = abs_p[0];
2425+ wm->input_dev->absfuzz[ABS_X] = abs_x[2];
2426+ wm->input_dev->absfuzz[ABS_Y] = abs_y[2];
2427+ wm->input_dev->absfuzz[ABS_PRESSURE] = abs_p[2];
2428+ wm->input_dev->private = wm;
2429+ wm->codec = &wm97xx_codec;
2430+ if((ret = input_register_device(wm->input_dev)) < 0) {
2431+ kfree(wm);
2432+ return -ENOMEM;
2433+ }
2434+
2435+ if(aux_sys)
2436+ wm97xx_sys_add(dev);
2437+
2438+ /* set up physical characteristics */
2439+ wm->codec->digitiser_ioctl(wm, WM97XX_PHY_INIT);
2440+
2441+ /* load gpio cache */
2442+ wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
2443+ wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
2444+ wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
2445+ wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
2446+ wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
2447+ wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
2448+
2449+ /* register our battery device */
2450+ if (!(wm->battery_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
2451+ ret = -ENOMEM;
2452+ goto batt_err;
2453+ }
2454+ wm->battery_dev->bus = &wm97xx_bus_type;
2455+ strcpy(wm->battery_dev->bus_id,"wm97xx-battery");
2456+ wm->battery_dev->driver_data = wm;
2457+ wm->battery_dev->parent = dev;
2458+ wm->battery_dev->release = wm97xx_release;
2459+ if((ret = device_register(wm->battery_dev)) < 0)
2460+ goto batt_reg_err;
2461+
2462+ /* register our extended touch device (for machine specific extensions) */
2463+ if (!(wm->touch_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
2464+ ret = -ENOMEM;
2465+ goto touch_err;
2466+ }
2467+ wm->touch_dev->bus = &wm97xx_bus_type;
2468+ strcpy(wm->touch_dev->bus_id,"wm97xx-touchscreen");
2469+ wm->touch_dev->driver_data = wm;
2470+ wm->touch_dev->parent = dev;
2471+ wm->touch_dev->release = wm97xx_release;
2472+ if((ret = device_register(wm->touch_dev)) < 0)
2473+ goto touch_reg_err;
2474+
2475+ return ret;
2476+
2477+touch_reg_err:
2478+ kfree(wm->touch_dev);
2479+touch_err:
2480+ device_unregister(wm->battery_dev);
2481+batt_reg_err:
2482+ kfree(wm->battery_dev);
2483+batt_err:
2484+ input_unregister_device(wm->input_dev);
2485+ kfree(wm);
2486+ return ret;
2487+}
2488+
2489+static int wm97xx_remove(struct device *dev)
2490+{
2491+ struct wm97xx *wm = dev_get_drvdata(dev);
2492+
2493+ /* Stop touch reader thread */
2494+ if (wm->ts_task) {
2495+ wm->ts_task = NULL;
2496+ wm->pen_is_down = 1;
2497+ wake_up_interruptible(&wm->pen_irq_wait);
2498+ wait_for_completion(&wm->ts_exit);
2499+ }
2500+ device_unregister(wm->battery_dev);
2501+ device_unregister(wm->touch_dev);
2502+ input_unregister_device(wm->input_dev);
2503+
2504+ if(aux_sys)
2505+ wm97xx_sys_remove(dev);
2506+
2507+ kfree(wm);
2508+ return 0;
2509+}
2510+
2511+#ifdef CONFIG_PM
2512+int wm97xx_resume(struct device* dev)
2513+{
2514+ struct wm97xx *wm = dev_get_drvdata(dev);
2515+
2516+ /* restore digitiser and gpio's */
2517+ if(wm->id == WM9713_ID2) {
2518+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
2519+ wm97xx_reg_write(wm, 0x5a, wm->misc);
2520+ if(wm->ts_use_count) {
2521+ u16 reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
2522+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
2523+ }
2524+ }
2525+
2526+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
2527+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
2528+
2529+ wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
2530+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
2531+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
2532+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
2533+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
2534+ wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
2535+
2536+ return 0;
2537+}
2538+
2539+#else
2540+#define wm97xx_resume NULL
2541+#endif
2542+
2543+int wm97xx_register_mach_ops(struct wm97xx *wm, struct wm97xx_mach_ops *mach_ops)
2544+{
2545+ mutex_lock(&wm->codec_mutex);
2546+ if(wm->mach_ops) {
2547+ mutex_unlock(&wm->codec_mutex);
2548+ return -EINVAL;
2549+ }
2550+ wm->mach_ops = mach_ops;
2551+ mutex_unlock(&wm->codec_mutex);
2552+ return 0;
2553+}
2554+
2555+void wm97xx_unregister_mach_ops(struct wm97xx *wm)
2556+{
2557+ mutex_lock(&wm->codec_mutex);
2558+ wm->mach_ops = NULL;
2559+ mutex_unlock(&wm->codec_mutex);
2560+}
2561+
2562+static struct device_driver wm97xx_driver = {
2563+ .name = "ac97",
2564+ .bus = &ac97_bus_type,
2565+ .owner = THIS_MODULE,
2566+ .probe = wm97xx_probe,
2567+ .remove = wm97xx_remove,
2568+ .resume = wm97xx_resume,
2569+};
2570+
2571+static int __init wm97xx_init(void)
2572+{
2573+ int ret;
2574+
2575+ info("version %s liam.girdwood@wolfsonmicro.com", WM_CORE_VERSION);
2576+ if((ret = bus_register(&wm97xx_bus_type)) < 0)
2577+ return ret;
2578+ return driver_register(&wm97xx_driver);
2579+}
2580+
2581+static void __exit wm97xx_exit(void)
2582+{
2583+ driver_unregister(&wm97xx_driver);
2584+ bus_unregister(&wm97xx_bus_type);
2585+}
2586+
2587+EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
2588+EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
2589+EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
2590+EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
2591+EXPORT_SYMBOL_GPL(wm97xx_reg_read);
2592+EXPORT_SYMBOL_GPL(wm97xx_reg_write);
2593+EXPORT_SYMBOL_GPL(wm97xx_bus_type);
2594+EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
2595+EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
2596+
2597+module_init(wm97xx_init);
2598+module_exit(wm97xx_exit);
2599+
2600+/* Module information */
2601+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
2602+MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
2603+MODULE_LICENSE("GPL");
2604Index: linux-2.6.17/include/linux/wm97xx.h
2605===================================================================
2606--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2607+++ linux-2.6.17/include/linux/wm97xx.h 2006-09-19 20:36:47.973052250 +0200
2608@@ -0,0 +1,291 @@
2609+
2610+/*
2611+ * Register bits and API for Wolfson WM97xx series of codecs
2612+ */
2613+
2614+#ifndef _LINUX_WM97XX_H
2615+#define _LINUX_WM97XX_H
2616+
2617+#include <sound/driver.h>
2618+#include <sound/core.h>
2619+#include <sound/pcm.h>
2620+#include <sound/ac97_codec.h>
2621+#include <sound/initval.h>
2622+#include <linux/types.h>
2623+#include <linux/list.h>
2624+#include <linux/input.h> /* Input device layer */
2625+
2626+/*
2627+ * WM97xx AC97 Touchscreen registers
2628+ */
2629+#define AC97_WM97XX_DIGITISER1 0x76
2630+#define AC97_WM97XX_DIGITISER2 0x78
2631+#define AC97_WM97XX_DIGITISER_RD 0x7a
2632+#define AC97_WM9713_DIG1 0x74
2633+#define AC97_WM9713_DIG2 AC97_WM97XX_DIGITISER1
2634+#define AC97_WM9713_DIG3 AC97_WM97XX_DIGITISER2
2635+
2636+/*
2637+ * WM97xx register bits
2638+ */
2639+#define WM97XX_POLL 0x8000 /* initiate a polling measurement */
2640+#define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */
2641+#define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */
2642+#define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */
2643+#define WM97XX_ADCSEL_MASK 0x7000
2644+#define WM97XX_COO 0x0800 /* enable coordinate mode */
2645+#define WM97XX_CTC 0x0400 /* enable continuous mode */
2646+#define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */
2647+#define WM97XX_CM_RATE_187 0x0100 /* 187.5Hz continuous rate */
2648+#define WM97XX_CM_RATE_375 0x0200 /* 375Hz continuous rate */
2649+#define WM97XX_CM_RATE_750 0x0300 /* 750Hz continuous rate */
2650+#define WM97XX_CM_RATE_8K 0x00f0 /* 8kHz continuous rate */
2651+#define WM97XX_CM_RATE_12K 0x01f0 /* 12kHz continuous rate */
2652+#define WM97XX_CM_RATE_24K 0x02f0 /* 24kHz continuous rate */
2653+#define WM97XX_CM_RATE_48K 0x03f0 /* 48kHz continuous rate */
2654+#define WM97XX_CM_RATE_MASK 0x03f0
2655+#define WM97XX_RATE(i) (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
2656+#define WM97XX_DELAY(i) ((i << 4) & 0x00f0) /* sample delay times */
2657+#define WM97XX_DELAY_MASK 0x00f0
2658+#define WM97XX_SLEN 0x0008 /* slot read back enable */
2659+#define WM97XX_SLT(i) ((i - 5) & 0x7) /* touchpanel slot selection (5-11) */
2660+#define WM97XX_SLT_MASK 0x0007
2661+#define WM97XX_PRP_DETW 0x4000 /* pen detect on, digitiser off, wake up */
2662+#define WM97XX_PRP_DET 0x8000 /* pen detect on, digitiser off, no wake up */
2663+#define WM97XX_PRP_DET_DIG 0xc000 /* pen detect on, digitiser on */
2664+#define WM97XX_RPR 0x2000 /* wake up on pen down */
2665+#define WM97XX_PEN_DOWN 0x8000 /* pen is down */
2666+#define WM97XX_ADCSRC_MASK 0x7000 /* ADC source mask */
2667+
2668+#define WM97XX_AUX_ID1 0x8001
2669+#define WM97XX_AUX_ID2 0x8002
2670+#define WM97XX_AUX_ID3 0x8003
2671+#define WM97XX_AUX_ID4 0x8004
2672+
2673+
2674+/* WM9712 Bits */
2675+#define WM9712_45W 0x1000 /* set for 5-wire touchscreen */
2676+#define WM9712_PDEN 0x0800 /* measure only when pen down */
2677+#define WM9712_WAIT 0x0200 /* wait until adc is read before next sample */
2678+#define WM9712_PIL 0x0100 /* current used for pressure measurement. set 400uA else 200uA */
2679+#define WM9712_MASK_HI 0x0040 /* hi on mask pin (47) stops conversions */
2680+#define WM9712_MASK_EDGE 0x0080 /* rising/falling edge on pin delays sample */
2681+#define WM9712_MASK_SYNC 0x00c0 /* rising/falling edge on mask initiates sample */
2682+#define WM9712_RPU(i) (i&0x3f) /* internal pull up on pen detect (64k / rpu) */
2683+#define WM9712_PD(i) (0x1 << i) /* power management */
2684+
2685+/* WM9712 Registers */
2686+#define AC97_WM9712_POWER 0x24
2687+#define AC97_WM9712_REV 0x58
2688+
2689+/* WM9705 Bits */
2690+#define WM9705_PDEN 0x1000 /* measure only when pen is down */
2691+#define WM9705_PINV 0x0800 /* inverts sense of pen down output */
2692+#define WM9705_BSEN 0x0400 /* BUSY flag enable, pin47 is 1 when busy */
2693+#define WM9705_BINV 0x0200 /* invert BUSY (pin47) output */
2694+#define WM9705_WAIT 0x0100 /* wait until adc is read before next sample */
2695+#define WM9705_PIL 0x0080 /* current used for pressure measurement. set 400uA else 200uA */
2696+#define WM9705_PHIZ 0x0040 /* set PHONE and PCBEEP inputs to high impedance */
2697+#define WM9705_MASK_HI 0x0010 /* hi on mask stops conversions */
2698+#define WM9705_MASK_EDGE 0x0020 /* rising/falling edge on pin delays sample */
2699+#define WM9705_MASK_SYNC 0x0030 /* rising/falling edge on mask initiates sample */
2700+#define WM9705_PDD(i) (i & 0x000f) /* pen detect comparator threshold */
2701+
2702+
2703+/* WM9713 Bits */
2704+#define WM9713_PDPOL 0x0400 /* Pen down polarity */
2705+#define WM9713_POLL 0x0200 /* initiate a polling measurement */
2706+#define WM9713_CTC 0x0100 /* enable continuous mode */
2707+#define WM9713_ADCSEL_X 0x0002 /* X measurement */
2708+#define WM9713_ADCSEL_Y 0x0004 /* Y measurement */
2709+#define WM9713_ADCSEL_PRES 0x0008 /* Pressure measurement */
2710+#define WM9713_COO 0x0001 /* enable coordinate mode */
2711+#define WM9713_PDEN 0x0800 /* measure only when pen down */
2712+#define WM9713_ADCSEL_MASK 0x00fe /* ADC selection mask */
2713+#define WM9713_WAIT 0x0200 /* coordinate wait */
2714+
2715+/* AUX ADC ID's */
2716+#define TS_COMP1 0x0
2717+#define TS_COMP2 0x1
2718+#define TS_BMON 0x2
2719+#define TS_WIPER 0x3
2720+
2721+/* ID numbers */
2722+#define WM97XX_ID1 0x574d
2723+#define WM9712_ID2 0x4c12
2724+#define WM9705_ID2 0x4c05
2725+#define WM9713_ID2 0x4c13
2726+
2727+/* Codec GPIO's */
2728+#define WM97XX_MAX_GPIO 16
2729+#define WM97XX_GPIO_1 (1 << 1)
2730+#define WM97XX_GPIO_2 (1 << 2)
2731+#define WM97XX_GPIO_3 (1 << 3)
2732+#define WM97XX_GPIO_4 (1 << 4)
2733+#define WM97XX_GPIO_5 (1 << 5)
2734+#define WM97XX_GPIO_6 (1 << 6)
2735+#define WM97XX_GPIO_7 (1 << 7)
2736+#define WM97XX_GPIO_8 (1 << 8)
2737+#define WM97XX_GPIO_9 (1 << 9)
2738+#define WM97XX_GPIO_10 (1 << 10)
2739+#define WM97XX_GPIO_11 (1 << 11)
2740+#define WM97XX_GPIO_12 (1 << 12)
2741+#define WM97XX_GPIO_13 (1 << 13)
2742+#define WM97XX_GPIO_14 (1 << 14)
2743+#define WM97XX_GPIO_15 (1 << 15)
2744+
2745+
2746+#define AC97_LINK_FRAME 21 /* time in uS for AC97 link frame */
2747+
2748+
2749+/*---------------- Return codes from sample reading functions ---------------*/
2750+
2751+/* More data is available; call the sample gathering function again */
2752+#define RC_AGAIN 0x00000001
2753+/* The returned sample is valid */
2754+#define RC_VALID 0x00000002
2755+/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
2756+#define RC_PENUP 0x00000004
2757+/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
2758+ to tell the handler that the pen is down but we don't know yet his coords,
2759+ so the handler should not sleep or wait for pendown irq) */
2760+#define RC_PENDOWN 0x00000008
2761+
2762+/* The wm97xx driver provides a private API for writing platform-specific
2763+ * drivers.
2764+ */
2765+
2766+/* The structure used to return arch specific sampled data into */
2767+struct wm97xx_data {
2768+ int x;
2769+ int y;
2770+ int p;
2771+};
2772+
2773+/* Codec GPIO status
2774+ */
2775+typedef enum {
2776+ WM97XX_GPIO_HIGH,
2777+ WM97XX_GPIO_LOW
2778+} wm97xx_gpio_status_t;
2779+
2780+/* Codec GPIO direction
2781+ */
2782+typedef enum {
2783+ WM97XX_GPIO_IN,
2784+ WM97XX_GPIO_OUT
2785+} wm97xx_gpio_dir_t;
2786+
2787+/* Codec GPIO polarity
2788+ */
2789+typedef enum {
2790+ WM97XX_GPIO_POL_HIGH,
2791+ WM97XX_GPIO_POL_LOW
2792+} wm97xx_gpio_pol_t;
2793+
2794+/* Codec GPIO sticky
2795+ */
2796+typedef enum {
2797+ WM97XX_GPIO_STICKY,
2798+ WM97XX_GPIO_NOTSTICKY
2799+} wm97xx_gpio_sticky_t;
2800+
2801+/* Codec GPIO wake
2802+ */
2803+typedef enum {
2804+ WM97XX_GPIO_WAKE,
2805+ WM97XX_GPIO_NOWAKE
2806+} wm97xx_gpio_wake_t;
2807+
2808+
2809+/*
2810+ * Digitiser ioctl commands
2811+ */
2812+#define WM97XX_DIG_START 0x1
2813+#define WM97XX_DIG_STOP 0x2
2814+#define WM97XX_PHY_INIT 0x3
2815+#define WM97XX_AUX_PREPARE 0x4
2816+#define WM97XX_DIG_RESTORE 0x5
2817+
2818+struct wm97xx;
2819+extern struct wm97xx_codec_drv wm97xx_codec;
2820+
2821+/*
2822+ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
2823+ */
2824+struct wm97xx_codec_drv {
2825+ u16 id;
2826+ char *name;
2827+ int (*poll_sample) (struct wm97xx *, int adcsel, int *sample); /* read 1 sample */
2828+ int (*poll_touch) (struct wm97xx *, struct wm97xx_data *); /* read X,Y,[P] in poll */
2829+ int (*digitiser_ioctl) (struct wm97xx *, int cmd);
2830+ int (*acc_enable) (struct wm97xx *, int enable);
2831+};
2832+
2833+
2834+/* Machine specific and accelerated touch operations */
2835+struct wm97xx_mach_ops {
2836+
2837+ /* accelerated touch readback - coords are transmited on AC97 link */
2838+ int acc_enabled;
2839+ void (*acc_pen_up) (struct wm97xx *);
2840+ int (*acc_pen_down) (struct wm97xx *);
2841+ int (*acc_startup) (struct wm97xx *);
2842+ void (*acc_shutdown) (struct wm97xx *);
2843+
2844+ /* pre and post sample - can be used to minimise any analog noise */
2845+ void (*pre_sample) (int); /* function to run before sampling */
2846+ void (*post_sample) (int); /* function to run after sampling */
2847+};
2848+
2849+struct wm97xx {
2850+ u16 dig[3], id, gpio[6], misc; /* Cached codec registers */
2851+ u16 dig_save[3]; /* saved during aux reading */
2852+ struct wm97xx_codec_drv *codec; /* attached codec driver*/
2853+ struct input_dev* input_dev; /* touchscreen input device */
2854+ ac97_t *ac97; /* ALSA codec access */
2855+ struct device *dev; /* ALSA device */
2856+ struct device *battery_dev;
2857+ struct device *touch_dev;
2858+ struct wm97xx_mach_ops *mach_ops;
2859+ struct mutex codec_mutex;
2860+ struct completion ts_init;
2861+ struct completion ts_exit;
2862+ struct task_struct *ts_task;
2863+ unsigned int pen_irq; /* Pen IRQ number in use */
2864+ wait_queue_head_t pen_irq_wait; /* Pen IRQ wait queue */
2865+ struct workqueue_struct *pen_irq_workq;
2866+ struct work_struct pen_event_work;
2867+ u16 acc_slot; /* AC97 slot used for acc touch data */
2868+ u16 acc_rate; /* acc touch data rate */
2869+ unsigned int ts_use_count;
2870+ unsigned pen_is_down:1; /* Pen is down */
2871+ unsigned aux_waiting:1; /* aux measurement waiting */
2872+ unsigned pen_probably_down:1; /* used in polling mode */
2873+};
2874+
2875+/* Codec GPIO access (not supported on WM9705)
2876+ * This can be used to set/get codec GPIO and Virtual GPIO status.
2877+ */
2878+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
2879+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
2880+ wm97xx_gpio_status_t status);
2881+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
2882+ wm97xx_gpio_dir_t dir,
2883+ wm97xx_gpio_pol_t pol,
2884+ wm97xx_gpio_sticky_t sticky,
2885+ wm97xx_gpio_wake_t wake);
2886+
2887+/* codec AC97 IO access */
2888+int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
2889+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
2890+
2891+/* aux adc readback */
2892+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
2893+
2894+/* machine ops */
2895+int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
2896+void wm97xx_unregister_mach_ops(struct wm97xx *);
2897+
2898+extern struct bus_type wm97xx_bus_type;
2899+#endif