From 901c0ecbc5c40e27a98df205b360f4b2ddd9d6e0 Mon Sep 17 00:00:00 2001 From: luowei Date: Wed, 10 Oct 2012 20:10:37 +0800 Subject: [PATCH] rk30_phonepad:improve auto touchscreen architecturefor gt8110 --- drivers/input/ts/chips/ft5306.c | 13 +-- drivers/input/ts/chips/gt8110.c | 177 ++++++++++++++++++++------------ drivers/input/ts/ts-auto.c | 76 +++++++++----- include/linux/ts-auto.h | 10 +- 4 files changed, 179 insertions(+), 97 deletions(-) mode change 100644 => 100755 drivers/input/ts/chips/ft5306.c mode change 100644 => 100755 drivers/input/ts/chips/gt8110.c mode change 100644 => 100755 drivers/input/ts/ts-auto.c mode change 100644 => 100755 include/linux/ts-auto.h diff --git a/drivers/input/ts/chips/ft5306.c b/drivers/input/ts/chips/ft5306.c old mode 100644 new mode 100755 index 4c045f15be9f..cb3a7417f0d6 --- a/drivers/input/ts/chips/ft5306.c +++ b/drivers/input/ts/chips/ft5306.c @@ -179,9 +179,6 @@ static int ts_suspend(struct i2c_client *client) struct ts_private_data *ts = (struct ts_private_data *) i2c_get_clientdata(client); struct ts_platform_data *pdata = ts->pdata; - - if(ts->pdata->irq_enable) - disable_irq_nosync(client->irq); if(ts->ops->active) ts->ops->active(client, 0); @@ -190,15 +187,14 @@ static int ts_suspend(struct i2c_client *client) } + + static int ts_resume(struct i2c_client *client) { struct ts_private_data *ts = (struct ts_private_data *) i2c_get_clientdata(client); struct ts_platform_data *pdata = ts->pdata; - if(ts->pdata->irq_enable) - enable_irq(client->irq); - if(ts->ops->active) ts->ops->active(client, 1); return 0; @@ -206,6 +202,8 @@ static int ts_resume(struct i2c_client *client) + + struct ts_operate ts_ft5306_ops = { .name = "ft5306", .slave_addr = 0x3e, @@ -221,8 +219,11 @@ struct ts_operate ts_ft5306_ops = { .x_revert = 1, .y_revert = 0, .range = {1024,768}, + .irq_enable = 1, + .poll_delay_ms = 0, .active = ts_active, .init = ts_init, + .check_irq = NULL, .report = ts_report_value, .firmware = NULL, .suspend = ts_suspend, diff --git a/drivers/input/ts/chips/gt8110.c b/drivers/input/ts/chips/gt8110.c old mode 100644 new mode 100755 index 99c8097c33d8..301bb273d838 --- a/drivers/input/ts/chips/gt8110.c +++ b/drivers/input/ts/chips/gt8110.c @@ -40,6 +40,10 @@ #define DBG(x...) #endif +#define PEN_DOWN 1 +#define PEN_RELEASE 0 +#define PEN_DOWN_UP 2 //from down to up + #define GT8110_ID_REG 0x00 #define GT8110_DATA_REG 0x00 @@ -57,7 +61,7 @@ static int ts_active(struct i2c_client *client, int enable) if(enable) { gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW); - mdelay(200); + mdelay(10); gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH); msleep(200); } @@ -84,16 +88,16 @@ static int ts_init(struct i2c_client *client) int irq_pin = irq_to_gpio(ts->pdata->irq); char version_data[18] = {240}; char init_data[95] = { - 0x65,0x02,0x00,0x10,0x00,0x10,0x0A,0x6E,0x0A,0x00, - 0x0F,0x1E,0x02,0x08,0x10,0x00,0x00,0x27,0x00,0x00, - 0x50,0x10,0x10,0x11,0x37,0x00,0x00,0x00,0x01,0x02, - 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0xFF, - 0xFF,0xFF,0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, - 0x07,0x08,0x09,0x0A,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, - 0x00,0x50,0x64,0x50,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,0x20 + 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 }; int result = 0, i = 0; @@ -133,6 +137,66 @@ static int ts_init(struct i2c_client *client) return result; } +static bool goodix_get_status(char *p1,int*p2) +{ + bool status = PEN_DOWN; + if((*p2==PEN_DOWN) && (*p1==PEN_RELEASE)) + { + *p2 = PEN_DOWN_UP; //¸Õ¸Õµ¯Æð + status = PEN_RELEASE; + } + else if((*p2==PEN_RELEASE) && (*p1==PEN_RELEASE)) + { + *p2 = PEN_RELEASE; + status = PEN_RELEASE; + } + else + { + *p2 = PEN_DOWN; + } + return status; +} + + + +static int ts_check_irq(struct i2c_client *client) +{ + struct ts_private_data *ts = + (struct ts_private_data *) i2c_get_clientdata(client); + struct ts_platform_data *pdata = ts->pdata; + struct ts_event *event = &ts->event; + int gpio_level_no_int = GPIO_HIGH; + int id = 0, i = 0; + + if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_FALLING)) + gpio_level_no_int = GPIO_HIGH; + else + gpio_level_no_int = GPIO_LOW; + + if(gpio_get_value(ts->pdata->irq) == gpio_level_no_int) + { + for(i = 0; iops->max_point; i++) + { + id = i; + if(event->point[id].last_status != 0) + { + event->point[i].last_status = PEN_RELEASE; + input_mt_slot(ts->input_dev, event->point[i].id); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + DBG("%s:%s press up,id=%d\n\n",__func__,ts->ops->name, event->point[i].id); + } + } + + input_sync(ts->input_dev); + memset(event, 0x00, sizeof(struct ts_event)); + enable_irq(ts->client->irq); + } + else + schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms)); + +} + static int ts_report_value(struct i2c_client *client) { @@ -155,49 +219,39 @@ static int ts_report_value(struct i2c_client *client) //for(i=0; iops->read_len; i++) //DBG("buf[%d]=0x%x\n",i,buf[i]); - //temp = (buf[2]<<8) + buf[1]; + temp = (buf[1] << 8) | buf[0]; - temp = ((buf[2]&0x03) << 8) | buf[1]; for(i=0; iops->max_point; i++) { if(temp & (1 << i)) + { + event->point[i].status = PEN_DOWN; num++; - } - - event->touch_point = num; -#if 0 - if(event->touch_point == 0) - { - for(i=0; iops->max_point; i++) - { - if(event->point[i].status != 0) - { - event->point[i].status = 0; - input_mt_slot(ts->input_dev, event->point[i].id); - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); - DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id); - } } - - input_sync(ts->input_dev); - memset(event, 0x00, sizeof(struct ts_event)); - - return 0; } -#endif - for(i = 0; iops->max_point; i++) + + if(num > event->touch_point) + event->touch_point = num; + + for(i = 0; itouch_point; i++) { - off = 3 + i*4; + off = 2 + i*4; id = i; event->point[id].id = id; - event->point[id].status = temp & (1 << (ts->ops->max_point - i -1)); - event->point[id].x = (unsigned int)(buf[off+0]<<8) + (unsigned int)buf[off+1]; - event->point[id].y = (unsigned int)(buf[off+2]<<8) + (unsigned int)buf[off+3]; - //event->point[id].press = buf[off+4]; - - //for(j=0; j<(3 + (i+1)*4); j++) + + if(goodix_get_status(&event->point[id].status,&event->point[id].last_status)) + { + event->point[id].x = (unsigned int)(buf[off+1]<<8) + (unsigned int)buf[off+0]; + event->point[id].y = (unsigned int)(buf[off+3]<<8) + (unsigned int)buf[off+2]; + } + + 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])) + { + event->point[id].status = 0; + continue; + } + //for(j=0; j<(2 + (i+1)*4); j++) //DBG("buf[%d]=0x%x\n",j,buf[j]); if(ts->ops->xy_swap) @@ -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; } - DBG("%s:point[%d].status=%d,point[%d].last_status=%d\n",__func__,i,event->point[i].status,i,event->point[i].last_status); - - if(event->point[id].status != 0) + + if(event->point[id].status==PEN_DOWN_UP) + { + event->point[id].status=PEN_RELEASE; + input_mt_slot(ts->input_dev, event->point[i].id); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + DBG("%s:%s press is uping,id=%d\n\n",__func__,ts->ops->name, event->point[i].id); + continue; + } + + if(event->point[id].status==PEN_DOWN) { input_mt_slot(ts->input_dev, event->point[id].id); input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id); @@ -227,15 +290,6 @@ static int ts_report_value(struct i2c_client *client) input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); 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); } - else if((event->point[id].status == 0) && (event->point[id].last_status != 0)) - { - event->point[i].status = 0; - input_mt_slot(ts->input_dev, event->point[i].id); - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); - DBG("%s:%s press up,id=%d\n\n",__func__,ts->ops->name, event->point[i].id); - - } event->point[id].last_status = event->point[id].status; } @@ -250,9 +304,6 @@ static int ts_suspend(struct i2c_client *client) struct ts_private_data *ts = (struct ts_private_data *) i2c_get_clientdata(client); struct ts_platform_data *pdata = ts->pdata; - - if(ts->pdata->irq_enable) - disable_irq_nosync(client->irq); if(ts->ops->active) ts->ops->active(client, 0); @@ -267,9 +318,6 @@ static int ts_resume(struct i2c_client *client) (struct ts_private_data *) i2c_get_clientdata(client); struct ts_platform_data *pdata = ts->pdata; - if(ts->pdata->irq_enable) - enable_irq(client->irq); - if(ts->ops->active) ts->ops->active(client, 1); return 0; @@ -286,14 +334,17 @@ struct ts_operate ts_gt8110_ops = { .id_data = TS_UNKNOW_DATA, .read_reg = GT8110_DATA_REG, //read data .read_len = 5*10+3+1, //data length - .trig = IRQ_TYPE_LEVEL_LOW | IRQF_ONESHOT, + .trig = IRQ_TYPE_LEVEL_LOW, .max_point = 10, .xy_swap = 0, .x_revert = 0, .y_revert = 0, .range = {4096,4096}, + .irq_enable = 1, + .poll_delay_ms = 30, .active = ts_active, - .init = ts_init, + .init = ts_init, + .check_irq = ts_check_irq, .report = ts_report_value, .firmware = NULL, .suspend = ts_suspend, diff --git a/drivers/input/ts/ts-auto.c b/drivers/input/ts/ts-auto.c old mode 100644 new mode 100755 index ca141fb66b29..2eff50e2748f --- a/drivers/input/ts/ts-auto.c +++ b/drivers/input/ts/ts-auto.c @@ -184,13 +184,20 @@ static void ts_delaywork_func(struct work_struct *work) if (ts_get_data(client) < 0) DBG(KERN_ERR "%s: Get data failed\n",__func__); - if(!ts->pdata->irq_enable)//restart work while polling - schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->pdata->poll_delay_ms)); - //else - //{ - //if((ts->ops->trig == IRQF_TRIGGER_LOW) || (ts->ops->trig == IRQF_TRIGGER_HIGH)) - //enable_irq(ts->client->irq); - //} + if(!ts->ops->irq_enable)//restart work while polling + schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms)); + else + { + if(ts->ops->check_irq) + { + ts->ops->check_irq(client); + } + else + { + if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_HIGH)) + enable_irq(ts->client->irq); + } + } mutex_unlock(&ts->ts_mutex); DBG("%s:%s\n",__func__,ts->i2c_id->name); @@ -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; //use threaded IRQ - if (ts_get_data(ts->client) < 0) - DBG(KERN_ERR "%s: Get data failed\n",__func__); - msleep(ts->pdata->poll_delay_ms); - - - //if((ts->ops->trig == IRQF_TRIGGER_LOW) || (ts->ops->trig == IRQF_TRIGGER_HIGH)) - //disable_irq_nosync(irq); - //schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->pdata->poll_delay_ms)); + //if (ts_get_data(ts->client) < 0) + // DBG(KERN_ERR "%s: Get data failed\n",__func__); + //msleep(ts->ops->poll_delay_ms); + if(ts->ops->check_irq) + { + disable_irq_nosync(irq); + } + else + { + if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_HIGH)) + disable_irq_nosync(irq); + } + schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms)); DBG("%s:irq=%d\n",__func__,irq); return IRQ_HANDLED; } @@ -229,11 +241,11 @@ static int ts_irq_init(struct i2c_client *client) (struct ts_private_data *) i2c_get_clientdata(client); int result = 0; int irq; - if((ts->pdata->irq_enable)&&(ts->ops->trig != TS_UNKNOW_DATA)) + if((ts->ops->irq_enable)&&(ts->ops->trig != TS_UNKNOW_DATA)) { - //INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func); - if(ts->pdata->poll_delay_ms < 0) - ts->pdata->poll_delay_ms = 30; + INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func); + if(ts->ops->poll_delay_ms < 0) + ts->ops->poll_delay_ms = 30; result = gpio_request(client->irq, ts->i2c_id->name); if (result) @@ -243,8 +255,8 @@ static int ts_irq_init(struct i2c_client *client) gpio_pull_updown(client->irq, PullEnable); irq = gpio_to_irq(client->irq); - //result = request_irq(irq, ts_interrupt, ts->ops->trig, ts->ops->name, ts); - result = request_threaded_irq(irq, NULL, ts_interrupt, ts->ops->trig, ts->ops->name, ts); + result = request_irq(irq, ts_interrupt, ts->ops->trig, ts->ops->name, ts); + //result = request_threaded_irq(irq, NULL, ts_interrupt, ts->ops->trig, ts->ops->name, ts); if (result) { printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, irq, result); goto error; @@ -252,13 +264,14 @@ static int ts_irq_init(struct i2c_client *client) client->irq = irq; printk("%s:use irq=%d\n",__func__,irq); } - else if(!ts->pdata->irq_enable) + else if(!ts->ops->irq_enable) { INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func); - if(ts->pdata->poll_delay_ms < 0) - ts->pdata->poll_delay_ms = 30; + if(ts->ops->poll_delay_ms < 0) + ts->ops->poll_delay_ms = 30; - printk("%s:use polling,delay=%d ms\n",__func__,ts->pdata->poll_delay_ms); + schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms)); + printk("%s:use polling,delay=%d ms\n",__func__,ts->ops->poll_delay_ms); } error: @@ -274,6 +287,11 @@ static void ts_suspend(struct early_suspend *h) if(ts->ops->suspend) ts->ops->suspend(ts->client); + if(ts->ops->irq_enable) + disable_irq_nosync(ts->client->irq); + else + cancel_delayed_work_sync(&ts->delaywork); + } static void ts_resume(struct early_suspend *h) @@ -283,6 +301,14 @@ static void ts_resume(struct early_suspend *h) if(ts->ops->resume) ts->ops->resume(ts->client); + + if(ts->ops->irq_enable) + enable_irq(ts->client->irq); + else + { + PREPARE_DELAYED_WORK(&ts->delaywork, ts_delaywork_func); + schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms)); + } } #endif diff --git a/include/linux/ts-auto.h b/include/linux/ts-auto.h old mode 100644 new mode 100755 index 0db065805be7..c5af819f39f4 --- a/include/linux/ts-auto.h +++ b/include/linux/ts-auto.h @@ -38,8 +38,7 @@ struct ts_platform_data { int irq; int power_pin; int reset_pin; - int irq_enable; //if irq_enable=1 then use irq else use polling - int poll_delay_ms; //polling + int (*init_platform_hw)(void); }; @@ -63,8 +62,12 @@ struct ts_operate { int x_revert; int y_revert; int range[2]; + int irq_enable; //if irq_enable=1 then use irq else use polling + int poll_delay_ms; //polling + int gpio_level_no_int; int (*active)(struct i2c_client *client, int enable); int (*init)(struct i2c_client *client); + int (*check_irq)(struct i2c_client *client); int (*report)(struct i2c_client *client); int (*firmware)(struct i2c_client *client); int (*suspend)(struct i2c_client *client); @@ -79,7 +82,8 @@ struct ts_private_data { struct input_dev *input_dev; struct ts_event event; struct work_struct work; - struct delayed_work delaywork; /*report second event*/ + struct delayed_work delaywork; /*report second event*/ + struct delayed_work poll_work; /*poll at last*/ char ts_data[40]; //max support40 bytes data struct mutex data_mutex; struct mutex ts_mutex; -- 2.34.1