Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
0004  *
0005  * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
0006  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
0007  * Parts Copyright : Ian Molton <spyro@f2s.com>
0008  *                   Andrew Zabolotny <zap@homelink.ru>
0009  *                   Russell King <rmk@arm.linux.org.uk>
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  * Module parameters
0026  */
0027 
0028 /*
0029  * Set internal pull up for pen detect.
0030  *
0031  * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
0032  * i.e. pull up resistance = 64k Ohms / rpu.
0033  *
0034  * Adjust this value if you are having problems with pen detect not
0035  * detecting any down event.
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  * Set current used for pressure measurement.
0043  *
0044  * Set pil = 2 to use 400uA
0045  *     pil = 1 to use 200uA and
0046  *     pil = 0 to disable pressure measurement.
0047  *
0048  * This is used to increase the range of values returned by the adc
0049  * when measureing touchpanel pressure.
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  * Set threshold for pressure measurement.
0057  *
0058  * Pen down pressure below threshold is ignored.
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  * Set adc sample delay.
0066  *
0067  * For accurate touchpanel measurements, some settling time may be
0068  * required between the switch matrix applying a voltage across the
0069  * touchpanel plate and the ADC sampling the signal.
0070  *
0071  * This delay can be set by setting delay = n, where n is the array
0072  * position of the delay in the array delay_table below.
0073  * Long delays > 1ms are supported for completeness, but are not
0074  * recommended.
0075  */
0076 static int delay = 3;
0077 module_param(delay, int, 0);
0078 MODULE_PARM_DESC(delay, "Set adc sample delay.");
0079 
0080 /*
0081  * Set five_wire = 1 to use a 5 wire touchscreen.
0082  *
0083  * NOTE: Five wire mode does not allow for readback of pressure.
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  * Set adc mask function.
0091  *
0092  * Sources of glitch noise, such as signals driving an LCD display, may feed
0093  * through to the touch screen plates and affect measurement accuracy. In
0094  * order to minimise this, a signal may be applied to the MASK pin to delay or
0095  * synchronise the sampling.
0096  *
0097  * 0 = No delay or sync
0098  * 1 = High on pin stops conversions
0099  * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
0100  * 3 = Edge triggered, edge on pin starts conversion after delay param
0101  */
0102 static int mask;
0103 module_param(mask, int, 0);
0104 MODULE_PARM_DESC(mask, "Set adc mask function.");
0105 
0106 /*
0107  * Coordinate Polling Enable.
0108  *
0109  * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
0110  * for every poll.
0111  */
0112 static int coord;
0113 module_param(coord, int, 0);
0114 MODULE_PARM_DESC(coord, "Polling coordinate mode");
0115 
0116 /*
0117  * ADC sample delay times in uS
0118  */
0119 static const int delay_table[] = {
0120     21,    /* 1 AC97 Link frames */
0121     42,    /* 2 */
0122     84,    /* 4 */
0123     167,   /* 8 */
0124     333,   /* 16 */
0125     667,   /* 32 */
0126     1000,  /* 48 */
0127     1333,  /* 64 */
0128     2000,  /* 96 */
0129     2667,  /* 128 */
0130     3333,  /* 160 */
0131     4000,  /* 192 */
0132     4667,  /* 224 */
0133     5333,  /* 256 */
0134     6000,  /* 288 */
0135     0      /* No delay, switch matrix always on */
0136 };
0137 
0138 /*
0139  * Delay after issuing a POLL command.
0140  *
0141  * The delay is 3 AC97 link frames + the touchpanel settling delay
0142  */
0143 static inline void poll_delay(int d)
0144 {
0145     udelay(3 * AC97_LINK_FRAME + delay_table[d]);
0146 }
0147 
0148 /*
0149  * set up the physical settings of the WM9712
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     /* WM9712 rpu */
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     /* WM9712 five wire */
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     /* touchpanel pressure current*/
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     /* polling mode sample settling delay */
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     /* mask */
0198     dig2 |= ((mask & 0x3) << 6);
0199     if (mask) {
0200         u16 reg;
0201         /* Set GPIO4 as Mask Pin*/
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     /* wait - coord mode */
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); /* dummy read */
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  * Read a sample from the WM9712 adc in polling mode.
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     /* set up digitiser */
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     /* wait 3 AC97 time slots + delay for conversion */
0269     poll_delay(delay);
0270 
0271     /* wait for POLL to go low */
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         /* If PDEN is set, we can get a timeout when pen goes up */
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     /* check we have correct sample */
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         /* Sometimes it reads a wrong value the first time. */
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  * Read a coord from the WM9712 adc in polling mode.
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     /* set up digitiser */
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     /* wait 3 AC97 time slots + delay for conversion and read x */
0333     poll_delay(delay);
0334     data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
0335     /* wait for POLL to go low */
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         /* If PDEN is set, we can get a timeout when pen goes up */
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     /* read back y data */
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     /* check we have correct sample */
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  * Sample the WM9712 touchscreen in polling mode
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  * Enable WM9712 continuous mode, i.e. touch data is streamed across
0411  * an AC97 slot
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         /* continuous mode */
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 /* Module information */
0464 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
0465 MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
0466 MODULE_LICENSE("GPL");