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 WM9705_VERSION "1.00"
0022 #define DEFAULT_PRESSURE 0xb0c0
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static int pil;
0039 module_param(pil, int, 0);
0040 MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
0041
0042
0043
0044
0045
0046
0047 static int pressure = DEFAULT_PRESSURE & 0xfff;
0048 module_param(pressure, int, 0);
0049 MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 static int delay = 4;
0064 module_param(delay, int, 0);
0065 MODULE_PARM_DESC(delay, "Set adc sample delay.");
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 static int pdd = 8;
0078 module_param(pdd, int, 0);
0079 MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static int mask;
0095 module_param(mask, int, 0);
0096 MODULE_PARM_DESC(mask, "Set adc mask function.");
0097
0098
0099
0100
0101 static const int delay_table[] = {
0102 21,
0103 42,
0104 84,
0105 167,
0106 333,
0107 667,
0108 1000,
0109 1333,
0110 2000,
0111 2667,
0112 3333,
0113 4000,
0114 4667,
0115 5333,
0116 6000,
0117 0
0118 };
0119
0120
0121
0122
0123
0124
0125 static inline void poll_delay(int d)
0126 {
0127 udelay(3 * AC97_LINK_FRAME + delay_table[d]);
0128 }
0129
0130
0131
0132
0133 static void wm9705_phy_init(struct wm97xx *wm)
0134 {
0135 u16 dig1 = 0, dig2 = WM97XX_RPR;
0136
0137
0138
0139
0140
0141 wm97xx_reg_write(wm, AC97_AUX, 0x8000);
0142 wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
0143
0144
0145 if (pil == 2) {
0146 dig2 |= WM9705_PIL;
0147 dev_dbg(wm->dev,
0148 "setting pressure measurement current to 400uA.");
0149 } else if (pil)
0150 dev_dbg(wm->dev,
0151 "setting pressure measurement current to 200uA.");
0152 if (!pil)
0153 pressure = 0;
0154
0155
0156 if (delay != 4) {
0157 if (delay < 0 || delay > 15) {
0158 dev_dbg(wm->dev, "supplied delay out of range.");
0159 delay = 4;
0160 }
0161 }
0162 dig1 &= 0xff0f;
0163 dig1 |= WM97XX_DELAY(delay);
0164 dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
0165 delay_table[delay]);
0166
0167
0168 dig2 |= (pdd & 0x000f);
0169 dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
0170
0171
0172 dig2 |= ((mask & 0x3) << 4);
0173
0174 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
0175 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
0176 }
0177
0178 static void wm9705_dig_enable(struct wm97xx *wm, int enable)
0179 {
0180 if (enable) {
0181 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
0182 wm->dig[2] | WM97XX_PRP_DET_DIG);
0183 wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0184 } else
0185 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
0186 wm->dig[2] & ~WM97XX_PRP_DET_DIG);
0187 }
0188
0189 static void wm9705_aux_prepare(struct wm97xx *wm)
0190 {
0191 memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
0192 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
0193 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
0194 }
0195
0196 static void wm9705_dig_restore(struct wm97xx *wm)
0197 {
0198 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
0199 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
0200 }
0201
0202 static inline int is_pden(struct wm97xx *wm)
0203 {
0204 return wm->dig[2] & WM9705_PDEN;
0205 }
0206
0207
0208
0209
0210 static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
0211 {
0212 int timeout = 5 * delay;
0213 bool wants_pen = adcsel & WM97XX_PEN_DOWN;
0214
0215 if (wants_pen && !wm->pen_probably_down) {
0216 u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0217 if (!(data & WM97XX_PEN_DOWN))
0218 return RC_PENUP;
0219 wm->pen_probably_down = 1;
0220 }
0221
0222
0223 if (wm->mach_ops && wm->mach_ops->pre_sample)
0224 wm->mach_ops->pre_sample(adcsel);
0225 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
0226 | WM97XX_POLL | WM97XX_DELAY(delay));
0227
0228
0229 poll_delay(delay);
0230
0231
0232 while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
0233 && timeout) {
0234 udelay(AC97_LINK_FRAME);
0235 timeout--;
0236 }
0237
0238 if (timeout == 0) {
0239
0240 if (is_pden(wm))
0241 wm->pen_probably_down = 0;
0242 else
0243 dev_dbg(wm->dev, "adc sample timeout");
0244 return RC_PENUP;
0245 }
0246
0247 *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0248 if (wm->mach_ops && wm->mach_ops->post_sample)
0249 wm->mach_ops->post_sample(adcsel);
0250
0251
0252 if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
0253 dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
0254 adcsel & WM97XX_ADCSEL_MASK,
0255 *sample & WM97XX_ADCSEL_MASK);
0256 return RC_PENUP;
0257 }
0258
0259 if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
0260 wm->pen_probably_down = 0;
0261 return RC_PENUP;
0262 }
0263
0264 return RC_VALID;
0265 }
0266
0267
0268
0269
0270 static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
0271 {
0272 int rc;
0273
0274 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
0275 if (rc != RC_VALID)
0276 return rc;
0277 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
0278 if (rc != RC_VALID)
0279 return rc;
0280 if (pil) {
0281 rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
0282 if (rc != RC_VALID)
0283 return rc;
0284 } else
0285 data->p = DEFAULT_PRESSURE;
0286
0287 return RC_VALID;
0288 }
0289
0290
0291
0292
0293
0294 static int wm9705_acc_enable(struct wm97xx *wm, int enable)
0295 {
0296 u16 dig1, dig2;
0297 int ret = 0;
0298
0299 dig1 = wm->dig[1];
0300 dig2 = wm->dig[2];
0301
0302 if (enable) {
0303
0304 if (wm->mach_ops->acc_startup &&
0305 (ret = wm->mach_ops->acc_startup(wm)) < 0)
0306 return ret;
0307 dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
0308 WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
0309 dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
0310 WM97XX_DELAY(delay) |
0311 WM97XX_SLT(wm->acc_slot) |
0312 WM97XX_RATE(wm->acc_rate);
0313 if (pil)
0314 dig1 |= WM97XX_ADCSEL_PRES;
0315 dig2 |= WM9705_PDEN;
0316 } else {
0317 dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
0318 dig2 &= ~WM9705_PDEN;
0319 if (wm->mach_ops->acc_shutdown)
0320 wm->mach_ops->acc_shutdown(wm);
0321 }
0322
0323 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
0324 wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
0325
0326 return ret;
0327 }
0328
0329 struct wm97xx_codec_drv wm9705_codec = {
0330 .id = WM9705_ID2,
0331 .name = "wm9705",
0332 .poll_sample = wm9705_poll_sample,
0333 .poll_touch = wm9705_poll_touch,
0334 .acc_enable = wm9705_acc_enable,
0335 .phy_init = wm9705_phy_init,
0336 .dig_enable = wm9705_dig_enable,
0337 .dig_restore = wm9705_dig_restore,
0338 .aux_prepare = wm9705_aux_prepare,
0339 };
0340 EXPORT_SYMBOL_GPL(wm9705_codec);
0341
0342
0343 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
0344 MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
0345 MODULE_LICENSE("GPL");