19448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
29448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
39448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
49448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
5b8d055a878ee0f997ded40649701089d2486f850Liam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk>
69448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Parts Copyright : Ian Molton <spyro@f2s.com>
79448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *                   Andrew Zabolotny <zap@homelink.ru>
89448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *                   Russell King <rmk@arm.linux.org.uk>
99448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
109448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *  This program is free software; you can redistribute  it and/or modify it
119448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *  under  the terms of  the GNU General  Public License as published by the
129448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *  Free Software Foundation;  either version 2 of the  License, or (at your
139448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *  option) any later version.
149448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
159448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
169448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
179448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/module.h>
189448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/moduleparam.h>
199448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/kernel.h>
209448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/input.h>
219448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/delay.h>
229448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/bitops.h>
239448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#include <linux/wm97xx.h>
249448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
259448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#define TS_NAME			"wm97xx"
269448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#define WM9705_VERSION		"1.00"
279448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown#define DEFAULT_PRESSURE	0xb0c0
289448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
299448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
309448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Module parameters
319448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
329448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
339448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
349448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Set current used for pressure measurement.
359448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
369448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Set pil = 2 to use 400uA
379448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *     pil = 1 to use 200uA and
389448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *     pil = 0 to disable pressure measurement.
399448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
409448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * This is used to increase the range of values returned by the adc
419448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * when measureing touchpanel pressure.
429448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
439448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int pil;
449448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownmodule_param(pil, int, 0);
459448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
469448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
479448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
489448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Set threshold for pressure measurement.
499448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
509448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Pen down pressure below threshold is ignored.
519448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
529448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int pressure = DEFAULT_PRESSURE & 0xfff;
539448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownmodule_param(pressure, int, 0);
549448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
559448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
569448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
579448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Set adc sample delay.
589448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
599448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * For accurate touchpanel measurements, some settling time may be
609448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * required between the switch matrix applying a voltage across the
619448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * touchpanel plate and the ADC sampling the signal.
629448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
639448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * This delay can be set by setting delay = n, where n is the array
649448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * position of the delay in the array delay_table below.
659448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Long delays > 1ms are supported for completeness, but are not
669448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * recommended.
679448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
689448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int delay = 4;
699448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownmodule_param(delay, int, 0);
709448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_PARM_DESC(delay, "Set adc sample delay.");
719448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
729448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
739448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Pen detect comparator threshold.
749448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
759448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
769448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * i.e. 1 =  Vmid/15 threshold
779448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *      15 =  Vmid/1 threshold
789448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
799448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Adjust this value if you are having problems with pen detect not
809448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * detecting any down events.
819448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
829448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int pdd = 8;
839448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownmodule_param(pdd, int, 0);
849448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
859448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
869448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
879448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Set adc mask function.
889448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
899448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Sources of glitch noise, such as signals driving an LCD display, may feed
909448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * through to the touch screen plates and affect measurement accuracy. In
919448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * order to minimise this, a signal may be applied to the MASK pin to delay or
929448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * synchronise the sampling.
939448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
949448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * 0 = No delay or sync
959448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * 1 = High on pin stops conversions
969448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
979448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * 3 = Edge triggered, edge on pin starts conversion after delay param
989448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
999448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int mask;
1009448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownmodule_param(mask, int, 0);
1019448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_PARM_DESC(mask, "Set adc mask function.");
1029448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1039448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
1049448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * ADC sample delay times in uS
1059448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
1069448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic const int delay_table[] = {
1079448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	21,    /* 1 AC97 Link frames */
1089448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	42,    /* 2                  */
1099448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	84,    /* 4                  */
1109448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	167,   /* 8                  */
1119448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	333,   /* 16                 */
1129448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	667,   /* 32                 */
1139448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	1000,  /* 48                 */
1149448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	1333,  /* 64                 */
1159448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	2000,  /* 96                 */
1169448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	2667,  /* 128                */
1179448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	3333,  /* 160                */
1189448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	4000,  /* 192                */
1199448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	4667,  /* 224                */
1209448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	5333,  /* 256                */
1219448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	6000,  /* 288                */
1229448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	0      /* No delay, switch matrix always on */
1239448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown};
1249448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1259448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
1269448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Delay after issuing a POLL command.
1279448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown *
1289448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * The delay is 3 AC97 link frames + the touchpanel settling delay
1299448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
1309448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic inline void poll_delay(int d)
1319448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
1329448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	udelay(3 * AC97_LINK_FRAME + delay_table[d]);
1339448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
1349448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1359448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
1369448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * set up the physical settings of the WM9705
1379448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
1389448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic void wm9705_phy_init(struct wm97xx *wm)
1399448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
1409448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	u16 dig1 = 0, dig2 = WM97XX_RPR;
1419448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1429448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/*
1439448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	* mute VIDEO and AUX as they share X and Y touchscreen
1449448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	* inputs on the WM9705
1459448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	*/
1469448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_AUX, 0x8000);
1479448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
1489448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1499448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* touchpanel pressure current*/
1509448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (pil == 2) {
1519448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig2 |= WM9705_PIL;
1529448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dev_dbg(wm->dev,
1539448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			"setting pressure measurement current to 400uA.");
1549448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	} else if (pil)
1559448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dev_dbg(wm->dev,
1569448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			"setting pressure measurement current to 200uA.");
1579448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (!pil)
1589448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		pressure = 0;
1599448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1609448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* polling mode sample settling delay */
1619448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (delay != 4) {
1629448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (delay < 0 || delay > 15) {
1639448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			dev_dbg(wm->dev, "supplied delay out of range.");
1649448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			delay = 4;
1659448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		}
1669448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
1679448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig1 &= 0xff0f;
1689448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig1 |= WM97XX_DELAY(delay);
1699448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
1709448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		delay_table[delay]);
1719448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1729448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* WM9705 pdd */
1739448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig2 |= (pdd & 0x000f);
1749448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
1759448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1769448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* mask */
1779448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig2 |= ((mask & 0x3) << 4);
1789448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1799448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
1809448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
1819448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
1829448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1839448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic void wm9705_dig_enable(struct wm97xx *wm, int enable)
1849448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
1859448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (enable) {
1869448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
1879448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown				 wm->dig[2] | WM97XX_PRP_DET_DIG);
1889448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
1899448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	} else
1909448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
1919448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown				 wm->dig[2] & ~WM97XX_PRP_DET_DIG);
1929448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
1939448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
1949448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic void wm9705_aux_prepare(struct wm97xx *wm)
1959448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
1969448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
1979448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
1989448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
1999448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
2009448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2019448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic void wm9705_dig_restore(struct wm97xx *wm)
2029448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
2039448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
2049448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
2059448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
2069448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2079448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic inline int is_pden(struct wm97xx *wm)
2089448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
2099448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	return wm->dig[2] & WM9705_PDEN;
2109448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
2119448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2129448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
2139448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Read a sample from the WM9705 adc in polling mode.
2149448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
2159448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
2169448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
2179448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	int timeout = 5 * delay;
21877da38387e1c6f473744afccd83795805f506498Wolfram Sang	bool wants_pen = adcsel & WM97XX_PEN_DOWN;
2199448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
22077da38387e1c6f473744afccd83795805f506498Wolfram Sang	if (wants_pen && !wm->pen_probably_down) {
2219448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
2229448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (!(data & WM97XX_PEN_DOWN))
2239448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			return RC_PENUP;
2249448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm->pen_probably_down = 1;
2259448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
2269448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2279448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* set up digitiser */
2289448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (wm->mach_ops && wm->mach_ops->pre_sample)
2299448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm->mach_ops->pre_sample(adcsel);
230c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
231c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang				| WM97XX_POLL | WM97XX_DELAY(delay));
2329448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2339448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* wait 3 AC97 time slots + delay for conversion */
2349448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	poll_delay(delay);
2359448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2369448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* wait for POLL to go low */
2379448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
2389448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	       && timeout) {
2399448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		udelay(AC97_LINK_FRAME);
2409448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		timeout--;
2419448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
2429448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2439448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (timeout == 0) {
2449448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		/* If PDEN is set, we can get a timeout when pen goes up */
2459448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (is_pden(wm))
2469448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			wm->pen_probably_down = 0;
2479448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		else
2489448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			dev_dbg(wm->dev, "adc sample timeout");
2499448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		return RC_PENUP;
2509448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
2519448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2529448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
2539448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (wm->mach_ops && wm->mach_ops->post_sample)
2549448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm->mach_ops->post_sample(adcsel);
2559448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2569448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	/* check we have correct sample */
257c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
258c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
259c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang			adcsel & WM97XX_ADCSEL_MASK,
260c8f205258bc8942e79cd37ebc1c8ec4652a1a501Wolfram Sang			*sample & WM97XX_ADCSEL_MASK);
2619448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		return RC_PENUP;
2629448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
2639448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
26477da38387e1c6f473744afccd83795805f506498Wolfram Sang	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
2659448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		wm->pen_probably_down = 0;
2669448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		return RC_PENUP;
2679448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
2689448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2699448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	return RC_VALID;
2709448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
2719448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2729448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
2739448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Sample the WM9705 touchscreen in polling mode
2749448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
2759448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
2769448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
2779448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	int rc;
2789448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
27977da38387e1c6f473744afccd83795805f506498Wolfram Sang	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
2809448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (rc != RC_VALID)
2819448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		return rc;
28277da38387e1c6f473744afccd83795805f506498Wolfram Sang	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
2839448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (rc != RC_VALID)
2849448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		return rc;
2859448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (pil) {
28677da38387e1c6f473744afccd83795805f506498Wolfram Sang		rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
2879448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (rc != RC_VALID)
2889448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			return rc;
2899448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	} else
2909448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		data->p = DEFAULT_PRESSURE;
2919448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2929448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	return RC_VALID;
2939448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
2949448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
2959448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/*
2969448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * Enable WM9705 continuous mode, i.e. touch data is streamed across
2979448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown * an AC97 slot
2989448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown */
2999448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstatic int wm9705_acc_enable(struct wm97xx *wm, int enable)
3009448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown{
3019448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	u16 dig1, dig2;
3029448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	int ret = 0;
3039448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3049448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig1 = wm->dig[1];
3059448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	dig2 = wm->dig[2];
3069448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3079448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	if (enable) {
30825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* continuous mode */
3099448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (wm->mach_ops->acc_startup &&
3109448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		    (ret = wm->mach_ops->acc_startup(wm)) < 0)
3119448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			return ret;
3129448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
3139448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			  WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
3149448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
3159448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			WM97XX_DELAY(delay) |
3169448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			WM97XX_SLT(wm->acc_slot) |
3179448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			WM97XX_RATE(wm->acc_rate);
3189448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (pil)
3199448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			dig1 |= WM97XX_ADCSEL_PRES;
3209448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig2 |= WM9705_PDEN;
3219448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	} else {
3229448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
3239448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		dig2 &= ~WM9705_PDEN;
3249448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown		if (wm->mach_ops->acc_shutdown)
3259448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown			wm->mach_ops->acc_shutdown(wm);
3269448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	}
3279448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3289448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
3299448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
3309448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3319448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	return ret;
3329448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown}
3339448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3349448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brownstruct wm97xx_codec_drv wm9705_codec = {
3359448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.id = WM9705_ID2,
3369448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.name = "wm9705",
3379448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.poll_sample = wm9705_poll_sample,
3389448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.poll_touch = wm9705_poll_touch,
3399448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.acc_enable = wm9705_acc_enable,
3409448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.phy_init = wm9705_phy_init,
3419448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.dig_enable = wm9705_dig_enable,
3429448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.dig_restore = wm9705_dig_restore,
3439448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown	.aux_prepare = wm9705_aux_prepare,
3449448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown};
3459448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownEXPORT_SYMBOL_GPL(wm9705_codec);
3469448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown
3479448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark Brown/* Module information */
348b8d055a878ee0f997ded40649701089d2486f850Liam GirdwoodMODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
3499448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_DESCRIPTION("WM9705 Touch Screen Driver");
3509448cefc6689aa51f1cd1cfe8b701dc94789c7eeMark BrownMODULE_LICENSE("GPL");
351