Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 115065
b: refs/heads/master
c: 4d5975e
h: refs/heads/master
i:
  115063: c2fe2fd
v: v3
  • Loading branch information
Eric Miao authored and Dmitry Torokhov committed Sep 10, 2008
1 parent 94d67eb commit 185708a
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d46ed1c747edfe6476961d4d9f732ceb7a29074
refs/heads/master: 4d5975e5016a9025814b92981de21eaf9203caa6
68 changes: 54 additions & 14 deletions trunk/drivers/input/touchscreen/ads7846.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <asm/irq.h>
Expand Down Expand Up @@ -116,6 +117,7 @@ struct ads7846 {
void *filter_data;
void (*filter_cleanup)(void *data);
int (*get_pendown_state)(void);
int gpio_pendown;
};

/* leave chip selected when we're done, for quicker re-select? */
Expand Down Expand Up @@ -492,6 +494,14 @@ static struct attribute_group ads784x_attr_group = {

/*--------------------------------------------------------------------------*/

static int get_pendown_state(struct ads7846 *ts)
{
if (ts->get_pendown_state)
return ts->get_pendown_state();

return !gpio_get_value(ts->gpio_pendown);
}

/*
* PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
* to retrieve touchscreen status.
Expand Down Expand Up @@ -551,7 +561,7 @@ static void ads7846_rx(void *ads)
*/
if (ts->penirq_recheck_delay_usecs) {
udelay(ts->penirq_recheck_delay_usecs);
if (!ts->get_pendown_state())
if (!get_pendown_state(ts))
Rt = 0;
}

Expand Down Expand Up @@ -678,7 +688,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)

spin_lock_irq(&ts->lock);

if (unlikely(!ts->get_pendown_state() ||
if (unlikely(!get_pendown_state(ts) ||
device_suspended(&ts->spi->dev))) {
if (ts->pendown) {
struct input_dev *input = ts->input;
Expand Down Expand Up @@ -717,7 +727,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
unsigned long flags;

spin_lock_irqsave(&ts->lock, flags);
if (likely(ts->get_pendown_state())) {
if (likely(get_pendown_state(ts))) {
if (!ts->irq_disabled) {
/* The ARM do_simple_IRQ() dispatcher doesn't act
* like the other dispatchers: it will report IRQs
Expand Down Expand Up @@ -807,6 +817,36 @@ static int ads7846_resume(struct spi_device *spi)
return 0;
}

static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
{
struct ads7846_platform_data *pdata = spi->dev.platform_data;
int err;

/* 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 && !gpio_is_valid(pdata->gpio_pendown)) {
dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
return -EINVAL;
}

if (pdata->get_pendown_state) {
ts->get_pendown_state = pdata->get_pendown_state;
return 0;
}

err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
if (err) {
dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
pdata->gpio_pendown);
return err;
}

ts->gpio_pendown = pdata->gpio_pendown;
return 0;
}

static int __devinit ads7846_probe(struct spi_device *spi)
{
struct ads7846 *ts;
Expand Down Expand Up @@ -834,15 +874,6 @@ 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 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.
Expand Down Expand Up @@ -894,7 +925,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->filter_data = ts;
} else
ts->filter = ads7846_no_filter;
ts->get_pendown_state = pdata->get_pendown_state;

err = setup_pendown(spi, ts);
if (err)
goto err_cleanup_filter;

if (pdata->penirq_recheck_delay_usecs)
ts->penirq_recheck_delay_usecs =
Expand Down Expand Up @@ -1086,7 +1120,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi->dev.driver->name, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
err = -EBUSY;
goto err_cleanup_filter;
goto err_free_gpio;
}

err = ads784x_hwmon_register(spi, ts);
Expand Down Expand Up @@ -1117,6 +1151,9 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ads784x_hwmon_unregister(spi, ts);
err_free_irq:
free_irq(spi->irq, ts);
err_free_gpio:
if (ts->gpio_pendown != -1)
gpio_free(ts->gpio_pendown);
err_cleanup_filter:
if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);
Expand All @@ -1141,6 +1178,9 @@ static int __devexit ads7846_remove(struct spi_device *spi)
/* suspend left the IRQ disabled */
enable_irq(ts->spi->irq);

if (ts->gpio_pendown != -1)
gpio_free(ts->gpio_pendown);

if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);

Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/spi/ads7846.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct ads7846_platform_data {
u16 debounce_tol; /* tolerance used for filtering */
u16 debounce_rep; /* additional consecutive good readings
* required after the first two */
int gpio_pendown; /* the GPIO used to decide the pendown
* state if get_pendown_state == NULL
*/
int (*get_pendown_state)(void);
int (*filter_init) (struct ads7846_platform_data *pdata,
void **filter_data);
Expand Down

0 comments on commit 185708a

Please sign in to comment.