Input: touchscreen-gt9xx: enable the gt9xx SLOT REPORT
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / gt819.c
index 0f9ef295049db75e89768524e9ea29a9b093067a..109be9dffd6d9e00b36fdc426a736f255ad7cc99 100755 (executable)
 #include <linux/completion.h>
 #include <asm/uaccess.h>
 #include <mach/board.h>
+#include <linux/reboot.h>
 
 #define GOODIX_I2C_NAME "Goodix-TS"
 //define default resolution of the touchscreen
 #define GOODIX_MULTI_TOUCH
-#define GT819_IIC_SPEED              350*1000    //400*1000
+#define GT819_IIC_SPEED              400*1000    //400*1000
 #define TOUCH_MAX_WIDTH              800
 #define TOUCH_MAX_HEIGHT             480
 #define TOUCH_MAJOR_MAX              200
@@ -97,6 +98,7 @@ unsigned int crc32_table[256];
 unsigned int oldcrc32 = 0xFFFFFFFF;
 unsigned int ulPolynomial = 0x04c11db7;
 struct i2c_client * i2c_connect_client = NULL;
+static struct early_suspend gt819_power;
 static u8 gt819_fw[]=
 {
 #include "gt819_fw.i"
@@ -125,6 +127,15 @@ static int gt819_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned
        if(ret>0)
                return ret; 
        ret = i2c_master_reg8_recv(client, reg, buf, len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_recv(client, reg, buf, len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_recv(client, reg, buf, len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_recv(client, reg, buf, len, GT819_IIC_SPEED);
        return ret;
 }
 
@@ -136,6 +147,15 @@ static int gt819_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], uns
        if(ret>0)
                return ret; 
        ret = i2c_master_reg8_send(client, reg, buf, (int)len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_send(client, reg, buf, (int)len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_send(client, reg, buf, (int)len, GT819_IIC_SPEED);
+       if(ret>0)
+               return ret; 
+       ret = i2c_master_reg8_send(client, reg, buf, (int)len, GT819_IIC_SPEED);
        return ret;
 }
 
@@ -165,6 +185,7 @@ int gt189_wait_for_slave(struct i2c_client *client, u8 status)
                printk("i2c read state byte:0x%x\n",i2c_state_buf[0]);
                if(ret < 0)
                        return ERROR_I2C_TRANSFER;
+               if(i2c_state_buf[0]==0xff)continue;
                if(i2c_state_buf[0] & status)
                        return i2c_state_buf[0];
                msleep(10);
@@ -175,7 +196,7 @@ int gt189_wait_for_slave(struct i2c_client *client, u8 status)
 
 int gt819_update_write_config(struct i2c_client *client)
        {
-               int i,ret,len = sizeof(config_info)-1;                  //byte[0] is the reg addr in the gt819.cfg
+               int ret,len = sizeof(config_info)-1;                    //byte[0] is the reg addr in the gt819.cfg
                u8 cfg_rd_buf[len];
                u8 cfg_cmd_buf = 0x03;
                u8 retries = 0;
@@ -209,10 +230,10 @@ int gt819_update_write_config(struct i2c_client *client)
        }
 
 
-static int  gt819_read_version(struct i2c_client *client)
+static int  gt819_read_version(struct i2c_client *client,char *version)
 {
        int ret, count = 0;
-       char version[17],*p;
+       char *p;
        
        ret = gt819_read_regs(client,240, version, 16);
        if (ret < 0) 
@@ -271,12 +292,14 @@ resend:
                if(ret < 0)
                        return ret;
                //gt819_printf(i2c_data_buf, data_len);
+               msleep(10);
                dev_info(&client->dev, "PACK[%d]:read data\n",frame_number);
                memset(i2c_rd_buf, 0, sizeof(i2c_rd_buf));
                ret = gt819_read_regs(client,ADDR_DAT, i2c_rd_buf, data_len);
                if(ret < 0)
                        return ret;
                //gt819_printf(i2c_data_buf, data_len);
+               msleep(10);
                dev_info(&client->dev, "PACK[%d]:check data\n",frame_number);
                if(memcmp(&i2c_rd_buf[4],&fw_buf[frame_number*PACK_SIZE],check_len))
                {
@@ -328,10 +351,12 @@ int gt819_update_fw(struct i2c_client *client)
 {
        int ret,file_len,update_need_config;
        unsigned char i2c_control_buf[10];
+       char version[17];
+       const char version_base[17]={"GT81XNI"};
        
        dev_info(&client->dev, "gt819 firmware update start...\n");
        dev_info(&client->dev, "step 1:read version...\n");
-       ret = gt819_read_version(client);
+       ret = gt819_read_version(client,version);
        if (ret < 0) 
                return ret;
        dev_info(&client->dev, "done!\n");
@@ -392,10 +417,17 @@ int gt819_update_fw(struct i2c_client *client)
        dev_info(&client->dev, "done!\n");
        msleep(1000);                                           //wait slave reset
        dev_info(&client->dev, "step 11:read version...\n");
-       ret = gt819_read_version(client);
+       ret = gt819_read_version(client,version);
        if (ret < 0) 
                return ret;
        dev_info(&client->dev, "done!\n");
+       version[7] = '\0';
+       if(strcmp(version ,version_base)==0)
+       {
+               sys_sync();
+               msleep(200);
+               kernel_restart(NULL);
+       }
        return 0;
 }
 
@@ -405,13 +437,18 @@ static void gt819_queue_work(struct work_struct *work)
        struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);
        uint8_t  point_data[53]={ 0 };
        int ret,i,offset,points;
+       int points_chect;
        int x,y,w;
+       unsigned int  count = 0;
+       uint8_t  check_sum = 0;
        
-       ret = gt819_read_regs(ts->client,1, point_data, 1);
+       ret = gt819_read_regs(ts->client,1, point_data, 2);
        if (ret < 0) {
                dev_err(&ts->client->dev, "i2c_read_bytes fail:%d!\n",ret);
+               enable_irq(ts->irq);
                return;
        }
+       check_sum =point_data[0]+point_data[1];
        
        points = point_data[0] & 0x1f;
        //dev_info(&ts->client->dev, "points = %d\n",points);
@@ -423,15 +460,39 @@ static void gt819_queue_work(struct work_struct *work)
                enable_irq(ts->irq);
                dev_info(&ts->client->dev, "touch release\n");
                return; 
+       }       
+       for(i=0;0!=points;)
+       {
+       if(points&0x01)
+               i++;
+       points>>=1;
        }
-       for(i=0;0!=points;i++)
-               points>>=1;
+       
        points = i;
-       ret = gt819_read_regs(ts->client,3, point_data, points*5);
+       points_chect = points;
+       ret = gt819_read_regs(ts->client,3, point_data, points*5+1);
        if (ret < 0) {
                dev_err(&ts->client->dev, "i2c_read_bytes fail:%d!\n",ret);
+               enable_irq(ts->irq);
                return;
        }
+       //add by Nitiion
+       for(points_chect *= 5; points_chect > 0; points_chect--)
+               {
+               check_sum += point_data[count++];
+               }
+               check_sum += point_data[count];
+       if(check_sum  != 0)                     //checksum verify error
+               {
+                       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(data->input_dev);
+                       input_sync(ts->input_dev);
+                       enable_irq(ts->irq);
+                       dev_info(&ts->client->dev, "coor checksum error!touch release\n");
+                       return;
+               }
+               
        for(i=0;i<points;i++){
                offset = i*5;
                x = (((s16)(point_data[offset+0]))<<8) | ((s16)point_data[offset+1]);
@@ -495,6 +556,17 @@ static int gt819_resume(struct i2c_client *client)
        return 0;
 }
 
+static void gt819_early_suspend(struct early_suspend *h)
+{
+       dev_info(&i2c_connect_client->dev, "gt819_early_suspend!\n");
+       gt819_suspend(i2c_connect_client,PMSG_SUSPEND);
+}
+
+static void gt819_early_resume(struct early_suspend *h)
+{
+       dev_info(&i2c_connect_client->dev, "gt819_resume_early!\n");
+       gt819_resume(i2c_connect_client);
+}
 
 /*******************************************************
 Description:
@@ -513,14 +585,16 @@ static int gt819_remove(struct i2c_client *client)
        remove_proc_entry("goodix-update", NULL);
 #endif
        //goodix_debug_sysfs_deinit();
-               gpio_direction_input(ts->irq_gpio);
-               gpio_free(ts->irq_gpio);
-               free_irq(client->irq, ts);
+       gpio_direction_input(ts->irq_gpio);
+       gpio_free(ts->irq_gpio);
+       free_irq(client->irq, ts);
        if(ts->goodix_wq)
                destroy_workqueue(ts->goodix_wq); 
        dev_notice(&client->dev,"The driver is removing...\n");
        i2c_set_clientdata(client, NULL);
        input_unregister_device(ts->input_dev);
+    unregister_early_suspend(&gt819_power);
+       i2c_connect_client = 0;
        kfree(ts);
        return 0;
 }
@@ -528,7 +602,22 @@ static int gt819_remove(struct i2c_client *client)
 static int gt819_init_panel(struct goodix_ts_data *ts)
 {
        int ret,I2cDelay;
+       int len = sizeof(config_info)-1;
        uint8_t rd_cfg_buf[10];
+       struct goodix_platform_data *pdata = ts->client->dev.platform_data;
+
+       ret = gt819_set_regs(ts->client, 101, &config_info[1], len);
+       if(ret < 0)
+       {
+               pdata->platform_sleep();
+               msleep(10);
+               pdata->platform_wakeup();
+               msleep(100);
+               printk("First IIC request failed,retry!\n");
+               ret = gt819_set_regs(ts->client, 101, &config_info[1], len);
+               if(ret<0)
+               return ret;
+       }
 
        ret = gt819_read_regs(ts->client, 101, rd_cfg_buf, 10);
        if (ret < 0)
@@ -575,6 +664,8 @@ return:
 static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        int ret = 0;
+       char version[17];
+       char version_base[17]={"GT81XNI_1R05_18Q"};
        struct goodix_ts_data *ts;
        struct goodix_platform_data *pdata = client->dev.platform_data;
        const char irq_table[4] = {IRQ_TYPE_EDGE_RISING,
@@ -582,7 +673,7 @@ static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id
                                                           IRQ_TYPE_LEVEL_LOW,
                                                           IRQ_TYPE_LEVEL_HIGH};
 
-       dev_info(&client->dev,"Install touch driver\n");
+       dev_info(&client->dev,"Install goodix touch driver\n");
 
        if (!pdata) {
                dev_err(&client->dev, "platform data is required!\n");
@@ -608,7 +699,12 @@ static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id
          dev_err(&client->dev,"init panel fail,ret = %d\n",ret);
          goto err_init_panel_fail;
        }
-       //gt819_update_fw(client);
+
+       ret = gt819_read_version(client,version);       
+       if((ret>=0) && (strcmp(version ,version_base)!=0)){
+               gt819_update_fw(client);
+       }
+
        if (!client->irq){
                dev_err(&client->dev,"no irq fail\n");
                ret = -ENODEV;
@@ -624,11 +720,11 @@ static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id
        
        ts->goodix_wq = create_workqueue("goodix_wq");
        if (!ts->goodix_wq) {
-               printk(KERN_ALERT "creat workqueue faiked\n");
+               printk(KERN_ALERT "creat workqueue failed\n");
                ret = -ENOMEM;
                goto err_create_work_queue_fail;
        }
-       //INIT_WORK(&ts->work, goodix_ts_work_func);
+
        INIT_WORK(&ts->work, gt819_queue_work);
 
        ts->input_dev = input_allocate_device();
@@ -659,6 +755,10 @@ static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id
        }
        i2c_set_clientdata(client, ts);
        
+       gt819_power.suspend = gt819_early_suspend;
+       gt819_power.resume = gt819_early_resume;
+       gt819_power.level = 0x2;
+       register_early_suspend(&gt819_power);
        return 0;
        i2c_set_clientdata(client, NULL);
        input_unregister_device(ts->input_dev);
@@ -687,8 +787,6 @@ static const struct i2c_device_id gt819_id[] = {
 static struct i2c_driver gt819_driver = {
        .probe          = gt819_probe,
        .remove         = gt819_remove,
-       .suspend        = gt819_suspend,
-       .resume     = gt819_resume,
        .id_table       = gt819_id,
        .driver = {
                .name   = GOODIX_I2C_NAME,