From 0b3b1d8c29668a929a2cad4e949866f4bbeff167 Mon Sep 17 00:00:00 2001 From: hhb <hhb@rock-chips.com> Date: Fri, 24 Jun 2011 15:00:49 +0800 Subject: [PATCH] rk29:touch screen -> modify tp suspend and resume function which would really work --- drivers/input/touchscreen/gt818_ts.c | 125 ++++++++++----------------- drivers/input/touchscreen/gt818_ts.h | 3 +- 2 files changed, 45 insertions(+), 83 deletions(-) diff --git a/drivers/input/touchscreen/gt818_ts.c b/drivers/input/touchscreen/gt818_ts.c index e5e59d3b1a88..1b2b943cfd58 100644 --- a/drivers/input/touchscreen/gt818_ts.c +++ b/drivers/input/touchscreen/gt818_ts.c @@ -1,10 +1,18 @@ /* drivers/input/touchscreen/gt818_ts.c * - * Copyright (C) 2011 Goodix, Inc. + * Copyright (C) 2011 Rockcip, Inc. * - * Author: Felix - * Date: 2011.04.28 + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. * + * 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. + * + * Author: hhb@rock-chips.com + * Date: 2011.06.20 */ #include <linux/kernel.h> #include <linux/module.h> @@ -79,14 +87,14 @@ static int i2c_read_bytes(struct i2c_client *client, u8 *buf, int len) msgs[0].flags = client->flags; msgs[0].len = 2; msgs[0].buf = &buf[0]; - msgs[0].scl_rate = 600*1000; + msgs[0].scl_rate = GT818_I2C_SCL; msgs[0].udelay = client->udelay; msgs[1].addr = client->addr; msgs[1].flags = client->flags | I2C_M_RD; msgs[1].len = len-2; msgs[1].buf = &buf[2]; - msgs[1].scl_rate = 600*1000; + msgs[1].scl_rate = GT818_I2C_SCL; //msgs[1].udelay = client->udelay; ret = i2c_transfer(client->adapter, msgs, 2); @@ -95,11 +103,6 @@ static int i2c_read_bytes(struct i2c_client *client, u8 *buf, int len) return ret; } -/******************************************************* -éç»å é� éæç² éååéçåµ -éåæé� client: i2cçæ§î¸éå±½å¯éî¥î澶å§æ¹´é§ï¿½ buf[0]éï¿½æ££æ §ç§éºåè´éæ¬æ¹´é§ï¿½ buf[1]~buf[len]éæ°æé¹î¾ç´¦éæå°¯ - lené�éçåµéå®å®³ -returné� éµÑîå¨å ä¼ é�*******************************************************/ /*Function as i2c_master_send */ static int i2c_write_bytes(struct i2c_client *client,u8 *data,int len) { @@ -110,7 +113,7 @@ static int i2c_write_bytes(struct i2c_client *client,u8 *data,int len) msg.flags = client->flags; //éæ¬ç§·é� msg.len = len; msg.buf = data; - msg.scl_rate = 600*1000; + msg.scl_rate = GT818_I2C_SCL; //msg.udelay = client->udelay; ret = i2c_transfer(client->adapter, &msg, 1); if(ret < 0) @@ -118,12 +121,7 @@ static int i2c_write_bytes(struct i2c_client *client,u8 *data,int len) return ret; } -/******************************************************* -éç»å é� éæ¦ï¿½éå¶ç´éææ¤ - ts: clientç»ä½¹æ¹éçåµç¼æ´ç¯æµ£ï¿½returné� - éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -*******************************************************/ static int i2c_pre_cmd(struct gt818_ts_data *ts) { int ret; @@ -135,12 +133,7 @@ static int i2c_pre_cmd(struct gt818_ts_data *ts) return ret; } -/******************************************************* -éç»å é� éæ¦ï¿½é庣ç´éææ¤ - ts: clientç»ä½¹æ¹éçåµç¼æ´ç¯æµ£ï¿½returné� - éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -*******************************************************/ static int i2c_end_cmd(struct gt818_ts_data *ts) { int ret; @@ -153,16 +146,14 @@ static int i2c_end_cmd(struct gt818_ts_data *ts) } -/******************************************************* -éç»å é� Guitaréæ¿îéæ §å±é帮ç´é¢ã¤ç°¬éæ¦ï¿½é°å¶çæ·âä¼ éå²å¹éæ «å¢éî¿ä¿é�éåæé� ts: clientç»ä½¹æ¹éçåµç¼æ´ç¯æµ£ï¿½returné� éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -*******************************************************/ + static int goodix_init_panel(struct gt818_ts_data *ts) { int ret = -1; // unsigned char i2c_control_buf[3] = {0x06,0x92,0x03}; #if 1 - u8 config_info[] = { //Touch key devlop board + u8 config_info[] = { 0x06,0xA2, 0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E, 0x10,0x12,0x00,0x00,0x10,0x00,0x20,0x00, @@ -211,10 +202,7 @@ static int goodix_init_panel(struct gt818_ts_data *ts) } -/******************************************************* -éç»å é� é¾å³°å½éå æ¹°æ·âä¼ -éåæé� ts: clientç»ä½¹æ¹éçåµç¼æ´ç¯æµ£ï¿½returné� éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -*******************************************************/ + static int goodix_read_version(struct gt818_ts_data *ts) { int ret; @@ -261,7 +249,6 @@ static void goodix_ts_work_func(struct work_struct *work) ret = i2c_read_bytes(ts->client, touch_status, sizeof(touch_status)/sizeof(touch_status[0])); if(ret <= 0) { - for(retry = 0; retry < 3; retry++) { ret = i2c_pre_cmd(ts); @@ -280,16 +267,15 @@ static void goodix_ts_work_func(struct work_struct *work) i2c_read_bytes(ts->client, touch_status, sizeof(touch_status)/sizeof(touch_status[0])); } } - + //judge whether the data is ready if((touch_status[2] & 0x30) != 0x20) { printk("%s:DATA_NO_READY\n", __func__); goto DATA_NO_READY; } - + //judge whether it is large area touch if(touch_status[13] & 0x0f) { - //printk("%s:touch area is too large\n", __func__); goto DATA_NO_READY; } @@ -298,10 +284,8 @@ static void goodix_ts_work_func(struct work_struct *work) key_value = touch_status + 15; key = key_value[2] & 0x0f; -// printk("finger:%d\n", finger); if(finger > 0) { - //printk("e\n"); point_data = key_value + 3; for(position = 0; position < (finger*8); position += 8) @@ -337,7 +321,6 @@ static void goodix_ts_work_func(struct work_struct *work) coor_point = (u16 *)coor_data; - //printk("%\n"); for(position = 1; position < MAX_FINGER_NUM + 1; position++) { //printk("%s:positon:%d\n", __func__, position); @@ -356,8 +339,6 @@ static void goodix_ts_work_func(struct work_struct *work) x = (*(coor_point+3*(position-1)))*SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH); y = (*(coor_point+3*(position-1)+1))*SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT); pressure = (*(coor_point+3*(position-1)+2)); - //printk("pressure:%d\n", pressure); - if(x < SCREEN_MAX_WIDTH){ x = SCREEN_MAX_WIDTH - x; } @@ -372,8 +353,6 @@ static void goodix_ts_work_func(struct work_struct *work) input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, pressure); input_mt_sync(ts->input_dev); syn_flag = 1; - //printk("position%d: x:%d y:%d\n",position, x, y); - //printk("$\n"); } } @@ -431,9 +410,7 @@ XFER_ERROR: } -/******************************************************* -éç»å é� çâæ¤é£ã¥æ·æ´æ¿å±é� é¢è¾«î ¸éè·ºæ«çï¹å½éå²çæ´ï¹Ðé½ç¨¿ç宸ã¤ç¶éè¥ææ©æ¯îéæ¶ç®£é庨å¸éæî ¸é�éåæé� timeréæ°¬å±éæ¿å§é±ææ®çâæ¤é£ï¿½ -returné� çâæ¤é£ã¥ä¼æµ£æ»Ä寮忥ç´HRTIMER_NORESTARTçã§ãæ¶å¶æ¸¶çä½½åéã©å¸é�********************************************************/ + static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer) { struct gt818_ts_data *ts = container_of(timer, struct gt818_ts_data, timer); @@ -442,10 +419,7 @@ static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer) return HRTIMER_NORESTART; } -/******************************************************* -éç»å é� æ¶î æéå¶ ç°²éè¥æ - é¢åè éî ¡Ðéæ¯ç´çå¨å®³ç︽æçå¿îµéåå±éæç¹ç�éåæé� timeréæ°¬å±éæ¿å§é±ææ®çâæ¤é£ï¿½ -returné� çâæ¤é£ã¥ä¼æµ£æ»Ä寮忥ç´HRTIMER_NORESTARTçã§ãæ¶å¶æ¸¶çä½½åéã©å¸é�********************************************************/ + static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) { struct gt818_ts_data *ts = dev_id; @@ -454,17 +428,12 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -/******************************************************* -éç»å é� ç» ï¼æGT801é¨åæ¸å©§æ¶ç´éä½½îGT801 PLUSæ©æ¶åé«ï¼æ¹¢é´æ §ç¢éè·ºæé±ï¿½éåæé� -on: 0çã§ãæµ£è¯å é«ï¼æ¹¢é�æ¶åæé±ï¿½returné� éîæçå§çé´æ¬å§é�æ¶çåé� -é¿æ¬î¤é®ä¾ç´°-1æ¶ç¯¿2cé¿æ¬î¤é�2æ¶ç¯PIOé¿æ¬î¤é�EINVALæ¶å弬éçné¿æ¬î¤ -********************************************************/ -//#if defined(INT_PORT) static int goodix_ts_power(struct gt818_ts_data * ts, int on) { int ret = -1; struct gt818_platform_data *pdata = ts->client->dev.platform_data; unsigned char i2c_control_buf[3] = {0x06,0x92,0x01}; //suspend cmd + unsigned char i2c_config_buf[3] = {0x06,0x92,0x01}; #ifdef INT_PORT if(ts != NULL && !ts->use_irq) @@ -474,6 +443,10 @@ static int goodix_ts_power(struct gt818_ts_data * ts, int on) { case 0: i2c_pre_cmd(ts); + // set the io port high level to avoid level change which might stop gt818 from sleeping + gpio_direction_output(pdata->gpio_reset, 1); + gpio_direction_output(pdata->gpio_pendown, 1); + msleep(5); ret = i2c_write_bytes(ts->client, i2c_control_buf, 3); if(ret < 0) { @@ -488,9 +461,13 @@ static int goodix_ts_power(struct gt818_ts_data * ts, int on) return ret; case 1: + gpio_direction_input(pdata->gpio_pendown); + gpio_pull_updown(pdata->gpio_pendown, 0); + msleep(2); gpio_direction_output(pdata->gpio_reset, 0); msleep(2); gpio_direction_input(pdata->gpio_reset); + gpio_pull_updown(pdata->gpio_reset, 0); msleep(30); ret = i2c_pre_cmd(ts); @@ -500,6 +477,7 @@ static int goodix_ts_power(struct gt818_ts_data * ts, int on) else{ printk(KERN_INFO"**gt818 resume fail**\n"); } + return ret; default: @@ -508,12 +486,8 @@ static int goodix_ts_power(struct gt818_ts_data * ts, int on) } } -/******************************************************* -éç»å é� ç︽æçå¿å¸°å¨´å¬ªå±é� é¦ã¦æéå²âéã¦æ¤çåªæ¤(çä½¹ç°ç樺湪çµç°ç°²é¨å¢lient)é� é¢ã¤ç°¬IO,æ¶î æç»å¤ç¥«å©§æ®æµçå¤ç´±çæ§î¸å¨ã¥å½éæ¶Ðé½ç¨¿çéæ¿îéæ «ç宸ã¤ç¶ -éåæé� clientéæ°¬ç·æ¤¹å姩é¨å®î澶å©ç²¨éåªç¶ - idéæ°³î澶åD -returné� éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -********************************************************/ + + static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; @@ -562,7 +536,7 @@ static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id } rk29_mux_api_set(pdata->resetpin_iomux_name, pdata->resetpin_iomux_mode); #if 1 - for(retry = 0; retry < 3; retry++) + for(retry = 0; retry < 4; retry++) { gpio_direction_output(pdata->gpio_reset, 0); msleep(2); @@ -587,13 +561,13 @@ static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id ret = goodix_init_panel(ts); dev_info(&client->dev,"the config ret is :%d\n", ret); msleep(20); - if(ret != 0) //Initiall failed + if(ret < 0) //Initiall failed continue; else break; } - if(ret != 0) { + if(ret < 0) { ts->bad_data = 1; goto err_init_godix_ts; } @@ -668,7 +642,7 @@ static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH #endif - ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE, + ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE, client->name, ts); if (ret != 0) { dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret); @@ -736,11 +710,6 @@ err_create_proc_entry: } -/******************************************************* -éç»å é� 椹å姩ç§å¬ç°®é²å©æ -éåæé� clientéæ°³î澶å©ç²¨éåªç¶ -returné� éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -********************************************************/ static int goodix_ts_remove(struct i2c_client *client) { struct gt818_ts_data *ts = i2c_get_clientdata(client); @@ -770,7 +739,7 @@ static int goodix_ts_remove(struct i2c_client *client) return 0; } -//éæ» æ¤çæ§î¸ + static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg) { int ret; @@ -783,7 +752,7 @@ static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg) //ret = cancel_work_sync(&ts->work); //if(ret && ts->use_irq) //enable_irq(client->irq); - if (ts->power) { /* è¹å´ãé¦ã¥å½å¨åµorké庡åéµÑîéå²ä¼©éå¶ æ´GPIOçµè°å§é§æç£æ¾¶åææµ ï½çå§è¯²æé�*/ + if (ts->power) { ret = ts->power(ts, 0); if (ret < 0) printk(KERN_ERR "goodix_ts_resume power off failed\n"); @@ -791,7 +760,7 @@ static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } -//é²å¶æéãå + static int goodix_ts_resume(struct i2c_client *client) { int ret; @@ -828,14 +797,13 @@ static void goodix_ts_late_resume(struct early_suspend *h) #endif -//éîæ¤æµåº¤î椹å姩é¨ï¿½çæ§î¸éå¶ï¿½çæ§î¸ID éæ¥ã //only one client static const struct i2c_device_id goodix_ts_id[] = { { GOODIX_I2C_NAME, 0 }, { } }; -//çæ§î¸æ¤¹å姩ç¼æ´ç¯æµ£ï¿½ + static struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, @@ -850,10 +818,7 @@ static struct i2c_driver goodix_ts_driver = { }, }; -/******************************************************* -éç»å é� 椹å姩éçºæµéè¥æ -returné� éµÑîç¼æ´çé®ä¾ç´0çã§ãå§ï½ ç¶éµÑî -********************************************************/ + static int __devinit goodix_ts_init(void) { int ret; @@ -866,10 +831,7 @@ static int __devinit goodix_ts_init(void) return ret; } -/******************************************************* -éç»å é� 椹å姩éææµéè¥æ -éåæé� clientéæ°³î澶å©ç²¨éåªç¶ -********************************************************/ + static void __exit goodix_ts_exit(void) { printk(KERN_ALERT "Touchscreen driver of guitar exited.\n"); @@ -882,5 +844,6 @@ late_initcall(goodix_ts_init); module_exit(goodix_ts_exit); MODULE_DESCRIPTION("Goodix Touchscreen Driver"); +MODULE_AUTHOR("hhb@rock-chips.com") MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/gt818_ts.h b/drivers/input/touchscreen/gt818_ts.h index 207f38f46c4d..f269a2e0f3e5 100644 --- a/drivers/input/touchscreen/gt818_ts.h +++ b/drivers/input/touchscreen/gt818_ts.h @@ -21,8 +21,7 @@ #define GT801_PLUS #define GT801_NUVOTON #define GUITAR_UPDATE_STATE 0x02 -//#define NO_DEFAULT_ID - +#define GT818_I2C_SCL 400*1000 //define resolution of the touchscreen #define TOUCH_MAX_HEIGHT 7168 -- 2.34.1