diff options
Diffstat (limited to 'drivers/input/touchscreen/ads7846.c')
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index c24946f51256..5196861b86ef 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -109,6 +109,7 @@ struct ads7846 { u16 pressure_max; bool swap_xy; + bool use_internal; struct ads7846_packet *packet; @@ -281,17 +282,24 @@ struct ser_req { u8 command; u8 ref_off; u16 scratch; - __be16 sample; struct spi_message msg; struct spi_transfer xfer[6]; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be16 sample ____cacheline_aligned; }; struct ads7845_ser_req { u8 command[3]; - u8 pwrdown[3]; - u8 sample[3]; struct spi_message msg; struct spi_transfer xfer[2]; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 sample[3] ____cacheline_aligned; }; static int ads7846_read12_ser(struct device *dev, unsigned command) @@ -300,7 +308,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) struct ads7846 *ts = dev_get_drvdata(dev); struct ser_req *req; int status; - int use_internal; req = kzalloc(sizeof *req, GFP_KERNEL); if (!req) @@ -308,11 +315,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) spi_message_init(&req->msg); - /* FIXME boards with ads7846 might use external vref instead ... */ - use_internal = (ts->model == 7846); - /* maybe turn on internal vREF, and let it settle */ - if (use_internal) { + if (ts->use_internal) { req->ref_on = REF_ON; req->xfer[0].tx_buf = &req->ref_on; req->xfer[0].len = 1; @@ -324,8 +328,14 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) /* for 1uF, settle for 800 usec; no cap, 100 usec. */ req->xfer[1].delay_usecs = ts->vref_delay_usecs; spi_message_add_tail(&req->xfer[1], &req->msg); + + /* Enable reference voltage */ + command |= ADS_PD10_REF_ON; } + /* Enable ADC in every case */ + command |= ADS_PD10_ADC_ON; + /* take sample */ req->command = (u8) command; req->xfer[2].tx_buf = &req->command; @@ -409,7 +419,7 @@ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct ads7846 *ts = dev_get_drvdata(dev); \ ssize_t v = ads7846_read12_ser(dev, \ - READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \ + READ_12BIT_SER(var)); \ if (v < 0) \ return v; \ return sprintf(buf, "%u\n", adjust(ts, v)); \ @@ -502,6 +512,7 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) if (!ts->vref_mv) { dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n"); ts->vref_mv = 2500; + ts->use_internal = true; } break; case 7845: @@ -962,6 +973,13 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 pdata->gpio_pendown); return err; } + err = gpio_direction_input(pdata->gpio_pendown); + if (err) { + dev_err(&spi->dev, "failed to setup pendown GPIO%d\n", + pdata->gpio_pendown); + gpio_free(pdata->gpio_pendown); + return err; + } ts->gpio_pendown = pdata->gpio_pendown; @@ -1333,8 +1351,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (ts->model == 7845) ads7845_read12_ser(&spi->dev, PWRDOWN); else - (void) ads7846_read12_ser(&spi->dev, - READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); + (void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux)); err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); if (err) |