newton: add goodix tp support and support goodix and focal detect
authorjyk <jyk@rock-chips.com>
Wed, 6 Jul 2011 12:02:37 +0000 (20:02 +0800)
committerjyk <jyk@rock-chips.com>
Wed, 6 Jul 2011 12:02:37 +0000 (20:02 +0800)
1. add goodix touchscreen support
2. modify focal touchscreen driver to support goodix and focal detect

arch/arm/mach-rk29/board-rk29-newton.c
arch/arm/mach-rk29/include/mach/board.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ft5406_ts.c
drivers/input/touchscreen/goodix_touch_newton.c [new file with mode: 0755]
drivers/input/touchscreen/goodix_touch_newton.h [new file with mode: 0755]

index 2f4accc94c30c6f2bc885da9cc8fd16b3d37c9fc..2beda078125524ba9b8427fdf938608d2b885123 100755 (executable)
@@ -571,7 +571,7 @@ struct platform_device rk29_device_newton = {
                }           
        };
 #endif
-#if defined (CONFIG_TOUCHSCREEN_FT5406)
+#if defined (CONFIG_TOUCHSCREEN_FT5406)|| defined (CONFIG_TOUCHSCREEN_GOODIX_NEWTON)
 #define TOUCH_RESET_PIN RK29_PIN6_PC3
 #define TOUCH_INT_PIN   RK29_PIN0_PA2
 
@@ -621,7 +621,9 @@ int ft5406_init_platform_hw(void)
 
     return 0;
 }
+#endif
 
+#if defined (CONFIG_TOUCHSCREEN_FT5406)
 
 struct ft5406_platform_data ft5406_info = {
 
@@ -630,6 +632,15 @@ struct ft5406_platform_data ft5406_info = {
 };
 #endif
 
+#if defined(CONFIG_TOUCHSCREEN_GOODIX_NEWTON)
+struct goodix_platform_data goodix_info = {
+
+  .init_platform_hw= ft5406_init_platform_hw,
+
+};
+#endif
+
+
 #if defined (CONFIG_SND_SOC_CS42L52)
 
 void cs42l52_init_platform_hw()
@@ -951,12 +962,26 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = {
       .platform_data  = &eeti_egalax_info,
     },
 #endif
+
+
+#if defined (CONFIG_TOUCHSCREEN_GOODIX_NEWTON)
+{
+       .type   = "Goodix-TS",
+               .addr   = 0x55,
+               .flags      =0,
+               //.irq          =RK29_PIN0_PA2,
+               .platform_data = &goodix_info,
+},
+#endif
+
+
+
 #if defined (CONFIG_TOUCHSCREEN_FT5406)
 {
        .type   ="ft5x0x_ts",
                .addr   = 0x38,    //0x70,
                .flags      =0,
-               .irq            =RK29_PIN0_PA2,
+               //.irq          =RK29_PIN0_PA2, // support goodix tp detect, 20110706
                .platform_data = &ft5406_info,
 },
        //added by koffu
index 8c9eec37c046913e3c1f6f29a0c1cbf15143ffff..7f1460d04b67459f475fa797efccd2aa1843ca15 100755 (executable)
@@ -229,6 +229,14 @@ struct ft5406_platform_data {
     void    (*exit_platform_hw)(void);
 };
 
+struct goodix_platform_data {
+    int     (*get_pendown_state)(void);
+    int     (*init_platform_hw)(void);
+    int     (*ft5406_platform_sleep)(void);
+    int     (*ft5406_platform_wakeup)(void);
+    void    (*exit_platform_hw)(void);
+};
+
 struct cs42l52_platform_data {
     int     (*get_pendown_state)(void);
     int     (*init_platform_hw)(void);
index 598ef991253b54cfdadba1244113e039b00e8dd3..753f1ef773a5ab842f850ab5bc2da180bc8cae14 100755 (executable)
@@ -758,6 +758,9 @@ config TOUCHSCREEN_GT818_IIC
 config D70_L3188A
        tristate "D70-L3188A based touchscreens"
        depends on I2C2_RK29
+config TOUCHSCREEN_GOODIX_NEWTON
+       tristate "GOODIX based touchscreens"
+       depends on I2C2_RK29
 config TOUCHSCREEN_FT5406
        tristate "FT5406 based touchscreens: FT5406 Interface"
        depends on I2C2_RK29
index ae6e8fc19f585750973a7f655f1c01bd952c5fba..77af57fbfa5f2d130b51f9c6429be8ea66957303 100644 (file)
@@ -58,4 +58,4 @@ obj-$(CONFIG_TOUCHSCREEN_GT818_IIC)      += gt818_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ILI2102_IIC)      += ili2102_ts.o
 obj-$(CONFIG_D70_L3188A)      += goodix_touch.o
 obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o  
-
+obj-$(CONFIG_TOUCHSCREEN_GOODIX_NEWTON) += goodix_touch_newton.o
index c8630e39495bf47f2454b673e73c0edc136d70e1..a7be67db1e562c21eb9777d688fa759dea338038 100755 (executable)
@@ -495,8 +495,8 @@ static void ft5x0x_report_value(struct ft5x0x_ts_data *data )
                input_report_abs(data->input_dev, ABS_Y, event->y1);
                input_report_abs(data->input_dev, ABS_PRESSURE, event->pressure);
        //}
-       printk("x = %d,y = %d\n",event->x1,event->y1);
-       //input_report_key(data->input_dev, BTN_TOUCH, 1);
+       //printk("x = %d,y = %d\n",event->x1,event->y1);
+       input_report_key(data->input_dev, BTN_TOUCH, 1);
 #endif /* CONFIG_FT5X0X_MULTITOUCH*/
        input_sync(data->input_dev);
 
@@ -1081,8 +1081,10 @@ static int  ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *
 
        int err = 0;
        int ret = 0;
+       int retry = 0;
        u8 buf_w[1];
        u8 buf_r[1];
+       const u8 buf_test[1] = {0};
        
     unsigned char reg_value;
     unsigned char reg_version;
@@ -1092,7 +1094,10 @@ static int  ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *
        if (!pdata) {
                dev_err(&client->dev, "platform data is required!\n");
                return -EINVAL;
-       }       
+       }
+
+       if (pdata->init_platform_hw)                              
+               pdata->init_platform_hw();
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
                return -EIO;
@@ -1146,6 +1151,18 @@ static int  ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *
        }
 
        this_client = client;
+
+       while(retry < 5)
+       {
+               ret=ft5406_set_regs(this_client,FT5X0X_REG_PMODE, buf_test,1);
+               if(ret > 0)break;
+               retry++;
+       }
+       if(ret <= 0)
+       {
+               printk("FT5406 I2C TEST ERROR!\n");
+               goto exit_err_i2c_test;
+       }
        ft5x0x_ts->client = client;
        ft5x0x_ts->irq = client->irq;
        ft5x0x_ts->input_dev = input_dev;
@@ -1196,9 +1213,8 @@ static int  ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *
        }
 
 //     printk("==probe over =\n");
-       if (pdata->init_platform_hw)                              
-               pdata->init_platform_hw();
 
+       ft5x0x_ts->irq = RK29_PIN0_PA2;
        if (!ft5x0x_ts->irq) {
                dev_dbg(&ft5x0x_ts->client->dev, "no IRQ?\n");
                return -ENODEV;
@@ -1254,7 +1270,6 @@ static int  ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *
 
        //printk("client->dev.driver->name %s  ,%d \n",client->dev.driver->name,ft5x0x_ts->irq);
 
-
        ret = request_irq(ft5x0x_ts->irq, ft5x0x_ts_interrupt, /*IRQF_TRIGGER_LOW*/IRQF_TRIGGER_FALLING,     //IRQF_DISABLED|IRQF_TRIGGER_FALLING,
                        client->dev.driver->name, ft5x0x_ts);
        
@@ -1308,6 +1323,7 @@ exit_platform_data_null:
        cancel_work_sync(&ft5x0x_ts->pen_event_work);
        destroy_workqueue(ft5x0x_ts->ts_workqueue);
 exit_create_singlethread:
+exit_err_i2c_test:
        printk("==singlethread error =\n");
        kfree(ft5x0x_ts);
 exit_alloc_data_failed:
diff --git a/drivers/input/touchscreen/goodix_touch_newton.c b/drivers/input/touchscreen/goodix_touch_newton.c
new file mode 100755 (executable)
index 0000000..e348127
--- /dev/null
@@ -0,0 +1,1905 @@
+/* drivers/input/touchscreen/goodix_touch.c
+ *
+ * Copyright (C) 2010 - 2011 Goodix, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/earlysuspend.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <mach/gpio.h>
+//#include <plat/gpio-cfg.h>
+//#include <plat/gpio-bank-l.h>
+//#include <plat/gpio-bank-f.h>
+#include <linux/irq.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include "goodix_touch_newton.h"
+
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/completion.h>
+#include <asm/uaccess.h>
+
+#include <mach/board.h>
+
+/*******************************************************       
+Description:
+       Read data from the i2c slave device;
+       This operation consisted of 2 i2c_msgs,the first msg used
+       to write the operate address,the second msg used to read data.
+
+Parameter:
+       client: i2c device.
+       buf[0]:operate address.
+       buf[1]~buf[len]:read data buffer.
+       len:operate length.
+       
+return:
+       numbers of i2c_msgs to transfer
+*********************************************************/
+static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)
+{
+       struct i2c_msg msgs[2];
+       int ret=-1;
+       int retries = 0;
+
+       msgs[0].flags=!I2C_M_RD;
+       msgs[0].addr=client->addr;
+       msgs[0].len=1;
+       msgs[0].buf=&buf[0];
+
+       msgs[1].flags=I2C_M_RD;
+       msgs[1].addr=client->addr;
+       msgs[1].len=len-1;
+       msgs[1].buf=&buf[1];
+
+       while(retries<5)
+       {
+               ret=i2c_transfer(client->adapter,msgs, 2);
+               if(ret == 2)break;
+               retries++;
+       }
+       return ret;
+}
+
+/*******************************************************       
+Description:
+       write data to the i2c slave device.
+
+Parameter:
+       client: i2c device.
+       buf[0]:operate address.
+       buf[1]~buf[len]:write data buffer.
+       len:operate length.
+       
+return:
+       numbers of i2c_msgs to transfer.
+*********************************************************/
+static int i2c_write_bytes(struct i2c_client *client,uint8_t *data,int len)
+{
+       struct i2c_msg msg;
+       int ret=-1;
+       int retries = 0;
+
+       msg.flags=!I2C_M_RD;
+       msg.addr=client->addr;
+       msg.len=len;
+       msg.buf=data;           
+       
+       while(retries<5)
+       {
+               ret=i2c_transfer(client->adapter,&msg, 1);
+               if(ret == 1)break;
+               retries++;
+       }
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Goodix touchscreen initialize function.
+
+Parameter:
+       ts:     i2c client private struct.
+       
+return:
+       Executive outcomes.0---succeed.
+*******************************************************/
+static int goodix_init_panel(struct goodix_ts_data *ts)
+{
+       int ret=-1;
+       uint8_t rd_cfg_buf[7] = {0x66,};
+
+#ifdef DRIVER_SEND_CFG                         //for kedi 9.7(puts your config info here,if need send config info)
+       uint8_t config_info[] = {
+       0x65,0x00,(TOUCH_MAX_HEIGHT>>8),(TOUCH_MAX_HEIGHT&0xff),
+       (TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_WIDTH&0xff),MAX_FINGER_NUM,(0x2C | INT_TRIGGER),
+       0x11,0x11,0x32,0x02,0x08,0x10,0x20,0x00,
+       0x00,0x88,0x88,0x88,0x03,0x13,0x32,0x64,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+       0x08,0x09,0x0A,0x0B,0x0C,0xFF,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
+       0x17,0x18,0x19,0xFF,0xFF,0xFF,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
+       };
+       //WAKEUP GREEN MODE
+       //disable_irq(client->irq);
+       gpio_direction_output(INT_PORT, 0);
+       msleep(5);
+       //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+       gpio_direction_input(INT_PORT);
+       //enable_irq(client->irq);
+
+       ret=i2c_write_bytes(ts->client,config_info, (sizeof(config_info)/sizeof(config_info[0])));
+       if (ret < 0) 
+               return ret;
+#endif
+       ret=i2c_read_bytes(ts->client, rd_cfg_buf, 7);
+       if(ret != 2)
+       {
+               dev_info(&ts->client->dev, "Read resolution & max_touch_num failed, use default value!\n");
+               ts->abs_x_max = TOUCH_MAX_HEIGHT;
+               ts->abs_y_max = TOUCH_MAX_WIDTH;
+               ts->max_touch_num = MAX_FINGER_NUM;
+               ts->int_trigger_type = INT_TRIGGER;
+               return 0;
+       }
+       ts->abs_x_max = (rd_cfg_buf[1]<<8) + rd_cfg_buf[2];
+       ts->abs_y_max = (rd_cfg_buf[3]<<8) + rd_cfg_buf[4];
+       ts->max_touch_num = rd_cfg_buf[5];
+       ts->int_trigger_type = rd_cfg_buf[6]&0x03;
+       if((!ts->abs_x_max)||(!ts->abs_y_max)||(!ts->max_touch_num))
+       {
+               dev_info(&ts->client->dev, "Read invalid resolution & max_touch_num, use default value!\n");
+               ts->abs_x_max = TOUCH_MAX_HEIGHT;
+               ts->abs_y_max = TOUCH_MAX_WIDTH;
+               ts->max_touch_num = MAX_FINGER_NUM;
+       }
+
+       dev_info(&ts->client->dev,"X_MAX = %d,Y_MAX = %d,MAX_TOUCH_NUM = %d\n",ts->abs_x_max,ts->abs_y_max,ts->max_touch_num);
+       //wake up mode from green mode
+       rd_cfg_buf[0] = 0x6e;
+       rd_cfg_buf[1] = 0x00;
+       i2c_read_bytes(ts->client, rd_cfg_buf, 2);
+       if((rd_cfg_buf[1]&0x0f)==0x0f)
+       {
+               dev_info(&ts->client->dev, "Touchscreen works in INT wake up green mode!\n");
+               ts->green_wake_mode = 1;
+       }
+       else
+       {
+               dev_info(&ts->client->dev, "Touchscreen works in IIC wake up green mode!\n");
+               ts->green_wake_mode = 0;
+       }
+
+       msleep(10);
+       return 0;
+
+}
+
+/*******************************************************
+Description:
+       Read goodix touchscreen version function.
+
+Parameter:
+       ts:     i2c client private struct.
+       
+return:
+       Executive outcomes.0---succeed.
+*******************************************************/
+static int  goodix_read_version(struct goodix_ts_data *ts, char **version)
+{
+       int ret = -1, count = 0;
+       char *version_data;
+       char *p;
+       
+       *version = (char *)vmalloc(18);
+       version_data = *version;
+       if(!version_data)
+               return -ENOMEM;
+       p = version_data;
+       memset(version_data, 0, sizeof(version_data));
+       version_data[0]=240;
+       if(ts->green_wake_mode)                 //WAKEUP GREEN MODE
+       {
+               disable_irq(ts->client->irq);
+               gpio_direction_output(INT_PORT, 0);
+               msleep(5);
+               //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+               gpio_direction_input(INT_PORT);
+               enable_irq(ts->client->irq);
+       }
+       ret=i2c_read_bytes(ts->client,version_data, 17);
+       if (ret < 0) 
+               return ret;
+       version_data[17]='\0';
+       
+       if(*p == '\0')
+               return 0;       
+       do                                      
+       {
+               if((*p > 122) || (*p < 48 && *p != 32) || (*p >57 && *p  < 65) 
+                       ||(*p > 90 && *p < 97 && *p  != '_'))           //check illeqal character
+                       count++;
+       }while(*++p != '\0' );
+       if(count > 2)
+               return 0;
+       else 
+               return 1;       
+}
+
+
+/*******************************************************
+Description:
+       Goodix touchscreen work function.
+
+Parameter:
+       ts:     i2c client private struct.
+       
+return:
+       Executive outcomes.0---succeed.
+*******************************************************/
+static void goodix_ts_work_func(struct work_struct *work)
+{      
+       int ret=-1;
+       int tmp = 0;
+       uint8_t  point_data[(1-READ_COOR_ADDR)+1+2+5*MAX_FINGER_NUM+1]={ 0 };  //read address(1byte)+key index(1byte)+point mask(2bytes)+5bytes*MAX_FINGER_NUM+coor checksum(1byte)
+       uint8_t  check_sum = 0;
+       uint16_t  finger_current = 0;
+       uint16_t  finger_bit = 0;
+       unsigned int  count = 0, point_count = 0;
+       unsigned int position = 0;      
+       uint8_t track_id[MAX_FINGER_NUM] = {0};
+       unsigned int input_x = 0;
+       unsigned int input_y = 0;
+       unsigned int input_w = 0;
+       unsigned char index = 0;
+       unsigned char touch_num = 0;
+       
+       struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);
+
+
+       if(g_enter_isp)return;
+#if defined(INT_PORT)
+COORDINATE_POLL:
+       if((ts->int_trigger_type> 1)&& (gpio_get_value(INT_PORT) != (ts->int_trigger_type&0x01)))
+       {
+               goto NO_ACTION;
+       }       
+#endif 
+
+
+       if( tmp > 9) {
+               
+               dev_info(&(ts->client->dev), "I2C transfer error,touchscreen stop working.\n");
+               goto XFER_ERROR ;
+       }
+       
+       if(ts->bad_data)        
+               msleep(20);
+       
+       point_data[0] = READ_COOR_ADDR;         //read coor address
+       ret=i2c_read_bytes(ts->client, point_data,  sizeof(point_data)/sizeof(point_data[0]));
+       if(ret <= 0)    
+       {
+               dev_err(&(ts->client->dev),"I2C transfer error. Number:%d\n ", ret);
+               ts->bad_data = 1;
+               tmp ++;
+               ts->retry++;
+       #if defined(INT_PORT)
+               if(ts->int_trigger_type> 1)
+                       goto COORDINATE_POLL;
+               else
+                       goto XFER_ERROR;
+       #endif
+       }       
+       ts->bad_data = 0; 
+       finger_current =  (point_data[3 - READ_COOR_ADDR]<<8) + point_data[2 - READ_COOR_ADDR];
+       
+       if(finger_current)
+       {       
+               point_count = 0, finger_bit = finger_current;
+               for(count = 0; (finger_bit != 0) && (count < ts->max_touch_num); count++)//cal how many point touch currntly
+               {
+                       if(finger_bit & 0x01)
+                       {
+                               track_id[point_count] = count;
+                               point_count++;
+                       }
+                       finger_bit >>= 1;
+               }
+               touch_num = point_count;
+
+               check_sum = point_data[2 - READ_COOR_ADDR] + point_data[3 - READ_COOR_ADDR];                    //cal coor checksum
+               count = 4 - READ_COOR_ADDR;
+               for(point_count *= 5; point_count > 0; point_count--)
+                       check_sum += point_data[count++];
+               check_sum += point_data[count];
+               if(check_sum  != 0)                     //checksum verify error
+               {
+               #if 0   
+                       dev_info(&ts->client->dev, "Check_sum:%d,  Data:%d\n", check_sum, point_data[count]);   
+                       printk(KERN_INFO "Finger Bit:%d\n",finger_current);
+                       for( ; count > 0; count--)
+                               printk(KERN_INFO "count=%d:%d  ",count, point_data[count]);
+                       printk(KERN_INFO "\n");
+               #endif
+                       printk("coor checksum error!\n");
+               #if defined(INT_PORT)
+                       if(ts->int_trigger_type> 1)
+                               goto COORDINATE_POLL;
+                       else    
+                               goto XFER_ERROR;
+               #endif
+               }
+       }
+
+       if(touch_num)
+       {
+               for(index=0; index<touch_num; index++)
+               {
+                       position = 4 - READ_COOR_ADDR + 5*index;
+                       input_x = (unsigned int) (point_data[position]<<8) + (unsigned int)( point_data[position+1]);
+                       input_y = (unsigned int)(point_data[position+2]<<8) + (unsigned int) (point_data[position+3]);
+                       input_w =(unsigned int) (point_data[position+4]);               
+                       //input_x = input_x *SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT);      
+                       //input_y = input_y *SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH);
+
+                       if((input_x > ts->abs_x_max)||(input_y > ts->abs_y_max))continue;
+                       //printk("input_x = %d,input_y = %d, input_w = %d\n", input_x, input_y, input_w);
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);                    
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
+                       input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, track_id[index]);
+                       input_mt_sync(ts->input_dev);
+               }
+       }
+       else
+       {
+               input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+               input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
+               input_mt_sync(ts->input_dev);
+       }
+
+       #ifdef HAVE_TOUCH_KEY
+       //printk(KERN_INFO"HAVE KEY DOWN!0x%x\n",point_data[1]);
+       for(count = 0; count < MAX_KEY_NUM; count++)
+       {
+               input_report_key(ts->input_dev, touch_key_array[count], !!(point_data[1]&(0x01<<count)));       
+       }          
+       #endif
+       input_sync(ts->input_dev);
+
+#if defined(INT_PORT)
+       if(ts->int_trigger_type> 1)
+       {
+               msleep(POLL_TIME);
+               goto COORDINATE_POLL;
+       }
+#endif
+       goto END_WORK_FUNC;
+
+NO_ACTION:     
+
+#ifdef HAVE_TOUCH_KEY
+       //printk(KERN_INFO"HAVE KEY DOWN!0x%x\n",point_data[1]);
+       for(count = 0; count < MAX_KEY_NUM; count++)
+       {
+               input_report_key(ts->input_dev, touch_key_array[count], !!(point_data[1]&(0x01<<count)));       
+       }
+       input_sync(ts->input_dev);         
+#endif
+END_WORK_FUNC:
+XFER_ERROR:
+       if(ts->use_irq)
+               enable_irq(ts->client->irq);
+
+}
+
+/*******************************************************
+Description:
+       Timer interrupt service routine.
+
+Parameter:
+       timer:  timer struct pointer.
+       
+return:
+       Timer work mode. HRTIMER_NORESTART---not restart mode
+*******************************************************/
+static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer)
+{
+       struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer);
+       queue_work(goodix_wq, &ts->work);
+       hrtimer_start(&ts->timer, ktime_set(0, (POLL_TIME+6)*1000000), HRTIMER_MODE_REL);
+       return HRTIMER_NORESTART;
+}
+
+/*******************************************************
+Description:
+       External interrupt service routine.
+
+Parameter:
+       irq:    interrupt number.
+       dev_id: private data pointer.
+       
+return:
+       irq execute status.
+*******************************************************/
+static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
+{
+       struct goodix_ts_data *ts = dev_id;
+
+       disable_irq_nosync(ts->client->irq);
+       queue_work(goodix_wq, &ts->work);
+       
+       return IRQ_HANDLED;
+}
+
+/*******************************************************
+Description:
+       Goodix touchscreen power manage function.
+
+Parameter:
+       on:     power status.0---suspend;1---resume.
+       
+return:
+       Executive outcomes.-1---i2c transfer error;0---succeed.
+*******************************************************/
+static int goodix_ts_power(struct goodix_ts_data * ts, int on)
+{
+       int ret = -1;
+       unsigned char i2c_control_buf[2] = {80,  1};            //suspend cmd
+       int retry = 0;
+       if(on != 0 && on !=1)
+       {
+               printk(KERN_DEBUG "%s: Cant't support this command.", goodix_ts_name);
+               return -EINVAL;
+       }
+       
+       if(ts != NULL && !ts->use_irq)
+               return -2;
+       
+       if(on == 0)             //suspend
+       { 
+               if(ts->green_wake_mode)
+               {
+                       disable_irq(ts->client->irq);
+                       gpio_direction_output(INT_PORT, 0);
+                       msleep(5);
+                       //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+                       gpio_direction_input(INT_PORT);
+                       enable_irq(ts->client->irq);
+               }
+               while(retry<5)
+               {
+                       ret = i2c_write_bytes(ts->client, i2c_control_buf, 2);
+                       if(ret == 1)
+                       {
+                               printk(KERN_INFO"Send suspend cmd\n");
+                               break;
+                       }
+                       printk("Send cmd failed!\n");
+                       retry++;
+                       msleep(10);
+               }
+               if(ret > 0)
+                       ret = 0;
+       }
+       else if(on == 1)                //resume
+       {
+               printk(KERN_INFO"Int resume\n");
+               gpio_direction_output(INT_PORT, 0); 
+               msleep(20);
+               //if(ts->use_irq) 
+                       //s3c_gpio_cfgpin(INT_PORT, INT_CFG);   //Set IO port as interrupt port 
+               //else 
+                       gpio_direction_input(INT_PORT);
+               //msleep(260);
+
+               ret = 0;
+       }        
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Goodix debug sysfs cat version function.
+
+Parameter:
+       standard sysfs show param.
+       
+return:
+       Executive outcomes. 0---failed.
+*******************************************************/
+static ssize_t goodix_debug_version_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+       char *version_info = NULL;
+       struct goodix_ts_data *ts;
+       
+       ts = i2c_get_clientdata(i2c_connect_client);
+       if(ts==NULL)
+               return 0;
+       
+       ret = goodix_read_version(ts, &version_info);
+       if(ret <= 0)
+       {
+               printk(KERN_INFO"Read version data failed!\n");
+               vfree(version_info);
+               return 0;
+       }
+
+       printk(KERN_INFO"Goodix TouchScreen Version:%s\n", (version_info+1));
+       sprintf(buf,"Goodix TouchScreen Version:%s\n",(version_info+1));
+       vfree(version_info);
+       ret = strlen(buf);
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Goodix debug sysfs cat resolution function.
+
+Parameter:
+       standard sysfs show param.
+       
+return:
+       Executive outcomes. 0---failed.
+*******************************************************/
+static ssize_t goodix_debug_resolution_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct goodix_ts_data *ts;
+       ts = i2c_get_clientdata(i2c_connect_client);
+       dev_info(&ts->client->dev,"ABS_X_MAX = %d,ABS_Y_MAX = %d\n",ts->abs_x_max,ts->abs_y_max);
+       sprintf(buf,"ABS_X_MAX = %d,ABS_Y_MAX = %d\n",ts->abs_x_max,ts->abs_y_max);
+
+       return strlen(buf);
+}
+/*******************************************************
+Description:
+       Goodix debug sysfs cat version function.
+
+Parameter:
+       standard sysfs show param.
+       
+return:
+       Executive outcomes. 0---failed.
+*******************************************************/
+static ssize_t goodix_debug_diffdata_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       //char diff_data[300];
+       unsigned char diff_data[2241] = {00,};
+       int ret = -1;
+       char diff_data_cmd[2] = {80, 202};
+       int i;
+       int short_tmp;
+       struct goodix_ts_data *ts;
+
+       disable_irq(TS_INT);
+       
+       ts = i2c_get_clientdata(i2c_connect_client);
+       //memset(diff_data, 0, sizeof(diff_data));
+       if(ts->green_wake_mode)
+       {
+               //disable_irq(client->irq);
+               gpio_direction_output(INT_PORT, 0);
+               msleep(5);
+               gpio_direction_input(INT_PORT);
+               //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+               //enable_irq(client->irq);
+       }
+       ret = i2c_write_bytes(ts->client, diff_data_cmd, 2);
+       if(ret != 1)
+       {
+               dev_info(&ts->client->dev, "Write diff data cmd failed!\n");
+               enable_irq(TS_INT);
+               return 0;
+       }
+
+       while(gpio_get_value(INT_PORT));
+       ret = i2c_read_bytes(ts->client, diff_data, sizeof(diff_data));
+       if(ret != 2)
+       {
+               dev_info(&ts->client->dev, "Read diff data failed!\n");
+               enable_irq(TS_INT);
+               return 0;
+       }
+       for(i=1; i<sizeof(diff_data); i+=2)
+       {
+               short_tmp = diff_data[i] + (diff_data[i+1]<<8);
+               if(short_tmp&0x8000)
+                       short_tmp -= 65535;
+               if(short_tmp == 512)continue;
+               sprintf(buf+strlen(buf)," %d",short_tmp);
+               //printk(" %d\n", short_tmp);
+       }
+       
+       diff_data_cmd[1] = 0;
+       ret = i2c_write_bytes(ts->client, diff_data_cmd, 2);
+       if(ret != 1)
+       {
+               dev_info(&ts->client->dev, "Write diff data cmd failed!\n");
+               enable_irq(TS_INT);
+               return 0;
+       }
+       enable_irq(TS_INT);
+       /*for (i=0; i<1024; i++)
+       {
+               sprintf(buf+strlen(buf)," %d",i);
+       }*/
+       
+       return strlen(buf);
+}
+
+
+/*******************************************************
+Description:
+       Goodix debug sysfs echo calibration function.
+
+Parameter:
+       standard sysfs store param.
+       
+return:
+       Executive outcomes..
+*******************************************************/
+static ssize_t goodix_debug_calibration_store(struct device *dev,
+                       struct device_attribute *attr, const char *buf, ssize_t count)
+{
+       int ret = -1;
+       char cal_cmd_buf[] = {110,1};
+       struct goodix_ts_data *ts;
+
+       ts = i2c_get_clientdata(i2c_connect_client);
+       dev_info(&ts->client->dev,"Begin calibration......\n");
+       if((*buf == 10)||(*buf == 49))
+       {
+               if(ts->green_wake_mode)
+               {
+                       disable_irq(ts->client->irq);
+                       gpio_direction_output(INT_PORT, 0);
+                       msleep(5);
+                       gpio_direction_input(INT_PORT);
+                       //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+                       enable_irq(ts->client->irq);
+               }
+               ret = i2c_write_bytes(ts->client,cal_cmd_buf,2);
+               if(ret!=1)
+               {
+                       dev_info(&ts->client->dev,"Calibration failed!\n");
+                       return count;
+               }
+               else
+               {
+                       dev_info(&ts->client->dev,"Calibration succeed!\n");
+               }
+       }
+       return count;
+}
+
+static DEVICE_ATTR(version, S_IRUGO, goodix_debug_version_show, NULL);
+static DEVICE_ATTR(resolution, S_IRUGO, goodix_debug_resolution_show, NULL);
+static DEVICE_ATTR(diffdata, S_IRUGO, goodix_debug_diffdata_show, NULL);
+static DEVICE_ATTR(calibration, S_IWUSR , NULL, goodix_debug_calibration_store); 
+
+
+/*******************************************************
+Description:
+       Goodix debug sysfs init function.
+
+Parameter:
+       none.
+       
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int goodix_debug_sysfs_init(void)
+{
+       int ret ;
+       struct goodix_ts_data *ts;
+       ts = i2c_get_clientdata(i2c_connect_client);
+
+       goodix_debug_kobj = kobject_create_and_add("goodix_debug", NULL) ;
+       if (goodix_debug_kobj == NULL) {
+               printk(KERN_ERR "%s: subsystem_register failed\n", __func__);
+               ret = -ENOMEM;
+               return ret;
+       }
+       ret = sysfs_create_file(goodix_debug_kobj, &dev_attr_version.attr);
+       if (ret) {
+               printk(KERN_ERR "%s: sysfs_create_version_file failed\n", __func__);
+               return ret;
+       }
+       ret = sysfs_create_file(goodix_debug_kobj, &dev_attr_calibration.attr);
+       if (ret) {
+               printk(KERN_ERR "%s: sysfs_create_calibration_file failed\n", __func__);
+               return ret;
+       }
+       ret = sysfs_create_file(goodix_debug_kobj, &dev_attr_diffdata.attr);
+       if (ret) 
+       {
+               printk(KERN_ERR "%s: sysfs_create_diffdata_file failed\n", __func__);
+               return ret;
+       }
+       ret = sysfs_create_file(goodix_debug_kobj, &dev_attr_resolution.attr);
+       if (ret) {
+               printk(KERN_ERR "%s: sysfs_create_resolution_file failed\n", __func__);
+               return ret;
+       }
+       dev_info(&ts->client->dev,"Goodix debug sysfs create success!\n");
+       return 0 ;
+}
+
+static void goodix_debug_sysfs_deinit(void)
+{
+       sysfs_remove_file(goodix_debug_kobj, &dev_attr_version.attr);
+       sysfs_remove_file(goodix_debug_kobj, &dev_attr_resolution.attr);
+       sysfs_remove_file(goodix_debug_kobj, &dev_attr_diffdata.attr);
+       sysfs_remove_file(goodix_debug_kobj, &dev_attr_calibration.attr);
+       kobject_del(goodix_debug_kobj);
+}
+
+/*******************************************************
+Description:
+       Goodix touchscreen probe function.
+
+Parameter:
+       client: i2c device struct.
+       id:device id.
+       
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       int ret = 0;
+       int retry=0;
+       struct goodix_ts_data *ts;
+       char *version_info = NULL;
+       char test_data = 1;
+       const char irq_table[4] = {IRQ_TYPE_EDGE_RISING,
+                                                          IRQ_TYPE_EDGE_FALLING,
+                                                          IRQ_TYPE_LEVEL_LOW,
+                                                          IRQ_TYPE_LEVEL_HIGH};
+
+       struct goodix_platform_data *pdata;
+       dev_dbg(&client->dev,"Install touch driver.\n");
+
+       pdata = client->dev.platform_data;
+       if (pdata && pdata->init_platform_hw)
+       {
+               pdata->init_platform_hw();
+       }       
+       else    
+       {
+               printk("*****************power manage failed!!!!!!!!*************************");
+       }
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
+       {
+               dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
+               ret = -ENODEV;
+               goto err_check_functionality_failed;
+       }
+       ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+       if (ts == NULL) {
+               ret = -ENOMEM;
+               goto err_alloc_data_failed;
+       }
+  
+       i2c_connect_client = client;
+       INIT_WORK(&ts->work, goodix_ts_work_func);
+       ts->client = client;
+       i2c_set_clientdata(client, ts);
+       pdata = client->dev.platform_data;
+       
+       for(retry=0;retry < 5; retry++)
+       {
+               gpio_direction_output(INT_PORT, 0);
+               msleep(5);
+               gpio_direction_input(INT_PORT);
+               ret =i2c_write_bytes(client, &test_data, 1);
+               if (ret > 0)
+                       break;
+               printk("GOODiX i2c test failed!\n");
+       }
+       if(ret <= 0)
+       {
+               dev_err(&client->dev, "I2C communication ERROR!Goodix touchscreen driver become invalid\n");            
+               goto err_i2c_failed;
+       }
+
+for(retry=0; retry<3; retry++)
+{
+       ret=goodix_init_panel(ts);
+       msleep(2);
+       if(ret != 0)
+               continue;
+       else
+               break;
+}
+
+
+
+#ifdef INT_PORT        
+       client->irq=TS_INT;
+       if (client->irq)
+       {
+               ts_irq = client->irq;
+               int_gpio = irq_to_gpio(client->irq);
+               gpio_direction_input(INT_PORT);
+       
+               ret  = request_irq(client->irq, goodix_ts_irq_handler ,  irq_table[ts->int_trigger_type],
+                       client->name, ts);
+               if (ret != 0) {
+                       dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);
+                       gpio_direction_input(INT_PORT);
+                       gpio_free(INT_PORT);
+                       goto works_maybe_polling_mode;
+               }
+               else 
+               {       
+                       disable_irq(client->irq);
+                       ts->use_irq = 1;
+                       dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n",TS_INT,INT_PORT);
+               }       
+       }
+#endif
+       
+works_maybe_polling_mode:      
+       
+       ts->input_dev = input_allocate_device();
+       if (ts->input_dev == NULL) {
+               ret = -ENOMEM;
+               dev_dbg(&client->dev,"Failed to allocate input device\n");
+               goto err_input_dev_alloc_failed;
+       }
+
+       
+
+       if(ret != 0) {
+               ts->bad_data=1;
+               goto err_init_godix_ts;
+       }
+
+       ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
+       ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       ts->input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);                                                 // absolute coor (x,y)
+#ifdef HAVE_TOUCH_KEY
+       for(retry = 0; retry < MAX_KEY_NUM; retry++)
+       {
+               input_set_capability(ts->input_dev,EV_KEY,touch_key_array[retry]);      
+       }
+#endif
+
+       input_set_abs_params(ts->input_dev, ABS_X, 0, ts->abs_x_max, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->abs_y_max, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
+
+#ifdef GOODIX_MULTI_TOUCH
+       input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, ts->max_touch_num, 0, 0);
+#endif 
+
+       sprintf(ts->phys, "input/ts");
+       ts->input_dev->name = goodix_ts_name;
+       ts->input_dev->phys = ts->phys;
+       ts->input_dev->id.bustype = BUS_I2C;
+       ts->input_dev->id.vendor = 0xDEAD;
+       ts->input_dev->id.product = 0xBEEF;
+       ts->input_dev->id.version = 10427;      //screen firmware version
+       
+       ret = input_register_device(ts->input_dev);
+       if (ret) {
+               dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
+               goto err_input_register_device_failed;
+       }
+       ts->bad_data = 0;
+               
+       if (!ts->use_irq) 
+       {
+               hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               ts->timer.function = goodix_ts_timer_func;
+               hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+       }
+       
+       if(ts->use_irq)
+               enable_irq(client->irq);
+#if defined(INT_PORT)
+       if(ts->use_irq)                 
+               ts->power = goodix_ts_power;
+#endif 
+       ret = goodix_read_version(ts, &version_info);
+       if(ret <= 0)
+       {
+               printk(KERN_INFO"Read version data failed!\n");
+       }
+       else
+       {
+               printk(KERN_INFO"Goodix TouchScreen Version:%s\n", (version_info+1));
+       }
+       vfree(version_info);
+       
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       ts->early_suspend.suspend = goodix_ts_early_suspend;
+       ts->early_suspend.resume = goodix_ts_late_resume;
+       register_early_suspend(&ts->early_suspend);
+#endif
+#ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP
+       goodix_proc_entry = create_proc_entry("goodix-update", 0666, NULL);
+       if(goodix_proc_entry == NULL)
+       {
+               dev_info(&client->dev, "Couldn't create proc entry!\n");
+               ret = -ENOMEM;
+               goto err_create_proc_entry;
+       }
+       else
+       {
+               dev_info(&client->dev, "Create proc entry success!\n");
+               goodix_proc_entry->write_proc = goodix_update_write;
+               goodix_proc_entry->read_proc = goodix_update_read;
+               //goodix_proc_entry->owner =THIS_MODULE;
+       }
+#endif
+       goodix_debug_sysfs_init();
+       dev_info(&client->dev,"Start %s in %s mode\n", 
+               ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
+       dev_info(&client->dev, "Driver Modify Date:2011-06-27\n");
+       return 0;
+
+err_init_godix_ts:
+       if(ts->use_irq)
+       {
+               ts->use_irq = 0;
+               free_irq(client->irq,ts);
+       #ifdef INT_PORT 
+               gpio_direction_input(INT_PORT);
+               gpio_free(INT_PORT);
+       #endif  
+       }
+       else 
+               hrtimer_cancel(&ts->timer);
+
+err_input_register_device_failed:
+       input_free_device(ts->input_dev);
+
+err_input_dev_alloc_failed:
+       i2c_set_clientdata(client, NULL);
+err_i2c_failed:        
+       kfree(ts);
+err_alloc_data_failed:
+err_check_functionality_failed:
+err_create_proc_entry:
+       return ret;
+}
+
+
+/*******************************************************
+Description:
+       Goodix touchscreen driver release function.
+
+Parameter:
+       client: i2c device struct.
+       
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int goodix_ts_remove(struct i2c_client *client)
+{
+       struct goodix_ts_data *ts = i2c_get_clientdata(client);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&ts->early_suspend);
+#endif
+#ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP
+       remove_proc_entry("goodix-update", NULL);
+#endif
+       goodix_debug_sysfs_deinit();
+       if (ts && ts->use_irq) 
+       {
+       #ifdef INT_PORT
+               gpio_direction_input(INT_PORT);
+               gpio_free(INT_PORT);
+       #endif  
+               free_irq(client->irq, ts);
+       }       
+       else if(ts)
+               hrtimer_cancel(&ts->timer);
+       
+       dev_notice(&client->dev,"The driver is removing...\n");
+       i2c_set_clientdata(client, NULL);
+       input_unregister_device(ts->input_dev);
+       kfree(ts);
+       return 0;
+}
+
+static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       int ret;
+       struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+       if (ts->use_irq)
+               disable_irq(client->irq);
+       else
+               hrtimer_cancel(&ts->timer);
+       //ret = cancel_work_sync(&ts->work);
+       //if(ret && ts->use_irq)        
+               //enable_irq(client->irq);
+       if (ts->power) {
+               ret = ts->power(ts, 0);
+               if (ret < 0)
+                       printk(KERN_ERR "goodix_ts_resume power off failed\n");
+       }
+       return 0;
+}
+
+static int goodix_ts_resume(struct i2c_client *client)
+{
+       int ret;
+       struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+       if (ts->power) {
+               ret = ts->power(ts, 1);
+               if (ret < 0)
+                       printk(KERN_ERR "goodix_ts_resume power on failed\n");
+       }
+
+       if (ts->use_irq)
+               enable_irq(client->irq);
+       else
+               hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+
+       return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void goodix_ts_early_suspend(struct early_suspend *h)
+{
+       struct goodix_ts_data *ts;
+       ts = container_of(h, struct goodix_ts_data, early_suspend);
+       goodix_ts_suspend(ts->client, PMSG_SUSPEND);
+}
+
+static void goodix_ts_late_resume(struct early_suspend *h)
+{
+       struct goodix_ts_data *ts;
+       ts = container_of(h, struct goodix_ts_data, early_suspend);
+       goodix_ts_resume(ts->client);
+}
+#endif
+
+//******************************Begin of firmware update surpport*******************************
+#ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP
+/**
+@brief CRC cal proc,include : Reflect,init_crc32_table,GenerateCRC32
+@param global var oldcrc32
+@return states
+*/
+static unsigned int Reflect(unsigned long int ref, char ch)
+{
+       unsigned int value=0;
+       int i;
+       for(i = 1; i < (ch + 1); i++)
+       {
+               if(ref & 1)
+                       value |= 1 << (ch - i);
+               ref >>= 1;
+       }
+       return value;
+}
+/*---------------------------------------------------------------------------------------------------------*/
+/*  CRC Check Program INIT                                                                                                                        */
+/*---------------------------------------------------------------------------------------------------------*/
+static void init_crc32_table(void)
+{
+       unsigned int temp;
+       unsigned int t1,t2;
+       unsigned int flag;
+       int i,j;
+       for(i = 0; i <= 0xFF; i++)
+       {
+               temp=Reflect(i, 8);
+               crc32_table[i]= temp<< 24;
+               for (j = 0; j < 8; j++)
+               {
+
+                       flag=crc32_table[i]&0x80000000;
+                       t1=(crc32_table[i] << 1);
+                       if(flag==0)
+                               t2=0;
+                       else
+                               t2=ulPolynomial;
+                       crc32_table[i] =t1^t2 ;
+
+               }
+               crc32_table[i] = Reflect(crc32_table[i], 32);
+       }
+}
+/*---------------------------------------------------------------------------------------------------------*/
+/*  CRC main Program                                                                                                                              */
+/*---------------------------------------------------------------------------------------------------------*/
+static void GenerateCRC32(unsigned char * buf, unsigned int len)
+{
+       unsigned int i;
+       unsigned int t;
+
+       for (i = 0; i != len; ++i)
+       {
+               t = (oldcrc32 ^ buf[i]) & 0xFF;
+               oldcrc32 = ((oldcrc32 >> 8) & 0xFFFFFF) ^ crc32_table[t];
+       }
+}
+
+static struct file * update_file_open(char * path, mm_segment_t * old_fs_p)
+{
+       struct file * filp = NULL;
+       int errno = -1;
+               
+       filp = filp_open(path, O_RDONLY, 0644);
+       
+       if(!filp || IS_ERR(filp))
+       {
+               if(!filp)
+                       errno = -ENOENT;
+               else 
+                       errno = PTR_ERR(filp);                                  
+               printk(KERN_ERR "The update file for Guitar open error.\n");
+               return NULL;
+       }
+       *old_fs_p = get_fs();
+       set_fs(get_ds());
+
+       filp->f_op->llseek(filp,0,0);
+       return filp ;
+}
+
+static void update_file_close(struct file * filp, mm_segment_t old_fs)
+{
+       set_fs(old_fs);
+       if(filp)
+               filp_close(filp, NULL);
+}
+static int update_get_flen(char * path)
+{
+       struct file * file_ck = NULL;
+       mm_segment_t old_fs;
+       int length ;
+       
+       file_ck = update_file_open(path, &old_fs);
+       if(file_ck == NULL)
+               return 0;
+
+       length = file_ck->f_op->llseek(file_ck, 0, SEEK_END);
+       //printk("File length: %d\n", length);
+       if(length < 0)
+               length = 0;
+       update_file_close(file_ck, old_fs);
+       return length;  
+}
+static int update_file_check(char * path)
+{
+       unsigned char buffer[64] = { 0 } ;
+       struct file * file_ck = NULL;
+       mm_segment_t old_fs;
+       int count, ret, length ;
+       
+       file_ck = update_file_open(path, &old_fs);
+       
+       if(path != NULL)
+               printk("File Path:%s\n", path);
+       
+       if(file_ck == NULL)
+               return -ERROR_NO_FILE;
+
+       length = file_ck->f_op->llseek(file_ck, 0, SEEK_END);
+#ifdef GUITAR_MESSAGE
+       printk(KERN_INFO "gt801 update: File length: %d\n",length);
+#endif 
+       if(length <= 0 || (length%4) != 0)
+       {
+               update_file_close(file_ck, old_fs);
+               return -ERROR_FILE_TYPE;
+       }
+       
+       //set file point to the begining of the file
+       file_ck->f_op->llseek(file_ck, 0, SEEK_SET);    
+       oldcrc32 = 0xFFFFFFFF;
+       init_crc32_table();
+       while(length > 0)
+       {
+               ret = file_ck->f_op->read(file_ck, buffer, sizeof(buffer), &file_ck->f_pos);
+               if(ret > 0)
+               {
+                       for(count = 0; count < ret;  count++)   
+                               GenerateCRC32(&buffer[count],1);                        
+               }
+               else 
+               {
+                       update_file_close(file_ck, old_fs);
+                       return -ERROR_FILE_READ;
+               }
+               length -= ret;
+       }
+       oldcrc32 = ~oldcrc32;
+#ifdef GUITAR_MESSAGE  
+       printk("CRC_Check: %u\n", oldcrc32);
+#endif 
+       update_file_close(file_ck, old_fs);
+       return 1;       
+}
+
+unsigned char wait_slave_ready(struct goodix_ts_data *ts, unsigned short *timeout)
+{
+       unsigned char i2c_state_buf[2] = {ADDR_STA, UNKNOWN_ERROR};
+       int ret;
+       while(*timeout < MAX_TIMEOUT)
+       {
+               ret = i2c_read_bytes(ts->client, i2c_state_buf, 2);
+               if(ret <= 0)
+                       return ERROR_I2C_TRANSFER;
+               if(i2c_state_buf[1] & SLAVE_READY)
+               {
+                       return i2c_state_buf[1];
+                       //return 1;
+               }
+               msleep(10);
+               *timeout += 5;
+       }
+       return 0;
+}
+
+static int goodix_update_write(struct file *filp, const char __user *buff, unsigned long len, void *data)
+{
+       unsigned char cmd[220];
+       int ret = -1;
+
+       static unsigned char update_path[100];
+       static unsigned short time_count = 0;
+       static unsigned int file_len = 0;
+       
+       unsigned char i2c_control_buf[2] = {ADDR_CMD, 0};
+       unsigned char i2c_states_buf[2] = {ADDR_STA, 0};
+       unsigned char i2c_data_buf[PACK_SIZE+1+8] = {ADDR_DAT,};
+       //unsigned char i2c_rd_buf[1+4+PACK_SIZE+4];
+       unsigned char i2c_rd_buf[160];
+       unsigned char retries = 0;
+       unsigned int rd_len;
+       unsigned char i = 0;
+       static unsigned char update_need_config = 0;
+
+       unsigned char checksum_error_times = 0;
+#ifdef UPDATE_NEW_PROTOCOL
+       unsigned int frame_checksum = 0;
+       unsigned int frame_number = 0;
+#else
+       unsigned char send_crc = 0;
+#endif
+
+       struct file * file_data = NULL;
+       mm_segment_t old_fs;
+       struct goodix_ts_data *ts;
+       
+       ts = i2c_get_clientdata(i2c_connect_client);
+       if(ts==NULL)
+               return 0;
+       
+       if(copy_from_user(&cmd, buff, len))
+       {
+               return -EFAULT;
+       }
+       switch(cmd[0])
+       {
+               case STEP_SET_PATH:
+                       printk(KERN_INFO"Write cmd is:%d,cmd arg is:%s,write len is:%ld\n",cmd[0], &cmd[1], len);
+                       memset(update_path, 0, 100);
+                       strncpy(update_path, cmd+1, 100);
+                       if(update_path[0] == 0)
+                               return 0;
+                       else
+                               return 1;
+               case STEP_CHECK_FILE:
+                       printk(KERN_INFO"Begin to firmware update ......\n");
+                       ret = update_file_check(update_path);
+                       if(ret <= 0)
+                       {
+                               printk(KERN_INFO"fialed to check update file!\n");
+                               return ret;
+                       }
+                       msleep(500);
+                       printk(KERN_INFO"Update check file success!\n");
+                       return 1;
+               case STEP_WRITE_SYN:
+                       printk(KERN_INFO"STEP1:Write synchronization signal!\n");
+                       i2c_control_buf[1] = UPDATE_START;
+                       if(ts->green_wake_mode)
+                       {
+                               //disable_irq(client->irq);
+                               gpio_direction_output(INT_PORT, 0);
+                               msleep(5);
+                               //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+                               gpio_direction_input(INT_PORT);
+                               //enable_irq(client->irq);
+                       }
+                       ret = i2c_write_bytes(ts->client, i2c_control_buf, 2);
+                       if(ret <= 0)
+                       {
+                               ret = ERROR_I2C_TRANSFER;
+                               return ret;
+                       }
+                       //the time include time(APROM -> LDROM) and time(LDROM init)
+                       msleep(1000);
+                       return 1;
+               case STEP_WAIT_SYN:
+                       printk(KERN_INFO"STEP2:Wait synchronization signal!\n");
+                       while(retries < MAX_I2C_RETRIES)
+                       {
+                               i2c_states_buf[1] = UNKNOWN_ERROR;
+                               ret = i2c_read_bytes(ts->client, i2c_states_buf, 2);
+                               printk(KERN_INFO"The read byte is:%d\n", i2c_states_buf[1]);
+                               if(i2c_states_buf[1] & UPDATE_START)
+                               {
+                                       if(i2c_states_buf[1] & NEW_UPDATE_START)
+                                       {
+                                       #ifdef UPDATE_NEW_PROTOCOL
+                                               update_need_config = 1;
+                                               return 2;
+                                       #else
+                                               return 1;
+                                       #endif
+                                       }
+                                       break;
+                               }
+                               msleep(5);
+                               retries++;
+                               time_count += 10;
+                       }
+                       if((retries >= MAX_I2C_RETRIES) && (!(i2c_states_buf[1] & UPDATE_START)))
+                       {
+                               if(ret <= 0)
+                                       return 0;
+                               else
+                                       return -1;
+                       }
+                       return 1;
+               case STEP_WRITE_LENGTH:
+                       printk(KERN_INFO"STEP3:Write total update file length!\n");
+                       file_len = update_get_flen(update_path);
+                       if(file_len <= 0)
+                       {
+                               printk(KERN_INFO"get update file length failed!\n");
+                               return -1;
+                       }
+                       file_len += 4;
+                       i2c_data_buf[1] = (file_len>>24) & 0xff;
+                       i2c_data_buf[2] = (file_len>>16) & 0xff;
+                       i2c_data_buf[3] = (file_len>>8) & 0xff;
+                       i2c_data_buf[4] = file_len & 0xff;
+                       file_len -= 4;
+                       ret = i2c_write_bytes(ts->client, i2c_data_buf, 5);
+                       if(ret <= 0)
+                       {
+                               ret = ERROR_I2C_TRANSFER;
+                               return 0;
+                       }
+                       return 1;
+               case STEP_WAIT_READY:
+                       printk(KERN_INFO"STEP4:Wait slave ready!\n");
+                       ret = wait_slave_ready(ts, &time_count);
+                       if(ret == ERROR_I2C_TRANSFER)
+                               return 0;
+                       if(!ret)
+                       {
+                               return -1;
+                       }
+                       printk(KERN_INFO"Slave ready!\n");
+                       return 1;
+               case STEP_WRITE_DATA:
+#ifdef UPDATE_NEW_PROTOCOL
+                       printk(KERN_INFO"STEP5:Begin to send file data use NEW protocol!\n");
+                       file_data = update_file_open(update_path, &old_fs);
+                       if(file_data == NULL)
+                       {
+                               return -1;
+                       }
+                       frame_number = 0;
+                       while(file_len >= 0)
+                       {
+                               i2c_data_buf[0] = ADDR_DAT;
+                               rd_len = (file_len >= PACK_SIZE) ? PACK_SIZE : file_len;
+                               frame_checksum = 0;
+                               if(file_len)
+                               {
+                                       ret = file_data->f_op->read(file_data, i2c_data_buf+1+4, rd_len, &file_data->f_pos);
+                                       if(ret <= 0)
+                                       {
+                                               printk("[GOODiX_ISP_NEW]:Read File Data Failed!\n");
+                                               return -1;
+                                       }
+                                       i2c_data_buf[1] = (frame_number>>24)&0xff;
+                                       i2c_data_buf[2] = (frame_number>>16)&0xff;
+                                       i2c_data_buf[3] = (frame_number>>8)&0xff;
+                                       i2c_data_buf[4] = frame_number&0xff;
+                                       frame_number++;
+                                       frame_checksum = 0;
+                                       for(i=0; i<rd_len; i++)
+                                       {
+                                               frame_checksum += i2c_data_buf[5+i];
+                                       }
+                                       frame_checksum = 0 - frame_checksum;
+                                       i2c_data_buf[5+rd_len+0] = frame_checksum&0xff;
+                                       i2c_data_buf[5+rd_len+1] = (frame_checksum>>8)&0xff;
+                                       i2c_data_buf[5+rd_len+2] = (frame_checksum>>16)&0xff;
+                                       i2c_data_buf[5+rd_len+3] = (frame_checksum>>24)&0xff;
+                               }
+rewrite:
+                               printk(KERN_INFO"[GOODiX_ISP_NEW]:%d\n", file_len);                             
+                               ret = i2c_write_bytes(ts->client, i2c_data_buf, 1+4+rd_len+4);
+                                       //if(ret <= 0)
+                               if(ret != 1)
+                               {
+                                       printk("[GOODiX_ISP_NEW]:Write File Data Failed!Return:%d\n", ret);
+                                       return 0;
+                               }
+
+                               memset(i2c_rd_buf, 0x00, 1+4+rd_len+4);
+                               ret = i2c_read_bytes(ts->client, i2c_rd_buf, 1+4+rd_len+4);
+                               if(ret != 2)
+                               {
+                                       printk("[GOODiX_ISP_NEW]:Read File Data Failed!Return:%d\n", ret);
+                                       return 0;
+                               }
+                               for(i=1; i<(1+4+rd_len+4); i++)                                         //check communication
+                               {
+                                       if(i2c_rd_buf[i] != i2c_data_buf[i])
+                                       {
+                                               i = 0;
+                                               break;
+                                       }
+                               }
+                               if(!i)
+                               {
+                                       i2c_control_buf[0] = ADDR_CMD;
+                                       i2c_control_buf[1] = 0x03;
+                                       i2c_write_bytes(ts->client, i2c_control_buf, 2);                //communication error
+                                       printk("[GOODiX_ISP_NEW]:File Data Frame readback check Error!\n");
+                               }
+                               else
+                               {
+                                       i2c_control_buf[1] = 0x04;                                                                                                      //let LDROM write flash
+                                       i2c_write_bytes(ts->client, i2c_control_buf, 2);
+                               }
+                               
+                               //Wait for slave ready signal.and read the checksum
+                               ret = wait_slave_ready(ts, &time_count);
+                               if((ret & CHECKSUM_ERROR)||(!i))
+                               {
+                                       if(i)
+                                       {
+                                               printk("[GOODiX_ISP_NEW]:File Data Frame checksum Error!\n");
+                                       }
+                                       checksum_error_times++;
+                                       msleep(20);
+                                       if(checksum_error_times > 20)                           //max retry times.
+                                               return 0;
+                                       goto rewrite;
+                               }
+                               checksum_error_times = 0;
+                               if(ret & (FRAME_ERROR))
+                               {
+                                       printk("[GOODiX_ISP_NEW]:File Data Frame Miss!\n");
+                                       return 0;
+                               }
+                               if(ret == ERROR_I2C_TRANSFER)
+                                       return 0;
+                               if(!ret)
+                               {
+                                       return -1;
+                               }
+                               if(file_len < PACK_SIZE)
+                               {
+                                       update_file_close(file_data, old_fs);
+                                       break;
+                               }
+                               file_len -= rd_len;
+                       }//end of while((file_len >= 0))
+                       return 1;
+#else
+                       printk(KERN_INFO"STEP5:Begin to send file data use OLD protocol!\n");
+                       file_data = update_file_open(update_path, &old_fs);
+                       if(file_data == NULL)   //file_data has been opened at the last time
+                       {
+                               return -1;
+                       }
+                       while((file_len >= 0) && (!send_crc))
+                       {
+                               printk(KERN_INFO"[GOODiX_ISP_OLD]:%d\n", file_len);
+                               i2c_data_buf[0] = ADDR_DAT;
+                               rd_len = (file_len >= PACK_SIZE) ? PACK_SIZE : file_len;
+                               if(file_len)
+                               {
+                                       ret = file_data->f_op->read(file_data, i2c_data_buf+1, rd_len, &file_data->f_pos);
+                                       if(ret <= 0)
+                                       {
+                                               return -1;
+                                       }
+                               }
+                               if(file_len < PACK_SIZE)
+                               {
+                                       send_crc = 1;
+                                       update_file_close(file_data, old_fs);
+                                       i2c_data_buf[file_len+1] = oldcrc32&0xff;
+                                       i2c_data_buf[file_len+2] = (oldcrc32>>8)&0xff;
+                                       i2c_data_buf[file_len+3] = (oldcrc32>>16)&0xff;
+                                       i2c_data_buf[file_len+4] = (oldcrc32>>24)&0xff;
+                                       ret = i2c_write_bytes(ts->client, i2c_data_buf, (file_len+1+4));
+                                       //if(ret <= 0)
+                                       if(ret != 1)
+                                       {
+                                               printk("[GOODiX_ISP_OLD]:Write File Data Failed!Return:%d\n", ret);
+                                               return 0;
+                                       }
+                                       break;
+                               }
+                               else
+                               {
+                                       ret = i2c_write_bytes(ts->client, i2c_data_buf, PACK_SIZE+1);
+                                       //if(ret <= 0)
+                                       if(ret != 1)
+                                       {
+                                               printk("[GOODiX_ISP_OLD]:Write File Data Failed!Return:%d\n", ret);
+                                               return 0;
+                                       }
+                               }
+                               file_len -= rd_len;
+                       
+                               //Wait for slave ready signal.
+                               ret = wait_slave_ready(ts, &time_count);
+                               if(ret == ERROR_I2C_TRANSFER)
+                                       return 0;
+                               if(!ret)
+                               {
+                                       return -1;
+                               }
+                               //Slave is ready.
+                       }//end of while((file_len >= 0) && (!send_crc))
+                       return 1;
+#endif
+               case STEP_READ_STATUS:
+                       printk(KERN_INFO"STEP6:Read update status!\n");
+                       while(time_count < MAX_TIMEOUT)
+                       {
+                               ret = i2c_read_bytes(ts->client, i2c_states_buf, 2);
+                               if(ret <= 0)
+                               {
+                                       return 0;
+                               }
+                               if(i2c_states_buf[1] & SLAVE_READY)
+                               {
+                                       if(!(i2c_states_buf[1] &0xf0))
+                                       {
+                                               printk(KERN_INFO"The firmware updating succeed!update state:0x%x\n",i2c_states_buf[1]);
+                                               return 1;
+                                       }
+                                       else
+                                       {
+                                               printk(KERN_INFO"The firmware updating failed!update state:0x%x\n",i2c_states_buf[1]);
+                                               return 0;
+
+                                       }
+                               }
+                               msleep(1);
+                               time_count += 5;
+                       }
+                       return -1;
+               case FUN_CLR_VAL:                                                               //clear the static val
+                       time_count = 0;
+                       file_len = 0;
+                       update_need_config = 0;
+                       return 1;
+               case FUN_CMD:                                                   //functional command
+                       if(cmd[1] == CMD_DISABLE_TP)
+                       {
+                               printk(KERN_INFO"Disable TS int!\n");
+                               g_enter_isp = 1;
+                               if(ts->use_irq)
+                                       disable_irq(TS_INT);
+                       }
+                       else if(cmd[1] == CMD_ENABLE_TP)
+                       {
+                               printk(KERN_INFO"Enable TS int!\n");
+                               g_enter_isp = 0;
+                               if(ts->use_irq)
+                                       enable_irq(TS_INT);
+                       }
+                       else if(cmd[1] == CMD_READ_VER)
+                       {
+                               printk(KERN_INFO"Read version!\n");
+                               ts->read_mode = MODE_RD_VER;
+                       }
+                       else if(cmd[1] == CMD_READ_RAW)
+                       {
+                               printk(KERN_INFO"Read raw data!\n");
+                               ts->read_mode = MODE_RD_RAW;
+                               i2c_control_buf[1] = 201;
+                               ret = i2c_write_bytes(ts->client, i2c_control_buf, 2);                  //read raw data cmd
+                               if(ret <= 0)
+                               {
+                                       printk(KERN_INFO"Write read raw data cmd failed!\n");
+                                       return 0;
+                               }
+                               msleep(200);
+                       }
+                       else if(cmd[1] == CMD_READ_DIF)
+                       {
+                               printk(KERN_INFO"Read diff data!\n");
+                               ts->read_mode = MODE_RD_DIF;
+                               i2c_control_buf[1] = 202;
+                               ret = i2c_write_bytes(ts->client, i2c_control_buf, 2);                  //read diff data cmd
+                               if(ret <= 0)
+                               {
+                                       printk(KERN_INFO"Write read raw data cmd failed!\n");
+                                       return 0;
+                               }
+                               msleep(200);
+                       }
+                       else if(cmd[1] == CMD_READ_CFG)
+                       {
+                               printk(KERN_INFO"Read config info!\n");
+                               ts->read_mode = MODE_RD_CFG;
+                               rd_cfg_addr = cmd[2];
+                               rd_cfg_len = cmd[3];
+                       }
+                       else if(cmd[1] == CMD_SYS_REBOOT)
+                       {
+                               printk(KERN_INFO"System reboot!\n");
+                               sys_sync();
+                               msleep(200);
+                               kernel_restart(NULL);
+                       }
+                       return 1;
+               case FUN_WRITE_CONFIG:
+                       
+                       printk(KERN_INFO"Begin write config info!Config length:%d\n",cmd[1]);
+                       for(i=3; i<cmd[1];i++)
+                       {
+                               //if((i-3)%5 == 0)printk("\n");
+                               printk("(%d):0x%x ", i-3, cmd[i]);
+                       }
+                       printk("\n");
+
+                       if((cmd[2]>83)&&(cmd[2]<240)&&cmd[1])
+                       {
+                               checksum_error_times = 0;
+                               if(ts->green_wake_mode)                 //WAKEUP GREEN MODE
+                               {
+                                       if(!update_need_config)
+                                               disable_irq(ts->client->irq);
+                                       gpio_direction_output(INT_PORT, 0);
+                                       msleep(5);
+                                       //s3c_gpio_cfgpin(INT_PORT, INT_CFG);
+                                       gpio_direction_input(INT_PORT);
+                                       if(!update_need_config)
+                                               enable_irq(ts->client->irq);
+                               }
+reconfig:
+                               ret = i2c_write_bytes(ts->client, cmd+2, cmd[1]); 
+                               if(ret != 1)
+                               {
+                                       printk("Write Config failed!return:%d\n",ret);
+                                       return -1;
+                               }
+                               if(!update_need_config)return 1;
+                               
+                               i2c_rd_buf[0] = cmd[2];
+                               ret = i2c_read_bytes(ts->client, i2c_rd_buf, cmd[1]);
+                               if(ret != 2)
+                               {
+                                       printk("Read Config failed!return:%d\n",ret);
+                                       return -1;
+                               }
+                               for(i=0; i<cmd[1]; i++)
+                               {
+                                       if(i2c_rd_buf[i] != cmd[i+2])
+                                       {
+                                               printk("Config readback check failed!\n");
+                                               i = 0;
+                                               break;
+                                       }
+                               }
+                               if(!i)
+                               {
+                                       i2c_control_buf[0] = ADDR_CMD;
+                                       i2c_control_buf[1] = 0x03;
+                                       i2c_write_bytes(ts->client, i2c_control_buf, 2);                //communication error
+                                       checksum_error_times++;
+                                       msleep(20);
+                                       if(checksum_error_times > 20)                           //max retry times.
+                                               return 0;
+                                       goto reconfig;
+                               }
+                               else
+                               {
+                                       i2c_control_buf[0] = ADDR_CMD;
+                                       i2c_control_buf[1] = 0x04;                                      //let LDROM write flash
+                                       i2c_write_bytes(ts->client, i2c_control_buf, 2);
+                                       return 1;
+                               }
+                               
+                       }
+                       else
+                       {
+                               printk(KERN_INFO"Invalid config addr!\n");
+                               return -1;
+                       }
+               default:
+                       return -ENOSYS;
+       }
+       return 0;
+}
+
+static int goodix_update_read( char *page, char **start, off_t off, int count, int *eof, void *data )
+{
+       int ret = -1;
+       struct goodix_ts_data *ts;
+       int len = 0;
+       char *version_info = NULL;
+       unsigned char read_data[1201] = {80, };
+
+       ts = i2c_get_clientdata(i2c_connect_client);
+       if(ts==NULL)
+               return 0;
+
+       if(ts->read_mode == MODE_RD_VER)                //read version data
+       {
+               ret = goodix_read_version(ts, &version_info);
+               if(ret <= 0)
+               {
+                       printk(KERN_INFO"Read version data failed!\n");
+                       vfree(version_info);
+                       return 0;
+               }
+
+               for(len=0;len<100;len++)
+               {
+                       if(*(version_info + len) == '\0')
+                               break;
+               }
+               printk(KERN_INFO"GOODiX Touchscreen Version is:%s\n", (version_info+1));
+               strncpy(page, version_info+1, len + 1);
+               vfree(version_info);
+               *eof = 1;
+               return len+1;
+       }
+       else if((ts->read_mode == MODE_RD_RAW)||(ts->read_mode == MODE_RD_DIF))         //read raw data or diff
+       {
+               //printk(KERN_INFO"Read raw data\n");
+               ret = i2c_read_bytes(ts->client, read_data, 1201);
+               if(ret <= 0)
+               {
+                       if(ts->read_mode == 2)
+                               printk(KERN_INFO"Read raw data failed!\n");
+                       if(ts->read_mode == 3)
+                               printk(KERN_INFO"Read diff data failed!\n");
+                       return 0;
+               }
+               memcpy(page, read_data+1, 1200);
+               *eof = 1;
+               *start = NULL;
+               return 1200;
+       }
+       else if(ts->read_mode == MODE_RD_CFG)
+       {
+               if((rd_cfg_addr>83)&&(rd_cfg_addr<240))
+               {
+                       read_data[0] = rd_cfg_addr;
+                       printk("read config addr is:%d\n", rd_cfg_addr);
+               }
+               else
+               {
+                       read_data[0] = 101;
+                       printk("invalid read config addr,use default!\n");
+               }
+               if((rd_cfg_len<0)||(rd_cfg_len>156))
+               {
+                       printk("invalid read config length,use default!\n");
+                       rd_cfg_len = 239 - read_data[0];
+               }
+               printk("read config length is:%d\n", rd_cfg_len);
+               ret = i2c_read_bytes(ts->client, read_data, rd_cfg_len);
+               if(ret <= 0)
+               {
+                       printk(KERN_INFO"Read config info failed!\n");
+                       return 0;
+               }
+               memcpy(page, read_data+1, rd_cfg_len);
+               return rd_cfg_len;
+       }
+       return len;
+}
+              
+#endif
+//******************************End of firmware update surpport*******************************
+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,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+       .suspend        = goodix_ts_suspend,
+       .resume         = goodix_ts_resume,
+#endif
+       .id_table       = goodix_ts_id,
+       .driver = {
+               .name   = GOODIX_I2C_NAME,
+               .owner = THIS_MODULE,
+       },
+};
+
+/*******************************************************       
+Description:
+       Driver Install function.
+return:
+       Executive Outcomes. 0---succeed.
+********************************************************/
+static int __devinit goodix_ts_init(void)
+{
+       int ret;
+       
+       goodix_wq = create_workqueue("goodix_wq");              //create a work queue and worker thread
+       if (!goodix_wq) {
+               printk(KERN_ALERT "creat workqueue faiked\n");
+               return -ENOMEM;
+               
+       }
+       ret=i2c_add_driver(&goodix_ts_driver);
+       return ret; 
+}
+
+/*******************************************************       
+Description:
+       Driver uninstall function.
+return:
+       Executive Outcomes. 0---succeed.
+********************************************************/
+static void __exit goodix_ts_exit(void)
+{
+       printk(KERN_ALERT "Touchscreen driver of guitar exited.\n");
+       i2c_del_driver(&goodix_ts_driver);
+       if (goodix_wq)
+               destroy_workqueue(goodix_wq);           //release our work queue
+}
+
+late_initcall(goodix_ts_init);
+module_exit(goodix_ts_exit);
+
+MODULE_DESCRIPTION("Goodix Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/goodix_touch_newton.h b/drivers/input/touchscreen/goodix_touch_newton.h
new file mode 100755 (executable)
index 0000000..6b16a13
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * include/linux/goodix_touch.h
+ *
+ * Copyright (C) 2010 - 2011 Goodix, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef        _LINUX_GOODIX_TOUCH_H
+#define                _LINUX_GOODIX_TOUCH_H
+
+#include <linux/earlysuspend.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+//*************************TouchScreen Work Part*****************************
+
+#define GOODIX_I2C_NAME "Goodix-TS"
+//define default resolution of the touchscreen
+#define TOUCH_MAX_HEIGHT       4096                    
+#define TOUCH_MAX_WIDTH                4096
+
+#define INT_PORT RK29_PIN0_PA2//           S3C64XX_GPN(15)                                             //Int IO port  S3C64XX_GPL(10)
+#ifdef INT_PORT
+       #define TS_INT          gpio_to_irq(INT_PORT)                   //Interrupt Number,EINT18(119)
+       #define INT_CFG         S3C_GPIO_SFN(3)                                 //IO configer as EINT
+#else
+       #define TS_INT  0
+#endif 
+
+//whether need send cfg?
+//#define DRIVER_SEND_CFG
+
+//set trigger mode
+#define INT_TRIGGER                    0
+
+#define POLL_TIME              10      //actual query spacing interval:POLL_TIME+6
+
+#define GOODIX_MULTI_TOUCH
+#ifdef GOODIX_MULTI_TOUCH
+       #define MAX_FINGER_NUM  10      
+#else
+       #define MAX_FINGER_NUM  1       
+#endif
+
+//#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
+
+struct goodix_ts_data {
+       uint16_t addr;
+       uint8_t bad_data;
+       struct i2c_client *client;
+       struct input_dev *input_dev;
+       int use_reset;          //use RESET flag
+       int use_irq;            //use EINT flag
+       int read_mode;          //read moudle mode,20110221 by andrew
+       struct hrtimer timer;
+       struct work_struct  work;
+       char phys[32];
+       int retry;
+       struct early_suspend early_suspend;
+       int (*power)(struct goodix_ts_data * ts, int on);
+       uint16_t abs_x_max;
+       uint16_t abs_y_max;
+       uint8_t max_touch_num;
+       uint8_t int_trigger_type;
+       uint8_t green_wake_mode;
+};
+
+static const char *goodix_ts_name = "Goodix Capacitive TouchScreen";
+static struct workqueue_struct *goodix_wq;
+struct i2c_client * i2c_connect_client = NULL;
+static struct proc_dir_entry *goodix_proc_entry;
+static struct kobject *goodix_debug_kobj;
+int ts_irq = 0;
+int int_gpio = 0;
+
+       
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void goodix_ts_early_suspend(struct early_suspend *h);
+static void goodix_ts_late_resume(struct early_suspend *h);
+#endif 
+
+//*****************************End of Part I *********************************
+
+//*************************Touchkey Surpport Part*****************************
+//#define HAVE_TOUCH_KEY
+#ifdef HAVE_TOUCH_KEY
+       #define READ_COOR_ADDR 0x00
+       const uint16_t touch_key_array[]={
+                                                                         KEY_MENU,                             //MENU
+                                                                         KEY_HOME,                             //HOME
+                                                                         KEY_SEND                              //CALL
+                                                                        }; 
+       #define MAX_KEY_NUM      (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
+#else
+       #define READ_COOR_ADDR 0x01
+#endif
+//*****************************End of Part II*********************************
+
+//*************************Firmware Update part*******************************
+#define CONFIG_TOUCHSCREEN_GOODIX_IAP
+#ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP
+#define UPDATE_NEW_PROTOCOL
+
+unsigned int oldcrc32 = 0xFFFFFFFF;
+unsigned int crc32_table[256];
+unsigned int ulPolynomial = 0x04c11db7;
+unsigned char rd_cfg_addr;
+unsigned char rd_cfg_len;
+unsigned char g_enter_isp = 0;
+
+static int goodix_update_write(struct file *filp, const char __user *buff, unsigned long len, void *data);
+static int goodix_update_read( char *page, char **start, off_t off, int count, int *eof, void *data );
+
+#define PACK_SIZE                                      64                                      //update file package size
+#define MAX_TIMEOUT                                    60000                           //update time out conut
+#define MAX_I2C_RETRIES                                20                                      //i2c retry times
+
+//I2C buf address
+#define ADDR_CMD                                       80
+#define ADDR_STA                                       81
+#ifdef UPDATE_NEW_PROTOCOL
+       #define ADDR_DAT                                0
+#else
+       #define ADDR_DAT                                82
+#endif
+
+//moudle state
+#define NEW_UPDATE_START                       0x01
+#define UPDATE_START                           0x02
+#define SLAVE_READY                                    0x08
+#define UNKNOWN_ERROR                          0x00
+#define FRAME_ERROR                                    0x10
+#define CHECKSUM_ERROR                         0x20
+#define TRANSLATE_ERROR                                0x40
+#define FLASH_ERROR                                    0X80
+
+//error no
+#define ERROR_NO_FILE                          2       //ENOENT
+#define ERROR_FILE_READ                                23      //ENFILE
+#define ERROR_FILE_TYPE                                21      //EISDIR
+#define ERROR_GPIO_REQUEST                     4       //EINTR
+#define ERROR_I2C_TRANSFER                     5       //EIO
+#define ERROR_NO_RESPONSE                      16      //EBUSY
+#define ERROR_TIMEOUT                          110     //ETIMEDOUT
+
+//update steps
+#define STEP_SET_PATH              1
+#define STEP_CHECK_FILE            2
+#define STEP_WRITE_SYN             3
+#define STEP_WAIT_SYN              4
+#define STEP_WRITE_LENGTH          5
+#define STEP_WAIT_READY            6
+#define STEP_WRITE_DATA            7
+#define STEP_READ_STATUS           8
+#define FUN_CLR_VAL                9
+#define FUN_CMD                    10
+#define FUN_WRITE_CONFIG           11
+
+//fun cmd
+#define CMD_DISABLE_TP             0
+#define CMD_ENABLE_TP              1
+#define CMD_READ_VER               2
+#define CMD_READ_RAW               3
+#define CMD_READ_DIF               4
+#define CMD_READ_CFG               5
+#define CMD_SYS_REBOOT             101
+
+//read mode
+#define MODE_RD_VER                1
+#define MODE_RD_RAW                2
+#define MODE_RD_DIF                3
+#define MODE_RD_CFG                4
+
+
+#endif
+//*****************************End of Part III********************************
+
+
+#endif /* _LINUX_GOODIX_TOUCH_H */