Skip to content

Commit

Permalink
[PATCH] ads7846 conversion accuracy
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Brownell authored and Linus Torvalds committed May 26, 2006
1 parent f09de59 commit 9084533
Showing 1 changed file with 28 additions and 25 deletions.
53 changes: 28 additions & 25 deletions drivers/input/touchscreen/ads7846.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
* 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
* edge triggered IRQs on some platforms like the OMAP1/2. These
* platforms don't handle the ARM lazy IRQ disabling properly, thus we
Expand Down Expand Up @@ -248,10 +245,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)

if (req->msg.status)
status = req->msg.status;

/* on-wire is a must-ignore bit, a BE12 value, then padding */
sample = be16_to_cpu(req->sample);
sample = sample >> 4;
kfree(req);
sample = sample >> 3;
sample &= 0x0fff;

kfree(req);
return status ? status : sample;
}

Expand Down Expand Up @@ -336,13 +336,13 @@ static void ads7846_rx(void *ads)
u16 x, y, z1, z2;
unsigned long flags;

/* adjust: 12 bit samples (left aligned), built from
* two 8 bit values writen msb-first.
/* adjust: on-wire is a must-ignore bit, a BE12 value, then padding;
* built from two 8 bit values written msb-first.
*/
x = be16_to_cpu(ts->tc.x) >> 4;
y = be16_to_cpu(ts->tc.y) >> 4;
z1 = be16_to_cpu(ts->tc.z1) >> 4;
z2 = be16_to_cpu(ts->tc.z2) >> 4;
x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;

/* range filtering */
if (x == MAX_12BIT)
Expand Down Expand Up @@ -420,7 +420,7 @@ static void ads7846_debounce(void *ads)

m = &ts->msg[ts->msg_idx];
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)) {
/* Repeat it, if this was the first read or the read
* wasn't consistent enough. */
Expand Down Expand Up @@ -469,7 +469,7 @@ static void ads7846_timer(unsigned long handle)
spin_lock_irq(&ts->lock);

if (unlikely(ts->msg_idx && !ts->pendown)) {
/* measurment cycle ended */
/* measurement cycle ended */
if (!device_suspended(&ts->spi->dev)) {
ts->irq_disabled = 0;
enable_irq(ts->spi->irq);
Expand All @@ -495,11 +495,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
spin_lock_irqsave(&ts->lock, flags);
if (likely(ts->get_pendown_state())) {
if (!ts->irq_disabled) {
/* REVISIT irq logic for many ARM chips has cloned a
* bug wherein disabling an irq in its handler won't
* work;(it's disabled lazily, and too late to work.
* until all their irq logic is fixed, we must shadow
* that state here.
/* The ARM do_simple_IRQ() dispatcher doesn't act
* like the other dispatchers: it will report IRQs
* even after they've been disabled. We work around
* that here. (The "generic irq" framework may help...)
*/
ts->irq_disabled = 1;
disable_irq(ts->spi->irq);
Expand Down Expand Up @@ -609,16 +608,20 @@ static int __devinit ads7846_probe(struct spi_device *spi)
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) {
dev_dbg(&spi->dev, "no get_pendown_state function?\n");
return -EINVAL;
}

/* We'd set the wordsize to 12 bits ... except that some controllers
* will then treat the 8 bit command words as 12 bits (and drop the
* four MSBs of the 12 bit result). Result: inputs must be shifted
* to discard the four garbage LSBs.
/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
* that even if the hardware can do that, the SPI controller driver
* may not. So we stick to very-portable 8 bit words, both RX and TX.
*/
spi->bits_per_word = 8;

ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
input_dev = input_allocate_device();
Expand Down Expand Up @@ -772,7 +775,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)

if (request_irq(spi->irq, ads7846_irq,
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);
err = -EBUSY;
goto err_free_mem;
Expand Down

0 comments on commit 9084533

Please sign in to comment.