aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-04-02 00:51:09 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-04-02 00:51:09 -0400
commitfebf1dff119ef27ee22a54d40f284d2454f00d8d (patch)
tree8369e232456e3ba52bfdc873d561ddcbea7d0baa
parent3797fec17193e05dee9666b990d6c84e16b188b3 (diff)
Input: add support for WM97xx familty touchscreens
Add support for the touchscreen controllers provided by Wolfson Microelectronics WM97xx series chips in both polled and streaming modes. These drivers have been maintained out of tree since 2003. During that time the driver the primary maintainer was Liam Girdwood and a number of people have made contributions including Dmitry Baryshkov, Stanley Cai, Rodolfo Giometti, Russell King, Marc Kleine-Budde, Ian Molton, Vincent Sanders, Andrew Zabolotny, Graeme Gregory, Mike Arthur and myself. Apologies to anyone I have omitted. Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com> Signed-off-by: Graeme Gregory <gg@opensource.wolfsonmicro.com> Signed-off-by: Mike Arthur <mike.arthur@wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--MAINTAINERS10
-rw-r--r--drivers/input/touchscreen/Kconfig14
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c789
-rw-r--r--include/linux/wm97xx.h311
5 files changed, 1127 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..a95a87cd1d59 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -185,6 +185,20 @@ 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
188config TOUCHSCREEN_USB_COMPOSITE 202config TOUCHSCREEN_USB_COMPOSITE
189 tristate "USB Touchscreen Driver" 203 tristate "USB Touchscreen Driver"
190 depends on USB_ARCH_HAS_HCD 204 depends on USB_ARCH_HAS_HCD
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 35d4097df35a..b4e7b5dbf649 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,4 @@ 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
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