rk30_phonepad:add auto touchscreen support
authorluowei <lw@rock-chips.com>
Tue, 9 Oct 2012 12:10:19 +0000 (20:10 +0800)
committerluowei <lw@rock-chips.com>
Tue, 9 Oct 2012 12:10:19 +0000 (20:10 +0800)
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/ts/Kconfig [new file with mode: 0755]
drivers/input/ts/Makefile [new file with mode: 0755]
drivers/input/ts/chips/Kconfig [new file with mode: 0755]
drivers/input/ts/chips/Makefile [new file with mode: 0755]
drivers/input/ts/chips/ft5306.c [new file with mode: 0644]
drivers/input/ts/chips/gt8110.c [new file with mode: 0644]
drivers/input/ts/ts-auto.c [new file with mode: 0644]
drivers/input/ts/ts-i2c.c [new file with mode: 0755]
include/linux/ts-auto.h [new file with mode: 0644]

index 972b67ffaffd0a3307db34b37e8e5aadd945b9c2..1682dbae1bda737686f3324c568988fd7f86b9c9 100755 (executable)
@@ -182,6 +182,8 @@ source "drivers/input/tablet/Kconfig"
 
 source "drivers/input/touchscreen/Kconfig"
 
+source "drivers/input/ts/Kconfig"
+
 source "drivers/input/misc/Kconfig"
 
 source "drivers/input/magnetometer/Kconfig"
index d9f2e938540e029b7a20a1ee64177c8c4ca3aa4b..89a28d2b86236a3cf6c4787164142db8915a611e 100755 (executable)
@@ -29,6 +29,7 @@ obj-$(CONFIG_LIGHT_SENSOR_DEVICE) += lightsensor/
 obj-$(CONFIG_MAG_SENSORS)      += magnetometer/
 
 obj-$(CONFIG_SENSOR_DEVICE)    += sensors/
+obj-$(CONFIG_TS_AUTO)  += ts/
 
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
 obj-$(CONFIG_INPUT_KEYRESET)   += keyreset.o
diff --git a/drivers/input/ts/Kconfig b/drivers/input/ts/Kconfig
new file mode 100755 (executable)
index 0000000..e205cb1
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# all auto touch screen drivers configuration\r
+#
+\r
+menuconfig TS_AUTO\r
+       bool "auto touch screen driver support"\r
+       default n       
+
+if TS_AUTO\r
+\r
+source "drivers/input/ts/chips/Kconfig"\r
+\r
+endif\r
+\r
+\r
diff --git a/drivers/input/ts/Makefile b/drivers/input/ts/Makefile
new file mode 100755 (executable)
index 0000000..a92c9b6
--- /dev/null
@@ -0,0 +1,6 @@
+# auto touch screen drivers\r
+obj-$(CONFIG_TS_AUTO)                  += chips/\r
+\r
+obj-$(CONFIG_TS_AUTO)                  += ts-i2c.o\r
+obj-$(CONFIG_TS_AUTO)                  += ts-auto.o\r
+\r
diff --git a/drivers/input/ts/chips/Kconfig b/drivers/input/ts/chips/Kconfig
new file mode 100755 (executable)
index 0000000..7dc4b2a
--- /dev/null
@@ -0,0 +1,11 @@
+config TS_FT5306\r
+  bool "touch screen ft5306"\r
+       default n
+config TS_CT360\r
+  bool "touch screen ct360"\r
+       default n
+
+config TS_GT8110\r
+  bool "touch screen gt8110"\r
+       default n         
\ No newline at end of file
diff --git a/drivers/input/ts/chips/Makefile b/drivers/input/ts/chips/Makefile
new file mode 100755 (executable)
index 0000000..aec7f1c
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_TS_FT5306)                        += ft5306.o\r
+obj-$(CONFIG_TS_CT360)                 += ct360.o\r
+obj-$(CONFIG_TS_GT8110)                        += gt8110.o
\ No newline at end of file
diff --git a/drivers/input/ts/chips/ft5306.c b/drivers/input/ts/chips/ft5306.c
new file mode 100644 (file)
index 0000000..4c045f1
--- /dev/null
@@ -0,0 +1,259 @@
+/* drivers/input/ts/chips/ts_ft5306.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <linux/input/mt.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif  \r
+#include <linux/ts-auto.h>\r
+        \r
+        \r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+#define FT5306_ID_REG          0x00\r
+#define FT5306_DEVID           0x00\r
+#define FT5306_DATA_REG                0x00\r
+\r
+\r
+/****************operate according to ts chip:start************/\r
+\r
+static int ts_active(struct i2c_client *client, int enable)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);      \r
+       int result = 0;\r
+\r
+       if(enable)\r
+       {\r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);\r
+               mdelay(10);\r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);\r
+               msleep(100);\r
+       }\r
+       else\r
+       {\r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);  \r
+       }\r
+               \r
+       \r
+       return result;\r
+}\r
+\r
+static int ts_init(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       int irq_pin = irq_to_gpio(ts->pdata->irq);\r
+       int result = 0;\r
+       \r
+       gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);\r
+       mdelay(10);\r
+       gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);\r
+       msleep(100);\r
+\r
+       //init some register\r
+       //to do\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int ts_report_value(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       struct ts_event *event = &ts->event;\r
+       unsigned char buf[32] = {0};\r
+       int result = 0 , i = 0, off = 0, id = 0;\r
+\r
+       buf[0] = ts->ops->read_reg;\r
+       result = ts_rx_data(client, buf, ts->ops->read_len);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init ts\n",__func__);\r
+               return result;\r
+       }\r
+\r
+       //for(i=0; i<ts->ops->read_len; i++)\r
+       //DBG("buf[%d]=0x%x\n",i,buf[i]);\r
+       \r
+       event->touch_point = buf[2] & 0x07;// 0000 1111\r
+\r
+       if(event->touch_point == 0)\r
+       {       \r
+               for(i=0; i<ts->ops->max_point; i++)\r
+               {\r
+                       if(event->point[i].status != 0)\r
+                       {\r
+                               event->point[i].status = 0;                             \r
+                               input_mt_slot(ts->input_dev, event->point[i].id);                               \r
+                               input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);\r
+                               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);\r
+                               DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id);\r
+                       }\r
+               }\r
+               \r
+               input_sync(ts->input_dev);\r
+               memset(event, 0x00, sizeof(struct ts_event));\r
+                               \r
+               return 0;\r
+       }\r
+       \r
+       for(i = 0; i<event->touch_point; i++)\r
+       {\r
+               off = i*6+3;\r
+               id = (buf[off+2] & 0xf0) >> 4;                          \r
+               event->point[id].id = id;\r
+               event->point[id].status = (buf[off+0] & 0xc0) >> 6;\r
+               event->point[id].x = ((buf[off+0] & 0x0f)<<8) | buf[off+1];\r
+               event->point[id].y = ((buf[off+2] & 0x0f)<<8) | buf[off+3];\r
+               \r
+               if(ts->ops->xy_swap)\r
+               {\r
+                       swap(event->point[id].x, event->point[id].y);\r
+               }\r
+\r
+               if(ts->ops->x_revert)\r
+               {\r
+                       event->point[id].x = ts->ops->pixel.max_x - event->point[id].x; \r
+               }\r
+\r
+               if(ts->ops->y_revert)\r
+               {\r
+                       event->point[id].y = ts->ops->pixel.max_y - event->point[id].y;\r
+               }\r
+\r
+               if(event->point[id].status != 0)\r
+               {               \r
+                       input_mt_slot(ts->input_dev, event->point[id].id);\r
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);\r
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);\r
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);\r
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);\r
+                       input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);\r
+                       DBG("%s:%s press down,id=%d,x=%d,y=%d\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);\r
+               }\r
+               \r
+               \r
+       }\r
+       \r
+       input_sync(ts->input_dev);\r
+\r
+       return 0;\r
+}\r
+\r
+static int ts_suspend(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       \r
+       if(ts->pdata->irq_enable)       \r
+               disable_irq_nosync(client->irq);\r
+\r
+       if(ts->ops->active)\r
+               ts->ops->active(client, 0);\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+static int ts_resume(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       \r
+       if(ts->pdata->irq_enable)       \r
+               enable_irq(client->irq);\r
+\r
+       if(ts->ops->active)\r
+               ts->ops->active(client, 1);\r
+       return 0;\r
+}\r
+\r
+\r
+\r
+struct ts_operate ts_ft5306_ops = {\r
+       .name                           = "ft5306",\r
+       .slave_addr                     = 0x3e,\r
+       .id_i2c                         = TS_ID_FT5306,                 //i2c id number\r
+       .pixel                          = {1024,768},\r
+       .id_reg                         = FT5306_ID_REG,\r
+       .id_data                        = TS_UNKNOW_DATA,       \r
+       .read_reg                       = FT5306_DATA_REG,              //read data\r
+       .read_len                       = 32,                           //data length\r
+       .trig                           = IRQF_TRIGGER_FALLING,         \r
+       .max_point                      = 5,\r
+       .xy_swap                        = 1,\r
+       .x_revert                       = 1,\r
+       .y_revert                       = 0,\r
+       .range                          = {1024,768},\r
+       .active                         = ts_active,    \r
+       .init                           = ts_init,\r
+       .report                         = ts_report_value,\r
+       .firmware                       = NULL,\r
+       .suspend                        = ts_suspend,\r
+       .resume                         = ts_resume,\r
+};\r
+\r
+/****************operate according to ts chip:end************/\r
+\r
+//function name should not be changed\r
+static struct ts_operate *ts_get_ops(void)\r
+{\r
+       return &ts_ft5306_ops;\r
+}\r
+\r
+\r
+static int __init ts_ft5306_init(void)\r
+{\r
+       struct ts_operate *ops = ts_get_ops();\r
+       int result = 0;\r
+       result = ts_register_slave(NULL, NULL, ts_get_ops);     \r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit ts_ft5306_exit(void)\r
+{\r
+       struct ts_operate *ops = ts_get_ops();\r
+       ts_unregister_slave(NULL, NULL, ts_get_ops);\r
+}\r
+\r
+\r
+subsys_initcall(ts_ft5306_init);\r
+module_exit(ts_ft5306_exit);\r
+\r
diff --git a/drivers/input/ts/chips/gt8110.c b/drivers/input/ts/chips/gt8110.c
new file mode 100644 (file)
index 0000000..99c8097
--- /dev/null
@@ -0,0 +1,330 @@
+/* drivers/input/ts/chips/gt8110.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <linux/input/mt.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif  \r
+#include <linux/ts-auto.h>\r
+        \r
+        \r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+#define GT8110_ID_REG          0x00\r
+#define GT8110_DATA_REG                0x00\r
+\r
+\r
+/****************operate according to ts chip:start************/\r
+\r
+static int ts_active(struct i2c_client *client, int enable)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       unsigned char buf_suspend[2] = {0x38, 0x56};            //suspend cmd\r
+       int result = 0;\r
+\r
+       if(enable)\r
+       {\r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);\r
+               mdelay(200);\r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);\r
+               msleep(200);\r
+       }\r
+       else\r
+       {\r
+               result = ts_tx_data(client, buf_suspend, 2);\r
+               if(result < 0)\r
+               {\r
+                       printk("%s:fail to init ts\n",__func__);\r
+                       return result;\r
+               }\r
+               \r
+               gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);  \r
+       }\r
+               \r
+       \r
+       return result;\r
+}\r
+\r
+static int ts_init(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       int irq_pin = irq_to_gpio(ts->pdata->irq);\r
+       char version_data[18] = {240};\r
+       char init_data[95] = {\r
+       0x65,0x02,0x00,0x10,0x00,0x10,0x0A,0x6E,0x0A,0x00,\r
+       0x0F,0x1E,0x02,0x08,0x10,0x00,0x00,0x27,0x00,0x00,\r
+       0x50,0x10,0x10,0x11,0x37,0x00,0x00,0x00,0x01,0x02,\r
+       0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0xFF,\r
+       0xFF,0xFF,0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,\r
+       0x07,0x08,0x09,0x0A,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,\r
+       0x00,0x50,0x64,0x50,0x00,0x00,0x00,0x00,0x00,0x00,\r
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
+       0x00,0x00,0x00,0x00,0x20\r
+        };\r
+       int result = 0, i = 0;\r
+\r
+       //read version\r
+       result = ts_rx_data(client, version_data, 17);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init ts\n",__func__);\r
+               return result;\r
+       }\r
+       version_data[17]='\0';\r
+\r
+       printk("%s:%s version is %s\n",__func__,ts->ops->name, version_data);\r
+#if 1\r
+       //init some register\r
+       result = ts_tx_data(client, init_data, 95);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init ts\n",__func__);\r
+               return result;\r
+       }\r
+#endif\r
+       result = ts_rx_data(client, init_data, 95);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init ts\n",__func__);\r
+               return result;\r
+       }\r
+\r
+       \r
+       printk("%s:rx:",__func__);\r
+       for(i=0; i<95; i++)\r
+       printk("0x%x,",init_data[i]);\r
+\r
+       printk("\n");\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int ts_report_value(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       struct ts_event *event = &ts->event;\r
+       unsigned char buf[54] = {0};\r
+       int result = 0 , i = 0, j = 0, off = 0, id = 0;\r
+       int temp = 0, num = 0;\r
+\r
+       buf[0] = ts->ops->read_reg;\r
+       result = ts_rx_data(client, buf, ts->ops->read_len);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init ts\n",__func__);\r
+               return result;\r
+       }\r
+\r
+       //for(i=0; i<ts->ops->read_len; i++)\r
+       //DBG("buf[%d]=0x%x\n",i,buf[i]);\r
+\r
+       //temp =  (buf[2]<<8) + buf[1];\r
+\r
+       temp = ((buf[2]&0x03) << 8) | buf[1];\r
+       for(i=0; i<ts->ops->max_point; i++)\r
+       {\r
+               if(temp & (1 << i)) \r
+                       num++;\r
+       }\r
+\r
+       event->touch_point = num;\r
+#if 0\r
+       if(event->touch_point == 0)\r
+       {       \r
+               for(i=0; i<ts->ops->max_point; i++)\r
+               {\r
+                       if(event->point[i].status != 0)\r
+                       {\r
+                               event->point[i].status = 0;                             \r
+                               input_mt_slot(ts->input_dev, event->point[i].id);                               \r
+                               input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);\r
+                               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);\r
+                               DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id);\r
+                       }\r
+               }\r
+               \r
+               input_sync(ts->input_dev);\r
+               memset(event, 0x00, sizeof(struct ts_event));\r
+                               \r
+               return 0;\r
+       }\r
+#endif \r
+       for(i = 0; i<ts->ops->max_point; i++)\r
+       {\r
+               off = 3 + i*4;\r
+               \r
+               id = i;                         \r
+               event->point[id].id = id;\r
+               event->point[id].status = temp & (1 << (ts->ops->max_point - i -1));\r
+               event->point[id].x = (unsigned int)(buf[off+0]<<8) + (unsigned int)buf[off+1];\r
+               event->point[id].y = (unsigned int)(buf[off+2]<<8) + (unsigned int)buf[off+3];\r
+               //event->point[id].press = buf[off+4];\r
+\r
+               //for(j=0; j<(3 + (i+1)*4); j++)\r
+               //DBG("buf[%d]=0x%x\n",j,buf[j]);\r
+               \r
+               if(ts->ops->xy_swap)\r
+               {\r
+                       swap(event->point[id].x, event->point[id].y);\r
+               }\r
+\r
+               if(ts->ops->x_revert)\r
+               {\r
+                       event->point[id].x = ts->ops->pixel.max_x - event->point[id].x; \r
+               }\r
+\r
+               if(ts->ops->y_revert)\r
+               {\r
+                       event->point[id].y = ts->ops->pixel.max_y - event->point[id].y;\r
+               }\r
+\r
+               DBG("%s:point[%d].status=%d,point[%d].last_status=%d\n",__func__,i,event->point[i].status,i,event->point[i].last_status);\r
+\r
+               if(event->point[id].status != 0)\r
+               {               \r
+                       input_mt_slot(ts->input_dev, event->point[id].id);\r
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);\r
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);\r
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);\r
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);\r
+                       input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); \r
+                       DBG("%s:%s press down,id=%d,x=%d,y=%d\n\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);\r
+               }\r
+               else if((event->point[id].status == 0) && (event->point[id].last_status != 0))\r
+               {\r
+                       event->point[i].status = 0;                             \r
+                       input_mt_slot(ts->input_dev, event->point[i].id);                               \r
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);\r
+                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);\r
+                       DBG("%s:%s press up,id=%d\n\n",__func__,ts->ops->name, event->point[i].id);\r
+\r
+               }\r
+               \r
+               event->point[id].last_status = event->point[id].status;\r
+       }\r
+       \r
+       input_sync(ts->input_dev);\r
+\r
+       return 0;\r
+}\r
+\r
+static int ts_suspend(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       \r
+       if(ts->pdata->irq_enable)       \r
+               disable_irq_nosync(client->irq);\r
+\r
+       if(ts->ops->active)\r
+               ts->ops->active(client, 0);\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+static int ts_resume(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+               (struct ts_private_data *) i2c_get_clientdata(client);  \r
+       struct ts_platform_data *pdata = ts->pdata;\r
+       \r
+       if(ts->pdata->irq_enable)       \r
+               enable_irq(client->irq);\r
+\r
+       if(ts->ops->active)\r
+               ts->ops->active(client, 1);\r
+       return 0;\r
+}\r
+\r
+\r
+\r
+struct ts_operate ts_gt8110_ops = {\r
+       .name                           = "gt8110",\r
+       .slave_addr                     = 0x5c,\r
+       .id_i2c                         = TS_ID_GT8110,                 //i2c id number\r
+       .pixel                          = {1280,800},\r
+       .id_reg                         = GT8110_ID_REG,\r
+       .id_data                        = TS_UNKNOW_DATA,       \r
+       .read_reg                       = GT8110_DATA_REG,              //read data\r
+       .read_len                       = 5*10+3+1,                     //data length\r
+       .trig                           = IRQ_TYPE_LEVEL_LOW | IRQF_ONESHOT,            \r
+       .max_point                      = 10,\r
+       .xy_swap                        = 0,\r
+       .x_revert                       = 0,\r
+       .y_revert                       = 0,\r
+       .range                          = {4096,4096},\r
+       .active                         = ts_active,    \r
+       .init                           = ts_init,\r
+       .report                         = ts_report_value,\r
+       .firmware                       = NULL,\r
+       .suspend                        = ts_suspend,\r
+       .resume                         = ts_resume,\r
+};\r
+\r
+/****************operate according to ts chip:end************/\r
+\r
+//function name should not be changed\r
+static struct ts_operate *ts_get_ops(void)\r
+{\r
+       return &ts_gt8110_ops;\r
+}\r
+\r
+\r
+static int __init ts_gt8110_init(void)\r
+{\r
+       struct ts_operate *ops = ts_get_ops();\r
+       int result = 0;\r
+       result = ts_register_slave(NULL, NULL, ts_get_ops);     \r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit ts_gt8110_exit(void)\r
+{\r
+       struct ts_operate *ops = ts_get_ops();\r
+       ts_unregister_slave(NULL, NULL, ts_get_ops);\r
+}\r
+\r
+\r
+subsys_initcall(ts_gt8110_init);\r
+module_exit(ts_gt8110_exit);\r
+\r
diff --git a/drivers/input/ts/ts-auto.c b/drivers/input/ts/ts-auto.c
new file mode 100644 (file)
index 0000000..ca141fb
--- /dev/null
@@ -0,0 +1,511 @@
+/* drivers/input/ts/ts-auto.c - handle all touchscreen in this file\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <linux/input/mt.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+\r
+#include <linux/ts-auto.h>\r
+\r
+\r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+struct ts_private_data *g_ts;\r
+static struct class *g_ts_class;\r
+static struct ts_operate *g_ts_ops[TS_NUM_ID]; \r
+\r
+static int ts_get_id(struct ts_operate *ops, struct i2c_client *client, int *value)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);      \r
+       int result = 0;\r
+       char temp = ops->id_reg;\r
+       int i = 0;\r
+       \r
+       DBG("%s:start\n",__func__);\r
+       if(ops->id_reg >= 0)\r
+       {\r
+               for(i=0; i<1; i++)\r
+               {\r
+                       result = ts_rx_data(client, &temp, 1);\r
+                       *value = temp;\r
+                       if(!result)\r
+                       break;\r
+               }\r
+\r
+               if(result)\r
+                       return result;\r
+               \r
+               if((ops->id_data != TS_UNKNOW_DATA)&&(ops->id_data != *value)) \r
+               {\r
+                       printk("%s:id=0x%x is not 0x%x\n",__func__,*value, ops->id_data);\r
+                       result = -1;\r
+               }\r
+                       \r
+               DBG("%s:devid=0x%x\n",__func__,*value);\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int ts_chip_init(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);      \r
+       struct ts_operate *ops = NULL;\r
+       int result = 0;\r
+       int i = 0;\r
+       \r
+       if(ts->pdata->init_platform_hw)\r
+               ts->pdata->init_platform_hw();\r
+       \r
+       for(i=TS_ID_INVALID+1; i<TS_NUM_ID; i++)\r
+       {\r
+               ops = g_ts_ops[i];\r
+               if(!ops)\r
+               {\r
+                       printk("%s:error:%p\n",__func__,ops);\r
+                       result = -1;    \r
+                       continue;\r
+               }\r
+               \r
+               if(!ops->init || !ops->report)\r
+               {\r
+                       printk("%s:error:%p,%p\n",__func__,ops->init,ops->report);\r
+                       result = -1;\r
+                       continue;\r
+               }\r
+\r
+               client->addr = ops->slave_addr; //use slave_addr of ops\r
+               \r
+               if(ops->active)\r
+               {\r
+                       result = ops->active(client, TS_ENABLE);\r
+                       if(result < 0)\r
+                       {\r
+                               printk("%s:fail to init ts\n",__func__);\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               result = ts_get_id(ops, client, &ts->devid);//get id\r
+               if(result < 0)\r
+               {       \r
+                       printk("%s:fail to read %s devid:0x%x\n",__func__, ops->name, ts->devid);       \r
+                       continue;\r
+               }\r
+       \r
+               ts->ops = ops;  //save ops\r
+\r
+               result = ops->init(client);\r
+               if(result < 0)\r
+               {\r
+                       printk("%s:fail to init ts\n",__func__);        \r
+                       continue;\r
+               }\r
+\r
+               if(ops->firmware)\r
+               {\r
+                       result = ops->firmware(client);\r
+                       if(result < 0)\r
+                       {\r
+                               printk("%s:fail to updata firmware ts\n",__func__);\r
+                               return result;\r
+                       }\r
+               }\r
+       \r
+               printk("%s:%s devid:0x%x\n",__func__, ts->ops->name, ts->devid);\r
+\r
+               break;\r
+                                       \r
+       }\r
+\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int ts_get_data(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);      \r
+       int result = 0;\r
+       \r
+       result = ts->ops->report(client);\r
+       if(result)\r
+               goto error;\r
+       \r
+error:         \r
+       return result;\r
+}\r
+\r
+\r
+static void  ts_delaywork_func(struct work_struct *work)\r
+{\r
+       struct delayed_work *delaywork = container_of(work, struct delayed_work, work);\r
+       struct ts_private_data *ts = container_of(delaywork, struct ts_private_data, delaywork);\r
+       struct i2c_client *client = ts->client;\r
+\r
+       mutex_lock(&ts->ts_mutex);      \r
+       if (ts_get_data(client) < 0) \r
+               DBG(KERN_ERR "%s: Get data failed\n",__func__);\r
+       \r
+       if(!ts->pdata->irq_enable)//restart work while polling\r
+       schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->pdata->poll_delay_ms));\r
+       //else\r
+       //{\r
+               //if((ts->ops->trig == IRQF_TRIGGER_LOW) || (ts->ops->trig == IRQF_TRIGGER_HIGH))\r
+               //enable_irq(ts->client->irq);\r
+       //}\r
+       mutex_unlock(&ts->ts_mutex);\r
+       \r
+       DBG("%s:%s\n",__func__,ts->i2c_id->name);\r
+}\r
+\r
+/*\r
+ * This is a threaded IRQ handler so can access I2C/SPI.  Since all\r
+ * interrupts are clear on read the IRQ line will be reasserted and\r
+ * the physical IRQ will be handled again if another interrupt is\r
+ * asserted while we run - in the normal course of events this is a\r
+ * rare occurrence so we save I2C/SPI reads.  We're also assuming that\r
+ * it's rare to get lots of interrupts firing simultaneously so try to\r
+ * minimise I/O.\r
+ */\r
+static irqreturn_t ts_interrupt(int irq, void *dev_id)\r
+{\r
+       struct ts_private_data *ts = (struct ts_private_data *)dev_id;\r
+\r
+       //use threaded IRQ\r
+       if (ts_get_data(ts->client) < 0) \r
+               DBG(KERN_ERR "%s: Get data failed\n",__func__);\r
+       msleep(ts->pdata->poll_delay_ms);\r
+\r
+       \r
+       //if((ts->ops->trig == IRQF_TRIGGER_LOW) || (ts->ops->trig == IRQF_TRIGGER_HIGH))\r
+       //disable_irq_nosync(irq);\r
+       //schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->pdata->poll_delay_ms));\r
+       DBG("%s:irq=%d\n",__func__,irq);\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+\r
+static int ts_irq_init(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);      \r
+       int result = 0;\r
+       int irq;\r
+       if((ts->pdata->irq_enable)&&(ts->ops->trig != TS_UNKNOW_DATA))\r
+       {\r
+               //INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);\r
+               if(ts->pdata->poll_delay_ms < 0)\r
+                       ts->pdata->poll_delay_ms = 30;\r
+               \r
+               result = gpio_request(client->irq, ts->i2c_id->name);\r
+               if (result)\r
+               {\r
+                       printk("%s:fail to request gpio :%d\n",__func__,client->irq);\r
+               }\r
+       \r
+               gpio_pull_updown(client->irq, PullEnable);\r
+               irq = gpio_to_irq(client->irq);\r
+               //result = request_irq(irq, ts_interrupt, ts->ops->trig, ts->ops->name, ts);\r
+               result = request_threaded_irq(irq, NULL, ts_interrupt, ts->ops->trig, ts->ops->name, ts);\r
+               if (result) {\r
+                       printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, irq, result);            \r
+                       goto error;            \r
+               }\r
+               client->irq = irq;\r
+               printk("%s:use irq=%d\n",__func__,irq);\r
+       }\r
+       else if(!ts->pdata->irq_enable)\r
+       {               \r
+               INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);\r
+               if(ts->pdata->poll_delay_ms < 0)\r
+                       ts->pdata->poll_delay_ms = 30;\r
+               \r
+               printk("%s:use polling,delay=%d ms\n",__func__,ts->pdata->poll_delay_ms);\r
+       }\r
+\r
+error: \r
+       return result;\r
+}\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+static void ts_suspend(struct early_suspend *h)\r
+{\r
+       struct ts_private_data *ts = \r
+                       container_of(h, struct ts_private_data, early_suspend);\r
+       \r
+       if(ts->ops->suspend)\r
+               ts->ops->suspend(ts->client);\r
+\r
+}\r
+\r
+static void ts_resume(struct early_suspend *h)\r
+{\r
+       struct ts_private_data *ts = \r
+                       container_of(h, struct ts_private_data, early_suspend);\r
+\r
+       if(ts->ops->resume)\r
+               ts->ops->resume(ts->client);\r
+}\r
+#endif\r
+\r
+\r
+\r
+int ts_register_slave(struct i2c_client *client,\r
+                       struct ts_platform_data *slave_pdata,\r
+                       struct ts_operate *(*get_ts_ops)(void))\r
+{\r
+       int result = 0;\r
+       struct ts_operate *ops = get_ts_ops();\r
+       if((ops->id_i2c >= TS_NUM_ID) || (ops->id_i2c <= TS_ID_INVALID))\r
+       {       \r
+               printk("%s:%s id is error %d\n", __func__, ops->name, ops->id_i2c);\r
+               return -1;      \r
+       }\r
+       g_ts_ops[ops->id_i2c] = ops;\r
+       printk("%s:%s,id=%d\n",__func__,g_ts_ops[ops->id_i2c]->name, ops->id_i2c);\r
+       return result;\r
+}\r
+\r
+\r
+int ts_unregister_slave(struct i2c_client *client,\r
+                       struct ts_platform_data *slave_pdata,\r
+                       struct ts_operate *(*get_ts_ops)(void))\r
+{\r
+       int result = 0;\r
+       struct ts_operate *ops = get_ts_ops();\r
+       if((ops->id_i2c >= TS_NUM_ID) || (ops->id_i2c <= TS_ID_INVALID))\r
+       {       \r
+               printk("%s:%s id is error %d\n", __func__, ops->name, ops->id_i2c);\r
+               return -1;      \r
+       }\r
+       printk("%s:%s,id=%d\n",__func__,g_ts_ops[ops->id_i2c]->name, ops->id_i2c);\r
+       g_ts_ops[ops->id_i2c] = NULL;   \r
+       return result;\r
+}\r
+\r
+\r
+int ts_probe(struct i2c_client *client, const struct i2c_device_id *devid)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       struct ts_platform_data *pdata;\r
+       int result = 0;\r
+       dev_info(&client->adapter->dev, "%s: %s,0x%x\n", __func__, devid->name,(unsigned int)client);\r
+\r
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {\r
+               result = -ENODEV;\r
+               goto out_no_free;\r
+       }\r
+\r
+       pdata = client->dev.platform_data;\r
+       if (!pdata) {\r
+               dev_err(&client->adapter->dev,\r
+                       "Missing platform data for slave %s\n", devid->name);\r
+               result = -EFAULT;\r
+               goto out_no_free;\r
+       }\r
+\r
+       ts = kzalloc(sizeof(*ts), GFP_KERNEL);\r
+       if (!ts) {\r
+               result = -ENOMEM;\r
+               goto out_no_free;\r
+       }\r
+       \r
+       i2c_set_clientdata(client, ts);\r
+       ts->client = client;    \r
+       ts->pdata = pdata;      \r
+       ts->i2c_id = (struct i2c_device_id *)devid;\r
+\r
+       mutex_init(&ts->data_mutex);    \r
+       mutex_init(&ts->ts_mutex);\r
+       mutex_init(&ts->i2c_mutex);\r
+       \r
+       result = ts_chip_init(ts->client);\r
+       if(result < 0)\r
+               goto out_free_memory;\r
+       \r
+       ts->client->addr = ts->ops->slave_addr;         \r
+       \r
+       ts->input_dev = input_allocate_device();\r
+       if (!ts->input_dev) {\r
+               result = -ENOMEM;\r
+               dev_err(&client->dev,\r
+                       "Failed to allocate input device %s\n", ts->input_dev->name);\r
+               goto out_free_memory;\r
+       }       \r
+\r
+       ts->input_dev->dev.parent = &client->dev;\r
+       ts->input_dev->name = ts->ops->name;\r
+       \r
+       result = input_register_device(ts->input_dev);\r
+       if (result) {\r
+               dev_err(&client->dev,\r
+                       "Unable to register input device %s\n", ts->input_dev->name);\r
+               goto out_input_register_device_failed;\r
+       }\r
+       \r
+       result = ts_irq_init(ts->client);\r
+       if (result) {\r
+               dev_err(&client->dev,\r
+                       "fail to init ts irq,ret=%d\n",result);\r
+               goto out_input_register_device_failed;\r
+       }\r
+       \r
+       __set_bit(EV_ABS, ts->input_dev->evbit);\r
+       __set_bit(EV_KEY, ts->input_dev->evbit);\r
+       __set_bit(EV_REP,  ts->input_dev->evbit);\r
+       __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);\r
+       set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit);\r
+       set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit);\r
+       set_bit(ABS_MT_TOUCH_MAJOR, ts->input_dev->absbit);\r
+       set_bit(ABS_MT_WIDTH_MAJOR, ts->input_dev->absbit);\r
+\r
+       if(ts->ops->max_point <= 0)\r
+               ts->ops->max_point = 1;\r
+       \r
+       input_mt_init_slots(ts->input_dev, ts->ops->max_point);\r
+
+       if((ts->ops->pixel.max_x <= 0) || (ts->ops->pixel.max_y <= 0))\r
+       {
+               ts->ops->pixel.max_x = 1024;\r
+               ts->ops->pixel.max_y = 600;\r
+       }\r
+       \r
+       input_set_abs_params(ts->input_dev,ABS_MT_POSITION_X, 0, ts->ops->range[0], 0, 0);\r
+       input_set_abs_params(ts->input_dev,ABS_MT_POSITION_Y, 0, ts->ops->range[1], 0, 0);\r
+       input_set_abs_params(ts->input_dev,ABS_MT_TOUCH_MAJOR, 0, 10, 0, 0);\r
+       input_set_abs_params(ts->input_dev,ABS_MT_WIDTH_MAJOR, 0, 10, 0, 0);\r
+       \r
+       g_ts = ts;\r
+       \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       if((ts->ops->suspend) && (ts->ops->resume))\r
+       {\r
+               ts->early_suspend.suspend = ts_suspend;\r
+               ts->early_suspend.resume = ts_resume;\r
+               ts->early_suspend.level = 0x02;\r
+               register_early_suspend(&ts->early_suspend);\r
+       }\r
+#endif\r
+\r
+       printk("%s:initialized ok,ts name:%s,devid=%d\n\n",__func__,ts->ops->name,ts->devid);\r
+\r
+       return result;\r
+       \r
+out_misc_device_register_device_failed:\r
+       input_unregister_device(ts->input_dev); \r
+out_input_register_device_failed:\r
+       input_free_device(ts->input_dev);       \r
+out_free_memory:       \r
+       kfree(ts);\r
+out_no_free:\r
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);\r
+       return result;\r
+\r
+}\r
+\r
+static void ts_shut_down(struct i2c_client *client)\r
+{\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       if((ts->ops->suspend) && (ts->ops->resume))             \r
+               unregister_early_suspend(&ts->early_suspend);\r
+       DBG("%s:%s\n",__func__,ts->i2c_id->name);\r
+#endif\r
+}\r
+\r
+static int ts_remove(struct i2c_client *client)\r
+{\r
+       struct ts_private_data *ts =\r
+           (struct ts_private_data *) i2c_get_clientdata(client);\r
+       int result = 0;\r
+       \r
+       cancel_delayed_work_sync(&ts->delaywork);\r
+       input_unregister_device(ts->input_dev); \r
+       input_free_device(ts->input_dev);       \r
+       kfree(ts);\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       if((ts->ops->suspend) && (ts->ops->resume))\r
+               unregister_early_suspend(&ts->early_suspend);\r
+#endif  \r
+       return result;\r
+}\r
+\r
+static const struct i2c_device_id ts_id_table[] = {\r
+       {"auto_ts", 0},\r
+       {},\r
+};\r
+\r
+\r
+static struct i2c_driver ts_driver = {\r
+       .probe = ts_probe,\r
+       .remove = ts_remove,\r
+       .shutdown = ts_shut_down,\r
+       .id_table = ts_id_table,\r
+       .driver = {\r
+                  .owner = THIS_MODULE,\r
+                  .name = "auto_ts",\r
+                  },\r
+};\r
+\r
+static int __init ts_init(void)\r
+{\r
+       int res = i2c_add_driver(&ts_driver);\r
+       pr_info("%s: Probe name %s\n", __func__, ts_driver.driver.name);\r
+       if (res)\r
+               pr_err("%s failed\n", __func__);\r
+       return res;\r
+}\r
+\r
+static void __exit ts_exit(void)\r
+{\r
+       pr_info("%s\n", __func__);\r
+       i2c_del_driver(&ts_driver);\r
+}\r
+\r
+subsys_initcall_sync(ts_init);\r
+module_exit(ts_exit);\r
+\r
+MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");\r
+MODULE_DESCRIPTION("User space character device interface for tss");\r
+MODULE_LICENSE("GPL");\r
+\r
diff --git a/drivers/input/ts/ts-i2c.c b/drivers/input/ts/ts-i2c.c
new file mode 100755 (executable)
index 0000000..8c00ff7
--- /dev/null
@@ -0,0 +1,233 @@
+/* drivers/input/ts/ts-i2c.c - touchscreen i2c handle\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/ts-auto.h>\r
+\r
+#define TS_I2C_RATE 200*1000\r
+\r
+#if 0\r
+#define TS_DEBUG_ENABLE\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+static int ts_i2c_write(struct i2c_adapter *i2c_adap,\r
+                           unsigned char address,\r
+                           unsigned int len, unsigned char const *data)\r
+{\r
+       struct i2c_msg msgs[1];\r
+       int res;\r
+\r
+       if (!data || !i2c_adap) {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return -EINVAL;\r
+       }\r
+\r
+       msgs[0].addr = address;\r
+       msgs[0].flags = 0;      /* write */\r
+       msgs[0].buf = (unsigned char *)data;\r
+       msgs[0].len = len;\r
+       msgs[0].scl_rate = TS_I2C_RATE;\r
+\r
+       res = i2c_transfer(i2c_adap, msgs, 1);\r
+       if (res == 1)\r
+               return 0;\r
+       else if(res == 0)\r
+               return -EBUSY;\r
+       else\r
+               return res;\r
+\r
+}\r
+\r
+static int senosr_i2c_read(struct i2c_adapter *i2c_adap,\r
+                          unsigned char address, unsigned char reg,\r
+                          unsigned int len, unsigned char *data)\r
+{\r
+       struct i2c_msg msgs[2];\r
+       int res;\r
+\r
+       if (!data || !i2c_adap) {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return -EINVAL;\r
+       }\r
+\r
+       msgs[0].addr = address;\r
+       msgs[0].flags = 0;      /* write */\r
+       msgs[0].buf = &reg;\r
+       msgs[0].len = 1;\r
+       msgs[0].scl_rate = TS_I2C_RATE;\r
+       \r
+       msgs[1].addr = address;\r
+       msgs[1].flags = I2C_M_RD;\r
+       msgs[1].buf = data;\r
+       msgs[1].len = len;\r
+       msgs[1].scl_rate = TS_I2C_RATE; \r
+\r
+       res = i2c_transfer(i2c_adap, msgs, 2);\r
+       if (res == 2)\r
+               return 0;\r
+       else if(res == 0)\r
+               return -EBUSY;\r
+       else\r
+               return res;\r
+\r
+}\r
+\r
+\r
+int ts_rx_data(struct i2c_client *client, char *rxData, int length)\r
+{\r
+#ifdef TS_DEBUG_ENABLE\r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       int i = 0;\r
+#endif\r
+       int ret = 0;\r
+       char reg = rxData[0];\r
+       ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);\r
+       \r
+#ifdef TS_DEBUG_ENABLE\r
+       DBG("addr=0x%x,len=%d,rxdata:",reg,length);\r
+       for(i=0; i<length; i++)\r
+               DBG("0x%x,",rxData[i]);\r
+       DBG("\n");\r
+#endif \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(ts_rx_data);\r
+\r
+int ts_tx_data(struct i2c_client *client, char *txData, int length)\r
+{\r
+#ifdef TS_DEBUG_ENABLE \r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       int i = 0;\r
+#endif\r
+       int ret = 0;\r
+#ifdef TS_DEBUG_ENABLE \r
+       DBG("addr=0x%x,len=%d,txdata:",txData[0],length);\r
+       for(i=1; i<length; i++)\r
+               DBG("0x%x,",txData[i]);\r
+       DBG("\n");\r
+#endif\r
+       ret = ts_i2c_write(client->adapter, client->addr, length, txData);\r
+       return ret;\r
+\r
+}\r
+EXPORT_SYMBOL(ts_tx_data);\r
+\r
+int ts_write_reg(struct i2c_client *client, int addr, int value)\r
+{\r
+       char buffer[2];\r
+       int ret = 0;\r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&ts->i2c_mutex);     \r
+       buffer[0] = addr;\r
+       buffer[1] = value;\r
+       ret = ts_tx_data(client, &buffer[0], 2);        \r
+       mutex_unlock(&ts->i2c_mutex);   \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(ts_write_reg);\r
+\r
+int ts_read_reg(struct i2c_client *client, int addr)\r
+{\r
+       char tmp[1] = {0};\r
+       int ret = 0;    \r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&ts->i2c_mutex);     \r
+       tmp[0] = addr;\r
+       ret = ts_rx_data(client, tmp, 1);\r
+       mutex_unlock(&ts->i2c_mutex);\r
+       \r
+       return tmp[0];\r
+}\r
+\r
+EXPORT_SYMBOL(ts_read_reg);\r
+\r
+\r
+int ts_tx_data_normal(struct i2c_client *client, char *buf, int num)\r
+{\r
+       int ret = 0;\r
+       ret = i2c_master_normal_send(client, buf, num, TS_I2C_RATE);\r
+       \r
+       return (ret == num) ? 0 : ret;\r
+}\r
+EXPORT_SYMBOL(ts_tx_data_normal);\r
+\r
+\r
+int ts_rx_data_normal(struct i2c_client *client, char *buf, int num)\r
+{\r
+       int ret = 0;\r
+       ret = i2c_master_normal_recv(client, buf, num, TS_I2C_RATE);\r
+       \r
+       return (ret == num) ? 0 : ret;\r
+}\r
+\r
+EXPORT_SYMBOL(ts_rx_data_normal);\r
+\r
+\r
+int ts_write_reg_normal(struct i2c_client *client, char value)\r
+{\r
+       char buffer[2];\r
+       int ret = 0;\r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&ts->i2c_mutex);     \r
+       buffer[0] = value;\r
+       ret = ts_tx_data_normal(client, &buffer[0], 1); \r
+       mutex_unlock(&ts->i2c_mutex);   \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(ts_write_reg_normal);\r
+\r
+int ts_read_reg_normal(struct i2c_client *client)\r
+{\r
+       char tmp[1] = {0};\r
+       int ret = 0;    \r
+       struct ts_private_data* ts = \r
+               (struct ts_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&ts->i2c_mutex);     \r
+       ret = ts_rx_data_normal(client, tmp, 1);\r
+       mutex_unlock(&ts->i2c_mutex);\r
+       \r
+       return tmp[0];\r
+}\r
+\r
+EXPORT_SYMBOL(ts_read_reg_normal);\r
+\r
diff --git a/include/linux/ts-auto.h b/include/linux/ts-auto.h
new file mode 100644 (file)
index 0000000..0db0658
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __TS_AUTO_H\r
+#define __TS_AUTO_H\r
+#include <linux/miscdevice.h>\r
+\r
+#define TS_ENABLE      1\r
+#define        TS_DISABLE      0\r
+#define TS_UNKNOW_DATA -1\r
+#define        TS_MAX_POINT    20\r
+\r
+enum ts_id {\r
+       TS_ID_INVALID = 0,\r
+               \r
+       TS_ID_FT5306,\r
+       TS_ID_CT360,\r
+       TS_ID_GT8110,\r
+       \r
+       TS_NUM_ID,\r
+};\r
+\r
+struct point_data {\r
+       int status;\r
+       int id;\r
+       int x;\r
+       int y;\r
+       int press;\r
+       int last_status;\r
+};\r
+\r
+struct ts_event {\r
+  int  touch_point;\r
+  struct point_data point[TS_MAX_POINT];\r
+};\r
+\r
+\r
+/* Platform data for the auto touchscreen */\r
+struct ts_platform_data {\r
+       unsigned char  slave_addr;\r
+       int irq;\r
+       int power_pin;\r
+       int reset_pin;\r
+       int irq_enable;         //if irq_enable=1 then use irq else use polling  \r
+       int poll_delay_ms;      //polling\r
+       int (*init_platform_hw)(void);  \r
+};\r
+\r
+struct ts_max_pixel{\r
+       int max_x;\r
+       int max_y;\r
+};\r
+\r
+struct ts_operate {\r
+       char *name;\r
+       char slave_addr;\r
+       int id_i2c;\r
+       struct ts_max_pixel pixel;      \r
+       int id_reg;\r
+       int id_data;\r
+       int read_reg;\r
+       int read_len;\r
+       int trig;       //intterupt trigger\r
+       int max_point;\r
+       int xy_swap;\r
+       int x_revert;\r
+       int y_revert;\r
+       int range[2];\r
+       int (*active)(struct i2c_client *client, int enable);   \r
+       int (*init)(struct i2c_client *client); \r
+       int (*report)(struct i2c_client *client);\r
+       int (*firmware)(struct i2c_client *client);\r
+       int (*suspend)(struct i2c_client *client);\r
+       int (*resume)(struct i2c_client *client);       \r
+       struct miscdevice *misc_dev;\r
+\r
+};\r
+\r
+\r
+struct ts_private_data {\r
+       struct i2c_client *client;      \r
+       struct input_dev *input_dev;\r
+       struct ts_event event;\r
+       struct work_struct work;\r
+       struct delayed_work delaywork;  /*report second event*/ \r
+       char ts_data[40];               //max support40 bytes data\r
+       struct mutex data_mutex;\r
+       struct mutex ts_mutex;\r
+       struct mutex i2c_mutex;\r
+       int devid;\r
+       struct i2c_device_id *i2c_id;\r
+       struct ts_platform_data *pdata;\r
+       struct ts_operate *ops; \r
+       struct file_operations fops;\r
+       struct miscdevice miscdev;\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       struct  early_suspend early_suspend;\r
+#endif\r
+};\r
+\r
+\r
+extern int ts_register_slave(struct i2c_client *client,\r
+                       struct ts_platform_data *slave_pdata,\r
+                       struct ts_operate *(*get_ts_ops)(void));\r
+\r
+\r
+extern int ts_unregister_slave(struct i2c_client *client,\r
+                       struct ts_platform_data *slave_pdata,\r
+                       struct ts_operate *(*get_ts_ops)(void));\r
+\r
+extern int ts_rx_data(struct i2c_client *client, char *rxData, int length);\r
+extern int ts_tx_data(struct i2c_client *client, char *txData, int length);\r
+extern int ts_write_reg(struct i2c_client *client, int addr, int value);\r
+extern int ts_read_reg(struct i2c_client *client, int addr);\r
+extern int ts_tx_data_normal(struct i2c_client *client, char *buf, int num);\r
+extern int ts_rx_data_normal(struct i2c_client *client, char *buf, int num);\r
+extern int ts_write_reg_normal(struct i2c_client *client, char value);\r
+extern int ts_read_reg_normal(struct i2c_client *client);\r
+\r
+#endif\r