This source file includes following definitions.
- poll_delay
- wm9712_phy_init
- wm9712_dig_enable
- wm9712_aux_prepare
- wm9712_dig_restore
- is_pden
- wm9712_poll_sample
- wm9712_poll_coord
- wm9712_poll_touch
- wm9712_acc_enable
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 #include <linux/module.h>
  13 #include <linux/moduleparam.h>
  14 #include <linux/kernel.h>
  15 #include <linux/input.h>
  16 #include <linux/delay.h>
  17 #include <linux/bitops.h>
  18 #include <linux/wm97xx.h>
  19 
  20 #define TS_NAME                 "wm97xx"
  21 #define WM9712_VERSION          "1.00"
  22 #define DEFAULT_PRESSURE        0xb0c0
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 static int rpu = 8;
  38 module_param(rpu, int, 0);
  39 MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 static int pil;
  52 module_param(pil, int, 0);
  53 MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
  54 
  55 
  56 
  57 
  58 
  59 
  60 static int pressure = DEFAULT_PRESSURE & 0xfff;
  61 module_param(pressure, int, 0);
  62 MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 static int delay = 3;
  77 module_param(delay, int, 0);
  78 MODULE_PARM_DESC(delay, "Set adc sample delay.");
  79 
  80 
  81 
  82 
  83 
  84 
  85 static int five_wire;
  86 module_param(five_wire, int, 0);
  87 MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 static int mask;
 103 module_param(mask, int, 0);
 104 MODULE_PARM_DESC(mask, "Set adc mask function.");
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 static int coord;
 113 module_param(coord, int, 0);
 114 MODULE_PARM_DESC(coord, "Polling coordinate mode");
 115 
 116 
 117 
 118 
 119 static const int delay_table[] = {
 120         21,    
 121         42,    
 122         84,    
 123         167,   
 124         333,   
 125         667,   
 126         1000,  
 127         1333,  
 128         2000,  
 129         2667,  
 130         3333,  
 131         4000,  
 132         4667,  
 133         5333,  
 134         6000,  
 135         0      
 136 };
 137 
 138 
 139 
 140 
 141 
 142 
 143 static inline void poll_delay(int d)
 144 {
 145         udelay(3 * AC97_LINK_FRAME + delay_table[d]);
 146 }
 147 
 148 
 149 
 150 
 151 static void wm9712_phy_init(struct wm97xx *wm)
 152 {
 153         u16 dig1 = 0;
 154         u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
 155 
 156         
 157         if (rpu) {
 158                 dig2 &= 0xffc0;
 159                 dig2 |= WM9712_RPU(rpu);
 160                 dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms\n",
 161                         64000 / rpu);
 162         }
 163 
 164         
 165         if (five_wire) {
 166                 dig2 |= WM9712_45W;
 167                 dev_dbg(wm->dev, "setting 5-wire touchscreen mode.\n");
 168 
 169                 if (pil) {
 170                         dev_warn(wm->dev, "pressure measurement is not "
 171                                  "supported in 5-wire mode\n");
 172                         pil = 0;
 173                 }
 174         }
 175 
 176         
 177         if (pil == 2) {
 178                 dig2 |= WM9712_PIL;
 179                 dev_dbg(wm->dev,
 180                         "setting pressure measurement current to 400uA.\n");
 181         } else if (pil)
 182                 dev_dbg(wm->dev,
 183                         "setting pressure measurement current to 200uA.\n");
 184         if (!pil)
 185                 pressure = 0;
 186 
 187         
 188         if (delay < 0 || delay > 15) {
 189                 dev_dbg(wm->dev, "supplied delay out of range.\n");
 190                 delay = 4;
 191         }
 192         dig1 &= 0xff0f;
 193         dig1 |= WM97XX_DELAY(delay);
 194         dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.\n",
 195                 delay_table[delay]);
 196 
 197         
 198         dig2 |= ((mask & 0x3) << 6);
 199         if (mask) {
 200                 u16 reg;
 201                 
 202                 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
 203                 wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
 204                 reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
 205                 wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
 206         }
 207 
 208         
 209         if (coord)
 210                 dig2 |= WM9712_WAIT;
 211 
 212         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
 213         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
 214 }
 215 
 216 static void wm9712_dig_enable(struct wm97xx *wm, int enable)
 217 {
 218         u16 dig2 = wm->dig[2];
 219 
 220         if (enable) {
 221                 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
 222                                  dig2 | WM97XX_PRP_DET_DIG);
 223                 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 
 224         } else
 225                 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
 226                                  dig2 & ~WM97XX_PRP_DET_DIG);
 227 }
 228 
 229 static void wm9712_aux_prepare(struct wm97xx *wm)
 230 {
 231         memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
 232         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
 233         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
 234 }
 235 
 236 static void wm9712_dig_restore(struct wm97xx *wm)
 237 {
 238         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
 239         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
 240 }
 241 
 242 static inline int is_pden(struct wm97xx *wm)
 243 {
 244         return wm->dig[2] & WM9712_PDEN;
 245 }
 246 
 247 
 248 
 249 
 250 static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 251 {
 252         int timeout = 5 * delay;
 253         bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 254 
 255         if (wants_pen && !wm->pen_probably_down) {
 256                 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 257                 if (!(data & WM97XX_PEN_DOWN))
 258                         return RC_PENUP;
 259                 wm->pen_probably_down = 1;
 260         }
 261 
 262         
 263         if (wm->mach_ops && wm->mach_ops->pre_sample)
 264                 wm->mach_ops->pre_sample(adcsel);
 265         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
 266                                 | WM97XX_POLL | WM97XX_DELAY(delay));
 267 
 268         
 269         poll_delay(delay);
 270 
 271         
 272         while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
 273                && timeout) {
 274                 udelay(AC97_LINK_FRAME);
 275                 timeout--;
 276         }
 277 
 278         if (timeout <= 0) {
 279                 
 280                 if (is_pden(wm))
 281                         wm->pen_probably_down = 0;
 282                 else
 283                         dev_dbg(wm->dev, "adc sample timeout\n");
 284                 return RC_PENUP;
 285         }
 286 
 287         *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 288         if (wm->mach_ops && wm->mach_ops->post_sample)
 289                 wm->mach_ops->post_sample(adcsel);
 290 
 291         
 292         if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
 293                 dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x\n",
 294                         adcsel & WM97XX_ADCSEL_MASK,
 295                         *sample & WM97XX_ADCSEL_MASK);
 296                 return RC_AGAIN;
 297         }
 298 
 299         if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
 300                 
 301                 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 302                 if (!(*sample & WM97XX_PEN_DOWN)) {
 303                         wm->pen_probably_down = 0;
 304                         return RC_PENUP;
 305                 }
 306         }
 307 
 308         return RC_VALID;
 309 }
 310 
 311 
 312 
 313 
 314 static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
 315 {
 316         int timeout = 5 * delay;
 317 
 318         if (!wm->pen_probably_down) {
 319                 u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 320                 if (!(data_rd & WM97XX_PEN_DOWN))
 321                         return RC_PENUP;
 322                 wm->pen_probably_down = 1;
 323         }
 324 
 325         
 326         if (wm->mach_ops && wm->mach_ops->pre_sample)
 327                 wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
 328 
 329         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
 330                 WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
 331 
 332         
 333         poll_delay(delay);
 334         data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 335         
 336         while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
 337                && timeout) {
 338                 udelay(AC97_LINK_FRAME);
 339                 timeout--;
 340         }
 341 
 342         if (timeout <= 0) {
 343                 
 344                 if (is_pden(wm))
 345                         wm->pen_probably_down = 0;
 346                 else
 347                         dev_dbg(wm->dev, "adc sample timeout\n");
 348                 return RC_PENUP;
 349         }
 350 
 351         
 352         data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 353         if (pil)
 354                 data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 355         else
 356                 data->p = DEFAULT_PRESSURE;
 357 
 358         if (wm->mach_ops && wm->mach_ops->post_sample)
 359                 wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
 360 
 361         
 362         if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
 363                 goto err;
 364         if (pil && !(data->p & WM97XX_ADCSEL_PRES))
 365                 goto err;
 366 
 367         if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
 368                 wm->pen_probably_down = 0;
 369                 return RC_PENUP;
 370         }
 371         return RC_VALID;
 372 err:
 373         return 0;
 374 }
 375 
 376 
 377 
 378 
 379 static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
 380 {
 381         int rc;
 382 
 383         if (coord) {
 384                 rc = wm9712_poll_coord(wm, data);
 385                 if (rc != RC_VALID)
 386                         return rc;
 387         } else {
 388                 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
 389                                         &data->x);
 390                 if (rc != RC_VALID)
 391                         return rc;
 392 
 393                 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
 394                                         &data->y);
 395                 if (rc != RC_VALID)
 396                         return rc;
 397 
 398                 if (pil && !five_wire) {
 399                         rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
 400                                                 &data->p);
 401                         if (rc != RC_VALID)
 402                                 return rc;
 403                 } else
 404                         data->p = DEFAULT_PRESSURE;
 405         }
 406         return RC_VALID;
 407 }
 408 
 409 
 410 
 411 
 412 
 413 static int wm9712_acc_enable(struct wm97xx *wm, int enable)
 414 {
 415         u16 dig1, dig2;
 416         int ret = 0;
 417 
 418         dig1 = wm->dig[1];
 419         dig2 = wm->dig[2];
 420 
 421         if (enable) {
 422                 
 423                 if (wm->mach_ops->acc_startup) {
 424                         ret = wm->mach_ops->acc_startup(wm);
 425                         if (ret < 0)
 426                                 return ret;
 427                 }
 428                 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
 429                         WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
 430                 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
 431                         WM97XX_DELAY(delay) |
 432                         WM97XX_SLT(wm->acc_slot) |
 433                         WM97XX_RATE(wm->acc_rate);
 434                 if (pil)
 435                         dig1 |= WM97XX_ADCSEL_PRES;
 436                 dig2 |= WM9712_PDEN;
 437         } else {
 438                 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
 439                 dig2 &= ~WM9712_PDEN;
 440                 if (wm->mach_ops->acc_shutdown)
 441                         wm->mach_ops->acc_shutdown(wm);
 442         }
 443 
 444         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
 445         wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
 446 
 447         return 0;
 448 }
 449 
 450 struct wm97xx_codec_drv wm9712_codec = {
 451         .id = WM9712_ID2,
 452         .name = "wm9712",
 453         .poll_sample = wm9712_poll_sample,
 454         .poll_touch = wm9712_poll_touch,
 455         .acc_enable = wm9712_acc_enable,
 456         .phy_init = wm9712_phy_init,
 457         .dig_enable = wm9712_dig_enable,
 458         .dig_restore = wm9712_dig_restore,
 459         .aux_prepare = wm9712_aux_prepare,
 460 };
 461 EXPORT_SYMBOL_GPL(wm9712_codec);
 462 
 463 
 464 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 465 MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
 466 MODULE_LICENSE("GPL");