1de22b9efSMark Brown /* 2de22b9efSMark Brown * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. 3de22b9efSMark Brown * 4de22b9efSMark Brown * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. 5b8d055a8SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 6de22b9efSMark Brown * Parts Copyright : Ian Molton <spyro@f2s.com> 7de22b9efSMark Brown * Andrew Zabolotny <zap@homelink.ru> 8de22b9efSMark Brown * Russell King <rmk@arm.linux.org.uk> 9de22b9efSMark Brown * 10de22b9efSMark Brown * This program is free software; you can redistribute it and/or modify it 11de22b9efSMark Brown * under the terms of the GNU General Public License as published by the 12de22b9efSMark Brown * Free Software Foundation; either version 2 of the License, or (at your 13de22b9efSMark Brown * option) any later version. 14de22b9efSMark Brown * 15de22b9efSMark Brown */ 16de22b9efSMark Brown 17de22b9efSMark Brown #include <linux/module.h> 18de22b9efSMark Brown #include <linux/moduleparam.h> 19de22b9efSMark Brown #include <linux/kernel.h> 20de22b9efSMark Brown #include <linux/input.h> 21de22b9efSMark Brown #include <linux/delay.h> 22de22b9efSMark Brown #include <linux/bitops.h> 23de22b9efSMark Brown #include <linux/wm97xx.h> 24de22b9efSMark Brown 25de22b9efSMark Brown #define TS_NAME "wm97xx" 26de22b9efSMark Brown #define WM9712_VERSION "1.00" 27de22b9efSMark Brown #define DEFAULT_PRESSURE 0xb0c0 28de22b9efSMark Brown 29de22b9efSMark Brown /* 30de22b9efSMark Brown * Module parameters 31de22b9efSMark Brown */ 32de22b9efSMark Brown 33de22b9efSMark Brown /* 34de22b9efSMark Brown * Set internal pull up for pen detect. 35de22b9efSMark Brown * 36de22b9efSMark Brown * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive) 37de22b9efSMark Brown * i.e. pull up resistance = 64k Ohms / rpu. 38de22b9efSMark Brown * 39de22b9efSMark Brown * Adjust this value if you are having problems with pen detect not 40de22b9efSMark Brown * detecting any down event. 41de22b9efSMark Brown */ 42de22b9efSMark Brown static int rpu = 8; 43de22b9efSMark Brown module_param(rpu, int, 0); 44de22b9efSMark Brown MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); 45de22b9efSMark Brown 46de22b9efSMark Brown /* 47de22b9efSMark Brown * Set current used for pressure measurement. 48de22b9efSMark Brown * 49de22b9efSMark Brown * Set pil = 2 to use 400uA 50de22b9efSMark Brown * pil = 1 to use 200uA and 51de22b9efSMark Brown * pil = 0 to disable pressure measurement. 52de22b9efSMark Brown * 53de22b9efSMark Brown * This is used to increase the range of values returned by the adc 54de22b9efSMark Brown * when measureing touchpanel pressure. 55de22b9efSMark Brown */ 56de22b9efSMark Brown static int pil; 57de22b9efSMark Brown module_param(pil, int, 0); 58de22b9efSMark Brown MODULE_PARM_DESC(pil, "Set current used for pressure measurement."); 59de22b9efSMark Brown 60de22b9efSMark Brown /* 61de22b9efSMark Brown * Set threshold for pressure measurement. 62de22b9efSMark Brown * 63de22b9efSMark Brown * Pen down pressure below threshold is ignored. 64de22b9efSMark Brown */ 65de22b9efSMark Brown static int pressure = DEFAULT_PRESSURE & 0xfff; 66de22b9efSMark Brown module_param(pressure, int, 0); 67de22b9efSMark Brown MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement."); 68de22b9efSMark Brown 69de22b9efSMark Brown /* 70de22b9efSMark Brown * Set adc sample delay. 71de22b9efSMark Brown * 72de22b9efSMark Brown * For accurate touchpanel measurements, some settling time may be 73de22b9efSMark Brown * required between the switch matrix applying a voltage across the 74de22b9efSMark Brown * touchpanel plate and the ADC sampling the signal. 75de22b9efSMark Brown * 76de22b9efSMark Brown * This delay can be set by setting delay = n, where n is the array 77de22b9efSMark Brown * position of the delay in the array delay_table below. 78de22b9efSMark Brown * Long delays > 1ms are supported for completeness, but are not 79de22b9efSMark Brown * recommended. 80de22b9efSMark Brown */ 81de22b9efSMark Brown static int delay = 3; 82de22b9efSMark Brown module_param(delay, int, 0); 83de22b9efSMark Brown MODULE_PARM_DESC(delay, "Set adc sample delay."); 84de22b9efSMark Brown 85de22b9efSMark Brown /* 86de22b9efSMark Brown * Set five_wire = 1 to use a 5 wire touchscreen. 87de22b9efSMark Brown * 88de22b9efSMark Brown * NOTE: Five wire mode does not allow for readback of pressure. 89de22b9efSMark Brown */ 90de22b9efSMark Brown static int five_wire; 91de22b9efSMark Brown module_param(five_wire, int, 0); 92de22b9efSMark Brown MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen."); 93de22b9efSMark Brown 94de22b9efSMark Brown /* 95de22b9efSMark Brown * Set adc mask function. 96de22b9efSMark Brown * 97de22b9efSMark Brown * Sources of glitch noise, such as signals driving an LCD display, may feed 98de22b9efSMark Brown * through to the touch screen plates and affect measurement accuracy. In 99de22b9efSMark Brown * order to minimise this, a signal may be applied to the MASK pin to delay or 100de22b9efSMark Brown * synchronise the sampling. 101de22b9efSMark Brown * 102de22b9efSMark Brown * 0 = No delay or sync 103de22b9efSMark Brown * 1 = High on pin stops conversions 104de22b9efSMark Brown * 2 = Edge triggered, edge on pin delays conversion by delay param (above) 105de22b9efSMark Brown * 3 = Edge triggered, edge on pin starts conversion after delay param 106de22b9efSMark Brown */ 107de22b9efSMark Brown static int mask; 108de22b9efSMark Brown module_param(mask, int, 0); 109de22b9efSMark Brown MODULE_PARM_DESC(mask, "Set adc mask function."); 110de22b9efSMark Brown 111de22b9efSMark Brown /* 112de22b9efSMark Brown * Coordinate Polling Enable. 113de22b9efSMark Brown * 114de22b9efSMark Brown * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together 115de22b9efSMark Brown * for every poll. 116de22b9efSMark Brown */ 117de22b9efSMark Brown static int coord; 118de22b9efSMark Brown module_param(coord, int, 0); 119de22b9efSMark Brown MODULE_PARM_DESC(coord, "Polling coordinate mode"); 120de22b9efSMark Brown 121de22b9efSMark Brown /* 122de22b9efSMark Brown * ADC sample delay times in uS 123de22b9efSMark Brown */ 124de22b9efSMark Brown static const int delay_table[] = { 125de22b9efSMark Brown 21, /* 1 AC97 Link frames */ 126de22b9efSMark Brown 42, /* 2 */ 127de22b9efSMark Brown 84, /* 4 */ 128de22b9efSMark Brown 167, /* 8 */ 129de22b9efSMark Brown 333, /* 16 */ 130de22b9efSMark Brown 667, /* 32 */ 131de22b9efSMark Brown 1000, /* 48 */ 132de22b9efSMark Brown 1333, /* 64 */ 133de22b9efSMark Brown 2000, /* 96 */ 134de22b9efSMark Brown 2667, /* 128 */ 135de22b9efSMark Brown 3333, /* 160 */ 136de22b9efSMark Brown 4000, /* 192 */ 137de22b9efSMark Brown 4667, /* 224 */ 138de22b9efSMark Brown 5333, /* 256 */ 139de22b9efSMark Brown 6000, /* 288 */ 140de22b9efSMark Brown 0 /* No delay, switch matrix always on */ 141de22b9efSMark Brown }; 142de22b9efSMark Brown 143de22b9efSMark Brown /* 144de22b9efSMark Brown * Delay after issuing a POLL command. 145de22b9efSMark Brown * 146de22b9efSMark Brown * The delay is 3 AC97 link frames + the touchpanel settling delay 147de22b9efSMark Brown */ 148de22b9efSMark Brown static inline void poll_delay(int d) 149de22b9efSMark Brown { 150de22b9efSMark Brown udelay(3 * AC97_LINK_FRAME + delay_table[d]); 151de22b9efSMark Brown } 152de22b9efSMark Brown 153de22b9efSMark Brown /* 154de22b9efSMark Brown * set up the physical settings of the WM9712 155de22b9efSMark Brown */ 156de22b9efSMark Brown static void wm9712_phy_init(struct wm97xx *wm) 157de22b9efSMark Brown { 158de22b9efSMark Brown u16 dig1 = 0; 159de22b9efSMark Brown u16 dig2 = WM97XX_RPR | WM9712_RPU(1); 160de22b9efSMark Brown 161de22b9efSMark Brown /* WM9712 rpu */ 162de22b9efSMark Brown if (rpu) { 163de22b9efSMark Brown dig2 &= 0xffc0; 164de22b9efSMark Brown dig2 |= WM9712_RPU(rpu); 165de22b9efSMark Brown dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms", 166de22b9efSMark Brown 64000 / rpu); 167de22b9efSMark Brown } 168de22b9efSMark Brown 1698a65c02fSMark Brown /* WM9712 five wire */ 1708a65c02fSMark Brown if (five_wire) { 1718a65c02fSMark Brown dig2 |= WM9712_45W; 1728a65c02fSMark Brown dev_dbg(wm->dev, "setting 5-wire touchscreen mode."); 1738a65c02fSMark Brown 1748a65c02fSMark Brown if (pil) { 1758a65c02fSMark Brown dev_warn(wm->dev, "pressure measurement is not " 1768a65c02fSMark Brown "supported in 5-wire mode\n"); 1778a65c02fSMark Brown pil = 0; 1788a65c02fSMark Brown } 1798a65c02fSMark Brown } 1808a65c02fSMark Brown 181de22b9efSMark Brown /* touchpanel pressure current*/ 182de22b9efSMark Brown if (pil == 2) { 183de22b9efSMark Brown dig2 |= WM9712_PIL; 184de22b9efSMark Brown dev_dbg(wm->dev, 185de22b9efSMark Brown "setting pressure measurement current to 400uA."); 186de22b9efSMark Brown } else if (pil) 187de22b9efSMark Brown dev_dbg(wm->dev, 188de22b9efSMark Brown "setting pressure measurement current to 200uA."); 189de22b9efSMark Brown if (!pil) 190de22b9efSMark Brown pressure = 0; 191de22b9efSMark Brown 192de22b9efSMark Brown /* polling mode sample settling delay */ 193de22b9efSMark Brown if (delay < 0 || delay > 15) { 194de22b9efSMark Brown dev_dbg(wm->dev, "supplied delay out of range."); 195de22b9efSMark Brown delay = 4; 196de22b9efSMark Brown } 197de22b9efSMark Brown dig1 &= 0xff0f; 198de22b9efSMark Brown dig1 |= WM97XX_DELAY(delay); 199de22b9efSMark Brown dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.", 200de22b9efSMark Brown delay_table[delay]); 201de22b9efSMark Brown 202de22b9efSMark Brown /* mask */ 203de22b9efSMark Brown dig2 |= ((mask & 0x3) << 6); 204de22b9efSMark Brown if (mask) { 205de22b9efSMark Brown u16 reg; 206de22b9efSMark Brown /* Set GPIO4 as Mask Pin*/ 207de22b9efSMark Brown reg = wm97xx_reg_read(wm, AC97_MISC_AFE); 208de22b9efSMark Brown wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4); 209de22b9efSMark Brown reg = wm97xx_reg_read(wm, AC97_GPIO_CFG); 210de22b9efSMark Brown wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4); 211de22b9efSMark Brown } 212de22b9efSMark Brown 213de22b9efSMark Brown /* wait - coord mode */ 214de22b9efSMark Brown if (coord) 215de22b9efSMark Brown dig2 |= WM9712_WAIT; 216de22b9efSMark Brown 217de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); 218de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); 219de22b9efSMark Brown } 220de22b9efSMark Brown 221de22b9efSMark Brown static void wm9712_dig_enable(struct wm97xx *wm, int enable) 222de22b9efSMark Brown { 223de22b9efSMark Brown u16 dig2 = wm->dig[2]; 224de22b9efSMark Brown 225de22b9efSMark Brown if (enable) { 226de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, 227de22b9efSMark Brown dig2 | WM97XX_PRP_DET_DIG); 228de22b9efSMark Brown wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */ 229de22b9efSMark Brown } else 230de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, 231de22b9efSMark Brown dig2 & ~WM97XX_PRP_DET_DIG); 232de22b9efSMark Brown } 233de22b9efSMark Brown 234de22b9efSMark Brown static void wm9712_aux_prepare(struct wm97xx *wm) 235de22b9efSMark Brown { 236de22b9efSMark Brown memcpy(wm->dig_save, wm->dig, sizeof(wm->dig)); 237de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0); 238de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG); 239de22b9efSMark Brown } 240de22b9efSMark Brown 241de22b9efSMark Brown static void wm9712_dig_restore(struct wm97xx *wm) 242de22b9efSMark Brown { 243de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]); 244de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]); 245de22b9efSMark Brown } 246de22b9efSMark Brown 247de22b9efSMark Brown static inline int is_pden(struct wm97xx *wm) 248de22b9efSMark Brown { 249de22b9efSMark Brown return wm->dig[2] & WM9712_PDEN; 250de22b9efSMark Brown } 251de22b9efSMark Brown 252de22b9efSMark Brown /* 253de22b9efSMark Brown * Read a sample from the WM9712 adc in polling mode. 254de22b9efSMark Brown */ 255de22b9efSMark Brown static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) 256de22b9efSMark Brown { 257de22b9efSMark Brown int timeout = 5 * delay; 25877da3838SWolfram Sang bool wants_pen = adcsel & WM97XX_PEN_DOWN; 259de22b9efSMark Brown 26077da3838SWolfram Sang if (wants_pen && !wm->pen_probably_down) { 261de22b9efSMark Brown u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 262de22b9efSMark Brown if (!(data & WM97XX_PEN_DOWN)) 263de22b9efSMark Brown return RC_PENUP; 264de22b9efSMark Brown wm->pen_probably_down = 1; 265de22b9efSMark Brown } 266de22b9efSMark Brown 267de22b9efSMark Brown /* set up digitiser */ 268de22b9efSMark Brown if (wm->mach_ops && wm->mach_ops->pre_sample) 269de22b9efSMark Brown wm->mach_ops->pre_sample(adcsel); 270c8f20525SWolfram Sang wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK) 271c8f20525SWolfram Sang | WM97XX_POLL | WM97XX_DELAY(delay)); 272de22b9efSMark Brown 273de22b9efSMark Brown /* wait 3 AC97 time slots + delay for conversion */ 274de22b9efSMark Brown poll_delay(delay); 275de22b9efSMark Brown 276de22b9efSMark Brown /* wait for POLL to go low */ 277de22b9efSMark Brown while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) 278de22b9efSMark Brown && timeout) { 279de22b9efSMark Brown udelay(AC97_LINK_FRAME); 280de22b9efSMark Brown timeout--; 281de22b9efSMark Brown } 282de22b9efSMark Brown 283de22b9efSMark Brown if (timeout <= 0) { 284de22b9efSMark Brown /* If PDEN is set, we can get a timeout when pen goes up */ 285de22b9efSMark Brown if (is_pden(wm)) 286de22b9efSMark Brown wm->pen_probably_down = 0; 287de22b9efSMark Brown else 288de22b9efSMark Brown dev_dbg(wm->dev, "adc sample timeout"); 289de22b9efSMark Brown return RC_PENUP; 290de22b9efSMark Brown } 291de22b9efSMark Brown 292de22b9efSMark Brown *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 293de22b9efSMark Brown if (wm->mach_ops && wm->mach_ops->post_sample) 294de22b9efSMark Brown wm->mach_ops->post_sample(adcsel); 295de22b9efSMark Brown 296de22b9efSMark Brown /* check we have correct sample */ 297c8f20525SWolfram Sang if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { 298c8f20525SWolfram Sang dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", 299c8f20525SWolfram Sang adcsel & WM97XX_ADCSEL_MASK, 300de22b9efSMark Brown *sample & WM97XX_ADCSEL_MASK); 301fa45255eSMarkus Pargmann return RC_AGAIN; 302de22b9efSMark Brown } 303de22b9efSMark Brown 30477da3838SWolfram Sang if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { 305de22b9efSMark Brown wm->pen_probably_down = 0; 306de22b9efSMark Brown return RC_PENUP; 307de22b9efSMark Brown } 308de22b9efSMark Brown 309de22b9efSMark Brown return RC_VALID; 310de22b9efSMark Brown } 311de22b9efSMark Brown 312de22b9efSMark Brown /* 313de22b9efSMark Brown * Read a coord from the WM9712 adc in polling mode. 314de22b9efSMark Brown */ 315de22b9efSMark Brown static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data) 316de22b9efSMark Brown { 317de22b9efSMark Brown int timeout = 5 * delay; 318de22b9efSMark Brown 319de22b9efSMark Brown if (!wm->pen_probably_down) { 320de22b9efSMark Brown u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 321de22b9efSMark Brown if (!(data_rd & WM97XX_PEN_DOWN)) 322de22b9efSMark Brown return RC_PENUP; 323de22b9efSMark Brown wm->pen_probably_down = 1; 324de22b9efSMark Brown } 325de22b9efSMark Brown 326de22b9efSMark Brown /* set up digitiser */ 327de22b9efSMark Brown if (wm->mach_ops && wm->mach_ops->pre_sample) 328de22b9efSMark Brown wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); 329de22b9efSMark Brown 330de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 331de22b9efSMark Brown WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay)); 332de22b9efSMark Brown 333de22b9efSMark Brown /* wait 3 AC97 time slots + delay for conversion and read x */ 334de22b9efSMark Brown poll_delay(delay); 335de22b9efSMark Brown data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 336de22b9efSMark Brown /* wait for POLL to go low */ 337de22b9efSMark Brown while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) 338de22b9efSMark Brown && timeout) { 339de22b9efSMark Brown udelay(AC97_LINK_FRAME); 340de22b9efSMark Brown timeout--; 341de22b9efSMark Brown } 342de22b9efSMark Brown 343de22b9efSMark Brown if (timeout <= 0) { 344de22b9efSMark Brown /* If PDEN is set, we can get a timeout when pen goes up */ 345de22b9efSMark Brown if (is_pden(wm)) 346de22b9efSMark Brown wm->pen_probably_down = 0; 347de22b9efSMark Brown else 348de22b9efSMark Brown dev_dbg(wm->dev, "adc sample timeout"); 349de22b9efSMark Brown return RC_PENUP; 350de22b9efSMark Brown } 351de22b9efSMark Brown 352de22b9efSMark Brown /* read back y data */ 353de22b9efSMark Brown data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 354de22b9efSMark Brown if (pil) 355de22b9efSMark Brown data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 356de22b9efSMark Brown else 357de22b9efSMark Brown data->p = DEFAULT_PRESSURE; 358de22b9efSMark Brown 359de22b9efSMark Brown if (wm->mach_ops && wm->mach_ops->post_sample) 360de22b9efSMark Brown wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); 361de22b9efSMark Brown 362de22b9efSMark Brown /* check we have correct sample */ 363de22b9efSMark Brown if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y)) 364de22b9efSMark Brown goto err; 365de22b9efSMark Brown if (pil && !(data->p & WM97XX_ADCSEL_PRES)) 366de22b9efSMark Brown goto err; 367de22b9efSMark Brown 368de22b9efSMark Brown if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) { 369de22b9efSMark Brown wm->pen_probably_down = 0; 370de22b9efSMark Brown return RC_PENUP; 371de22b9efSMark Brown } 372de22b9efSMark Brown return RC_VALID; 373de22b9efSMark Brown err: 374de22b9efSMark Brown return 0; 375de22b9efSMark Brown } 376de22b9efSMark Brown 377de22b9efSMark Brown /* 378de22b9efSMark Brown * Sample the WM9712 touchscreen in polling mode 379de22b9efSMark Brown */ 380de22b9efSMark Brown static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) 381de22b9efSMark Brown { 382de22b9efSMark Brown int rc; 383de22b9efSMark Brown 384de22b9efSMark Brown if (coord) { 385de22b9efSMark Brown rc = wm9712_poll_coord(wm, data); 386de22b9efSMark Brown if (rc != RC_VALID) 387de22b9efSMark Brown return rc; 388de22b9efSMark Brown } else { 38977da3838SWolfram Sang rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, 39077da3838SWolfram Sang &data->x); 391de22b9efSMark Brown if (rc != RC_VALID) 392de22b9efSMark Brown return rc; 393de22b9efSMark Brown 39477da3838SWolfram Sang rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, 39577da3838SWolfram Sang &data->y); 396de22b9efSMark Brown if (rc != RC_VALID) 397de22b9efSMark Brown return rc; 398de22b9efSMark Brown 399de22b9efSMark Brown if (pil && !five_wire) { 40077da3838SWolfram Sang rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, 401de22b9efSMark Brown &data->p); 402de22b9efSMark Brown if (rc != RC_VALID) 403de22b9efSMark Brown return rc; 404de22b9efSMark Brown } else 405de22b9efSMark Brown data->p = DEFAULT_PRESSURE; 406de22b9efSMark Brown } 407de22b9efSMark Brown return RC_VALID; 408de22b9efSMark Brown } 409de22b9efSMark Brown 410de22b9efSMark Brown /* 411de22b9efSMark Brown * Enable WM9712 continuous mode, i.e. touch data is streamed across 412de22b9efSMark Brown * an AC97 slot 413de22b9efSMark Brown */ 414de22b9efSMark Brown static int wm9712_acc_enable(struct wm97xx *wm, int enable) 415de22b9efSMark Brown { 416de22b9efSMark Brown u16 dig1, dig2; 417de22b9efSMark Brown int ret = 0; 418de22b9efSMark Brown 419de22b9efSMark Brown dig1 = wm->dig[1]; 420de22b9efSMark Brown dig2 = wm->dig[2]; 421de22b9efSMark Brown 422de22b9efSMark Brown if (enable) { 42325985edcSLucas De Marchi /* continuous mode */ 424de22b9efSMark Brown if (wm->mach_ops->acc_startup) { 425de22b9efSMark Brown ret = wm->mach_ops->acc_startup(wm); 426de22b9efSMark Brown if (ret < 0) 427de22b9efSMark Brown return ret; 428de22b9efSMark Brown } 429de22b9efSMark Brown dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK | 430de22b9efSMark Brown WM97XX_DELAY_MASK | WM97XX_SLT_MASK); 431de22b9efSMark Brown dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN | 432de22b9efSMark Brown WM97XX_DELAY(delay) | 433de22b9efSMark Brown WM97XX_SLT(wm->acc_slot) | 434de22b9efSMark Brown WM97XX_RATE(wm->acc_rate); 435de22b9efSMark Brown if (pil) 436de22b9efSMark Brown dig1 |= WM97XX_ADCSEL_PRES; 437de22b9efSMark Brown dig2 |= WM9712_PDEN; 438de22b9efSMark Brown } else { 439de22b9efSMark Brown dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN); 440de22b9efSMark Brown dig2 &= ~WM9712_PDEN; 441de22b9efSMark Brown if (wm->mach_ops->acc_shutdown) 442de22b9efSMark Brown wm->mach_ops->acc_shutdown(wm); 443de22b9efSMark Brown } 444de22b9efSMark Brown 445de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); 446de22b9efSMark Brown wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); 447de22b9efSMark Brown 448de22b9efSMark Brown return 0; 449de22b9efSMark Brown } 450de22b9efSMark Brown 451de22b9efSMark Brown struct wm97xx_codec_drv wm9712_codec = { 452de22b9efSMark Brown .id = WM9712_ID2, 453de22b9efSMark Brown .name = "wm9712", 454de22b9efSMark Brown .poll_sample = wm9712_poll_sample, 455de22b9efSMark Brown .poll_touch = wm9712_poll_touch, 456de22b9efSMark Brown .acc_enable = wm9712_acc_enable, 457de22b9efSMark Brown .phy_init = wm9712_phy_init, 458de22b9efSMark Brown .dig_enable = wm9712_dig_enable, 459de22b9efSMark Brown .dig_restore = wm9712_dig_restore, 460de22b9efSMark Brown .aux_prepare = wm9712_aux_prepare, 461de22b9efSMark Brown }; 462de22b9efSMark Brown EXPORT_SYMBOL_GPL(wm9712_codec); 463de22b9efSMark Brown 464de22b9efSMark Brown /* Module information */ 465b8d055a8SLiam Girdwood MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); 466de22b9efSMark Brown MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); 467de22b9efSMark Brown MODULE_LICENSE("GPL"); 468