> -----Original Message-----
> From: Hiremath, Vaibhav
> Sent: Thursday, November 19, 2009 8:17 PM
> To: linux-in...@vger.kernel.org
> Cc: linux-omap@vger.kernel.org; Hiremath, Vaibhav
> Subject: [PATCH 2/3] Input:TouchScreen: Introduce TSC2004 driver
> support
>
> From: Vaibhav Hiremath <hvaib...@ti.com>
>
> Signed-off-by: Vaibhav Hiremath <hvaib...@ti.com>
> ---
>  drivers/input/touchscreen/Kconfig   |   11 +
>  drivers/input/touchscreen/Makefile  |    1 +
>  drivers/input/touchscreen/tsc2004.c |  525
> +++++++++++++++++++++++++++++++++++
>  include/linux/i2c/tsc2004.h         |   17 ++
>  4 files changed, 554 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/input/touchscreen/tsc2004.c
>  create mode 100644 include/linux/i2c/tsc2004.h
>
[Hiremath, Vaibhav] Dmitry,

Any update on this? This driver support is important for AM3517EVM, can we 
merge this patch?

Thanks,
Vaibhav

> diff --git a/drivers/input/touchscreen/Kconfig
> b/drivers/input/touchscreen/Kconfig
> index 8cc453c..08aba0b 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -512,6 +512,17 @@ config TOUCHSCREEN_TSC2007
>         To compile this driver as a module, choose M here: the
>         module will be called tsc2007.
>
> +config TOUCHSCREEN_TSC2004
> +     tristate "TSC2004 based touchscreens"
> +     depends on I2C
> +     help
> +       Say Y here if you have a TSC2004 based touchscreen.
> +
> +       If unsure, say N.
> +
> +       To compile this driver as a module, choose M here: the
> +       module will be called tsc2004.
> +
>  config TOUCHSCREEN_W90X900
>       tristate "W90P910 touchscreen driver"
>       depends on HAVE_CLK
> diff --git a/drivers/input/touchscreen/Makefile
> b/drivers/input/touchscreen/Makefile
> index 15fa62c..4ac5b81 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)        +=
> touchit213.o
>  obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
>  obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)   += touchwin.o
>  obj-$(CONFIG_TOUCHSCREEN_TSC2007)    += tsc2007.o
> +obj-$(CONFIG_TOUCHSCREEN_TSC2004)    += tsc2004.o
>  obj-$(CONFIG_TOUCHSCREEN_UCB1400)    += ucb1400_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)        += wacom_w8001.o
>  obj-$(CONFIG_TOUCHSCREEN_WM97XX)     += wm97xx-ts.o
> diff --git a/drivers/input/touchscreen/tsc2004.c
> b/drivers/input/touchscreen/tsc2004.c
> new file mode 100644
> index 0000000..0bba2e6
> --- /dev/null
> +++ b/drivers/input/touchscreen/tsc2004.c
> @@ -0,0 +1,525 @@
> +/*
> + * drivers/input/touchscreen/tsc2004.c
> + *
> + * Copyright (C) 2009 Texas Instruments Inc
> + * Author: Vaibhav Hiremath <hvaib...@ti.com>
> + *
> + * Using code from:
> + *  - tsc2007.c
> + *
> + * This package is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License version 2
> as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/input.h>
> +#include <linux/interrupt.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c/tsc2004.h>
> +
> +
> +#define TS_POLL_DELAY                        1 /* ms delay between samples */
> +#define TS_POLL_PERIOD                       1 /* ms delay between samples */
> +
> +/* Control byte 0 */
> +#define TSC2004_CMD0(addr, pnd, rw) ((addr<<3)|(pnd<<1)|rw)
> +/* Control byte 1 */
> +#define TSC2004_CMD1(cmd, mode, rst)
> ((1<<7)|(cmd<<4)|(mode<<2)|(rst<<1))
> +
> +/* Command Bits */
> +#define READ_REG     1
> +#define WRITE_REG    0
> +#define SWRST_TRUE   1
> +#define SWRST_FALSE  0
> +#define PND0_TRUE    1
> +#define PND0_FALSE   0
> +
> +/* Converter function mapping */
> +enum convertor_function {
> +     MEAS_X_Y_Z1_Z2, /* Measure X,Y,z1 and Z2:       0x0 */
> +     MEAS_X_Y,       /* Measure X and Y only:        0x1 */
> +     MEAS_X,         /* Measure X only:              0x2 */
> +     MEAS_Y,         /* Measure Y only:              0x3 */
> +     MEAS_Z1_Z2,     /* Measure Z1 and Z2 only:      0x4 */
> +     MEAS_AUX,       /* Measure Auxillary input:     0x5 */
> +     MEAS_TEMP1,     /* Measure Temparature1:        0x6 */
> +     MEAS_TEMP2,     /* Measure Temparature2:        0x7 */
> +     MEAS_AUX_CONT,  /* Continuously measure Auxillary input: 0x8
> */
> +     X_DRV_TEST,     /* X-Axis drivers tested        0x9 */
> +     Y_DRV_TEST,     /* Y-Axis drivers tested        0xA */
> +     /*Command Reserved*/
> +     SHORT_CKT_TST = 0xC,    /* Short circuit test:  0xC */
> +     XP_XN_DRV_STAT, /* X+,Y- drivers status:        0xD */
> +     YP_YN_DRV_STAT, /* X+,Y- drivers status:        0xE */
> +     YP_XN_DRV_STAT  /* Y+,X- drivers status:        0xF */
> +};
> +
> +/* Register address mapping */
> +enum register_address {
> +     X_REG,          /* X register:          0x0 */
> +     Y_REG,          /* Y register:          0x1 */
> +     Z1_REG,         /* Z1 register:         0x2 */
> +     Z2_REG,         /* Z2 register:         0x3 */
> +     AUX_REG,        /* AUX register:        0x4 */
> +     TEMP1_REG,      /* Temp1 register:      0x5 */
> +     TEMP2_REG,      /* Temp2 register:      0x6 */
> +     STAT_REG,       /* Status Register:     0x7 */
> +     AUX_HGH_TH_REG, /* AUX high threshold register: 0x8 */
> +     AUX_LOW_TH_REG, /* AUX low threshold register:  0x9 */
> +     TMP_HGH_TH_REG, /* Temp high threshold register:0xA */
> +     TMP_LOW_TH_REG, /* Temp low threshold register: 0xB */
> +     CFR0_REG,       /* Configuration register 0:    0xC */
> +     CFR1_REG,       /* Configuration register 1:    0xD */
> +     CFR2_REG,       /* Configuration register 2:    0xE */
> +     CONV_FN_SEL_STAT        /* Convertor function select register:
>       0xF */
> +};
> +
> +/* Supported Resolution modes */
> +enum resolution_mode {
> +     MODE_10BIT,     /* 10 bit resolution */
> +     MODE_12BIT              /* 12 bit resolution */
> +};
> +
> +/* Configuraton register bit fields */
> +/* CFR0 */
> +#define PEN_STS_CTRL_MODE    (1<<15)
> +#define ADC_STS                      (1<<14)
> +#define RES_CTRL             (1<<13)
> +#define ADC_CLK_4MHZ         (0<<11)
> +#define ADC_CLK_2MHZ         (1<<11)
> +#define ADC_CLK_1MHZ         (2<<11)
> +#define PANEL_VLTG_STB_TIME_0US              (0<<8)
> +#define PANEL_VLTG_STB_TIME_100US    (1<<8)
> +#define PANEL_VLTG_STB_TIME_500US    (2<<8)
> +#define PANEL_VLTG_STB_TIME_1MS              (3<<8)
> +#define PANEL_VLTG_STB_TIME_5MS              (4<<8)
> +#define PANEL_VLTG_STB_TIME_10MS     (5<<8)
> +#define PANEL_VLTG_STB_TIME_50MS     (6<<8)
> +#define PANEL_VLTG_STB_TIME_100MS    (7<<8)
> +
> +/* CFR2 */
> +#define PINTS1                       (1<<15)
> +#define PINTS0                       (1<<14)
> +#define MEDIAN_VAL_FLTR_SIZE_1       (0<<12)
> +#define MEDIAN_VAL_FLTR_SIZE_3       (1<<12)
> +#define MEDIAN_VAL_FLTR_SIZE_7       (2<<12)
> +#define MEDIAN_VAL_FLTR_SIZE_15      (3<<12)
> +#define AVRG_VAL_FLTR_SIZE_1 (0<<10)
> +#define AVRG_VAL_FLTR_SIZE_3_4       (1<<10)
> +#define AVRG_VAL_FLTR_SIZE_7_8       (2<<10)
> +#define AVRG_VAL_FLTR_SIZE_16        (3<<10)
> +#define MAV_FLTR_EN_X                (1<<4)
> +#define MAV_FLTR_EN_Y                (1<<3)
> +#define MAV_FLTR_EN_Z                (1<<2)
> +
> +#define      MAX_12BIT               ((1 << 12) - 1)
> +#define MEAS_MASK            0xFFF
> +
> +struct ts_event {
> +     u16     x;
> +     u16     y;
> +     u16     z1, z2;
> +};
> +
> +struct tsc2004 {
> +     struct input_dev        *input;
> +     char                    phys[32];
> +     struct delayed_work     work;
> +
> +     struct i2c_client       *client;
> +
> +     u16                     model;
> +     u16                     x_plate_ohms;
> +
> +     bool                    pendown;
> +     int                     irq;
> +
> +     int                     (*get_pendown_state)(void);
> +     void                    (*clear_penirq)(void);
> +};
> +
> +static inline int tsc2004_read_word_data(struct tsc2004 *tsc, u8
> cmd)
> +{
> +     s32 data;
> +     u16 val;
> +
> +     data = i2c_smbus_read_word_data(tsc->client, cmd);
> +     if (data < 0) {
> +             dev_err(&tsc->client->dev, "i2c io (read) error: %d\n",
> data);
> +             return data;
> +     }
> +
> +     /* The protocol and raw data format from i2c interface:
> +      * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh]
> NA P
> +      * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 |
> Dummy 4bit].
> +      */
> +     val = swab16(data) >> 4;
> +
> +     dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data,
> val);
> +
> +     return val;
> +}
> +
> +static inline int tsc2004_write_word_data(struct tsc2004 *tsc, u8
> cmd, u16 data)
> +{
> +     u16 val;
> +
> +     val = swab16(data);
> +     return i2c_smbus_write_word_data(tsc->client, cmd, val);
> +}
> +
> +static inline int tsc2004_write_cmd(struct tsc2004 *tsc, u8 value)
> +{
> +     return i2c_smbus_write_byte(tsc->client, value);
> +}
> +
> +static int tsc2004_prepare_for_reading(struct tsc2004 *ts)
> +{
> +     int err;
> +     int cmd, data;
> +
> +     /* Reset the TSC, configure for 12 bit */
> +     cmd = TSC2004_CMD1(MEAS_X_Y_Z1_Z2, MODE_12BIT, SWRST_TRUE);
> +     err = tsc2004_write_cmd(ts, cmd);
> +     if (err < 0)
> +             return err;
> +
> +     /* Enable interrupt for PENIRQ and DAV */
> +     cmd = TSC2004_CMD0(CFR2_REG, PND0_FALSE, WRITE_REG);
> +     data = PINTS1 | PINTS0 | MEDIAN_VAL_FLTR_SIZE_15 |
> +             AVRG_VAL_FLTR_SIZE_7_8 | MAV_FLTR_EN_X | MAV_FLTR_EN_Y |
> +             MAV_FLTR_EN_Z;
> +     err = tsc2004_write_word_data(ts, cmd, data);
> +     if (err < 0)
> +             return err;
> +
> +     /* Configure the TSC in TSMode 1 */
> +     cmd = TSC2004_CMD0(CFR0_REG, PND0_FALSE, WRITE_REG);
> +     data = PEN_STS_CTRL_MODE | ADC_CLK_2MHZ |
> PANEL_VLTG_STB_TIME_1MS;
> +     err = tsc2004_write_word_data(ts, cmd, data);
> +     if (err < 0)
> +             return err;
> +
> +     /* Enable x, y, z1 and z2 conversion functions */
> +     cmd = TSC2004_CMD1(MEAS_X_Y_Z1_Z2, MODE_12BIT, SWRST_FALSE);
> +     err = tsc2004_write_cmd(ts, cmd);
> +     if (err < 0)
> +             return err;
> +
> +     return 0;
> +}
> +
> +static void tsc2004_read_values(struct tsc2004 *tsc, struct
> ts_event *tc)
> +{
> +     int cmd;
> +
> +     /* Read X Measurement */
> +     cmd = TSC2004_CMD0(X_REG, PND0_FALSE, READ_REG);
> +     tc->x = tsc2004_read_word_data(tsc, cmd);
> +
> +     /* Read Y Measurement */
> +     cmd = TSC2004_CMD0(Y_REG, PND0_FALSE, READ_REG);
> +     tc->y = tsc2004_read_word_data(tsc, cmd);
> +
> +     /* Read Z1 Measurement */
> +     cmd = TSC2004_CMD0(Z1_REG, PND0_FALSE, READ_REG);
> +     tc->z1 = tsc2004_read_word_data(tsc, cmd);
> +
> +     /* Read Z2 Measurement */
> +     cmd = TSC2004_CMD0(Z2_REG, PND0_FALSE, READ_REG);
> +     tc->z2 = tsc2004_read_word_data(tsc, cmd);
> +
> +
> +     tc->x &= MEAS_MASK;
> +     tc->y &= MEAS_MASK;
> +     tc->z1 &= MEAS_MASK;
> +     tc->z2 &= MEAS_MASK;
> +
> +     /* Prepare for touch readings */
> +     if (tsc2004_prepare_for_reading(tsc) < 0)
> +             dev_dbg(&tsc->client->dev, "Failed to prepare TSC for
> next"
> +                             "reading\n");
> +}
> +
> +static u32 tsc2004_calculate_pressure(struct tsc2004 *tsc, struct
> ts_event *tc)
> +{
> +     u32 rt = 0;
> +
> +     /* range filtering */
> +     if (tc->x == MAX_12BIT)
> +             tc->x = 0;
> +
> +     if (likely(tc->x && tc->z1)) {
> +             /* compute touch pressure resistance using equation #1
> */
> +             rt = tc->z2 - tc->z1;
> +             rt *= tc->x;
> +             rt *= tsc->x_plate_ohms;
> +             rt /= tc->z1;
> +             rt = (rt + 2047) >> 12;
> +     }
> +
> +     return rt;
> +}
> +
> +static void tsc2004_send_up_event(struct tsc2004 *tsc)
> +{
> +     struct input_dev *input = tsc->input;
> +
> +     dev_dbg(&tsc->client->dev, "UP\n");
> +
> +     input_report_key(input, BTN_TOUCH, 0);
> +     input_report_abs(input, ABS_PRESSURE, 0);
> +     input_sync(input);
> +}
> +
> +static void tsc2004_work(struct work_struct *work)
> +{
> +     struct tsc2004 *ts =
> +             container_of(to_delayed_work(work), struct tsc2004,
> work);
> +     struct ts_event tc;
> +     u32 rt;
> +
> +     /*
> +      * NOTE: We can't rely on the pressure to determine the pen
> down
> +      * state, even though 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.
> +      *
> +      * The only safe way to check for the pen up condition is in
> the
> +      * work function by reading the pen signal state (it's a GPIO
> +      * and IRQ). Unfortunately such callback is not always
> available,
> +      * in that case we have rely on the pressure anyway.
> +      */
> +     if (ts->get_pendown_state) {
> +             if (unlikely(!ts->get_pendown_state())) {
> +                     tsc2004_send_up_event(ts);
> +                     ts->pendown = false;
> +                     goto out;
> +             }
> +
> +             dev_dbg(&ts->client->dev, "pen is still down\n");
> +     }
> +
> +     tsc2004_read_values(ts, &tc);
> +
> +     rt = tsc2004_calculate_pressure(ts, &tc);
> +     if (rt > MAX_12BIT) {
> +             /*
> +              * Sample found inconsistent by debouncing or pressure
> is
> +              * beyond the maximum. Don't report it to user space,
> +              * repeat at least once more the measurement.
> +              */
> +             dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
> +             goto out;
> +
> +     }
> +
> +     if (rt) {
> +             struct input_dev *input = ts->input;
> +
> +             if (!ts->pendown) {
> +                     dev_dbg(&ts->client->dev, "DOWN\n");
> +
> +                     input_report_key(input, BTN_TOUCH, 1);
> +                     ts->pendown = true;
> +             }
> +
> +             input_report_abs(input, ABS_X, tc.x);
> +             input_report_abs(input, ABS_Y, tc.y);
> +             input_report_abs(input, ABS_PRESSURE, rt);
> +
> +             input_sync(input);
> +
> +             dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure
> (%4u)\n",
> +                     tc.x, tc.y, rt);
> +
> +     } else if (!ts->get_pendown_state && ts->pendown) {
> +             /*
> +              * We don't have callback to check pendown state, so we
> +              * have to assume that since pressure reported is 0 the
> +              * pen was lifted up.
> +              */
> +             tsc2004_send_up_event(ts);
> +             ts->pendown = false;
> +     }
> +
> + out:
> +     if (ts->pendown)
> +             schedule_delayed_work(&ts->work,
> +                                   msecs_to_jiffies(TS_POLL_PERIOD));
> +     else
> +             enable_irq(ts->irq);
> +}
> +
> +static irqreturn_t tsc2004_irq(int irq, void *handle)
> +{
> +     struct tsc2004 *ts = handle;
> +
> +     if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
> {
> +             disable_irq_nosync(ts->irq);
> +             schedule_delayed_work(&ts->work,
> +                                   msecs_to_jiffies(TS_POLL_DELAY));
> +     }
> +
> +     if (ts->clear_penirq)
> +             ts->clear_penirq();
> +
> +     return IRQ_HANDLED;
> +}
> +
> +static void tsc2004_free_irq(struct tsc2004 *ts)
> +{
> +     free_irq(ts->irq, ts);
> +     if (cancel_delayed_work_sync(&ts->work)) {
> +             /*
> +              * Work was pending, therefore we need to enable
> +              * IRQ here to balance the disable_irq() done in the
> +              * interrupt handler.
> +              */
> +             enable_irq(ts->irq);
> +     }
> +}
> +
> +static int __devinit tsc2004_probe(struct i2c_client *client,
> +                                const struct i2c_device_id *id)
> +{
> +     struct tsc2004 *ts;
> +     struct tsc2004_platform_data *pdata = pdata = client-
> >dev.platform_data;
> +     struct input_dev *input_dev;
> +     int err;
> +
> +     if (!pdata) {
> +             dev_err(&client->dev, "platform data is required!\n");
> +             return -EINVAL;
> +     }
> +
> +     if (!i2c_check_functionality(client->adapter,
> +                                  I2C_FUNC_SMBUS_READ_WORD_DATA))
> +             return -EIO;
> +
> +     ts = kzalloc(sizeof(struct tsc2004), GFP_KERNEL);
> +     input_dev = input_allocate_device();
> +     if (!ts || !input_dev) {
> +             err = -ENOMEM;
> +             goto err_free_mem;
> +     }
> +
> +     ts->client = client;
> +     ts->irq = client->irq;
> +     ts->input = input_dev;
> +     INIT_DELAYED_WORK(&ts->work, tsc2004_work);
> +
> +     ts->model             = pdata->model;
> +     ts->x_plate_ohms      = pdata->x_plate_ohms;
> +     ts->get_pendown_state = pdata->get_pendown_state;
> +     ts->clear_penirq      = pdata->clear_penirq;
> +
> +     snprintf(ts->phys, sizeof(ts->phys),
> +              "%s/input0", dev_name(&client->dev));
> +
> +     input_dev->name = "TSC2004 Touchscreen";
> +     input_dev->phys = ts->phys;
> +     input_dev->id.bustype = BUS_I2C;
> +
> +     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> +     input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> +
> +     input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
> +     input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
> +     input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0,
> 0);
> +
> +     if (pdata->init_platform_hw)
> +             pdata->init_platform_hw();
> +
> +     err = request_irq(ts->irq, tsc2004_irq, IRQF_TRIGGER_FALLING,
> +                     client->dev.driver->name, ts);
> +     if (err < 0) {
> +             dev_err(&client->dev, "irq %d busy?\n", ts->irq);
> +             goto err_free_mem;
> +     }
> +
> +     /* Prepare for touch readings */
> +     err = tsc2004_prepare_for_reading(ts);
> +     if (err < 0)
> +             goto err_free_irq;
> +
> +     err = input_register_device(input_dev);
> +     if (err)
> +             goto err_free_irq;
> +
> +     i2c_set_clientdata(client, ts);
> +
> +     return 0;
> +
> + err_free_irq:
> +     tsc2004_free_irq(ts);
> +     if (pdata->exit_platform_hw)
> +             pdata->exit_platform_hw();
> + err_free_mem:
> +     input_free_device(input_dev);
> +     kfree(ts);
> +     return err;
> +}
> +
> +static int __devexit tsc2004_remove(struct i2c_client *client)
> +{
> +     struct tsc2004  *ts = i2c_get_clientdata(client);
> +     struct tsc2004_platform_data *pdata = client-
> >dev.platform_data;
> +
> +     tsc2004_free_irq(ts);
> +
> +     if (pdata->exit_platform_hw)
> +             pdata->exit_platform_hw();
> +
> +     input_unregister_device(ts->input);
> +     kfree(ts);
> +
> +     return 0;
> +}
> +
> +static struct i2c_device_id tsc2004_idtable[] = {
> +     { "tsc2004", 0 },
> +     { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
> +
> +static struct i2c_driver tsc2004_driver = {
> +     .driver = {
> +             .owner  = THIS_MODULE,
> +             .name   = "tsc2004"
> +     },
> +     .id_table       = tsc2004_idtable,
> +     .probe          = tsc2004_probe,
> +     .remove         = __devexit_p(tsc2004_remove),
> +};
> +
> +static int __init tsc2004_init(void)
> +{
> +     return i2c_add_driver(&tsc2004_driver);
> +}
> +
> +static void __exit tsc2004_exit(void)
> +{
> +     i2c_del_driver(&tsc2004_driver);
> +}
> +
> +module_init(tsc2004_init);
> +module_exit(tsc2004_exit);
> +
> +MODULE_AUTHOR("Vaibhav Hiremath <hvaib...@ti.com>");
> +MODULE_DESCRIPTION("TSC2004 TouchScreen Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/i2c/tsc2004.h
> b/include/linux/i2c/tsc2004.h
> new file mode 100644
> index 0000000..044c36f
> --- /dev/null
> +++ b/include/linux/i2c/tsc2004.h
> @@ -0,0 +1,17 @@
> +#ifndef __LINUX_I2C_TSC2004_H
> +#define __LINUX_I2C_TSC2004_H
> +
> +/* linux/i2c/tsc2004.h */
> +
> +struct tsc2004_platform_data {
> +     u16     model;                          /* 2004. */
> +     u16     x_plate_ohms;
> +
> +     int     (*get_pendown_state)(void);
> +     void    (*clear_penirq)(void);          /* If needed, clear 2nd
> level
> +                                                interrupt source */
> +     int     (*init_platform_hw)(void);
> +     void    (*exit_platform_hw)(void);
> +};
> +
> +#endif
> --
> 1.6.2.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to