aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
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 /drivers/input
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>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/Kconfig14
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c789
3 files changed, 806 insertions, 0 deletions
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");