rk30_phonepad:improve auto touchscreen architecturefor gt8110
authorluowei <lw@rock-chips.com>
Wed, 10 Oct 2012 12:10:37 +0000 (20:10 +0800)
committerluowei <lw@rock-chips.com>
Wed, 10 Oct 2012 12:11:31 +0000 (20:11 +0800)
drivers/input/ts/chips/ft5306.c [changed mode: 0644->0755]
drivers/input/ts/chips/gt8110.c [changed mode: 0644->0755]
drivers/input/ts/ts-auto.c [changed mode: 0644->0755]
include/linux/ts-auto.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 4c045f1..cb3a741
@@ -179,9 +179,6 @@ static int ts_suspend(struct i2c_client *client)
        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
@@ -190,15 +187,14 @@ static int ts_suspend(struct i2c_client *client)
 }\r
 \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
@@ -206,6 +202,8 @@ static int ts_resume(struct i2c_client *client)
 \r
 \r
 \r
+\r
+\r
 struct ts_operate ts_ft5306_ops = {\r
        .name                           = "ft5306",\r
        .slave_addr                     = 0x3e,\r
@@ -221,8 +219,11 @@ struct ts_operate ts_ft5306_ops = {
        .x_revert                       = 1,\r
        .y_revert                       = 0,\r
        .range                          = {1024,768},\r
+       .irq_enable                     = 1,\r
+       .poll_delay_ms                  = 0,\r
        .active                         = ts_active,    \r
        .init                           = ts_init,\r
+       .check_irq                      = NULL,\r
        .report                         = ts_report_value,\r
        .firmware                       = NULL,\r
        .suspend                        = ts_suspend,\r
old mode 100644 (file)
new mode 100755 (executable)
index 99c8097..301bb27
 #define DBG(x...)\r
 #endif\r
 \r
+#define PEN_DOWN 1\r
+#define PEN_RELEASE 0\r
+#define PEN_DOWN_UP 2  //from down to up\r
+\r
 \r
 #define GT8110_ID_REG          0x00\r
 #define GT8110_DATA_REG                0x00\r
@@ -57,7 +61,7 @@ static int ts_active(struct i2c_client *client, int enable)
        if(enable)\r
        {\r
                gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);\r
-               mdelay(200);\r
+               mdelay(10);\r
                gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);\r
                msleep(200);\r
        }\r
@@ -84,16 +88,16 @@ static int ts_init(struct i2c_client *client)
        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
+       0x65,0x02,0x00,0x10,0x00,0x10,0x0A,0x62,0x4A,0x00,
+       0x0F,0x28,0x02,0x10,0x10,0x00,0x00,0x20,0x00,0x00,
+       0x10,0x10,0x10,0x00,0x37,0x00,0x00,0x00,0x01,0x02,
+       0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,
+       0x0D,0xFF,0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
+       0x07,0x08,0x09,0x0A,0x0B,0x0C,0xFF,0xFF,0xFF,0x00,
+       0x00,0x3C,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00\r
         };\r
        int result = 0, i = 0;\r
 \r
@@ -133,6 +137,66 @@ static int ts_init(struct i2c_client *client)
        return result;\r
 }\r
 \r
+static bool goodix_get_status(char *p1,int*p2)\r
+{\r
+       bool status = PEN_DOWN;\r
+       if((*p2==PEN_DOWN) && (*p1==PEN_RELEASE))\r
+       {\r
+               *p2 = PEN_DOWN_UP; //¸Õ¸Õµ¯Æð\r
+               status = PEN_RELEASE; \r
+       }\r
+       else if((*p2==PEN_RELEASE) && (*p1==PEN_RELEASE))\r
+       {\r
+               *p2 = PEN_RELEASE;\r
+               status = PEN_RELEASE; \r
+       }\r
+       else\r
+       {\r
+               *p2 = PEN_DOWN;\r
+       }\r
+       return status;\r
+}\r
+\r
+\r
+\r
+static int ts_check_irq(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
+       int gpio_level_no_int = GPIO_HIGH;\r
+       int id = 0, i = 0;\r
+       \r
+       if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_FALLING))\r
+               gpio_level_no_int = GPIO_HIGH;\r
+       else    \r
+               gpio_level_no_int = GPIO_LOW;\r
+\r
+       if(gpio_get_value(ts->pdata->irq) == gpio_level_no_int) \r
+       {\r
+               for(i = 0; i<ts->ops->max_point; i++)\r
+               {                       \r
+                       id = i;                         \r
+                       if(event->point[id].last_status != 0)\r
+                       {\r
+                               event->point[i].last_status = PEN_RELEASE;                              \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
+               input_sync(ts->input_dev);      \r
+               memset(event, 0x00, sizeof(struct ts_event));   \r
+               enable_irq(ts->client->irq);\r
+       }\r
+       else\r
+       schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));\r
+       \r
+}\r
+\r
 \r
 static int ts_report_value(struct i2c_client *client)\r
 {\r
@@ -155,49 +219,39 @@ static int ts_report_value(struct i2c_client *client)
        //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
+       temp = (buf[1] << 8) | buf[0];\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
+               {       \r
+                       event->point[i].status = PEN_DOWN;\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
+       if(num > event->touch_point)\r
+       event->touch_point = num;\r
+\r
+       for(i = 0; i<event->touch_point; i++)\r
        {\r
-               off = 3 + i*4;\r
+               off = 2 + 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
+               \r
+               if(goodix_get_status(&event->point[id].status,&event->point[id].last_status))\r
+               {\r
+                       event->point[id].x = (unsigned int)(buf[off+1]<<8) + (unsigned int)buf[off+0];\r
+                       event->point[id].y = (unsigned int)(buf[off+3]<<8) + (unsigned int)buf[off+2];\r
+               }\r
+               \r
+               if((event->point[id].x <= 0) || (event->point[id].x >= ts->ops->range[0]) || (event->point[id].y <= 0) || (event->point[id].y >= ts->ops->range[1]))\r
+               {\r
+                       event->point[id].status = 0;\r
+                       continue;\r
+               }\r
+               //for(j=0; j<(2 + (i+1)*4); j++)\r
                //DBG("buf[%d]=0x%x\n",j,buf[j]);\r
                \r
                if(ts->ops->xy_swap)\r
@@ -215,9 +269,18 @@ static int ts_report_value(struct i2c_client *client)
                        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
+               if(event->point[id].status==PEN_DOWN_UP)\r
+               {\r
+                       event->point[id].status=PEN_RELEASE;\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 is uping,id=%d\n\n",__func__,ts->ops->name, event->point[i].id);\r
+                       continue;\r
+               }\r
+               \r
+               if(event->point[id].status==PEN_DOWN)\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
@@ -227,15 +290,6 @@ static int ts_report_value(struct i2c_client *client)
                        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
@@ -250,9 +304,6 @@ static int ts_suspend(struct i2c_client *client)
        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
@@ -267,9 +318,6 @@ static int ts_resume(struct i2c_client *client)
                (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
@@ -286,14 +334,17 @@ struct ts_operate ts_gt8110_ops = {
        .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
+       .trig                           = IRQ_TYPE_LEVEL_LOW,           \r
        .max_point                      = 10,\r
        .xy_swap                        = 0,\r
        .x_revert                       = 0,\r
        .y_revert                       = 0,\r
        .range                          = {4096,4096},\r
+       .irq_enable                     = 1,\r
+       .poll_delay_ms                  = 30,\r
        .active                         = ts_active,    \r
-       .init                           = ts_init,\r
+       .init                           = ts_init,      \r
+       .check_irq                      = ts_check_irq,\r
        .report                         = ts_report_value,\r
        .firmware                       = NULL,\r
        .suspend                        = ts_suspend,\r
old mode 100644 (file)
new mode 100755 (executable)
index ca141fb..2eff50e
@@ -184,13 +184,20 @@ static void  ts_delaywork_func(struct work_struct *work)
        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
+       if(!ts->ops->irq_enable)//restart work while polling\r
+       schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));\r
+       else\r
+       {\r
+               if(ts->ops->check_irq)\r
+               {\r
+                       ts->ops->check_irq(client);             \r
+               }\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
+       }\r
        mutex_unlock(&ts->ts_mutex);\r
        \r
        DBG("%s:%s\n",__func__,ts->i2c_id->name);\r
@@ -210,14 +217,19 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id)
        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
+       //if (ts_get_data(ts->client) < 0) \r
+       //      DBG(KERN_ERR "%s: Get data failed\n",__func__);\r
+       //msleep(ts->ops->poll_delay_ms);\r
+       if(ts->ops->check_irq)\r
+       {\r
+               disable_irq_nosync(irq);\r
+       }\r
+       else\r
+       {\r
+               if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_HIGH))\r
+               disable_irq_nosync(irq);\r
+       }\r
+       schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));\r
        DBG("%s:irq=%d\n",__func__,irq);\r
        return IRQ_HANDLED;\r
 }\r
@@ -229,11 +241,11 @@ static int ts_irq_init(struct i2c_client *client)
            (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
+       if((ts->ops->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
+               INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);\r
+               if(ts->ops->poll_delay_ms < 0)\r
+                       ts->ops->poll_delay_ms = 30;\r
                \r
                result = gpio_request(client->irq, ts->i2c_id->name);\r
                if (result)\r
@@ -243,8 +255,8 @@ static int ts_irq_init(struct i2c_client *client)
        \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
+               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
@@ -252,13 +264,14 @@ static int ts_irq_init(struct i2c_client *client)
                client->irq = irq;\r
                printk("%s:use irq=%d\n",__func__,irq);\r
        }\r
-       else if(!ts->pdata->irq_enable)\r
+       else if(!ts->ops->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
+               if(ts->ops->poll_delay_ms < 0)\r
+                       ts->ops->poll_delay_ms = 30;\r
                \r
-               printk("%s:use polling,delay=%d ms\n",__func__,ts->pdata->poll_delay_ms);\r
+               schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));\r
+               printk("%s:use polling,delay=%d ms\n",__func__,ts->ops->poll_delay_ms);\r
        }\r
 \r
 error: \r
@@ -274,6 +287,11 @@ static void ts_suspend(struct early_suspend *h)
        if(ts->ops->suspend)\r
                ts->ops->suspend(ts->client);\r
 \r
+       if(ts->ops->irq_enable) \r
+               disable_irq_nosync(ts->client->irq);\r
+       else\r
+               cancel_delayed_work_sync(&ts->delaywork);       \r
+\r
 }\r
 \r
 static void ts_resume(struct early_suspend *h)\r
@@ -283,6 +301,14 @@ static void ts_resume(struct early_suspend *h)
 \r
        if(ts->ops->resume)\r
                ts->ops->resume(ts->client);\r
+\r
+       if(ts->ops->irq_enable) \r
+               enable_irq(ts->client->irq);\r
+       else\r
+       {\r
+               PREPARE_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);\r
+               schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));\r
+       }\r
 }\r
 #endif\r
 \r
old mode 100644 (file)
new mode 100755 (executable)
index 0db0658..c5af819
@@ -38,8 +38,7 @@ struct ts_platform_data {
        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
+\r
        int (*init_platform_hw)(void);  \r
 };\r
 \r
@@ -63,8 +62,12 @@ struct ts_operate {
        int x_revert;\r
        int y_revert;\r
        int range[2];\r
+       int irq_enable;         //if irq_enable=1 then use irq else use polling  \r
+       int poll_delay_ms;      //polling\r
+       int gpio_level_no_int;\r
        int (*active)(struct i2c_client *client, int enable);   \r
        int (*init)(struct i2c_client *client); \r
+       int (*check_irq)(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
@@ -79,7 +82,8 @@ struct ts_private_data {
        struct input_dev *input_dev;\r
        struct ts_event event;\r
        struct work_struct work;\r
-       struct delayed_work delaywork;  /*report second event*/ \r
+       struct delayed_work delaywork;  /*report second event*/\r
+       struct delayed_work poll_work;  /*poll at last*/        \r
        char ts_data[40];               //max support40 bytes data\r
        struct mutex data_mutex;\r
        struct mutex ts_mutex;\r