Skip to content

Commit

Permalink
Input: ads7846 - detect pen up from GPIO state
Browse files Browse the repository at this point in the history
We can't depend on the pressure value to determine when the pen was
lifted, so use the GPIO line state instead. This also helps with
chips (like ads7843) that don't have pressure sensors.

Signed-off-by: Imre Deak <imre.deak@solidboot.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
  • Loading branch information
Imre Deak authored and Dmitry Torokhov committed Jan 18, 2007
1 parent 7937e86 commit 15e3589
Showing 1 changed file with 41 additions and 39 deletions.
80 changes: 41 additions & 39 deletions drivers/input/touchscreen/ads7846.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,8 @@ static struct attribute_group ads7845_attr_group = {
static void ads7846_rx(void *ads)
{
struct ads7846 *ts = ads;
struct input_dev *input_dev = ts->input;
unsigned Rt;
unsigned sync = 0;
u16 x, y, z1, z2;
unsigned long flags;

/* ads7846_rx_val() did in-place conversion (including byteswap) from
* on-the-wire format as part of debouncing to get stable readings.
Expand All @@ -396,7 +393,7 @@ static void ads7846_rx(void *ads)
if (x == MAX_12BIT)
x = 0;

if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
if (likely(x && z1)) {
/* compute touch pressure resistance using equation #2 */
Rt = z2;
Rt -= z1;
Expand All @@ -412,52 +409,44 @@ static void ads7846_rx(void *ads)
* once more the measurement
*/
if (ts->tc.ignore || Rt > ts->pressure_max) {
#ifdef VERBOSE
pr_debug("%s: ignored %d pressure %d\n",
ts->spi->dev.bus_id, ts->tc.ignore, Rt);
#endif
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
HRTIMER_REL);
return;
}

/* NOTE: "pendown" is inferred from pressure; we don't rely on
* being able to check nPENIRQ status, or "friendly" trigger modes
* (both-edges is much better than just-falling or low-level).
*
* REVISIT: some boards may require reading nPENIRQ; it's
* needed on 7843. and 7845 reads pressure differently...
/* NOTE: We can't rely on the pressure to determine the pen down
* state, even this controller has a pressure sensor. The pressure
* value can fluctuate for quite a while after lifting the pen and
* in some cases may not even settle at the expected value.
*
* REVISIT: the touchscreen might not be connected; this code
* won't notice that, even if nPENIRQ never fires ...
* The only safe way to check for the pen up condition is in the
* timer by reading the pen signal state (it's a GPIO _and_ IRQ).
*/
if (!ts->pendown && Rt != 0) {
input_report_key(input_dev, BTN_TOUCH, 1);
sync = 1;
} else if (ts->pendown && Rt == 0) {
input_report_key(input_dev, BTN_TOUCH, 0);
sync = 1;
}

if (Rt) {
input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y, y);
sync = 1;
}
struct input_dev *input = ts->input;

if (sync) {
input_report_abs(input_dev, ABS_PRESSURE, Rt);
input_sync(input_dev);
}

#ifdef VERBOSE
if (Rt || ts->pendown)
pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
x, y, Rt, Rt ? "" : " UP");
if (!ts->pendown) {
input_report_key(input, BTN_TOUCH, 1);
ts->pendown = 1;
#ifdef VERBOSE
dev_dbg(&ts->spi->dev, "DOWN\n");
#endif
}
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, Rt);

spin_lock_irqsave(&ts->lock, flags);
input_sync(input);
#ifdef VERBOSE
dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
#endif
}

ts->pendown = (Rt != 0);
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL);

spin_unlock_irqrestore(&ts->lock, flags);
}

static int ads7846_debounce(void *ads, int data_idx, int *val)
Expand Down Expand Up @@ -553,14 +542,27 @@ static int ads7846_timer(struct hrtimer *handle)

spin_lock_irq(&ts->lock);

if (unlikely(ts->msg_idx && !ts->pendown)) {
if (unlikely(!ts->get_pendown_state() ||
device_suspended(&ts->spi->dev))) {
if (ts->pendown) {
struct input_dev *input = ts->input;

input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0);
input_sync(input);

ts->pendown = 0;
#ifdef VERBOSE
dev_dbg(&ts->spi->dev, "UP\n");
#endif
}

/* measurement cycle ended */
if (!device_suspended(&ts->spi->dev)) {
ts->irq_disabled = 0;
enable_irq(ts->spi->irq);
}
ts->pending = 0;
ts->msg_idx = 0;
} else {
/* pen is still down, continue with the measurement */
ts->msg_idx = 0;
Expand Down

0 comments on commit 15e3589

Please sign in to comment.