MLK-13244 input: touchscreen: add support for vtl touchscreen
authorAlejandro Lozano <alejandro.lozano@nxp.com>
Tue, 6 Sep 2016 21:41:13 +0000 (16:41 -0500)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:52:31 +0000 (14:52 -0500)
Add the support for a CT36X based touchscreens using
the CT36X controller and i2c touchscreen interface.

Signed-off-by: Alejandro Lozano <alejandro.lozano@nxp.com>
Signed-off-by: Juan Gutierrez <juan.gutierrez@nxp.com>
Signed-off-by: Alejandro Sierra <alejandro.sierra@nxp.com>
Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/vtl/Makefile [new file with mode: 0644]
drivers/input/touchscreen/vtl/vtl_ts.c [new file with mode: 0644]
drivers/input/touchscreen/vtl/vtl_ts.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt
new file mode 100644 (file)
index 0000000..a41a0b9
--- /dev/null
@@ -0,0 +1,18 @@
+* VTL Touchscreen Controller
+
+Required properties:
+- compatible: must be "vtl,ct365"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- gpios: the gpio pin to be used for reset
+
+Example:
+
+        touchscreen@01 {
+                compatible = "vtl,ct365";
+                reg = <0x01>;
+                interrupt-parent = <&gpio6>;
+                interrupts = <14 0>;
+                gpios = <&gpio4 10 0>;
+        };
index 5c488b6..1beb197 100644 (file)
@@ -46,6 +46,19 @@ config TOUCHSCREEN_ADS7846
          To compile this driver as a module, choose M here: the
          module will be called ads7846.
 
+config TOUCHSCREEN_CT36X_WLD
+        default y
+        tristate "CT36X based touchscreens for WLD"
+        help
+          Say Y here if you have a touchscreen interface using the
+          CT36X controller, i2c touchscreen
+          controller.
+
+          If unsure, say N (but it's safe to say "Y").
+
+          To compile this driver as a module, choose M here: the
+          module will be called vtl_ts.
+
 config TOUCHSCREEN_AD7877
        tristate "AD7877 based touchscreens"
        depends on SPI_MASTER
index 1af3ebf..27de5a4 100644 (file)
@@ -97,6 +97,7 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)     += zylonite-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_W90X900)      += w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_SX8654)       += sx8654.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)     += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_CT36X_WLD)    += vtl/
 obj-$(CONFIG_TOUCHSCREEN_ZFORCE)       += zforce_ts.o
 obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
diff --git a/drivers/input/touchscreen/vtl/Makefile b/drivers/input/touchscreen/vtl/Makefile
new file mode 100644 (file)
index 0000000..2ee7f7a
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the VTL touchscreen driver.
+#
+
+obj-y          += vtl_ts.o
diff --git a/drivers/input/touchscreen/vtl/vtl_ts.c b/drivers/input/touchscreen/vtl/vtl_ts.c
new file mode 100644 (file)
index 0000000..f7bef9e
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * VTL CTP driver
+ *
+ * Copyright (C) 2013 VTL Corporation
+ * Copyright (C) 2016 Freescale Semiconductor, Inc
+ *
+ * This program 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_qos.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define FORCE_SINGLE_EVENT 1
+
+#include "vtl_ts.h"
+
+#define MIN_X       0x00
+#define MIN_Y       0x00
+#define MAX_X       1023
+#define MAX_Y       767
+#define MAX_AREA    0xff
+#define MAX_FINGERS 2
+
+
+/* Global or static variables */
+struct ts_driver g_driver;
+
+static struct ts_info g_ts = {
+       .driver = &g_driver,
+};
+static struct ts_info *pg_ts = &g_ts;
+
+static struct i2c_device_id vtl_ts_id[] = {
+       { DRIVER_NAME, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, vtl_ts_id);
+
+
+static int vtl_ts_config(struct ts_info *ts)
+{
+       struct device *dev;
+
+       DEBUG();
+
+       dev = &ts->driver->client->dev;
+
+       /* ts config */
+       ts->config_info.touch_point_number = TOUCH_POINT_NUM;
+
+       pr_info("Configuring vtl\n");
+       ts->config_info.screen_max_x = SCREEN_MAX_X;
+       ts->config_info.screen_max_y = SCREEN_MAX_y;
+       return 0;
+}
+
+void vtl_ts_free_gpio(void)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       gpio_free(ts->config_info.irq_gpio_number);
+}
+
+void vtl_ts_hw_reset(void)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       gpio_set_value(ts->config_info.rst_gpio_number, 0);
+       mdelay(50);
+       gpio_set_value(ts->config_info.rst_gpio_number, 1);
+}
+
+static irqreturn_t vtl_ts_irq(int irq, void *dev)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       queue_work(ts->driver->workqueue, &ts->driver->event_work);
+
+       return IRQ_HANDLED;
+}
+
+static union ts_xy_data *vtl_read_xy_data(struct ts_info *ts)
+{
+       struct i2c_msg msgs;
+       int err;
+
+       DEBUG();
+
+       msgs.addr = ts->driver->client->addr;
+       msgs.flags = 0x01;
+       msgs.len = sizeof(ts->xy_data.buf);
+       msgs.buf = ts->xy_data.buf;
+
+       err = i2c_transfer(ts->driver->client->adapter, &msgs, 1);
+       if (err != 1) {
+               pr_err("___%s:i2c read err___\n", __func__);
+               return NULL;
+       }
+       return &ts->xy_data;
+}
+
+static void vtl_report_xy_coord(struct input_dev *input_dev,
+                               union ts_xy_data *xy_data,
+                               unsigned char touch_point_number)
+{
+       struct ts_info *ts;
+       int id;
+       int sync;
+       int x, y;
+       unsigned int press;
+       static unsigned int release;
+
+       ts = pg_ts;
+       DEBUG();
+
+       /* report points */
+       sync = 0;  press = 0;
+       for (id = 0; id < touch_point_number; id++) {
+               if ((xy_data->point[id].xhi != 0xFF) &&
+                   (xy_data->point[id].yhi != 0xFF) &&
+                  ((xy_data->point[id].status == 1) ||
+                   (xy_data->point[id].status == 2))) {
+                       x = (xy_data->point[id].xhi<<4) |
+                           (xy_data->point[id].xlo&0xF);
+                       y = (xy_data->point[id].yhi<<4) |
+                           (xy_data->point[id].ylo&0xF);
+
+               if (ts->config_info.exchange_x_y_flag)
+                       swap(x, y);
+
+               if (ts->config_info.revert_x_flag)
+                       x = ts->config_info.screen_max_x - x;
+
+               if (ts->config_info.revert_y_flag)
+                       y = ts->config_info.screen_max_y - y;
+#ifndef FORCE_SINGLE_EVENT
+                       input_mt_slot(input_dev, xy_data->point[id].id - 1);
+                       input_mt_report_slot_state(input_dev,
+                                                  MT_TOOL_FINGER, true);
+                       input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+                       input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+                       input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 30);
+                       input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 128);
+#else
+                       input_report_abs(input_dev, ABS_X, x);
+                       input_report_abs(input_dev, ABS_Y, y);
+                       input_report_key(input_dev, BTN_TOUCH, 1);
+                       input_report_abs(input_dev, ABS_PRESSURE, 1);
+#endif
+                       sync = 1;
+                       press |= 0x01 << (xy_data->point[id].id - 1);
+               }
+       }
+
+       release &= (release ^ press); /*release point flag */
+       for (id = 0; id < touch_point_number; id++) {
+               if (release & (0x01 << id)) {
+#ifndef FORCE_SINGLE_EVENT
+                       input_mt_slot(input_dev, id);
+                       input_mt_report_slot_state(input_dev,
+                                                  MT_TOOL_FINGER, false);
+#else
+                       input_report_key(input_dev, BTN_TOUCH, 0);
+                       input_report_abs(input_dev, ABS_PRESSURE, 0);
+#endif
+                       sync = 1;
+               }
+
+       }
+       release = press;
+
+       if (sync)
+               input_sync(input_dev);
+}
+
+static void vtl_ts_workfunc(struct work_struct *work)
+{
+
+       union ts_xy_data *xy_data;
+       struct input_dev *input_dev;
+       unsigned char touch_point_number;
+
+       DEBUG();
+
+       input_dev = pg_ts->driver->input_dev;
+       touch_point_number = pg_ts->config_info.touch_point_number;
+
+       xy_data = vtl_read_xy_data(pg_ts);
+       if (xy_data != NULL)
+               vtl_report_xy_coord(input_dev, xy_data, touch_point_number);
+       else
+               pr_err("____xy_data error___\n");
+}
+
+#ifdef CONFIG_PM_SLEEP
+int vtl_ts_suspend(struct device *dev)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       disable_irq(ts->config_info.irq_number);
+       cancel_work_sync(&ts->driver->event_work);
+
+       return 0;
+}
+
+int vtl_ts_resume(struct device *dev)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       /* Hardware reset */
+       vtl_ts_hw_reset();
+       enable_irq(ts->config_info.irq_number);
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void vtl_ts_early_suspend(struct early_suspend *handler)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       vtl_ts_suspend(ts->driver->client, PMSG_SUSPEND);
+}
+
+static void vtl_ts_early_resume(struct early_suspend *handler)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       vtl_ts_resume(ts->driver->client);
+}
+#endif
+
+int  vtl_ts_remove(struct i2c_client *client)
+{
+       struct ts_info *ts;
+
+       ts = pg_ts;
+       DEBUG();
+
+       /* Driver clean up */
+
+       free_irq(ts->config_info.irq_number, ts);
+       vtl_ts_free_gpio();
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&ts->driver->early_suspend);
+#endif
+
+       cancel_work_sync(&ts->driver->event_work);
+       destroy_workqueue(ts->driver->workqueue);
+
+       input_unregister_device(ts->driver->input_dev);
+       input_free_device(ts->driver->input_dev);
+
+       if (ts->driver->proc_entry != NULL)
+               remove_proc_entry(DRIVER_NAME, NULL);
+
+       return 0;
+}
+
+static int init_input_dev(struct ts_info *ts)
+{
+       struct input_dev *input_dev;
+       struct device *dev;
+       int err;
+
+       DEBUG();
+
+       dev = &ts->driver->client->dev;
+
+       /* allocate input device */
+       ts->driver->input_dev = devm_input_allocate_device(dev);
+       if (ts->driver->input_dev == NULL) {
+               dev_err(dev, "Unable to allocate input device for device %s\n",
+                       DRIVER_NAME);
+               return -1;
+       }
+
+       input_dev = ts->driver->input_dev;
+
+       input_dev->name = "VTL for wld";
+       input_dev->phys = "I2C";
+       input_dev->id.bustype = BUS_I2C;
+       input_dev->id.vendor  = 0xaaaa;
+       input_dev->id.product = 0x5555;
+       input_dev->id.version = 0x0001;
+       input_dev->dev.parent = dev;
+
+       /* config input device */
+       __set_bit(EV_SYN, input_dev->evbit);
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(EV_ABS, input_dev->evbit);
+
+#ifdef FORCE_SINGLE_EVENT
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
+       input_set_abs_params(input_dev, ABS_X, MIN_X, MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, MIN_Y, MAX_Y, 0, 0);
+#else
+       __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+       input_mt_init_slots(input_dev, TOUCH_POINT_NUM, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+                            ts->config_info.screen_max_x, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+                            ts->config_info.screen_max_y, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+#endif
+       /* register input device */
+       err = input_register_device(input_dev);
+       if (err) {
+               dev_err(dev, "Unable to register input device for device %s\n",
+                       DRIVER_NAME);
+               return -1;
+       }
+
+       return 0;
+}
+
+int ct36x_test_tp(struct i2c_client *client)
+{
+       struct i2c_msg msgs;
+       char buf;
+
+       msgs.addr = 0x7F;
+       msgs.flags = 0x01;
+       msgs.len = 1;
+       msgs.buf = &buf;
+
+       if (i2c_transfer(client->adapter, &msgs, 1) != 1)
+               return -1;
+
+       return 0;
+}
+
+int vtl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       int err = -1;
+       struct ts_info *ts;
+       struct device *dev;
+
+       ts = pg_ts;
+       ts->driver->client = client;
+       dev = &ts->driver->client->dev;
+
+       /*Probing TouchScreen*/
+       pr_info("Probing vtl touchscreen, touchscreen node found\n");
+       if (ct36x_test_tp(client) < 0) {
+                       pr_err("vtl tp not found\n");
+                       goto ERR_TS_CONFIG;
+       }
+
+       /* Request platform resources (gpio/interrupt pins) */
+       err = vtl_ts_config(ts);
+       if (err) {
+               dev_err(dev, "VTL touch screen config Failed.\n");
+               goto ERR_TS_CONFIG;
+       }
+
+       /*Requestion GPIO*/
+       ts->config_info.rst_gpio_number = of_get_gpio(client->dev.of_node, 0);
+       if (gpio_is_valid(ts->config_info.rst_gpio_number)) {
+               err = devm_gpio_request(dev,
+                                       ts->config_info.rst_gpio_number, NULL);
+               if (err) {
+                       dev_err(dev, "Unable to request GPIO %d\n",
+                               ts->config_info.rst_gpio_number);
+                       return err;
+               }
+       }
+
+       /* Check I2C Functionality */
+       err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
+       if (!err) {
+               dev_err(dev, "Check I2C Functionality Failed.\n");
+               return -ENODEV;
+       }
+
+       err = devm_request_threaded_irq(dev, client->irq,
+                                       NULL, vtl_ts_irq,
+                                       IRQF_ONESHOT,
+                                       client->name, ts);
+       if (err) {
+               dev_err(&client->dev, "VTL Failed to register interrupt\n");
+
+               goto ERR_IRQ_REQ;
+       }
+
+       vtl_ts_hw_reset();
+
+       /*init input dev*/
+       err = init_input_dev(ts);
+       if (err) {
+
+               dev_err(dev, "init input dev failed.\n");
+               goto ERR_INIT_INPUT;
+       }
+
+       /* register early suspend */
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       ts->driver->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       ts->driver->early_suspend.suspend = vtl_ts_early_suspend;
+       ts->driver->early_suspend.resume = vtl_ts_early_resume;
+       register_early_suspend(&ts->driver->early_suspend);
+#endif
+       /* Create work queue */
+       INIT_WORK(&ts->driver->event_work, vtl_ts_workfunc);
+       ts->driver->workqueue = create_singlethread_workqueue(DRIVER_NAME);
+
+       return 0;
+
+ERR_IRQ_REQ:
+       cancel_work_sync(&ts->driver->event_work);
+       destroy_workqueue(ts->driver->workqueue);
+
+ERR_INIT_INPUT:
+       input_free_device(ts->driver->input_dev);
+       gpio_free(ts->config_info.rst_gpio_number);
+ERR_TS_CONFIG:
+
+       return err;
+}
+
+
+static SIMPLE_DEV_PM_OPS(vtl_ts_pm_ops, vtl_ts_suspend, vtl_ts_resume);
+
+static const struct of_device_id vtl_ts_dt_ids[] = {
+       { .compatible = "vtl,ct365", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, vtl_ts_dt_ids);
+
+
+static struct i2c_driver vtl_ts_driver  = {
+       .probe      = vtl_ts_probe,
+       .remove     = vtl_ts_remove,
+       .id_table   = vtl_ts_id,
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = DRIVER_NAME,
+               .pm     = &vtl_ts_pm_ops,
+               .of_match_table = of_match_ptr(vtl_ts_dt_ids),
+       },
+};
+
+module_i2c_driver(vtl_ts_driver);
+
+MODULE_AUTHOR("VTL");
+MODULE_DESCRIPTION("VTL TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/vtl/vtl_ts.h b/drivers/input/touchscreen/vtl/vtl_ts.h
new file mode 100644 (file)
index 0000000..9f61565
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * VTL CTP driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc
+ *
+ * Using code from:
+ *  - github.com/qdk0901/q98_source:drivers/input/touchscreen/vtl/vtl_ts.h
+ *
+ * This program 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.
+ *
+ */
+
+#ifndef _TS_CORE_H_
+#define _TS_CORE_H_
+
+#include <linux/gpio.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+
+#ifdef TS_DEBUG
+#define DEBUG() pr_debug("___%s___\n", __func__)
+#else
+#define DEBUG()
+#endif
+
+
+/* platform define */
+#define COMMON    0x01 /* Samsung,Freescale,Amlogic,actions */
+#define ROCKCHIP  0X02
+#define ALLWINER  0X03
+#define MTK       0X04
+
+/* vtl touch IC define */
+#define CT36X     0x01
+#define CT360     0x02
+
+/* xy data protocol */
+#define OLD_PROTOCOL    0x01
+#define NEW_PROTOCOL    0x02
+
+
+/* vtl ts driver config */
+
+/*platform config*/
+#define PLATFORM COMMON
+
+/*vtl ts driver name*/
+#define DRIVER_NAME "vtl_ts"
+
+/*vtl chip ID*/
+#define CHIP_ID CT36X
+
+#define XY_DATA_PROTOCOL NEW_PROTOCOL
+
+
+/* maybe not use,please refer to the function
+ * vtl_ts_config() in the file "vtl_ts.c"
+ */
+#define SCREEN_MAX_X    1024
+#define SCREEN_MAX_y    600
+
+#define TS_IRQ_GPIO_NUM           /* RK30_PIN4_PC2 */
+#define TS_RST_GPIO_NUM           /* RK30_PIN4_PD0 */
+#define TS_I2C_SPEED    400000    /* for rockchip  */
+
+
+/* priate define and declare */
+#if (CHIP_ID == CT360)
+#define TOUCH_POINT_NUM    1
+#elif (CHIP_ID == CT36X)
+#define TOUCH_POINT_NUM    1
+#endif
+
+
+#if (CHIP_ID == CT360)
+struct xy_data {
+#if (XY_DATA_PROTOCOL == OLD_PROTOCOL)
+       unsigned char status:4; /* Action information, 1:Down;
+                                  2: Move; 3: Up */
+       unsigned char id:4;     /* ID information, from 1 to
+                                  CFG_MAX_POINT_NUM */
+#endif
+       unsigned char xhi;      /* X coordinate Hi */
+       unsigned char yhi;      /* Y coordinate Hi */
+       unsigned char ylo:4;    /* Y coordinate Lo */
+       unsigned char xlo:4;    /* X coordinate Lo */
+#if (XY_DATA_PROTOCOL == NEW_PROTOCOL)
+       unsigned char status:4; /* Action information, 1: Down;
+                                  2: Move; 3: Up */
+       unsigned char id:4;     /* ID information, from 1 to
+                                  CFG_MAX_POINT_NUM */
+#endif
+};
+#else
+struct xy_data {
+#if (XY_DATA_PROTOCOL == OLD_PROTOCOL)
+       unsigned char status:3; /* Action information, 1: Down;
+                                  2: Move; 3: Up */
+       unsigned char id:5;     /* ID information, from 1 to
+                                  CFG_MAX_POINT_NUM */
+#endif
+       unsigned char xhi;      /* X coordinate Hi */
+       unsigned char yhi;      /* Y coordinate Hi */
+       unsigned char ylo:4;    /* Y coordinate Lo */
+       unsigned char xlo:4;    /* X coordinate Lo */
+#if (XY_DATA_PROTOCOL == NEW_PROTOCOL)
+       unsigned char status:3; /* Action information, 1: Down;
+                                  2: Move; 3: Up */
+       unsigned char id:5;     /* ID information, from 1 to
+                                  CFG_MAX_POINT_NUM */
+#endif
+       unsigned char area;     /* Touch area */
+       unsigned char pressure; /* Touch Pressure */
+};
+#endif
+
+
+union ts_xy_data {
+       struct xy_data point[TOUCH_POINT_NUM];
+       unsigned char buf[TOUCH_POINT_NUM * sizeof(struct xy_data)];
+};
+
+
+struct ts_driver {
+
+       struct i2c_client *client;
+
+       /* input devices */
+       struct input_dev *input_dev;
+
+       struct proc_dir_entry *proc_entry;
+
+       /* Work thread settings */
+       struct work_struct event_work;
+       struct workqueue_struct *workqueue;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend early_suspend;
+#endif
+};
+
+struct ts_config_info {
+
+       unsigned int screen_max_x;
+       unsigned int screen_max_y;
+       unsigned int irq_gpio_number;
+       unsigned int irq_number;
+       unsigned int rst_gpio_number;
+       unsigned char touch_point_number;
+       unsigned char ctp_used;
+       unsigned char i2c_bus_number;
+       unsigned char revert_x_flag;
+       unsigned char revert_y_flag;
+       unsigned char exchange_x_y_flag;
+       int (*tp_enter_init)(void);
+       void (*tp_exit_init)(int state);
+};
+
+
+struct ts_chip_info {
+       unsigned char chip_id;
+};
+
+struct ts_info {
+
+       struct ts_driver *driver;
+       struct ts_config_info config_info;
+       struct  ts_chip_info chip_info;
+       union ts_xy_data xy_data;
+};
+
+#endif