[PATCH] ads7846 conversion accuracy
This improves accuracy of the touchscreen and hwmon sensor readings, addressing an issue noted by Imre Deak: there's an extra bit written before the sample (12 bits) gets written out. It also catches up to various comments, and makes the /proc/interrupts entry sensible again. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Imre Deak <imre.deak@nokia.com> Cc: Jean Delvare <khali@linux-fr.org> Cc: Dmitry Torokhov <dtor_core@ameritech.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
f09de595b5
Коммит
9084533e79
|
@ -36,13 +36,10 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This code has been tested on an ads7846 / N770 device.
|
* This code has been heavily tested on a Nokia 770, and lightly
|
||||||
|
* tested on other ads7846 devices (OSK/Mistral, Lubbock).
|
||||||
* Support for ads7843 and ads7845 has only been stubbed in.
|
* Support for ads7843 and ads7845 has only been stubbed in.
|
||||||
*
|
*
|
||||||
* Not yet done: How accurate are the temperature and voltage
|
|
||||||
* readings? (System-specific calibration should support
|
|
||||||
* accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
|
|
||||||
*
|
|
||||||
* IRQ handling needs a workaround because of a shortcoming in handling
|
* IRQ handling needs a workaround because of a shortcoming in handling
|
||||||
* edge triggered IRQs on some platforms like the OMAP1/2. These
|
* edge triggered IRQs on some platforms like the OMAP1/2. These
|
||||||
* platforms don't handle the ARM lazy IRQ disabling properly, thus we
|
* platforms don't handle the ARM lazy IRQ disabling properly, thus we
|
||||||
|
@ -248,10 +245,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
|
||||||
|
|
||||||
if (req->msg.status)
|
if (req->msg.status)
|
||||||
status = req->msg.status;
|
status = req->msg.status;
|
||||||
sample = be16_to_cpu(req->sample);
|
|
||||||
sample = sample >> 4;
|
|
||||||
kfree(req);
|
|
||||||
|
|
||||||
|
/* on-wire is a must-ignore bit, a BE12 value, then padding */
|
||||||
|
sample = be16_to_cpu(req->sample);
|
||||||
|
sample = sample >> 3;
|
||||||
|
sample &= 0x0fff;
|
||||||
|
|
||||||
|
kfree(req);
|
||||||
return status ? status : sample;
|
return status ? status : sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,13 +336,13 @@ static void ads7846_rx(void *ads)
|
||||||
u16 x, y, z1, z2;
|
u16 x, y, z1, z2;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/* adjust: 12 bit samples (left aligned), built from
|
/* adjust: on-wire is a must-ignore bit, a BE12 value, then padding;
|
||||||
* two 8 bit values writen msb-first.
|
* built from two 8 bit values written msb-first.
|
||||||
*/
|
*/
|
||||||
x = be16_to_cpu(ts->tc.x) >> 4;
|
x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
|
||||||
y = be16_to_cpu(ts->tc.y) >> 4;
|
y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
|
||||||
z1 = be16_to_cpu(ts->tc.z1) >> 4;
|
z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
|
||||||
z2 = be16_to_cpu(ts->tc.z2) >> 4;
|
z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;
|
||||||
|
|
||||||
/* range filtering */
|
/* range filtering */
|
||||||
if (x == MAX_12BIT)
|
if (x == MAX_12BIT)
|
||||||
|
@ -420,7 +420,7 @@ static void ads7846_debounce(void *ads)
|
||||||
|
|
||||||
m = &ts->msg[ts->msg_idx];
|
m = &ts->msg[ts->msg_idx];
|
||||||
t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
|
t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
|
||||||
val = (*(u16 *)t->rx_buf) >> 3;
|
val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff;
|
||||||
if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
|
if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
|
||||||
/* Repeat it, if this was the first read or the read
|
/* Repeat it, if this was the first read or the read
|
||||||
* wasn't consistent enough. */
|
* wasn't consistent enough. */
|
||||||
|
@ -469,7 +469,7 @@ static void ads7846_timer(unsigned long handle)
|
||||||
spin_lock_irq(&ts->lock);
|
spin_lock_irq(&ts->lock);
|
||||||
|
|
||||||
if (unlikely(ts->msg_idx && !ts->pendown)) {
|
if (unlikely(ts->msg_idx && !ts->pendown)) {
|
||||||
/* measurment cycle ended */
|
/* measurement cycle ended */
|
||||||
if (!device_suspended(&ts->spi->dev)) {
|
if (!device_suspended(&ts->spi->dev)) {
|
||||||
ts->irq_disabled = 0;
|
ts->irq_disabled = 0;
|
||||||
enable_irq(ts->spi->irq);
|
enable_irq(ts->spi->irq);
|
||||||
|
@ -495,11 +495,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
|
||||||
spin_lock_irqsave(&ts->lock, flags);
|
spin_lock_irqsave(&ts->lock, flags);
|
||||||
if (likely(ts->get_pendown_state())) {
|
if (likely(ts->get_pendown_state())) {
|
||||||
if (!ts->irq_disabled) {
|
if (!ts->irq_disabled) {
|
||||||
/* REVISIT irq logic for many ARM chips has cloned a
|
/* The ARM do_simple_IRQ() dispatcher doesn't act
|
||||||
* bug wherein disabling an irq in its handler won't
|
* like the other dispatchers: it will report IRQs
|
||||||
* work;(it's disabled lazily, and too late to work.
|
* even after they've been disabled. We work around
|
||||||
* until all their irq logic is fixed, we must shadow
|
* that here. (The "generic irq" framework may help...)
|
||||||
* that state here.
|
|
||||||
*/
|
*/
|
||||||
ts->irq_disabled = 1;
|
ts->irq_disabled = 1;
|
||||||
disable_irq(ts->spi->irq);
|
disable_irq(ts->spi->irq);
|
||||||
|
@ -609,16 +608,20 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* REVISIT when the irq can be triggered active-low, or if for some
|
||||||
|
* reason the touchscreen isn't hooked up, we don't need to access
|
||||||
|
* the pendown state.
|
||||||
|
*/
|
||||||
if (pdata->get_pendown_state == NULL) {
|
if (pdata->get_pendown_state == NULL) {
|
||||||
dev_dbg(&spi->dev, "no get_pendown_state function?\n");
|
dev_dbg(&spi->dev, "no get_pendown_state function?\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We'd set the wordsize to 12 bits ... except that some controllers
|
/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
|
||||||
* will then treat the 8 bit command words as 12 bits (and drop the
|
* that even if the hardware can do that, the SPI controller driver
|
||||||
* four MSBs of the 12 bit result). Result: inputs must be shifted
|
* may not. So we stick to very-portable 8 bit words, both RX and TX.
|
||||||
* to discard the four garbage LSBs.
|
|
||||||
*/
|
*/
|
||||||
|
spi->bits_per_word = 8;
|
||||||
|
|
||||||
ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
|
ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
|
||||||
input_dev = input_allocate_device();
|
input_dev = input_allocate_device();
|
||||||
|
@ -772,7 +775,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
||||||
|
|
||||||
if (request_irq(spi->irq, ads7846_irq,
|
if (request_irq(spi->irq, ads7846_irq,
|
||||||
SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
|
SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
|
||||||
spi->dev.bus_id, ts)) {
|
spi->dev.driver->name, ts)) {
|
||||||
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
|
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto err_free_mem;
|
goto err_free_mem;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче