0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/moduleparam.h>
0014 #include <linux/kernel.h>
0015 #include <linux/input.h>
0016 #include <linux/delay.h>
0017 #include <linux/bitops.h>
0018 #include <linux/wm97xx.h>
0019
0020 #define TS_NAME "wm97xx"
0021 #define WM9712_VERSION "1.00"
0022 #define DEFAULT_PRESSURE 0xb0c0
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 static int rpu = 8;
0038 module_param(rpu, int, 0);
0039 MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 static int pil;
0052 module_param(pil, int, 0);
0053 MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
0054
0055
0056
0057
0058
0059
0060 static int pressure = DEFAULT_PRESSURE & 0xfff;
0061 module_param(pressure, int, 0);
0062 MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 static int delay = 3;
0077 module_param(delay, int, 0);
0078 MODULE_PARM_DESC(delay, "Set adc sample delay.");
0079
0080
0081
0082
0083
0084
0085 static int five_wire;
0086 module_param(five_wire, int, 0);
0087 MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 static int mask;
0103 module_param(mask, int, 0);
0104 MODULE_PARM_DESC(mask, "Set adc mask function.");
0105
0106
0107
0108
0109
0110
0111
0112 static int coord;
0113 module_param(coord, int, 0);
0114 MODULE_PARM_DESC(coord, "Polling coordinate mode");
0115
0116
0117
0118
0119 static const int delay_table[] = {
0120 21,
0121 42,
0122 84,
0123 167,
0124 333,
0125 667,
0126 1000,
0127 1333,
0128 2000,
0129 2667,
0130 3333,
0131 4000,
0132 4667,
0133 5333,
0134 6000,
0135 0
0136 };
0137
0138
0139
0140
0141
0142
0143 static inline void poll_delay(int d)
0144 {
0145 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
0146 }
0147
0148
0149
0150
0151 static void wm9712_phy_init(struct wm97xx *wm)
0152 {
0153 u16 dig1 = 0;
0154 u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
0155
0156
0157 if (rpu) {
0158 dig2 &= 0xffc0;
0159 dig2 |= WM9712_RPU(rpu);
0160 dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms\n",
0161 64000 / rpu);
0162 }
0163
0164
0165 if (five_wire) {
0166 dig2 |= WM9712_45W;
0167 dev_dbg(wm->dev, "setting 5-wire touchscreen mode.\n");
0168
0169 if (pil) {
0170 dev_warn(wm->dev, "pressure measurement is not "
0171 "supported in 5-wire mode\n");
0172 pil = 0;
0173 }
0174 }
0175
0176
0177 if (pil == 2) {
0178 dig2 |= WM9712_PIL;
0179 dev_dbg(wm->dev,
0180 "setting pressure measurement current to 400uA.\n");
0181 } else if (pil)
0182 dev_dbg(wm->dev,
0183 "setting pressure measurement current to 200uA.\n");
0184 if (!pil)
0185 pressure = 0;
0186
0187
0188 if (delay < 0 || delay > 15) {
0189 dev_dbg(wm->dev, "supplied delay out of range.\n");
0190 delay = 4;
0191 }
0192 dig1 &= 0xff0f;
0193 dig1 |= WM97XX_DELAY(delay);
0194 dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.\n",
0195 delay_table[delay]);
0196
0197
0198 dig2 |= ((mask & 0x3) << 6);
0199 if (mask) {
0200 u16 reg;
0201
0202 reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
0203 wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
0204 reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
0205 wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
0206 }
0207
0208
0209 if (coord)
0210 dig2 |= WM9712_WAIT;
0211
0212 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
0213 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
0214 }
0215
0216 static void wm9712_dig_enable(struct wm97xx *wm, int enable)
0217 {
0218 u16 dig2 = wm->dig[2];
0219
0220 if (enable) {
0221 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
0222 dig2 | WM97XX_PRP_DET_DIG);
0223 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0224 } else
0225 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
0226 dig2 & ~WM97XX_PRP_DET_DIG);
0227 }
0228
0229 static void wm9712_aux_prepare(struct wm97xx *wm)
0230 {
0231 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
0232 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
0233 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
0234 }
0235
0236 static void wm9712_dig_restore(struct wm97xx *wm)
0237 {
0238 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
0239 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
0240 }
0241
0242 static inline int is_pden(struct wm97xx *wm)
0243 {
0244 return wm->dig[2] & WM9712_PDEN;
0245 }
0246
0247
0248
0249
0250 static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
0251 {
0252 int timeout = 5 * delay;
0253 bool wants_pen = adcsel & WM97XX_PEN_DOWN;
0254
0255 if (wants_pen && !wm->pen_probably_down) {
0256 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0257 if (!(data & WM97XX_PEN_DOWN))
0258 return RC_PENUP;
0259 wm->pen_probably_down = 1;
0260 }
0261
0262
0263 if (wm->mach_ops && wm->mach_ops->pre_sample)
0264 wm->mach_ops->pre_sample(adcsel);
0265 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
0266 | WM97XX_POLL | WM97XX_DELAY(delay));
0267
0268
0269 poll_delay(delay);
0270
0271
0272 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
0273 && timeout) {
0274 udelay(AC97_LINK_FRAME);
0275 timeout--;
0276 }
0277
0278 if (timeout <= 0) {
0279
0280 if (is_pden(wm))
0281 wm->pen_probably_down = 0;
0282 else
0283 dev_dbg(wm->dev, "adc sample timeout\n");
0284 return RC_PENUP;
0285 }
0286
0287 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0288 if (wm->mach_ops && wm->mach_ops->post_sample)
0289 wm->mach_ops->post_sample(adcsel);
0290
0291
0292 if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
0293 dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x\n",
0294 adcsel & WM97XX_ADCSEL_MASK,
0295 *sample & WM97XX_ADCSEL_MASK);
0296 return RC_AGAIN;
0297 }
0298
0299 if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
0300
0301 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0302 if (!(*sample & WM97XX_PEN_DOWN)) {
0303 wm->pen_probably_down = 0;
0304 return RC_PENUP;
0305 }
0306 }
0307
0308 return RC_VALID;
0309 }
0310
0311
0312
0313
0314 static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
0315 {
0316 int timeout = 5 * delay;
0317
0318 if (!wm->pen_probably_down) {
0319 u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0320 if (!(data_rd & WM97XX_PEN_DOWN))
0321 return RC_PENUP;
0322 wm->pen_probably_down = 1;
0323 }
0324
0325
0326 if (wm->mach_ops && wm->mach_ops->pre_sample)
0327 wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
0328
0329 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
0330 WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
0331
0332
0333 poll_delay(delay);
0334 data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0335
0336 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
0337 && timeout) {
0338 udelay(AC97_LINK_FRAME);
0339 timeout--;
0340 }
0341
0342 if (timeout <= 0) {
0343
0344 if (is_pden(wm))
0345 wm->pen_probably_down = 0;
0346 else
0347 dev_dbg(wm->dev, "adc sample timeout\n");
0348 return RC_PENUP;
0349 }
0350
0351
0352 data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0353 if (pil)
0354 data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0355 else
0356 data->p = DEFAULT_PRESSURE;
0357
0358 if (wm->mach_ops && wm->mach_ops->post_sample)
0359 wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
0360
0361
0362 if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
0363 goto err;
0364 if (pil && !(data->p & WM97XX_ADCSEL_PRES))
0365 goto err;
0366
0367 if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
0368 wm->pen_probably_down = 0;
0369 return RC_PENUP;
0370 }
0371 return RC_VALID;
0372 err:
0373 return 0;
0374 }
0375
0376
0377
0378
0379 static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
0380 {
0381 int rc;
0382
0383 if (coord) {
0384 rc = wm9712_poll_coord(wm, data);
0385 if (rc != RC_VALID)
0386 return rc;
0387 } else {
0388 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
0389 &data->x);
0390 if (rc != RC_VALID)
0391 return rc;
0392
0393 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
0394 &data->y);
0395 if (rc != RC_VALID)
0396 return rc;
0397
0398 if (pil && !five_wire) {
0399 rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
0400 &data->p);
0401 if (rc != RC_VALID)
0402 return rc;
0403 } else
0404 data->p = DEFAULT_PRESSURE;
0405 }
0406 return RC_VALID;
0407 }
0408
0409
0410
0411
0412
0413 static int wm9712_acc_enable(struct wm97xx *wm, int enable)
0414 {
0415 u16 dig1, dig2;
0416 int ret = 0;
0417
0418 dig1 = wm->dig[1];
0419 dig2 = wm->dig[2];
0420
0421 if (enable) {
0422
0423 if (wm->mach_ops->acc_startup) {
0424 ret = wm->mach_ops->acc_startup(wm);
0425 if (ret < 0)
0426 return ret;
0427 }
0428 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
0429 WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
0430 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
0431 WM97XX_DELAY(delay) |
0432 WM97XX_SLT(wm->acc_slot) |
0433 WM97XX_RATE(wm->acc_rate);
0434 if (pil)
0435 dig1 |= WM97XX_ADCSEL_PRES;
0436 dig2 |= WM9712_PDEN;
0437 } else {
0438 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
0439 dig2 &= ~WM9712_PDEN;
0440 if (wm->mach_ops->acc_shutdown)
0441 wm->mach_ops->acc_shutdown(wm);
0442 }
0443
0444 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
0445 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
0446
0447 return 0;
0448 }
0449
0450 struct wm97xx_codec_drv wm9712_codec = {
0451 .id = WM9712_ID2,
0452 .name = "wm9712",
0453 .poll_sample = wm9712_poll_sample,
0454 .poll_touch = wm9712_poll_touch,
0455 .acc_enable = wm9712_acc_enable,
0456 .phy_init = wm9712_phy_init,
0457 .dig_enable = wm9712_dig_enable,
0458 .dig_restore = wm9712_dig_restore,
0459 .aux_prepare = wm9712_aux_prepare,
0460 };
0461 EXPORT_SYMBOL_GPL(wm9712_codec);
0462
0463
0464 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
0465 MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
0466 MODULE_LICENSE("GPL");