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