aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2008-04-02 10:02:43 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-04-02 10:02:43 -0400
commit45d09e1e097ea5fc0bcb98a6226d90b412e6923a (patch)
tree1338f1c493a89b11ed0cb3e9e9dbe2d6c317b568
parentf23c1d7579211c801494c7a8d6fca12905f7949f (diff)
parent4db8a5f21e5149e09949516eef98b78b68880075 (diff)
Merge branch 'wm97xx'
-rw-r--r--MAINTAINERS10
-rw-r--r--drivers/input/touchscreen/Kconfig53
-rw-r--r--drivers/input/touchscreen/Makefile7
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c302
-rw-r--r--drivers/input/touchscreen/wm9705.c353
-rw-r--r--drivers/input/touchscreen/wm9712.c462
-rw-r--r--drivers/input/touchscreen/wm9713.c460
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c789
-rw-r--r--include/linux/wm97xx.h311
9 files changed, 2747 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 90dcbbcad91c..87bdced169a4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4343,6 +4343,16 @@ L: linux-wireless@vger.kernel.org
4343W: http://oops.ghostprotocols.net:81/blog 4343W: http://oops.ghostprotocols.net:81/blog
4344S: Maintained 4344S: Maintained
4345 4345
4346WM97XX TOUCHSCREEN DRIVERS
4347P: Mark Brown
4348M: broonie@opensource.wolfsonmicro.com
4349P: Liam Girdwood
4350M: liam.girdwood@wolfsonmicro.com
4351L: linux-input@vger.kernel.org
4352T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
4353W: http://opensource.wolfsonmicro.com/node/7
4354S: Supported
4355
4346X.25 NETWORK LAYER 4356X.25 NETWORK LAYER
4347P: Henner Eisen 4357P: Henner Eisen
4348M: eis@baty.hanse.de 4358M: eis@baty.hanse.de
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 90e8e92dfe47..565ec711c2ee 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -185,6 +185,59 @@ config TOUCHSCREEN_UCB1400
185 To compile this driver as a module, choose M here: the 185 To compile this driver as a module, choose M here: the
186 module will be called ucb1400_ts. 186 module will be called ucb1400_ts.
187 187
188config TOUCHSCREEN_WM97XX
189 tristate "Support for WM97xx AC97 touchscreen controllers"
190 depends on AC97_BUS
191 help
192 Say Y here if you have a Wolfson Microelectronics WM97xx
193 touchscreen connected to your system. Note that this option
194 only enables core driver, you will also need to select
195 support for appropriate chip below.
196
197 If unsure, say N.
198
199 To compile this driver as a module, choose M here: the
200 module will be called wm97xx-ts.
201
202config TOUCHSCREEN_WM9705
203 bool "WM9705 Touchscreen interface support"
204 depends on TOUCHSCREEN_WM97XX
205 help
206 Say Y here if you have a Wolfson Microelectronics WM9705
207 touchscreen controller connected to your system.
208
209 If unsure, say N.
210
211config TOUCHSCREEN_WM9712
212 bool "WM9712 Touchscreen interface support"
213 depends on TOUCHSCREEN_WM97XX
214 help
215 Say Y here if you have a Wolfson Microelectronics WM9712
216 touchscreen controller connected to your system.
217
218 If unsure, say N.
219
220config TOUCHSCREEN_WM9713
221 bool "WM9713 Touchscreen interface support"
222 depends on TOUCHSCREEN_WM97XX
223 help
224 Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen
225 controller connected to your system.
226
227 If unsure, say N.
228
229config TOUCHSCREEN_WM97XX_MAINSTONE
230 tristate "WM97xx Mainstone accelerated touch"
231 depends on TOUCHSCREEN_WM97XX && ARCH_PXA
232 help
233 Say Y here for support for streaming mode with WM97xx touchscreens
234 on Mainstone systems.
235
236 If unsure, say N.
237
238 To compile this driver as a module, choose M here: the
239 module will be called mainstone-wm97xx.
240
188config TOUCHSCREEN_USB_COMPOSITE 241config TOUCHSCREEN_USB_COMPOSITE
189 tristate "USB Touchscreen Driver" 242 tristate "USB Touchscreen Driver"
190 depends on USB_ARCH_HAS_HCD 243 depends on USB_ARCH_HAS_HCD
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 35d4097df35a..3c096d75651d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -4,6 +4,8 @@
4 4
5# Each configuration option enables a list of files. 5# Each configuration option enables a list of files.
6 6
7wm97xx-ts-y := wm97xx-core.o
8
7obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o 9obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
8obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o 10obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
9obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o 11obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
19obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o 21obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
20obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o 22obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
21obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o 23obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
24obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
25wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
26wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
27wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
28obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
new file mode 100644
index 000000000000..a79f029b91c0
--- /dev/null
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -0,0 +1,302 @@
1/*
2 * mainstone-wm97xx.c -- Mainstone Continuous Touch screen driver for
3 * Wolfson WM97xx AC97 Codecs.
4 *
5 * Copyright 2004, 2007 Wolfson Microelectronics PLC.
6 * Author: Liam Girdwood
7 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
8 * Parts Copyright : Ian Molton <spyro@f2s.com>
9 * Andrew Zabolotny <zap@homelink.ru>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * Notes:
17 * This is a wm97xx extended touch driver to capture touch
18 * data in a continuous manner on the Intel XScale archictecture
19 *
20 * Features:
21 * - codecs supported:- WM9705, WM9712, WM9713
22 * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/version.h>
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <linux/delay.h>
32#include <linux/irq.h>
33#include <linux/interrupt.h>
34#include <linux/wm97xx.h>
35#include <linux/io.h>
36#include <asm/arch/pxa-regs.h>
37
38#define VERSION "0.13"
39
40struct continuous {
41 u16 id; /* codec id */
42 u8 code; /* continuous code */
43 u8 reads; /* number of coord reads per read cycle */
44 u32 speed; /* number of coords per second */
45};
46
47#define WM_READS(sp) ((sp / HZ) + 1)
48
49static const struct continuous cinfo[] = {
50 {WM9705_ID2, 0, WM_READS(94), 94},
51 {WM9705_ID2, 1, WM_READS(188), 188},
52 {WM9705_ID2, 2, WM_READS(375), 375},
53 {WM9705_ID2, 3, WM_READS(750), 750},
54 {WM9712_ID2, 0, WM_READS(94), 94},
55 {WM9712_ID2, 1, WM_READS(188), 188},
56 {WM9712_ID2, 2, WM_READS(375), 375},
57 {WM9712_ID2, 3, WM_READS(750), 750},
58 {WM9713_ID2, 0, WM_READS(94), 94},
59 {WM9713_ID2, 1, WM_READS(120), 120},
60 {WM9713_ID2, 2, WM_READS(154), 154},
61 {WM9713_ID2, 3, WM_READS(188), 188},
62};
63
64/* continuous speed index */
65static int sp_idx;
66static u16 last, tries;
67
68/*
69 * Pen sampling frequency (Hz) in continuous mode.
70 */
71static int cont_rate = 200;
72module_param(cont_rate, int, 0);
73MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
74
75/*
76 * Pen down detection.
77 *
78 * This driver can either poll or use an interrupt to indicate a pen down
79 * event. If the irq request fails then it will fall back to polling mode.
80 */
81static int pen_int;
82module_param(pen_int, int, 0);
83MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
84
85/*
86 * Pressure readback.
87 *
88 * Set to 1 to read back pen down pressure
89 */
90static int pressure;
91module_param(pressure, int, 0);
92MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
93
94/*
95 * AC97 touch data slot.
96 *
97 * Touch screen readback data ac97 slot
98 */
99static int ac97_touch_slot = 5;
100module_param(ac97_touch_slot, int, 0);
101MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
102
103
104/* flush AC97 slot 5 FIFO on pxa machines */
105#ifdef CONFIG_PXA27x
106static void wm97xx_acc_pen_up(struct wm97xx *wm)
107{
108 schedule_timeout_uninterruptible(1);
109
110 while (MISR & (1 << 2))
111 MODR;
112}
113#else
114static void wm97xx_acc_pen_up(struct wm97xx *wm)
115{
116 int count = 16;
117 schedule_timeout_uninterruptible(1);
118
119 while (count < 16) {
120 MODR;
121 count--;
122 }
123}
124#endif
125
126static int wm97xx_acc_pen_down(struct wm97xx *wm)
127{
128 u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
129 int reads = 0;
130
131 /* When the AC97 queue has been drained we need to allow time
132 * to buffer up samples otherwise we end up spinning polling
133 * for samples. The controller can't have a suitably low
134 * threashold set to use the notifications it gives.
135 */
136 schedule_timeout_uninterruptible(1);
137
138 if (tries > 5) {
139 tries = 0;
140 return RC_PENUP;
141 }
142
143 x = MODR;
144 if (x == last) {
145 tries++;
146 return RC_AGAIN;
147 }
148 last = x;
149 do {
150 if (reads)
151 x = MODR;
152 y = MODR;
153 if (pressure)
154 p = MODR;
155
156 /* are samples valid */
157 if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
158 (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
159 (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
160 goto up;
161
162 /* coordinate is good */
163 tries = 0;
164 input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
165 input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
166 input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
167 input_sync(wm->input_dev);
168 reads++;
169 } while (reads < cinfo[sp_idx].reads);
170up:
171 return RC_PENDOWN | RC_AGAIN;
172}
173
174static int wm97xx_acc_startup(struct wm97xx *wm)
175{
176 int idx = 0;
177
178 /* check we have a codec */
179 if (wm->ac97 == NULL)
180 return -ENODEV;
181
182 /* Go you big red fire engine */
183 for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
184 if (wm->id != cinfo[idx].id)
185 continue;
186 sp_idx = idx;
187 if (cont_rate <= cinfo[idx].speed)
188 break;
189 }
190 wm->acc_rate = cinfo[sp_idx].code;
191 wm->acc_slot = ac97_touch_slot;
192 dev_info(wm->dev,
193 "mainstone accelerated touchscreen driver, %d samples/sec\n",
194 cinfo[sp_idx].speed);
195
196 /* codec specific irq config */
197 if (pen_int) {
198 switch (wm->id) {
199 case WM9705_ID2:
200 wm->pen_irq = IRQ_GPIO(4);
201 set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
202 break;
203 case WM9712_ID2:
204 case WM9713_ID2:
205 /* enable pen down interrupt */
206 /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
207 wm->pen_irq = MAINSTONE_AC97_IRQ;
208 wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
209 WM97XX_GPIO_POL_HIGH,
210 WM97XX_GPIO_STICKY,
211 WM97XX_GPIO_WAKE);
212 wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
213 WM97XX_GPIO_POL_HIGH,
214 WM97XX_GPIO_NOTSTICKY,
215 WM97XX_GPIO_NOWAKE);
216 break;
217 default:
218 dev_err(wm->dev,
219 "pen down irq not supported on this device\n");
220 pen_int = 0;
221 break;
222 }
223 }
224
225 return 0;
226}
227
228static void wm97xx_acc_shutdown(struct wm97xx *wm)
229{
230 /* codec specific deconfig */
231 if (pen_int) {
232 switch (wm->id & 0xffff) {
233 case WM9705_ID2:
234 wm->pen_irq = 0;
235 break;
236 case WM9712_ID2:
237 case WM9713_ID2:
238 /* disable interrupt */
239 wm->pen_irq = 0;
240 break;
241 }
242 }
243}
244
245static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
246{
247 if (enable)
248 enable_irq(wm->pen_irq);
249 else
250 disable_irq(wm->pen_irq);
251}
252
253static struct wm97xx_mach_ops mainstone_mach_ops = {
254 .acc_enabled = 1,
255 .acc_pen_up = wm97xx_acc_pen_up,
256 .acc_pen_down = wm97xx_acc_pen_down,
257 .acc_startup = wm97xx_acc_startup,
258 .acc_shutdown = wm97xx_acc_shutdown,
259 .irq_enable = wm97xx_irq_enable,
260 .irq_gpio = WM97XX_GPIO_2,
261};
262
263static int mainstone_wm97xx_probe(struct platform_device *pdev)
264{
265 struct wm97xx *wm = platform_get_drvdata(pdev);
266
267 return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
268}
269
270static int mainstone_wm97xx_remove(struct platform_device *pdev)
271{
272 struct wm97xx *wm = platform_get_drvdata(pdev);
273
274 wm97xx_unregister_mach_ops(wm);
275 return 0;
276}
277
278static struct platform_driver mainstone_wm97xx_driver = {
279 .probe = mainstone_wm97xx_probe,
280 .remove = mainstone_wm97xx_remove,
281 .driver = {
282 .name = "wm97xx-touch",
283 },
284};
285
286static int __init mainstone_wm97xx_init(void)
287{
288 return platform_driver_register(&mainstone_wm97xx_driver);
289}
290
291static void __exit mainstone_wm97xx_exit(void)
292{
293 platform_driver_unregister(&mainstone_wm97xx_driver);
294}
295
296module_init(mainstone_wm97xx_init);
297module_exit(mainstone_wm97xx_exit);
298
299/* Module information */
300MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
301MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
302MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
new file mode 100644
index 000000000000..978e1a13ffc7
--- /dev/null
+++ b/drivers/input/touchscreen/wm9705.c
@@ -0,0 +1,353 @@
1/*
2 * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
3 *
4 * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * Parts Copyright : Ian Molton <spyro@f2s.com>
8 * Andrew Zabolotny <zap@homelink.ru>
9 * Russell King <rmk@arm.linux.org.uk>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/version.h>
21#include <linux/kernel.h>
22#include <linux/input.h>
23#include <linux/delay.h>
24#include <linux/bitops.h>
25#include <linux/wm97xx.h>
26
27#define TS_NAME "wm97xx"
28#define WM9705_VERSION "1.00"
29#define DEFAULT_PRESSURE 0xb0c0
30
31/*
32 * Module parameters
33 */
34
35/*
36 * Set current used for pressure measurement.
37 *
38 * Set pil = 2 to use 400uA
39 * pil = 1 to use 200uA and
40 * pil = 0 to disable pressure measurement.
41 *
42 * This is used to increase the range of values returned by the adc
43 * when measureing touchpanel pressure.
44 */
45static int pil;
46module_param(pil, int, 0);
47MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
48
49/*
50 * Set threshold for pressure measurement.
51 *
52 * Pen down pressure below threshold is ignored.
53 */
54static int pressure = DEFAULT_PRESSURE & 0xfff;
55module_param(pressure, int, 0);
56MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
57
58/*
59 * Set adc sample delay.
60 *
61 * For accurate touchpanel measurements, some settling time may be
62 * required between the switch matrix applying a voltage across the
63 * touchpanel plate and the ADC sampling the signal.
64 *
65 * This delay can be set by setting delay = n, where n is the array
66 * position of the delay in the array delay_table below.
67 * Long delays > 1ms are supported for completeness, but are not
68 * recommended.
69 */
70static int delay = 4;
71module_param(delay, int, 0);
72MODULE_PARM_DESC(delay, "Set adc sample delay.");
73
74/*
75 * Pen detect comparator threshold.
76 *
77 * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
78 * i.e. 1 = Vmid/15 threshold
79 * 15 = Vmid/1 threshold
80 *
81 * Adjust this value if you are having problems with pen detect not
82 * detecting any down events.
83 */
84static int pdd = 8;
85module_param(pdd, int, 0);
86MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
87
88/*
89 * Set adc mask function.
90 *
91 * Sources of glitch noise, such as signals driving an LCD display, may feed
92 * through to the touch screen plates and affect measurement accuracy. In
93 * order to minimise this, a signal may be applied to the MASK pin to delay or
94 * synchronise the sampling.
95 *
96 * 0 = No delay or sync
97 * 1 = High on pin stops conversions
98 * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
99 * 3 = Edge triggered, edge on pin starts conversion after delay param
100 */
101static int mask;
102module_param(mask, int, 0);
103MODULE_PARM_DESC(mask, "Set adc mask function.");
104
105/*
106 * ADC sample delay times in uS
107 */
108static const int delay_table[] = {
109 21, /* 1 AC97 Link frames */
110 42, /* 2 */
111 84, /* 4 */
112 167, /* 8 */
113 333, /* 16 */
114 667, /* 32 */
115 1000, /* 48 */
116 1333, /* 64 */
117 2000, /* 96 */
118 2667, /* 128 */
119 3333, /* 160 */
120 4000, /* 192 */
121 4667, /* 224 */
122 5333, /* 256 */
123 6000, /* 288 */
124 0 /* No delay, switch matrix always on */
125};
126
127/*
128 * Delay after issuing a POLL command.
129 *
130 * The delay is 3 AC97 link frames + the touchpanel settling delay
131 */
132static inline void poll_delay(int d)
133{
134 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
135}
136
137/*
138 * set up the physical settings of the WM9705
139 */
140static void wm9705_phy_init(struct wm97xx *wm)
141{
142 u16 dig1 = 0, dig2 = WM97XX_RPR;
143
144 /*
145 * mute VIDEO and AUX as they share X and Y touchscreen
146 * inputs on the WM9705
147 */
148 wm97xx_reg_write(wm, AC97_AUX, 0x8000);
149 wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
150
151 /* touchpanel pressure current*/
152 if (pil == 2) {
153 dig2 |= WM9705_PIL;
154 dev_dbg(wm->dev,
155 "setting pressure measurement current to 400uA.");
156 } else if (pil)
157 dev_dbg(wm->dev,
158 "setting pressure measurement current to 200uA.");
159 if (!pil)
160 pressure = 0;
161
162 /* polling mode sample settling delay */
163 if (delay != 4) {
164 if (delay < 0 || delay > 15) {
165 dev_dbg(wm->dev, "supplied delay out of range.");
166 delay = 4;
167 }
168 }
169 dig1 &= 0xff0f;
170 dig1 |= WM97XX_DELAY(delay);
171 dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
172 delay_table[delay]);
173
174 /* WM9705 pdd */
175 dig2 |= (pdd & 0x000f);
176 dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
177
178 /* mask */
179 dig2 |= ((mask & 0x3) << 4);
180
181 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
182 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
183}
184
185static void wm9705_dig_enable(struct wm97xx *wm, int enable)
186{
187 if (enable) {
188 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
189 wm->dig[2] | WM97XX_PRP_DET_DIG);
190 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
191 } else
192 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
193 wm->dig[2] & ~WM97XX_PRP_DET_DIG);
194}
195
196static void wm9705_aux_prepare(struct wm97xx *wm)
197{
198 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
199 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
200 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
201}
202
203static void wm9705_dig_restore(struct wm97xx *wm)
204{
205 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
206 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
207}
208
209static inline int is_pden(struct wm97xx *wm)
210{
211 return wm->dig[2] & WM9705_PDEN;
212}
213
214/*
215 * Read a sample from the WM9705 adc in polling mode.
216 */
217static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
218{
219 int timeout = 5 * delay;
220
221 if (!wm->pen_probably_down) {
222 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
223 if (!(data & WM97XX_PEN_DOWN))
224 return RC_PENUP;
225 wm->pen_probably_down = 1;
226 }
227
228 /* set up digitiser */
229 if (adcsel & 0x8000)
230 adcsel = ((adcsel & 0x7fff) + 3) << 12;
231
232 if (wm->mach_ops && wm->mach_ops->pre_sample)
233 wm->mach_ops->pre_sample(adcsel);
234 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
235 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
236
237 /* wait 3 AC97 time slots + delay for conversion */
238 poll_delay(delay);
239
240 /* wait for POLL to go low */
241 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
242 && timeout) {
243 udelay(AC97_LINK_FRAME);
244 timeout--;
245 }
246
247 if (timeout == 0) {
248 /* If PDEN is set, we can get a timeout when pen goes up */
249 if (is_pden(wm))
250 wm->pen_probably_down = 0;
251 else
252 dev_dbg(wm->dev, "adc sample timeout");
253 return RC_PENUP;
254 }
255
256 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
257 if (wm->mach_ops && wm->mach_ops->post_sample)
258 wm->mach_ops->post_sample(adcsel);
259
260 /* check we have correct sample */
261 if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
262 dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
263 *sample & WM97XX_ADCSEL_MASK);
264 return RC_PENUP;
265 }
266
267 if (!(*sample & WM97XX_PEN_DOWN)) {
268 wm->pen_probably_down = 0;
269 return RC_PENUP;
270 }
271
272 return RC_VALID;
273}
274
275/*
276 * Sample the WM9705 touchscreen in polling mode
277 */
278static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
279{
280 int rc;
281
282 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
283 if (rc != RC_VALID)
284 return rc;
285 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
286 if (rc != RC_VALID)
287 return rc;
288 if (pil) {
289 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
290 if (rc != RC_VALID)
291 return rc;
292 } else
293 data->p = DEFAULT_PRESSURE;
294
295 return RC_VALID;
296}
297
298/*
299 * Enable WM9705 continuous mode, i.e. touch data is streamed across
300 * an AC97 slot
301 */
302static int wm9705_acc_enable(struct wm97xx *wm, int enable)
303{
304 u16 dig1, dig2;
305 int ret = 0;
306
307 dig1 = wm->dig[1];
308 dig2 = wm->dig[2];
309
310 if (enable) {
311 /* continous mode */
312 if (wm->mach_ops->acc_startup &&
313 (ret = wm->mach_ops->acc_startup(wm)) < 0)
314 return ret;
315 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
316 WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
317 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
318 WM97XX_DELAY(delay) |
319 WM97XX_SLT(wm->acc_slot) |
320 WM97XX_RATE(wm->acc_rate);
321 if (pil)
322 dig1 |= WM97XX_ADCSEL_PRES;
323 dig2 |= WM9705_PDEN;
324 } else {
325 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
326 dig2 &= ~WM9705_PDEN;
327 if (wm->mach_ops->acc_shutdown)
328 wm->mach_ops->acc_shutdown(wm);
329 }
330
331 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
332 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
333
334 return ret;
335}
336
337struct wm97xx_codec_drv wm9705_codec = {
338 .id = WM9705_ID2,
339 .name = "wm9705",
340 .poll_sample = wm9705_poll_sample,
341 .poll_touch = wm9705_poll_touch,
342 .acc_enable = wm9705_acc_enable,
343 .phy_init = wm9705_phy_init,
344 .dig_enable = wm9705_dig_enable,
345 .dig_restore = wm9705_dig_restore,
346 .aux_prepare = wm9705_aux_prepare,
347};
348EXPORT_SYMBOL_GPL(wm9705_codec);
349
350/* Module information */
351MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
352MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
353MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
new file mode 100644
index 000000000000..0b6e4cfa6a21
--- /dev/null
+++ b/drivers/input/touchscreen/wm9712.c
@@ -0,0 +1,462 @@
1/*
2 * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
3 *
4 * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * Parts Copyright : Ian Molton <spyro@f2s.com>
8 * Andrew Zabolotny <zap@homelink.ru>
9 * Russell King <rmk@arm.linux.org.uk>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/version.h>
21#include <linux/kernel.h>
22#include <linux/input.h>
23#include <linux/delay.h>
24#include <linux/bitops.h>
25#include <linux/wm97xx.h>
26
27#define TS_NAME "wm97xx"
28#define WM9712_VERSION "1.00"
29#define DEFAULT_PRESSURE 0xb0c0
30
31/*
32 * Module parameters
33 */
34
35/*
36 * Set internal pull up for pen detect.
37 *
38 * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
39 * i.e. pull up resistance = 64k Ohms / rpu.
40 *
41 * Adjust this value if you are having problems with pen detect not
42 * detecting any down event.
43 */
44static int rpu = 8;
45module_param(rpu, int, 0);
46MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
47
48/*
49 * Set current used for pressure measurement.
50 *
51 * Set pil = 2 to use 400uA
52 * pil = 1 to use 200uA and
53 * pil = 0 to disable pressure measurement.
54 *
55 * This is used to increase the range of values returned by the adc
56 * when measureing touchpanel pressure.
57 */
58static int pil;
59module_param(pil, int, 0);
60MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
61
62/*
63 * Set threshold for pressure measurement.
64 *
65 * Pen down pressure below threshold is ignored.
66 */
67static int pressure = DEFAULT_PRESSURE & 0xfff;
68module_param(pressure, int, 0);
69MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
70
71/*
72 * Set adc sample delay.
73 *
74 * For accurate touchpanel measurements, some settling time may be
75 * required between the switch matrix applying a voltage across the
76 * touchpanel plate and the ADC sampling the signal.
77 *
78 * This delay can be set by setting delay = n, where n is the array
79 * position of the delay in the array delay_table below.
80 * Long delays > 1ms are supported for completeness, but are not
81 * recommended.
82 */
83static int delay = 3;
84module_param(delay, int, 0);
85MODULE_PARM_DESC(delay, "Set adc sample delay.");
86
87/*
88 * Set five_wire = 1 to use a 5 wire touchscreen.
89 *
90 * NOTE: Five wire mode does not allow for readback of pressure.
91 */
92static int five_wire;
93module_param(five_wire, int, 0);
94MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
95
96/*
97 * Set adc mask function.
98 *
99 * Sources of glitch noise, such as signals driving an LCD display, may feed
100 * through to the touch screen plates and affect measurement accuracy. In
101 * order to minimise this, a signal may be applied to the MASK pin to delay or
102 * synchronise the sampling.
103 *
104 * 0 = No delay or sync
105 * 1 = High on pin stops conversions
106 * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
107 * 3 = Edge triggered, edge on pin starts conversion after delay param
108 */
109static int mask;
110module_param(mask, int, 0);
111MODULE_PARM_DESC(mask, "Set adc mask function.");
112
113/*
114 * Coordinate Polling Enable.
115 *
116 * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
117 * for every poll.
118 */
119static int coord;
120module_param(coord, int, 0);
121MODULE_PARM_DESC(coord, "Polling coordinate mode");
122
123/*
124 * ADC sample delay times in uS
125 */
126static const int delay_table[] = {
127 21, /* 1 AC97 Link frames */
128 42, /* 2 */
129 84, /* 4 */
130 167, /* 8 */
131 333, /* 16 */
132 667, /* 32 */
133 1000, /* 48 */
134 1333, /* 64 */
135 2000, /* 96 */
136 2667, /* 128 */
137 3333, /* 160 */
138 4000, /* 192 */
139 4667, /* 224 */
140 5333, /* 256 */
141 6000, /* 288 */
142 0 /* No delay, switch matrix always on */
143};
144
145/*
146 * Delay after issuing a POLL command.
147 *
148 * The delay is 3 AC97 link frames + the touchpanel settling delay
149 */
150static inline void poll_delay(int d)
151{
152 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
153}
154
155/*
156 * set up the physical settings of the WM9712
157 */
158static void wm9712_phy_init(struct wm97xx *wm)
159{
160 u16 dig1 = 0;
161 u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
162
163 /* WM9712 rpu */
164 if (rpu) {
165 dig2 &= 0xffc0;
166 dig2 |= WM9712_RPU(rpu);
167 dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
168 64000 / rpu);
169 }
170
171 /* touchpanel pressure current*/
172 if (pil == 2) {
173 dig2 |= WM9712_PIL;
174 dev_dbg(wm->dev,
175 "setting pressure measurement current to 400uA.");
176 } else if (pil)
177 dev_dbg(wm->dev,
178 "setting pressure measurement current to 200uA.");
179 if (!pil)
180 pressure = 0;
181
182 /* WM9712 five wire */
183 if (five_wire) {
184 dig2 |= WM9712_45W;
185 dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
186 }
187
188 /* polling mode sample settling delay */
189 if (delay < 0 || delay > 15) {
190 dev_dbg(wm->dev, "supplied delay out of range.");
191 delay = 4;
192 }
193 dig1 &= 0xff0f;
194 dig1 |= WM97XX_DELAY(delay);
195 dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
196 delay_table[delay]);
197
198 /* mask */
199 dig2 |= ((mask & 0x3) << 6);
200 if (mask) {
201 u16 reg;
202 /* Set GPIO4 as Mask Pin*/
203 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
204 wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
205 reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
206 wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
207 }
208
209 /* wait - coord mode */
210 if (coord)
211 dig2 |= WM9712_WAIT;
212
213 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
214 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
215}
216
217static void wm9712_dig_enable(struct wm97xx *wm, int enable)
218{
219 u16 dig2 = wm->dig[2];
220
221 if (enable) {
222 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
223 dig2 | WM97XX_PRP_DET_DIG);
224 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
225 } else
226 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
227 dig2 & ~WM97XX_PRP_DET_DIG);
228}
229
230static void wm9712_aux_prepare(struct wm97xx *wm)
231{
232 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
233 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
234 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
235}
236
237static void wm9712_dig_restore(struct wm97xx *wm)
238{
239 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
240 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
241}
242
243static inline int is_pden(struct wm97xx *wm)
244{
245 return wm->dig[2] & WM9712_PDEN;
246}
247
248/*
249 * Read a sample from the WM9712 adc in polling mode.
250 */
251static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
252{
253 int timeout = 5 * delay;
254
255 if (!wm->pen_probably_down) {
256 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
257 if (!(data & WM97XX_PEN_DOWN))
258 return RC_PENUP;
259 wm->pen_probably_down = 1;
260 }
261
262 /* set up digitiser */
263 if (adcsel & 0x8000)
264 adcsel = ((adcsel & 0x7fff) + 3) << 12;
265
266 if (wm->mach_ops && wm->mach_ops->pre_sample)
267 wm->mach_ops->pre_sample(adcsel);
268 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
269 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
270
271 /* wait 3 AC97 time slots + delay for conversion */
272 poll_delay(delay);
273
274 /* wait for POLL to go low */
275 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
276 && timeout) {
277 udelay(AC97_LINK_FRAME);
278 timeout--;
279 }
280
281 if (timeout <= 0) {
282 /* If PDEN is set, we can get a timeout when pen goes up */
283 if (is_pden(wm))
284 wm->pen_probably_down = 0;
285 else
286 dev_dbg(wm->dev, "adc sample timeout");
287 return RC_PENUP;
288 }
289
290 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
291 if (wm->mach_ops && wm->mach_ops->post_sample)
292 wm->mach_ops->post_sample(adcsel);
293
294 /* check we have correct sample */
295 if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
296 dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
297 *sample & WM97XX_ADCSEL_MASK);
298 return RC_PENUP;
299 }
300
301 if (!(*sample & WM97XX_PEN_DOWN)) {
302 wm->pen_probably_down = 0;
303 return RC_PENUP;
304 }
305
306 return RC_VALID;
307}
308
309/*
310 * Read a coord from the WM9712 adc in polling mode.
311 */
312static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
313{
314 int timeout = 5 * delay;
315
316 if (!wm->pen_probably_down) {
317 u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
318 if (!(data_rd & WM97XX_PEN_DOWN))
319 return RC_PENUP;
320 wm->pen_probably_down = 1;
321 }
322
323 /* set up digitiser */
324 if (wm->mach_ops && wm->mach_ops->pre_sample)
325 wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
326
327 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
328 WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
329
330 /* wait 3 AC97 time slots + delay for conversion and read x */
331 poll_delay(delay);
332 data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
333 /* wait for POLL to go low */
334 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
335 && timeout) {
336 udelay(AC97_LINK_FRAME);
337 timeout--;
338 }
339
340 if (timeout <= 0) {
341 /* If PDEN is set, we can get a timeout when pen goes up */
342 if (is_pden(wm))
343 wm->pen_probably_down = 0;
344 else
345 dev_dbg(wm->dev, "adc sample timeout");
346 return RC_PENUP;
347 }
348
349 /* read back y data */
350 data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
351 if (pil)
352 data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
353 else
354 data->p = DEFAULT_PRESSURE;
355
356 if (wm->mach_ops && wm->mach_ops->post_sample)
357 wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
358
359 /* check we have correct sample */
360 if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
361 goto err;
362 if (pil && !(data->p & WM97XX_ADCSEL_PRES))
363 goto err;
364
365 if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
366 wm->pen_probably_down = 0;
367 return RC_PENUP;
368 }
369 return RC_VALID;
370err:
371 return 0;
372}
373
374/*
375 * Sample the WM9712 touchscreen in polling mode
376 */
377static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
378{
379 int rc;
380
381 if (coord) {
382 rc = wm9712_poll_coord(wm, data);
383 if (rc != RC_VALID)
384 return rc;
385 } else {
386 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
387 if (rc != RC_VALID)
388 return rc;
389
390 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
391 if (rc != RC_VALID)
392 return rc;
393
394 if (pil && !five_wire) {
395 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
396 &data->p);
397 if (rc != RC_VALID)
398 return rc;
399 } else
400 data->p = DEFAULT_PRESSURE;
401 }
402 return RC_VALID;
403}
404
405/*
406 * Enable WM9712 continuous mode, i.e. touch data is streamed across
407 * an AC97 slot
408 */
409static int wm9712_acc_enable(struct wm97xx *wm, int enable)
410{
411 u16 dig1, dig2;
412 int ret = 0;
413
414 dig1 = wm->dig[1];
415 dig2 = wm->dig[2];
416
417 if (enable) {
418 /* continous mode */
419 if (wm->mach_ops->acc_startup) {
420 ret = wm->mach_ops->acc_startup(wm);
421 if (ret < 0)
422 return ret;
423 }
424 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
425 WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
426 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
427 WM97XX_DELAY(delay) |
428 WM97XX_SLT(wm->acc_slot) |
429 WM97XX_RATE(wm->acc_rate);
430 if (pil)
431 dig1 |= WM97XX_ADCSEL_PRES;
432 dig2 |= WM9712_PDEN;
433 } else {
434 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
435 dig2 &= ~WM9712_PDEN;
436 if (wm->mach_ops->acc_shutdown)
437 wm->mach_ops->acc_shutdown(wm);
438 }
439
440 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
441 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
442
443 return 0;
444}
445
446struct wm97xx_codec_drv wm9712_codec = {
447 .id = WM9712_ID2,
448 .name = "wm9712",
449 .poll_sample = wm9712_poll_sample,
450 .poll_touch = wm9712_poll_touch,
451 .acc_enable = wm9712_acc_enable,
452 .phy_init = wm9712_phy_init,
453 .dig_enable = wm9712_dig_enable,
454 .dig_restore = wm9712_dig_restore,
455 .aux_prepare = wm9712_aux_prepare,
456};
457EXPORT_SYMBOL_GPL(wm9712_codec);
458
459/* Module information */
460MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
461MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
462MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
new file mode 100644
index 000000000000..01278bd7e65c
--- /dev/null
+++ b/drivers/input/touchscreen/wm9713.c
@@ -0,0 +1,460 @@
1/*
2 * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
3 *
4 * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * Parts Copyright : Ian Molton <spyro@f2s.com>
8 * Andrew Zabolotny <zap@homelink.ru>
9 * Russell King <rmk@arm.linux.org.uk>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/version.h>
21#include <linux/kernel.h>
22#include <linux/input.h>
23#include <linux/delay.h>
24#include <linux/bitops.h>
25#include <linux/wm97xx.h>
26
27#define TS_NAME "wm97xx"
28#define WM9713_VERSION "1.00"
29#define DEFAULT_PRESSURE 0xb0c0
30
31/*
32 * Module parameters
33 */
34
35/*
36 * Set internal pull up for pen detect.
37 *
38 * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
39 * i.e. pull up resistance = 64k Ohms / rpu.
40 *
41 * Adjust this value if you are having problems with pen detect not
42 * detecting any down event.
43 */
44static int rpu = 8;
45module_param(rpu, int, 0);
46MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
47
48/*
49 * Set current used for pressure measurement.
50 *
51 * Set pil = 2 to use 400uA
52 * pil = 1 to use 200uA and
53 * pil = 0 to disable pressure measurement.
54 *
55 * This is used to increase the range of values returned by the adc
56 * when measureing touchpanel pressure.
57 */
58static int pil;
59module_param(pil, int, 0);
60MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
61
62/*
63 * Set threshold for pressure measurement.
64 *
65 * Pen down pressure below threshold is ignored.
66 */
67static int pressure = DEFAULT_PRESSURE & 0xfff;
68module_param(pressure, int, 0);
69MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
70
71/*
72 * Set adc sample delay.
73 *
74 * For accurate touchpanel measurements, some settling time may be
75 * required between the switch matrix applying a voltage across the
76 * touchpanel plate and the ADC sampling the signal.
77 *
78 * This delay can be set by setting delay = n, where n is the array
79 * position of the delay in the array delay_table below.
80 * Long delays > 1ms are supported for completeness, but are not
81 * recommended.
82 */
83static int delay = 4;
84module_param(delay, int, 0);
85MODULE_PARM_DESC(delay, "Set adc sample delay.");
86
87/*
88 * Set adc mask function.
89 *
90 * Sources of glitch noise, such as signals driving an LCD display, may feed
91 * through to the touch screen plates and affect measurement accuracy. In
92 * order to minimise this, a signal may be applied to the MASK pin to delay or
93 * synchronise the sampling.
94 *
95 * 0 = No delay or sync
96 * 1 = High on pin stops conversions
97 * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
98 * 3 = Edge triggered, edge on pin starts conversion after delay param
99 */
100static int mask;
101module_param(mask, int, 0);
102MODULE_PARM_DESC(mask, "Set adc mask function.");
103
104/*
105 * Coordinate Polling Enable.
106 *
107 * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
108 * for every poll.
109 */
110static int coord;
111module_param(coord, int, 0);
112MODULE_PARM_DESC(coord, "Polling coordinate mode");
113
114/*
115 * ADC sample delay times in uS
116 */
117static const int delay_table[] = {
118 21, /* 1 AC97 Link frames */
119 42, /* 2 */
120 84, /* 4 */
121 167, /* 8 */
122 333, /* 16 */
123 667, /* 32 */
124 1000, /* 48 */
125 1333, /* 64 */
126 2000, /* 96 */
127 2667, /* 128 */
128 3333, /* 160 */
129 4000, /* 192 */
130 4667, /* 224 */
131 5333, /* 256 */
132 6000, /* 288 */
133 0 /* No delay, switch matrix always on */
134};
135
136/*
137 * Delay after issuing a POLL command.
138 *
139 * The delay is 3 AC97 link frames + the touchpanel settling delay
140 */
141static inline void poll_delay(int d)
142{
143 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
144}
145
146/*
147 * set up the physical settings of the WM9713
148 */
149static void wm9713_phy_init(struct wm97xx *wm)
150{
151 u16 dig1 = 0, dig2, dig3;
152
153 /* default values */
154 dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
155 dig3 = WM9712_RPU(1);
156
157 /* rpu */
158 if (rpu) {
159 dig3 &= 0xffc0;
160 dig3 |= WM9712_RPU(rpu);
161 dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
162 64000 / rpu);
163 }
164
165 /* touchpanel pressure */
166 if (pil == 2) {
167 dig3 |= WM9712_PIL;
168 dev_info(wm->dev,
169 "setting pressure measurement current to 400uA.");
170 } else if (pil)
171 dev_info(wm->dev,
172 "setting pressure measurement current to 200uA.");
173 if (!pil)
174 pressure = 0;
175
176 /* sample settling delay */
177 if (delay < 0 || delay > 15) {
178 dev_info(wm->dev, "supplied delay out of range.");
179 delay = 4;
180 dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
181 delay_table[delay]);
182 }
183 dig2 &= 0xff0f;
184 dig2 |= WM97XX_DELAY(delay);
185
186 /* mask */
187 dig3 |= ((mask & 0x3) << 4);
188 if (coord)
189 dig3 |= WM9713_WAIT;
190
191 wm->misc = wm97xx_reg_read(wm, 0x5a);
192
193 wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
194 wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
195 wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
196 wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
197}
198
199static void wm9713_dig_enable(struct wm97xx *wm, int enable)
200{
201 u16 val;
202
203 if (enable) {
204 val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
205 wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
206 wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
207 WM97XX_PRP_DET_DIG);
208 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
209 } else {
210 wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
211 ~WM97XX_PRP_DET_DIG);
212 val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
213 wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
214 }
215}
216
217static void wm9713_dig_restore(struct wm97xx *wm)
218{
219 wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
220 wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
221 wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
222}
223
224static void wm9713_aux_prepare(struct wm97xx *wm)
225{
226 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
227 wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
228 wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
229 wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
230}
231
232static inline int is_pden(struct wm97xx *wm)
233{
234 return wm->dig[2] & WM9713_PDEN;
235}
236
237/*
238 * Read a sample from the WM9713 adc in polling mode.
239 */
240static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
241{
242 u16 dig1;
243 int timeout = 5 * delay;
244
245 if (!wm->pen_probably_down) {
246 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
247 if (!(data & WM97XX_PEN_DOWN))
248 return RC_PENUP;
249 wm->pen_probably_down = 1;
250 }
251
252 /* set up digitiser */
253 if (adcsel & 0x8000)
254 adcsel = 1 << ((adcsel & 0x7fff) + 3);
255
256 dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
257 dig1 &= ~WM9713_ADCSEL_MASK;
258
259 if (wm->mach_ops && wm->mach_ops->pre_sample)
260 wm->mach_ops->pre_sample(adcsel);
261 wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
262
263 /* wait 3 AC97 time slots + delay for conversion */
264 poll_delay(delay);
265
266 /* wait for POLL to go low */
267 while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
268 timeout) {
269 udelay(AC97_LINK_FRAME);
270 timeout--;
271 }
272
273 if (timeout <= 0) {
274 /* If PDEN is set, we can get a timeout when pen goes up */
275 if (is_pden(wm))
276 wm->pen_probably_down = 0;
277 else
278 dev_dbg(wm->dev, "adc sample timeout");
279 return RC_PENUP;
280 }
281
282 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
283 if (wm->mach_ops && wm->mach_ops->post_sample)
284 wm->mach_ops->post_sample(adcsel);
285
286 /* check we have correct sample */
287 if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
288 dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
289 *sample & WM97XX_ADCSRC_MASK);
290 return RC_PENUP;
291 }
292
293 if (!(*sample & WM97XX_PEN_DOWN)) {
294 wm->pen_probably_down = 0;
295 return RC_PENUP;
296 }
297
298 return RC_VALID;
299}
300
301/*
302 * Read a coordinate from the WM9713 adc in polling mode.
303 */
304static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
305{
306 u16 dig1;
307 int timeout = 5 * delay;
308
309 if (!wm->pen_probably_down) {
310 u16 val = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
311 if (!(val & WM97XX_PEN_DOWN))
312 return RC_PENUP;
313 wm->pen_probably_down = 1;
314 }
315
316 /* set up digitiser */
317 dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
318 dig1 &= ~WM9713_ADCSEL_MASK;
319 if (pil)
320 dig1 |= WM9713_ADCSEL_PRES;
321
322 if (wm->mach_ops && wm->mach_ops->pre_sample)
323 wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
324 wm97xx_reg_write(wm, AC97_WM9713_DIG1,
325 dig1 | WM9713_POLL | WM9713_COO);
326
327 /* wait 3 AC97 time slots + delay for conversion */
328 poll_delay(delay);
329 data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
330 /* wait for POLL to go low */
331 while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL)
332 && timeout) {
333 udelay(AC97_LINK_FRAME);
334 timeout--;
335 }
336
337 if (timeout <= 0) {
338 /* If PDEN is set, we can get a timeout when pen goes up */
339 if (is_pden(wm))
340 wm->pen_probably_down = 0;
341 else
342 dev_dbg(wm->dev, "adc sample timeout");
343 return RC_PENUP;
344 }
345
346 /* read back data */
347 data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
348 if (pil)
349 data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
350 else
351 data->p = DEFAULT_PRESSURE;
352
353 if (wm->mach_ops && wm->mach_ops->post_sample)
354 wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
355
356 /* check we have correct sample */
357 if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
358 goto err;
359 if (pil && !(data->p & WM97XX_ADCSEL_PRES))
360 goto err;
361
362 if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
363 wm->pen_probably_down = 0;
364 return RC_PENUP;
365 }
366 return RC_VALID;
367err:
368 return 0;
369}
370
371/*
372 * Sample the WM9713 touchscreen in polling mode
373 */
374static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
375{
376 int rc;
377
378 if (coord) {
379 rc = wm9713_poll_coord(wm, data);
380 if (rc != RC_VALID)
381 return rc;
382 } else {
383 rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
384 if (rc != RC_VALID)
385 return rc;
386 rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
387 if (rc != RC_VALID)
388 return rc;
389 if (pil) {
390 rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
391 &data->p);
392 if (rc != RC_VALID)
393 return rc;
394 } else
395 data->p = DEFAULT_PRESSURE;
396 }
397 return RC_VALID;
398}
399
400/*
401 * Enable WM9713 continuous mode, i.e. touch data is streamed across
402 * an AC97 slot
403 */
404static int wm9713_acc_enable(struct wm97xx *wm, int enable)
405{
406 u16 dig1, dig2, dig3;
407 int ret = 0;
408
409 dig1 = wm->dig[0];
410 dig2 = wm->dig[1];
411 dig3 = wm->dig[2];
412
413 if (enable) {
414 /* continous mode */
415 if (wm->mach_ops->acc_startup &&
416 (ret = wm->mach_ops->acc_startup(wm)) < 0)
417 return ret;
418
419 dig1 &= ~WM9713_ADCSEL_MASK;
420 dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X |
421 WM9713_ADCSEL_Y;
422 if (pil)
423 dig1 |= WM9713_ADCSEL_PRES;
424 dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK |
425 WM97XX_CM_RATE_MASK);
426 dig2 |= WM97XX_SLEN | WM97XX_DELAY(delay) |
427 WM97XX_SLT(wm->acc_slot) | WM97XX_RATE(wm->acc_rate);
428 dig3 |= WM9713_PDEN;
429 } else {
430 dig1 &= ~(WM9713_CTC | WM9713_COO);
431 dig2 &= ~WM97XX_SLEN;
432 dig3 &= ~WM9713_PDEN;
433 if (wm->mach_ops->acc_shutdown)
434 wm->mach_ops->acc_shutdown(wm);
435 }
436
437 wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
438 wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
439 wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
440
441 return ret;
442}
443
444struct wm97xx_codec_drv wm9713_codec = {
445 .id = WM9713_ID2,
446 .name = "wm9713",
447 .poll_sample = wm9713_poll_sample,
448 .poll_touch = wm9713_poll_touch,
449 .acc_enable = wm9713_acc_enable,
450 .phy_init = wm9713_phy_init,
451 .dig_enable = wm9713_dig_enable,
452 .dig_restore = wm9713_dig_restore,
453 .aux_prepare = wm9713_aux_prepare,
454};
455EXPORT_SYMBOL_GPL(wm9713_codec);
456
457/* Module information */
458MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
459MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
460MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
new file mode 100644
index 000000000000..2910999e05a0
--- /dev/null
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -0,0 +1,789 @@
1/*
2 * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
3 * and WM9713 AC97 Codecs.
4 *
5 * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
6 * Author: Liam Girdwood
7 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
8 * Parts Copyright : Ian Molton <spyro@f2s.com>
9 * Andrew Zabolotny <zap@homelink.ru>
10 * Russell King <rmk@arm.linux.org.uk>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * Notes:
18 *
19 * Features:
20 * - supports WM9705, WM9712, WM9713
21 * - polling mode
22 * - continuous mode (arch-dependent)
23 * - adjustable rpu/dpp settings
24 * - adjustable pressure current
25 * - adjustable sample settle delay
26 * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
27 * - pen down detection
28 * - battery monitor
29 * - sample AUX adcs
30 * - power management
31 * - codec GPIO
32 * - codec event notification
33 * Todo
34 * - Support for async sampling control for noisy LCDs.
35 *
36 */
37
38#include <linux/module.h>
39#include <linux/moduleparam.h>
40#include <linux/version.h>
41#include <linux/kernel.h>
42#include <linux/init.h>
43#include <linux/delay.h>
44#include <linux/string.h>
45#include <linux/proc_fs.h>
46#include <linux/pm.h>
47#include <linux/interrupt.h>
48#include <linux/bitops.h>
49#include <linux/workqueue.h>
50#include <linux/wm97xx.h>
51#include <linux/uaccess.h>
52#include <linux/io.h>
53
54#define TS_NAME "wm97xx"
55#define WM_CORE_VERSION "1.00"
56#define DEFAULT_PRESSURE 0xb0c0
57
58
59/*
60 * Touchscreen absolute values
61 *
62 * These parameters are used to help the input layer discard out of
63 * range readings and reduce jitter etc.
64 *
65 * o min, max:- indicate the min and max values your touch screen returns
66 * o fuzz:- use a higher number to reduce jitter
67 *
68 * The default values correspond to Mainstone II in QVGA mode
69 *
70 * Please read
71 * Documentation/input/input-programming.txt for more details.
72 */
73
74static int abs_x[3] = {350, 3900, 5};
75module_param_array(abs_x, int, NULL, 0);
76MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
77
78static int abs_y[3] = {320, 3750, 40};
79module_param_array(abs_y, int, NULL, 0);
80MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
81
82static int abs_p[3] = {0, 150, 4};
83module_param_array(abs_p, int, NULL, 0);
84MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
85
86/*
87 * wm97xx IO access, all IO locking done by AC97 layer
88 */
89int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
90{
91 if (wm->ac97)
92 return wm->ac97->bus->ops->read(wm->ac97, reg);
93 else
94 return -1;
95}
96EXPORT_SYMBOL_GPL(wm97xx_reg_read);
97
98void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
99{
100 /* cache digitiser registers */
101 if (reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
102 wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
103
104 /* cache gpio regs */
105 if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
106 wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
107
108 /* wm9713 irq reg */
109 if (reg == 0x5a)
110 wm->misc = val;
111
112 if (wm->ac97)
113 wm->ac97->bus->ops->write(wm->ac97, reg, val);
114}
115EXPORT_SYMBOL_GPL(wm97xx_reg_write);
116
117/**
118 * wm97xx_read_aux_adc - Read the aux adc.
119 * @wm: wm97xx device.
120 * @adcsel: codec ADC to be read
121 *
122 * Reads the selected AUX ADC.
123 */
124
125int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
126{
127 int power_adc = 0, auxval;
128 u16 power = 0;
129
130 /* get codec */
131 mutex_lock(&wm->codec_mutex);
132
133 /* When the touchscreen is not in use, we may have to power up
134 * the AUX ADC before we can use sample the AUX inputs->
135 */
136 if (wm->id == WM9713_ID2 &&
137 (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
138 power_adc = 1;
139 wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
140 }
141
142 /* Prepare the codec for AUX reading */
143 wm->codec->aux_prepare(wm);
144
145 /* Turn polling mode on to read AUX ADC */
146 wm->pen_probably_down = 1;
147 wm->codec->poll_sample(wm, adcsel, &auxval);
148
149 if (power_adc)
150 wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
151
152 wm->codec->dig_restore(wm);
153
154 wm->pen_probably_down = 0;
155
156 mutex_unlock(&wm->codec_mutex);
157 return auxval & 0xfff;
158}
159EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
160
161/**
162 * wm97xx_get_gpio - Get the status of a codec GPIO.
163 * @wm: wm97xx device.
164 * @gpio: gpio
165 *
166 * Get the status of a codec GPIO pin
167 */
168
169enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
170{
171 u16 status;
172 enum wm97xx_gpio_status ret;
173
174 mutex_lock(&wm->codec_mutex);
175 status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
176
177 if (status & gpio)
178 ret = WM97XX_GPIO_HIGH;
179 else
180 ret = WM97XX_GPIO_LOW;
181
182 mutex_unlock(&wm->codec_mutex);
183 return ret;
184}
185EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
186
187/**
188 * wm97xx_set_gpio - Set the status of a codec GPIO.
189 * @wm: wm97xx device.
190 * @gpio: gpio
191 *
192 *
193 * Set the status of a codec GPIO pin
194 */
195
196void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
197 enum wm97xx_gpio_status status)
198{
199 u16 reg;
200
201 mutex_lock(&wm->codec_mutex);
202 reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
203
204 if (status & WM97XX_GPIO_HIGH)
205 reg |= gpio;
206 else
207 reg &= ~gpio;
208
209 if (wm->id == WM9712_ID2)
210 wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
211 else
212 wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
213 mutex_unlock(&wm->codec_mutex);
214}
215EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
216
217/*
218 * Codec GPIO pin configuration, this sets pin direction, polarity,
219 * stickyness and wake up.
220 */
221void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
222 enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky,
223 enum wm97xx_gpio_wake wake)
224{
225 u16 reg;
226
227 mutex_lock(&wm->codec_mutex);
228 reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
229
230 if (pol == WM97XX_GPIO_POL_HIGH)
231 reg |= gpio;
232 else
233 reg &= ~gpio;
234
235 wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
236 reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
237
238 if (sticky == WM97XX_GPIO_STICKY)
239 reg |= gpio;
240 else
241 reg &= ~gpio;
242
243 wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
244 reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
245
246 if (wake == WM97XX_GPIO_WAKE)
247 reg |= gpio;
248 else
249 reg &= ~gpio;
250
251 wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
252 reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
253
254 if (dir == WM97XX_GPIO_IN)
255 reg |= gpio;
256 else
257 reg &= ~gpio;
258
259 wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
260 mutex_unlock(&wm->codec_mutex);
261}
262EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
263
264/*
265 * Handle a pen down interrupt.
266 */
267static void wm97xx_pen_irq_worker(struct work_struct *work)
268{
269 struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work);
270 int pen_was_down = wm->pen_is_down;
271
272 /* do we need to enable the touch panel reader */
273 if (wm->id == WM9705_ID2) {
274 if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) &
275 WM97XX_PEN_DOWN)
276 wm->pen_is_down = 1;
277 else
278 wm->pen_is_down = 0;
279 } else {
280 u16 status, pol;
281 mutex_lock(&wm->codec_mutex);
282 status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
283 pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
284
285 if (WM97XX_GPIO_13 & pol & status) {
286 wm->pen_is_down = 1;
287 wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol &
288 ~WM97XX_GPIO_13);
289 } else {
290 wm->pen_is_down = 0;
291 wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol |
292 WM97XX_GPIO_13);
293 }
294
295 if (wm->id == WM9712_ID2)
296 wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status &
297 ~WM97XX_GPIO_13) << 1);
298 else
299 wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
300 ~WM97XX_GPIO_13);
301 mutex_unlock(&wm->codec_mutex);
302 }
303
304 /* If the system is not using continuous mode or it provides a
305 * pen down operation then we need to schedule polls while the
306 * pen is down. Otherwise the machine driver is responsible
307 * for scheduling reads.
308 */
309 if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
310 if (wm->pen_is_down && !pen_was_down) {
311 /* Data is not availiable immediately on pen down */
312 queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
313 }
314
315 /* Let ts_reader report the pen up for debounce. */
316 if (!wm->pen_is_down && pen_was_down)
317 wm->pen_is_down = 1;
318 }
319
320 if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
321 wm->mach_ops->acc_pen_up(wm);
322
323 wm->mach_ops->irq_enable(wm, 1);
324}
325
326/*
327 * Codec PENDOWN irq handler
328 *
329 * We have to disable the codec interrupt in the handler because it
330 * can take upto 1ms to clear the interrupt source. We schedule a task
331 * in a work queue to do the actual interaction with the chip (it
332 * doesn't matter if we end up reenqueing it before it is executed
333 * since we don't touch the chip until it has run). The interrupt is
334 * then enabled again in the slow handler when the source has been
335 * cleared.
336 */
337static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
338{
339 struct wm97xx *wm = dev_id;
340
341 wm->mach_ops->irq_enable(wm, 0);
342 queue_work(wm->ts_workq, &wm->pen_event_work);
343
344 return IRQ_HANDLED;
345}
346
347/*
348 * initialise pen IRQ handler and workqueue
349 */
350static int wm97xx_init_pen_irq(struct wm97xx *wm)
351{
352 u16 reg;
353
354 /* If an interrupt is supplied an IRQ enable operation must also be
355 * provided. */
356 BUG_ON(!wm->mach_ops->irq_enable);
357
358 if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED,
359 "wm97xx-pen", wm)) {
360 dev_err(wm->dev,
361 "Failed to register pen down interrupt, polling");
362 wm->pen_irq = 0;
363 return -EINVAL;
364 }
365
366 /* Configure GPIO as interrupt source on WM971x */
367 if (wm->id != WM9705_ID2) {
368 BUG_ON(!wm->mach_ops->irq_gpio);
369 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
370 wm97xx_reg_write(wm, AC97_MISC_AFE,
371 reg & ~(wm->mach_ops->irq_gpio));
372 reg = wm97xx_reg_read(wm, 0x5a);
373 wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
374 }
375
376 return 0;
377}
378
379static int wm97xx_read_samples(struct wm97xx *wm)
380{
381 struct wm97xx_data data;
382 int rc;
383
384 mutex_lock(&wm->codec_mutex);
385
386 if (wm->mach_ops && wm->mach_ops->acc_enabled)
387 rc = wm->mach_ops->acc_pen_down(wm);
388 else
389 rc = wm->codec->poll_touch(wm, &data);
390
391 if (rc & RC_PENUP) {
392 if (wm->pen_is_down) {
393 wm->pen_is_down = 0;
394 dev_dbg(wm->dev, "pen up\n");
395 input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
396 input_sync(wm->input_dev);
397 } else if (!(rc & RC_AGAIN)) {
398 /* We need high frequency updates only while
399 * pen is down, the user never will be able to
400 * touch screen faster than a few times per
401 * second... On the other hand, when the user
402 * is actively working with the touchscreen we
403 * don't want to lose the quick response. So we
404 * will slowly increase sleep time after the
405 * pen is up and quicky restore it to ~one task
406 * switch when pen is down again.
407 */
408 if (wm->ts_reader_interval < HZ / 10)
409 wm->ts_reader_interval++;
410 }
411
412 } else if (rc & RC_VALID) {
413 dev_dbg(wm->dev,
414 "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
415 data.x >> 12, data.x & 0xfff, data.y >> 12,
416 data.y & 0xfff, data.p >> 12, data.p & 0xfff);
417 input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
418 input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
419 input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
420 input_sync(wm->input_dev);
421 wm->pen_is_down = 1;
422 wm->ts_reader_interval = wm->ts_reader_min_interval;
423 } else if (rc & RC_PENDOWN) {
424 dev_dbg(wm->dev, "pen down\n");
425 wm->pen_is_down = 1;
426 wm->ts_reader_interval = wm->ts_reader_min_interval;
427 }
428
429 mutex_unlock(&wm->codec_mutex);
430 return rc;
431}
432
433/*
434* The touchscreen sample reader.
435*/
436static void wm97xx_ts_reader(struct work_struct *work)
437{
438 int rc;
439 struct wm97xx *wm = container_of(work, struct wm97xx, ts_reader.work);
440
441 BUG_ON(!wm->codec);
442
443 do {
444 rc = wm97xx_read_samples(wm);
445 } while (rc & RC_AGAIN);
446
447 if (wm->pen_is_down || !wm->pen_irq)
448 queue_delayed_work(wm->ts_workq, &wm->ts_reader,
449 wm->ts_reader_interval);
450}
451
452/**
453 * wm97xx_ts_input_open - Open the touch screen input device.
454 * @idev: Input device to be opened.
455 *
456 * Called by the input sub system to open a wm97xx touchscreen device.
457 * Starts the touchscreen thread and touch digitiser.
458 */
459static int wm97xx_ts_input_open(struct input_dev *idev)
460{
461 struct wm97xx *wm = input_get_drvdata(idev);
462
463 wm->ts_workq = create_singlethread_workqueue("kwm97xx");
464 if (wm->ts_workq == NULL) {
465 dev_err(wm->dev,
466 "Failed to create workqueue\n");
467 return -EINVAL;
468 }
469
470 /* start digitiser */
471 if (wm->mach_ops && wm->mach_ops->acc_enabled)
472 wm->codec->acc_enable(wm, 1);
473 wm->codec->dig_enable(wm, 1);
474
475 INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader);
476 INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
477
478 wm->ts_reader_min_interval = HZ >= 100 ? HZ / 100 : 1;
479 if (wm->ts_reader_min_interval < 1)
480 wm->ts_reader_min_interval = 1;
481 wm->ts_reader_interval = wm->ts_reader_min_interval;
482
483 wm->pen_is_down = 0;
484 if (wm->pen_irq)
485 wm97xx_init_pen_irq(wm);
486 else
487 dev_err(wm->dev, "No IRQ specified\n");
488
489 /* If we either don't have an interrupt for pen down events or
490 * failed to acquire it then we need to poll.
491 */
492 if (wm->pen_irq == 0)
493 queue_delayed_work(wm->ts_workq, &wm->ts_reader,
494 wm->ts_reader_interval);
495
496 return 0;
497}
498
499/**
500 * wm97xx_ts_input_close - Close the touch screen input device.
501 * @idev: Input device to be closed.
502 *
503 * Called by the input sub system to close a wm97xx touchscreen
504 * device. Kills the touchscreen thread and stops the touch
505 * digitiser.
506 */
507
508static void wm97xx_ts_input_close(struct input_dev *idev)
509{
510 struct wm97xx *wm = input_get_drvdata(idev);
511 u16 reg;
512
513 if (wm->pen_irq) {
514 /* Return the interrupt to GPIO usage (disabling it) */
515 if (wm->id != WM9705_ID2) {
516 BUG_ON(!wm->mach_ops->irq_gpio);
517 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
518 wm97xx_reg_write(wm, AC97_MISC_AFE,
519 reg | wm->mach_ops->irq_gpio);
520 }
521
522 free_irq(wm->pen_irq, wm);
523 }
524
525 wm->pen_is_down = 0;
526
527 /* Balance out interrupt disables/enables */
528 if (cancel_work_sync(&wm->pen_event_work))
529 wm->mach_ops->irq_enable(wm, 1);
530
531 /* ts_reader rearms itself so we need to explicitly stop it
532 * before we destroy the workqueue.
533 */
534 cancel_delayed_work_sync(&wm->ts_reader);
535
536 destroy_workqueue(wm->ts_workq);
537
538 /* stop digitiser */
539 wm->codec->dig_enable(wm, 0);
540 if (wm->mach_ops && wm->mach_ops->acc_enabled)
541 wm->codec->acc_enable(wm, 0);
542}
543
544static int wm97xx_probe(struct device *dev)
545{
546 struct wm97xx *wm;
547 int ret = 0, id = 0;
548
549 wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
550 if (!wm)
551 return -ENOMEM;
552 mutex_init(&wm->codec_mutex);
553
554 wm->dev = dev;
555 dev->driver_data = wm;
556 wm->ac97 = to_ac97_t(dev);
557
558 /* check that we have a supported codec */
559 id = wm97xx_reg_read(wm, AC97_VENDOR_ID1);
560 if (id != WM97XX_ID1) {
561 dev_err(dev, "Device with vendor %04x is not a wm97xx\n", id);
562 ret = -ENODEV;
563 goto alloc_err;
564 }
565
566 wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
567
568 dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff);
569
570 switch (wm->id & 0xff) {
571#ifdef CONFIG_TOUCHSCREEN_WM9705
572 case 0x05:
573 wm->codec = &wm9705_codec;
574 break;
575#endif
576#ifdef CONFIG_TOUCHSCREEN_WM9712
577 case 0x12:
578 wm->codec = &wm9712_codec;
579 break;
580#endif
581#ifdef CONFIG_TOUCHSCREEN_WM9713
582 case 0x13:
583 wm->codec = &wm9713_codec;
584 break;
585#endif
586 default:
587 dev_err(wm->dev, "Support for wm97%02x not compiled in.\n",
588 wm->id & 0xff);
589 ret = -ENODEV;
590 goto alloc_err;
591 }
592
593 wm->input_dev = input_allocate_device();
594 if (wm->input_dev == NULL) {
595 ret = -ENOMEM;
596 goto alloc_err;
597 }
598
599 /* set up touch configuration */
600 wm->input_dev->name = "wm97xx touchscreen";
601 wm->input_dev->open = wm97xx_ts_input_open;
602 wm->input_dev->close = wm97xx_ts_input_close;
603 set_bit(EV_ABS, wm->input_dev->evbit);
604 set_bit(ABS_X, wm->input_dev->absbit);
605 set_bit(ABS_Y, wm->input_dev->absbit);
606 set_bit(ABS_PRESSURE, wm->input_dev->absbit);
607 input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
608 abs_x[2], 0);
609 input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],
610 abs_y[2], 0);
611 input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1],
612 abs_p[2], 0);
613 input_set_drvdata(wm->input_dev, wm);
614 wm->input_dev->dev.parent = dev;
615 ret = input_register_device(wm->input_dev);
616 if (ret < 0)
617 goto dev_alloc_err;
618
619 /* set up physical characteristics */
620 wm->codec->phy_init(wm);
621
622 /* load gpio cache */
623 wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
624 wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
625 wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
626 wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
627 wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
628 wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
629
630 /* register our battery device */
631 wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
632 if (!wm->battery_dev) {
633 ret = -ENOMEM;
634 goto batt_err;
635 }
636 platform_set_drvdata(wm->battery_dev, wm);
637 wm->battery_dev->dev.parent = dev;
638 ret = platform_device_add(wm->battery_dev);
639 if (ret < 0)
640 goto batt_reg_err;
641
642 /* register our extended touch device (for machine specific
643 * extensions) */
644 wm->touch_dev = platform_device_alloc("wm97xx-touch", -1);
645 if (!wm->touch_dev) {
646 ret = -ENOMEM;
647 goto touch_err;
648 }
649 platform_set_drvdata(wm->touch_dev, wm);
650 wm->touch_dev->dev.parent = dev;
651 ret = platform_device_add(wm->touch_dev);
652 if (ret < 0)
653 goto touch_reg_err;
654
655 return ret;
656
657 touch_reg_err:
658 platform_device_put(wm->touch_dev);
659 touch_err:
660 platform_device_unregister(wm->battery_dev);
661 wm->battery_dev = NULL;
662 batt_reg_err:
663 platform_device_put(wm->battery_dev);
664 batt_err:
665 input_unregister_device(wm->input_dev);
666 wm->input_dev = NULL;
667 dev_alloc_err:
668 input_free_device(wm->input_dev);
669 alloc_err:
670 kfree(wm);
671
672 return ret;
673}
674
675static int wm97xx_remove(struct device *dev)
676{
677 struct wm97xx *wm = dev_get_drvdata(dev);
678
679 platform_device_unregister(wm->battery_dev);
680 platform_device_unregister(wm->touch_dev);
681 input_unregister_device(wm->input_dev);
682 kfree(wm);
683
684 return 0;
685}
686
687#ifdef CONFIG_PM
688static int wm97xx_suspend(struct device *dev, pm_message_t state)
689{
690 struct wm97xx *wm = dev_get_drvdata(dev);
691
692 if (wm->input_dev->users)
693 cancel_delayed_work_sync(&wm->ts_reader);
694
695 return 0;
696}
697
698static int wm97xx_resume(struct device *dev)
699{
700 struct wm97xx *wm = dev_get_drvdata(dev);
701
702 /* restore digitiser and gpios */
703 if (wm->id == WM9713_ID2) {
704 wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
705 wm97xx_reg_write(wm, 0x5a, wm->misc);
706 if (wm->input_dev->users) {
707 u16 reg;
708 reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
709 wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
710 }
711 }
712
713 wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
714 wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
715
716 wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
717 wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
718 wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
719 wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
720 wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
721 wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
722
723 if (wm->input_dev->users && !wm->pen_irq) {
724 wm->ts_reader_interval = wm->ts_reader_min_interval;
725 queue_delayed_work(wm->ts_workq, &wm->ts_reader,
726 wm->ts_reader_interval);
727 }
728
729 return 0;
730}
731
732#else
733#define wm97xx_suspend NULL
734#define wm97xx_resume NULL
735#endif
736
737/*
738 * Machine specific operations
739 */
740int wm97xx_register_mach_ops(struct wm97xx *wm,
741 struct wm97xx_mach_ops *mach_ops)
742{
743 mutex_lock(&wm->codec_mutex);
744 if (wm->mach_ops) {
745 mutex_unlock(&wm->codec_mutex);
746 return -EINVAL;
747 }
748 wm->mach_ops = mach_ops;
749 mutex_unlock(&wm->codec_mutex);
750
751 return 0;
752}
753EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
754
755void wm97xx_unregister_mach_ops(struct wm97xx *wm)
756{
757 mutex_lock(&wm->codec_mutex);
758 wm->mach_ops = NULL;
759 mutex_unlock(&wm->codec_mutex);
760}
761EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
762
763static struct device_driver wm97xx_driver = {
764 .name = "ac97",
765 .bus = &ac97_bus_type,
766 .owner = THIS_MODULE,
767 .probe = wm97xx_probe,
768 .remove = wm97xx_remove,
769 .suspend = wm97xx_suspend,
770 .resume = wm97xx_resume,
771};
772
773static int __init wm97xx_init(void)
774{
775 return driver_register(&wm97xx_driver);
776}
777
778static void __exit wm97xx_exit(void)
779{
780 driver_unregister(&wm97xx_driver);
781}
782
783module_init(wm97xx_init);
784module_exit(wm97xx_exit);
785
786/* Module information */
787MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
788MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
789MODULE_LICENSE("GPL");
diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
new file mode 100644
index 000000000000..ed01c7df54a3
--- /dev/null
+++ b/include/linux/wm97xx.h
@@ -0,0 +1,311 @@
1
2/*
3 * Register bits and API for Wolfson WM97xx series of codecs
4 */
5
6#ifndef _LINUX_WM97XX_H
7#define _LINUX_WM97XX_H
8
9#include <sound/core.h>
10#include <sound/pcm.h>
11#include <sound/ac97_codec.h>
12#include <sound/initval.h>
13#include <linux/types.h>
14#include <linux/list.h>
15#include <linux/input.h> /* Input device layer */
16#include <linux/platform_device.h>
17
18/*
19 * WM97xx AC97 Touchscreen registers
20 */
21#define AC97_WM97XX_DIGITISER1 0x76
22#define AC97_WM97XX_DIGITISER2 0x78
23#define AC97_WM97XX_DIGITISER_RD 0x7a
24#define AC97_WM9713_DIG1 0x74
25#define AC97_WM9713_DIG2 AC97_WM97XX_DIGITISER1
26#define AC97_WM9713_DIG3 AC97_WM97XX_DIGITISER2
27
28/*
29 * WM97xx register bits
30 */
31#define WM97XX_POLL 0x8000 /* initiate a polling measurement */
32#define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */
33#define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */
34#define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */
35#define WM97XX_ADCSEL_MASK 0x7000
36#define WM97XX_COO 0x0800 /* enable coordinate mode */
37#define WM97XX_CTC 0x0400 /* enable continuous mode */
38#define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */
39#define WM97XX_CM_RATE_187 0x0100 /* 187.5Hz continuous rate */
40#define WM97XX_CM_RATE_375 0x0200 /* 375Hz continuous rate */
41#define WM97XX_CM_RATE_750 0x0300 /* 750Hz continuous rate */
42#define WM97XX_CM_RATE_8K 0x00f0 /* 8kHz continuous rate */
43#define WM97XX_CM_RATE_12K 0x01f0 /* 12kHz continuous rate */
44#define WM97XX_CM_RATE_24K 0x02f0 /* 24kHz continuous rate */
45#define WM97XX_CM_RATE_48K 0x03f0 /* 48kHz continuous rate */
46#define WM97XX_CM_RATE_MASK 0x03f0
47#define WM97XX_RATE(i) (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
48#define WM97XX_DELAY(i) ((i << 4) & 0x00f0) /* sample delay times */
49#define WM97XX_DELAY_MASK 0x00f0
50#define WM97XX_SLEN 0x0008 /* slot read back enable */
51#define WM97XX_SLT(i) ((i - 5) & 0x7) /* panel slot (5-11) */
52#define WM97XX_SLT_MASK 0x0007
53#define WM97XX_PRP_DETW 0x4000 /* detect on, digitise off, wake */
54#define WM97XX_PRP_DET 0x8000 /* detect on, digitise off, no wake */
55#define WM97XX_PRP_DET_DIG 0xc000 /* setect on, digitise on */
56#define WM97XX_RPR 0x2000 /* wake up on pen down */
57#define WM97XX_PEN_DOWN 0x8000 /* pen is down */
58#define WM97XX_ADCSRC_MASK 0x7000 /* ADC source mask */
59
60#define WM97XX_AUX_ID1 0x8001
61#define WM97XX_AUX_ID2 0x8002
62#define WM97XX_AUX_ID3 0x8003
63#define WM97XX_AUX_ID4 0x8004
64
65
66/* WM9712 Bits */
67#define WM9712_45W 0x1000 /* set for 5-wire touchscreen */
68#define WM9712_PDEN 0x0800 /* measure only when pen down */
69#define WM9712_WAIT 0x0200 /* wait until adc is read before next sample */
70#define WM9712_PIL 0x0100 /* current used for pressure measurement. set 400uA else 200uA */
71#define WM9712_MASK_HI 0x0040 /* hi on mask pin (47) stops conversions */
72#define WM9712_MASK_EDGE 0x0080 /* rising/falling edge on pin delays sample */
73#define WM9712_MASK_SYNC 0x00c0 /* rising/falling edge on mask initiates sample */
74#define WM9712_RPU(i) (i&0x3f) /* internal pull up on pen detect (64k / rpu) */
75#define WM9712_PD(i) (0x1 << i) /* power management */
76
77/* WM9712 Registers */
78#define AC97_WM9712_POWER 0x24
79#define AC97_WM9712_REV 0x58
80
81/* WM9705 Bits */
82#define WM9705_PDEN 0x1000 /* measure only when pen is down */
83#define WM9705_PINV 0x0800 /* inverts sense of pen down output */
84#define WM9705_BSEN 0x0400 /* BUSY flag enable, pin47 is 1 when busy */
85#define WM9705_BINV 0x0200 /* invert BUSY (pin47) output */
86#define WM9705_WAIT 0x0100 /* wait until adc is read before next sample */
87#define WM9705_PIL 0x0080 /* current used for pressure measurement. set 400uA else 200uA */
88#define WM9705_PHIZ 0x0040 /* set PHONE and PCBEEP inputs to high impedance */
89#define WM9705_MASK_HI 0x0010 /* hi on mask stops conversions */
90#define WM9705_MASK_EDGE 0x0020 /* rising/falling edge on pin delays sample */
91#define WM9705_MASK_SYNC 0x0030 /* rising/falling edge on mask initiates sample */
92#define WM9705_PDD(i) (i & 0x000f) /* pen detect comparator threshold */
93
94
95/* WM9713 Bits */
96#define WM9713_PDPOL 0x0400 /* Pen down polarity */
97#define WM9713_POLL 0x0200 /* initiate a polling measurement */
98#define WM9713_CTC 0x0100 /* enable continuous mode */
99#define WM9713_ADCSEL_X 0x0002 /* X measurement */
100#define WM9713_ADCSEL_Y 0x0004 /* Y measurement */
101#define WM9713_ADCSEL_PRES 0x0008 /* Pressure measurement */
102#define WM9713_COO 0x0001 /* enable coordinate mode */
103#define WM9713_PDEN 0x0800 /* measure only when pen down */
104#define WM9713_ADCSEL_MASK 0x00fe /* ADC selection mask */
105#define WM9713_WAIT 0x0200 /* coordinate wait */
106
107/* AUX ADC ID's */
108#define TS_COMP1 0x0
109#define TS_COMP2 0x1
110#define TS_BMON 0x2
111#define TS_WIPER 0x3
112
113/* ID numbers */
114#define WM97XX_ID1 0x574d
115#define WM9712_ID2 0x4c12
116#define WM9705_ID2 0x4c05
117#define WM9713_ID2 0x4c13
118
119/* Codec GPIO's */
120#define WM97XX_MAX_GPIO 16
121#define WM97XX_GPIO_1 (1 << 1)
122#define WM97XX_GPIO_2 (1 << 2)
123#define WM97XX_GPIO_3 (1 << 3)
124#define WM97XX_GPIO_4 (1 << 4)
125#define WM97XX_GPIO_5 (1 << 5)
126#define WM97XX_GPIO_6 (1 << 6)
127#define WM97XX_GPIO_7 (1 << 7)
128#define WM97XX_GPIO_8 (1 << 8)
129#define WM97XX_GPIO_9 (1 << 9)
130#define WM97XX_GPIO_10 (1 << 10)
131#define WM97XX_GPIO_11 (1 << 11)
132#define WM97XX_GPIO_12 (1 << 12)
133#define WM97XX_GPIO_13 (1 << 13)
134#define WM97XX_GPIO_14 (1 << 14)
135#define WM97XX_GPIO_15 (1 << 15)
136
137
138#define AC97_LINK_FRAME 21 /* time in uS for AC97 link frame */
139
140
141/*---------------- Return codes from sample reading functions ---------------*/
142
143/* More data is available; call the sample gathering function again */
144#define RC_AGAIN 0x00000001
145/* The returned sample is valid */
146#define RC_VALID 0x00000002
147/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
148#define RC_PENUP 0x00000004
149/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
150 to tell the handler that the pen is down but we don't know yet his coords,
151 so the handler should not sleep or wait for pendown irq) */
152#define RC_PENDOWN 0x00000008
153
154/*
155 * The wm97xx driver provides a private API for writing platform-specific
156 * drivers.
157 */
158
159/* The structure used to return arch specific sampled data into */
160struct wm97xx_data {
161 int x;
162 int y;
163 int p;
164};
165
166/*
167 * Codec GPIO status
168 */
169enum wm97xx_gpio_status {
170 WM97XX_GPIO_HIGH,
171 WM97XX_GPIO_LOW
172};
173
174/*
175 * Codec GPIO direction
176 */
177enum wm97xx_gpio_dir {
178 WM97XX_GPIO_IN,
179 WM97XX_GPIO_OUT
180};
181
182/*
183 * Codec GPIO polarity
184 */
185enum wm97xx_gpio_pol {
186 WM97XX_GPIO_POL_HIGH,
187 WM97XX_GPIO_POL_LOW
188};
189
190/*
191 * Codec GPIO sticky
192 */
193enum wm97xx_gpio_sticky {
194 WM97XX_GPIO_STICKY,
195 WM97XX_GPIO_NOTSTICKY
196};
197
198/*
199 * Codec GPIO wake
200 */
201enum wm97xx_gpio_wake {
202 WM97XX_GPIO_WAKE,
203 WM97XX_GPIO_NOWAKE
204};
205
206/*
207 * Digitiser ioctl commands
208 */
209#define WM97XX_DIG_START 0x1
210#define WM97XX_DIG_STOP 0x2
211#define WM97XX_PHY_INIT 0x3
212#define WM97XX_AUX_PREPARE 0x4
213#define WM97XX_DIG_RESTORE 0x5
214
215struct wm97xx;
216
217extern struct wm97xx_codec_drv wm9705_codec;
218extern struct wm97xx_codec_drv wm9712_codec;
219extern struct wm97xx_codec_drv wm9713_codec;
220
221/*
222 * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
223 */
224struct wm97xx_codec_drv {
225 u16 id;
226 char *name;
227
228 /* read 1 sample */
229 int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);
230
231 /* read X,Y,[P] in poll */
232 int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);
233
234 int (*acc_enable) (struct wm97xx *, int enable);
235 void (*phy_init) (struct wm97xx *);
236 void (*dig_enable) (struct wm97xx *, int enable);
237 void (*dig_restore) (struct wm97xx *);
238 void (*aux_prepare) (struct wm97xx *);
239};
240
241
242/* Machine specific and accelerated touch operations */
243struct wm97xx_mach_ops {
244
245 /* accelerated touch readback - coords are transmited on AC97 link */
246 int acc_enabled;
247 void (*acc_pen_up) (struct wm97xx *);
248 int (*acc_pen_down) (struct wm97xx *);
249 int (*acc_startup) (struct wm97xx *);
250 void (*acc_shutdown) (struct wm97xx *);
251
252 /* interrupt mask control - required for accelerated operation */
253 void (*irq_enable) (struct wm97xx *, int enable);
254
255 /* GPIO pin used for accelerated operation */
256 int irq_gpio;
257
258 /* pre and post sample - can be used to minimise any analog noise */
259 void (*pre_sample) (int); /* function to run before sampling */
260 void (*post_sample) (int); /* function to run after sampling */
261};
262
263struct wm97xx {
264 u16 dig[3], id, gpio[6], misc; /* Cached codec registers */
265 u16 dig_save[3]; /* saved during aux reading */
266 struct wm97xx_codec_drv *codec; /* attached codec driver*/
267 struct input_dev *input_dev; /* touchscreen input device */
268 struct snd_ac97 *ac97; /* ALSA codec access */
269 struct device *dev; /* ALSA device */
270 struct platform_device *battery_dev;
271 struct platform_device *touch_dev;
272 struct wm97xx_mach_ops *mach_ops;
273 struct mutex codec_mutex;
274 struct delayed_work ts_reader; /* Used to poll touchscreen */
275 unsigned long ts_reader_interval; /* Current interval for timer */
276 unsigned long ts_reader_min_interval; /* Minimum interval */
277 unsigned int pen_irq; /* Pen IRQ number in use */
278 struct workqueue_struct *ts_workq;
279 struct work_struct pen_event_work;
280 u16 acc_slot; /* AC97 slot used for acc touch data */
281 u16 acc_rate; /* acc touch data rate */
282 unsigned pen_is_down:1; /* Pen is down */
283 unsigned aux_waiting:1; /* aux measurement waiting */
284 unsigned pen_probably_down:1; /* used in polling mode */
285};
286
287/*
288 * Codec GPIO access (not supported on WM9705)
289 * This can be used to set/get codec GPIO and Virtual GPIO status.
290 */
291enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
292void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
293 enum wm97xx_gpio_status status);
294void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
295 enum wm97xx_gpio_dir dir,
296 enum wm97xx_gpio_pol pol,
297 enum wm97xx_gpio_sticky sticky,
298 enum wm97xx_gpio_wake wake);
299
300/* codec AC97 IO access */
301int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
302void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
303
304/* aux adc readback */
305int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
306
307/* machine ops */
308int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
309void wm97xx_unregister_mach_ops(struct wm97xx *);
310
311#endif