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