您的位置:首页 > 编程语言 > Go语言

goodix 五点触摸屏驱动源文件分析

2012-08-18 16:26 453 查看
驱动的目录结构如下:

.../build.sh

.../driver

.../driver/gt818.h

.../driver/gt818_update.h

.../driver/gt818.mod.c //编译时自动生成

.../driver/gt818.c //主要驱动文件

.../driver/Makefile

.../firmware

.../firmware/update_0080.bin //固件

.../init.3rdparty.rc



备注:头文件(gt818.h) 请查看如下链接,这两份都是完整的代码。gt818_update.h 对于使用来说没有什么用处,可以不用。

/article/1921593.html

头文件(gt818_update.h)请查看如下链接。 内容很简单,就是一个存储参数的数组。

http://blog.csdn.net/duanlove/article/details/11127833




--------------------------------------------- gt818.c -----------------------------------------------------------------------------

/* drivers/input/touchscreen/goodix_touch.c

*

* Copyright (C) 2011 Goodix, Inc.

*

* Author: Felix

* Date: 2011.04.28

*

*/

#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 "gt818.h"//<linux/gt818.h>

#include "gt818_update.h"//<linux/gt818_50.h>

//#include <linux/goodix_queue.h>

#include <linux/vmalloc.h>

#include <linux/fs.h>

#include <linux/string.h>

#include <linux/completion.h>

#include <asm/uaccess.h>

#include <mach/ldo.h>

#include <mach/regs_ana.h>

#if !defined(GT801_PLUS) && !defined(GT801_NUVOTON)

#error The code does not match this touchscreen.

#endif



static struct workqueue_struct *goodix_wq;

static const char *s3c_ts_name = "pixcir_ts";

//static struct point_queue finger_list;

struct i2c_client * i2c_connect_client = NULL;

//EXPORT_SYMBOL(i2c_connect_client);

static struct proc_dir_entry *goodix_proc_entry;

static short goodix_read_version(struct goodix_ts_data *ts);

#ifdef CONFIG_HAS_EARLYSUSPEND

static void goodix_ts_early_suspend(struct early_suspend *h);

static void goodix_ts_late_resume(struct early_suspend *h);

static int gt818_downloader( struct goodix_ts_data *ts, unsigned char * data,unsigned char * path );

#endif

//used by firmware update CRC

unsigned int oldcrc32 = 0xFFFFFFFF;

unsigned int crc32_table[256];

unsigned int ulPolynomial = 0x04c11db7;

//static int gt818_gpio_tp_irq=0;

//static int shout_down_num=0;

//static int int_cfg_num=0;

//static int ts_int=0;

static int gt818_gpio_tp_irq_int_num=0;

static int gt818_gpio_tp_rst = 59;

static int gt818_gpio_tp_irq = 60;

static int gt818_wrong_num =0;

#define TS_DEBUG_MSG 1

//#define I2C_BOARD_INFO_METHOD 0

//#define TS_DATA_THRESHOLD_CHECK 1

//#define TS_WIDTH_MAX 320

//#define TS_HEIGHT_MAX 480

//static int debug_level=0;

#if TS_DEBUG_MSG

#define TS_DBG(format, ...) \

printk(KERN_INFO "gt818 " format "\n", ## __VA_ARGS__)

#else

#define TS_DBG(format, ...)

#endif

static struct sprd_i2c_setup_data {

unsigned i2c_bus; //the same number as i2c->adap.nr in adapter probe function

unsigned short i2c_address;

int irq;

char type[I2C_NAME_SIZE];

};

static struct sprd_i2c_setup_data gt818_ts_setup={1, GT818_TS_ADDR, 0, GOODIX_I2C_NAME};

static int gt818_sprd_add_i2c_device(struct sprd_i2c_setup_data *i2c_set_data, struct i2c_driver *driver)

{

struct i2c_board_info info;

struct i2c_adapter *adapter;

struct i2c_client *client;

int ret,err;

TS_DBG("%s : i2c_bus=%d; slave_address=0x%x; i2c_name=%s",__func__,i2c_set_data->i2c_bus, \

i2c_set_data->i2c_address, i2c_set_data->type);

memset(&info, 0, sizeof(struct i2c_board_info));

info.addr = i2c_set_data->i2c_address;

strlcpy(info.type, i2c_set_data->type, I2C_NAME_SIZE);

if(i2c_set_data->irq > 0)

info.irq = i2c_set_data->irq;

adapter = i2c_get_adapter( i2c_set_data->i2c_bus);

if (!adapter) {

printk("%s: can't get i2c adapter %d\n",

__func__, i2c_set_data->i2c_bus);

err = -ENODEV;

goto err_driver;

}

client = i2c_new_device(adapter, &info);

if (!client) {

printk("%s: can't add i2c device at 0x%x\n",

__func__, (unsigned int)info.addr);

err = -ENODEV;

goto err_driver;

}

i2c_put_adapter(adapter);

ret = i2c_add_driver(driver);

if (ret != 0) {

printk("%s: can't add i2c driver\n", __func__);

err = -ENODEV;

goto err_driver;

}

return 0;

err_driver:

return err;

}

static void gt818_sprd_del_i2c_device(struct i2c_client *client, struct i2c_driver *driver)

{

TS_DBG("%s : slave_address=0x%x; i2c_name=%s",__func__, client->addr, client->name);

i2c_unregister_device(client);

i2c_del_driver(driver);

}

//static struct sprd_i2c_setup_data ft5x0x_ts_setup={0, FT5206_TS_ADDR_R, 0, FT5206_TS_NAME};

/*******************************************************************************

* Function : ft5x0x_ts_config_pins

* Description : config gpio pins and set relative TS pins

* Parameters : void

* Return : int irq_num;

*******************************************************************************/

static int gt818_config_pins(void)

{

int gt818irq;

gpio_direction_output(gt818_gpio_tp_rst, 1);

gpio_direction_input(gt818_gpio_tp_irq);

gpio_set_value(gt818_gpio_tp_rst, 1);

gt818irq=sprd_alloc_gpio_irq(gt818_gpio_tp_irq);

msleep(10); //wait for stable



return gt818irq;

}



/*******************************************************

鍔熻兘锛?

璇诲彇浠庢満鏁版嵁

姣忎釜璇绘搷浣滅敤涓ゆ潯i2c_msg缁勬垚锛岀1鏉℃秷鎭敤浜庡彂閫佷粠鏈哄湴鍧€锛? 绗?鏉$敤浜庡彂閫佽鍙栧湴鍧€鍜屽彇鍥炴暟鎹紱姣忔潯娑堟伅鍓嶅彂閫佽捣濮嬩俊鍙?鍙傛暟锛? client: i2c璁惧锛屽寘鍚澶囧湴鍧€

buf[0]锛?棣栧瓧鑺備负璇诲彇鍦板潃

buf[1]~buf[len]锛氭暟鎹紦鍐插尯

len锛?璇诲彇鏁版嵁闀垮害

return锛? 鎵ц娑堟伅鏁?*********************************************************/

/*Function as i2c_master_send */

static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)

{

struct i2c_msg msgs[2];

int ret=-1;

//鍙戦€佸啓鍦板潃

msgs[0].flags=!I2C_M_RD;//鍐欐秷鎭? msgs[0].addr=client->addr;

msgs[0].len=2;

msgs[0].buf=&buf[0];

//鎺ユ敹鏁版嵁

msgs[1].flags=I2C_M_RD;//璇绘秷鎭? msgs[1].addr=client->addr;

msgs[1].len=len-2;

msgs[1].buf=&buf[2];



ret=i2c_transfer(client->adapter,msgs, 2);

return ret;

}

/*******************************************************

鍔熻兘锛? 鍚戜粠鏈哄啓鏁版嵁

鍙傛暟锛? client: i2c璁惧锛屽寘鍚澶囧湴鍧€

buf[0]锛?棣栧瓧鑺備负鍐欏湴鍧€

buf[1]~buf[len]锛氭暟鎹紦鍐插尯

len锛?鏁版嵁闀垮害

return锛? 鎵ц娑堟伅鏁?*******************************************************/

/*Function as i2c_master_send */

static int i2c_write_bytes(struct i2c_client *client,uint8_t *data,int len)

{

struct i2c_msg msg;

int ret=-1;

//鍙戦€佽澶囧湴鍧€

msg.flags=!I2C_M_RD;//鍐欐秷鎭? msg.addr=client->addr;

msg.len=len;

msg.buf=data;



ret=i2c_transfer(client->adapter,&msg, 1);

return ret;

}

/*******************************************************

鍔熻兘锛? 鍙戦€佸墠缂€鍛戒护



ts: client绉佹湁鏁版嵁缁撴瀯浣?return锛?

鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

*******************************************************/

static int i2c_pre_cmd(struct goodix_ts_data *ts)

{

int ret;

uint8_t pre_cmd_data[2]={0};

pre_cmd_data[0]=0x0f;

pre_cmd_data[1]=0xff;

ret=i2c_write_bytes(ts->client,pre_cmd_data,2);

//msleep(2);

return ret;

}

/*******************************************************

鍔熻兘锛? 鍙戦€佸悗缂€鍛戒护



ts: client绉佹湁鏁版嵁缁撴瀯浣?return锛?

鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

*******************************************************/

static int i2c_end_cmd(struct goodix_ts_data *ts)

{

int ret;

uint8_t end_cmd_data[2]={0};

end_cmd_data[0]=0x80;

end_cmd_data[1]=0x00;

ret=i2c_write_bytes(ts->client,end_cmd_data,2);

//msleep(2);

return ret;

}

/*

*/

static short get_chip_version( unsigned int sw_ver )

{

if ( (sw_ver&0xff) < TPD_CHIP_VERSION_C_FIRMWARE_BASE )

return TPD_GT818_VERSION_B;

else if ( (sw_ver&0xff) < TPD_CHIP_VERSION_D_FIRMWARE_BASE )

return TPD_GT818_VERSION_C;

else

return TPD_GT818_VERSION_D;

}

/*******************************************************

鍔熻兘锛? Guitar鍒濆鍖栧嚱鏁帮紝鐢ㄤ簬鍙戦€侀厤缃俊鎭紝鑾峰彇鐗堟湰淇℃伅

鍙傛暟锛? ts: client绉佹湁鏁版嵁缁撴瀯浣?return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

*******************************************************/

static int goodix_init_panel(struct goodix_ts_data *ts)

{

short ret=-1;

// int ic_size = 0;

#if 1

uint8_t config_info_c[] = { //Touch key devlop board

0x06,0xA2,

0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0xE0,0x00,0xD0,0x00,0xC0,0x00,

0xB0,0x00,0xA0,0x00,0x90,0x00,0x80,0x00,

0x70,0x00,0x00,0x00,0x10,0x00,0x20,0x00,

0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,

0x00,0x00,0x01,0x13,0x80,0x88,0x90,0x14,

0x15,0x40,0x0F,0x0F,0x0A,0x50,0x3C,0x0C,

0x00,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x46,0x5A,0x00,0x00,0x00,0x00,0x03,

0x19,0x05,0x00,0x00,0x00,0x00,0x00,0x00,

0x20,0x10,0x00,0x04,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,

0x00,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

};



uint8_t config_info_d[] = { //Touch key devlop board

#if 0

0x06,0xA2,

0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0xE0,0x00,0xD0,0x00,0xC0,0x00,

0xB0,0x00,0xA0,0x00,0x90,0x00,0x80,0x00,

0x70,0x00,0x00,0x00,0x10,0x00,0x20,0x00,

0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,

0x00,0x00,0x0B,0x13,0x90,0x90,0x90,0x27,

0x27,0x27,0x0F,0x0F,0x0A,0x50,0x3C,0x4B,

0x00,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x46,0x5A,0x00,0x00,0x00,0x00,0x03,

0x19,0x05,0x05,0x00,0x00,0x00,0x00,0x00,

0x20,0x10,0x00,0x04,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,

0x00,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

/*0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0xE0,0x00,0xD0,0x00,0xC0,0x00,

0xB0,0x00,0xA0,0x00,0x90,0x00,0x80,0x00,

0x70,0x00,0x00,0x00,0x10,0x00,0x20,0x00,

0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,

0x00,0x00,0x01,0x13,0x80,0x88,0x90,0x14,

0x15,0x40,0x0F,0x0F,0x0A,0x50,0x3C,0x0C,

0x00,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x46,0x5A,0x00,0x00,0x00,0x00,0x03,

0x19,0x05,0x00,0x00,0x00,0x00,0x00,0x00,

0x20,0x10,0x00,0x04,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,

0x00,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

*/

#endif



#if 1 //defined(CONFIG_S9_IPhone) //s9 hua fei jeed



/*0x06,0xA2,

0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,

0x02,0x00,0x02,0x22,0x12,0x22,0x22,0x22,

0x32,0x22,0x42,0x22,0x52,0x22,0x62,0x22,

0xE2,0x22,0xD2,0x22,0xC2,0x22,0xB2,0x22,

0xA2,0x22,0x92,0x22,0x82,0x22,0x72,0x22,

0xF2,0x22,0x37,0x03,0xA8,0xA8,0xA8,0x1A,

0x1A,0x1A,0x0F,0x0E,0x0A,0x48,0x38,0x09,

//0x03,0x00,0x05,0x40,0x01,0xE0,0x01,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x5C,0x57,0x60,0x5A,0x00,0x00,0x23,

0x14,0x05,0x05,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0xCE,0x03,0x00,0x40,0x37,0x10,

0x31,0x00,0x40,0x50,0x60,0x70,0x0D,0x40,

0x30,0x25,0x20,0x00,0x00,0x00,0x00,0x00,

0x00,0x01*/

/*0x06,0xA2,

0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0x60,0x00,0x50,0x00,0x40,0x00,

0x30,0x00,0x20,0x00,0x10,0x00,0x00,0x00,

0xF0,0x00,0xE0,0x00,0xD0,0x00,0xC0,0x00,

0xB0,0x00,0xA0,0x00,0x90,0x00,0x80,0x00,

0x70,0x00,0x1B,0x03,0x70,0x70,0x70,0x26,

0x26,0x26,0x10,0x0F,0x0A,0x50,0x30,0x45,

//0x03,0x16,0x05,0xE0,0x01,0x20,0x03,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x55,0x4F,0x58,0x52,0x00,0x00,0x03,

0x14,0x05,0x06,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0x74,0x03,0x00,0x40,0x37,0x50,

0x26,0x00,0x10,0x20,0x00,0x00,0x0D,0x40,

0x30,0x3C,0x14,0x00,0x00,0x00,0x00,0x00,

0x00,0x01*/

/*

0x06,0xA2,

0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,

0x02,0x00,0x70,0x00,0x60,0x00,0x50,0x00,

0x40,0x00,0x30,0x00,0x20,0x00,0x10,0x00,

0x00,0x00,0xF0,0x00,0xE0,0x00,0xD0,0x00,

0xC0,0x00,0xB0,0x00,0xA0,0x00,0x90,0x00,

0x80,0x00,0x1B,0x03,0x70,0x70,0x70,0x27,

0x27,0x27,0x10,0x0F,0x0A,0x50,0x30,0x0D,

//0x03,0x16,0x05,0xE0,0x01,0x20,0x03,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x55,0x4F,0x58,0x52,0x00,0x00,0x03,

0x14,0x05,0x06,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0x74,0x03,0x00,0x40,0x37,0x30,

0x26,0x00,0x70,0x80,0x90,0xA0,0x0D,0x40,

0x30,0x3C,0x14,0x00,0x00,0x00,0x00,0x00,

0x00,0x01*/

0x06,0xA2,

0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0x00,0x00,0x10,0x00,0x20,0x00,

0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,

0x70,0x00,0x80,0x00,0x90,0x00,0xA0,0x00,

0xB0,0x00,0xC0,0x00,0xD0,0x00,0xE0,0x00,

0xF0,0x00,0x3B,0x13,0x10,0x10,0x10,0x1E,

0x1E,0x1E,0x10,0x0F,0x0A,0x5A,0x4A,0x4F,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x50,0x49,0x54,0x4C,0x00,0x00,0x1B,

0x14,0x05,0x0A,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0x31,0x03,0x00,0x40,0x3B,0x10,

0x21,0x00,0x70,0x80,0x90,0xA0,0x0B,0x50,

0x40,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

#elif 0 //defined(CONFIG_S1_IPhone) // s1 lce



0x06,0xA2,

0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,

0x02,0x00,0x80,0x00,0x90,0x00,0xA0,0x00,

0xB0,0x00,0xC0,0x00,0xD0,0x00,0xE0,0x00,

0xF0,0x00,0x70,0x00,0x60,0x00,0x50,0x00,

0x40,0x00,0x30,0x00,0x20,0x00,0x10,0x00,

0x00,0x00,0x07,0x03,0x10,0x10,0x10,0x24,

0x24,0x24,0x10,0x0F,0x0A,0x40,0x30,0x0D,

//0x03,0x00,0x05,0x00,0x14,0x00,0x1E,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x5A,0x5D,0x5E,0x61,0x00,0x00,0x03,

0x14,0x00,0x06,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0xEF,0x03,0x00,0x00,0x00,0x00,

0x00,0x00,0x22,0x45,0x6C,0x92,0x0D,0x40,

0x30,0x25,0x20,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

#elif 0 //s9 hua fei soeya



/*0x06,0xA2,

0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,

0x10,0x12,0x81,0x11,0x91,0x11,0xA1,0x11,

0xB1,0x11,0xC1,0x11,0xD1,0x11,0xE1,0x11,

0x71,0x11,0x61,0x11,0x51,0x11,0x41,0x11,

0x31,0x11,0x21,0x11,0x11,0x11,0x01,0x11,

0xF1,0x11,0x07,0x03,0x10,0x10,0x10,0x25,

0x25,0x25,0x0F,0x0E,0x0A,0x40,0x30,0x09,

//0x03,0x00,0x05,0x40,0x01,0xE0,0x01,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x5C,0x4F,0x60,0x53,0x00,0x00,0x02,

0x14,0x00,0x04,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0x74,0x03,0x00,0x30,0x37,0x10,

0x28,0x00,0x40,0x72,0x61,0x50,0x0F,0x35,

0x25,0x25,0x1A,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

*/

#else

0x06,0xA2, // lce jeed

0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,

0x02,0x00,0x70,0x00,0x60,0x00,0x50,0x00,

0x40,0x00,0x30,0x00,0x20,0x00,0x10,0x00,

0x00,0x00,0x80,0x00,0x90,0x00,0xA0,0x00,

0xB0,0x00,0xC0,0x00,0xD0,0x00,0xE0,0x00,

0xF0,0x00,0x17,0x13,0xE8,0xE8,0xE8,0x1C,

0x1C,0x1C,0x10,0x0F,0x0A,0x50,0x40,0x09,

//0x03,0x00,0x05,0xE0,0x01,0x20,0x03,0x00,

0x03,0x00,MAX_FINGER_NUM,(TOUCH_MAX_WIDTH&0xff),(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_HEIGHT&0xff),(TOUCH_MAX_HEIGHT>>8),0x00,

0x00,0x5C,0x5C,0x60,0x60,0x00,0x00,0x23,

0x14,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0x06,0x04,0x00,0x40,0x17,0x10,

0x1E,0x00,0x30,0x40,0x50,0x60,0x0A,0x50,

0x40,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,

0x00,0x01

#endif



};

#endif







ret = goodix_read_version(ts);

if (ret < 0)

return ret;



dev_info(&ts->client->dev," Guitar Version: %d\n",ts->version);



if((ts->version&0xff) < TPD_CHIP_VERSION_D_FIRMWARE_BASE)

{

dev_info(&ts->client->dev," Guitar Version: C\n");

config_info_c[57] = (config_info_c[57]&0xf7)|(INT_TRIGGER<<3);

ret=i2c_write_bytes(ts->client,config_info_c, (sizeof(config_info_c)/sizeof(config_info_c[0])));

}

else

{

dev_info(&ts->client->dev," Guitar Version: D\n");

config_info_d[57] = (config_info_d[57]&0xf7)|(INT_TRIGGER<<3);

ret=i2c_write_bytes(ts->client,config_info_d, (sizeof(config_info_d)/sizeof(config_info_d[0])));

}

if (ret < 0)

return ret;

msleep(10);

return 0;

}

/*******************************************************

鍔熻兘锛? 鑾峰彇鐗堟湰淇℃伅

鍙傛暟锛? ts: client绉佹湁鏁版嵁缁撴瀯浣?return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

*******************************************************/

static short goodix_read_version(struct goodix_ts_data *ts)

{

short ret;

uint8_t version_data[5]={0}; //store touchscreen version infomation

memset(version_data, 0, 5);

version_data[0]=0x07;

version_data[1]=0x17;

msleep(5);

//ret=i2c_read_bytes(ts->client, version_data, 4);

//msleep(2);

ret=i2c_read_bytes(ts->client, version_data, 4);

if (ret < 0)

return ret;

dev_info(&ts->client->dev," Guitar Version: %d.%d\n",version_data[3],version_data[2]);

ts->version = (version_data[3]<<8)+version_data[2];

return ret;



}

/*******************************************************

鍔熻兘锛? 瑙︽懜灞忓伐浣滃嚱鏁? 鐢变腑鏂Е鍙戯紝鎺ュ彈1缁勫潗鏍囨暟鎹紝鏍¢獙鍚庡啀鍒嗘瀽杈撳嚭

鍙傛暟锛? ts: client绉佹湁鏁版嵁缁撴瀯浣?return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

********************************************************/

static void goodix_ts_work_func(struct work_struct *work)

{

uint8_t touch_data[3] = {READ_TOUCH_ADDR_H,READ_TOUCH_ADDR_L,0};

uint8_t key_data[3] ={READ_KEY_ADDR_H,READ_KEY_ADDR_L,0};

uint8_t point_data[8*MAX_FINGER_NUM+2]={ 0 };

static uint8_t finger_last[MAX_FINGER_NUM+1]={0}; //涓婃瑙︽懜鎸夐敭鐨勬墜鎸囩储寮? uint8_t finger_current[MAX_FINGER_NUM+1] = {0}; //褰撳墠瑙︽懜鎸夐敭鐨勬墜鎸囩储寮? uint8_t coor_data[6*MAX_FINGER_NUM] = {0}; //瀵瑰簲鎵嬫寚鐨勬暟鎹? static uint8_t last_key = 0;

uint8_t finger = 0;

uint8_t key = 0;

unsigned int count = 0;

unsigned int position = 0;

int ret=-1;

int tmp = 0;

int temp = 0;

uint16_t *coor_point;

//printk("goodix \n");

struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);

i2c_pre_cmd(ts);

#ifndef INT_PORT

COORDINATE_POLL:

#endif

if( tmp > 9) {

dev_info(&(ts->client->dev), "Because of transfer error,touchscreen stop working.\n");

goto XFER_ERROR ;

}

ret=i2c_read_bytes(ts->client, touch_data,sizeof(touch_data)/sizeof(touch_data[0])); //璇?x712锛岃Е鎽? if(ret <= 0) {

dev_err(&(ts->client->dev),"I2C transfer error. Number:%d\n ", ret);

ts->bad_data = 1;

tmp ++;

ts->retry++;

#ifndef INT_PORT

goto COORDINATE_POLL;

#else

goto XFER_ERROR;

#endif

}



#ifdef H***E_TOUCH_KEY

ret=i2c_read_bytes(ts->client, key_data,sizeof(key_data)/sizeof(key_data[0])); //璇?x721锛屾寜閿?

if(ret <= 0) {

dev_err(&(ts->client->dev),"I2C transfer error. Number:%d\n ", ret);

ts->bad_data = 1;

tmp ++;

ts->retry++;

#ifndef INT_PORT

goto COORDINATE_POLL;

#else

goto XFER_ERROR;

#endif

}

key = key_data[2]&0x0f;

#endif

if(ts->bad_data)

//TODO:Is sending config once again (to reset the chip) useful?

msleep(20);

#if 1

if(touch_data[2] == 0x0f)

{

printk("goodix 01=%x\n",touch_data[2]);

goodix_init_panel(ts);

goto DATA_NO_READY;

}



if((touch_data[2]&0x30)!=0x20)

{

printk("goodix 02=%x\n",touch_data[2]&0x30);

gt818_wrong_num++;

if(gt818_wrong_num>5)

{

gt818_wrong_num=0;

goodix_init_panel(ts);

}

goto DATA_NO_READY;

}

gt818_wrong_num=0;



#else

printk("goodix %x\n",touch_data[2]);



if((touch_data[2]&0x30)!=0x20)

{

printk("goodix 01=%x\n",touch_data[2]&0x30);

gt818_wrong_num++;

if(gt818_wrong_num>5)

{

gt818_wrong_num=0;

//goodix_init_panel(ts);

}

goto DATA_NO_READY;

}

gt818_wrong_num=0;

if((touch_data[2]&0x0f) == 0x0f)

{

printk("goodix 02=%x\n",touch_data[2]&0x0f);

goodix_init_panel(ts);

goto DATA_NO_READY;

}

#endif



ts->bad_data = 0;



finger = touch_data[2]&0x0f;

if(finger != 0)

{

point_data[0] = READ_COOR_ADDR_H; //read coor high address

point_data[1] = READ_COOR_ADDR_L; //read coor low address

ret=i2c_read_bytes(ts->client, point_data, finger*8+2);

if(ret <= 0)

{

dev_err(&(ts->client->dev),"I2C transfer error. Number:%d\n ", ret);

ts->bad_data = 1;

tmp ++;

ts->retry++;

#ifndef INT_PORT

goto COORDINATE_POLL;

#else

goto XFER_ERROR;

#endif

}



for(position=2; position<((finger-1)*8+2+1); position += 8)

{

temp = point_data[position];

if(temp<(MAX_FINGER_NUM+1))

{

finger_current[temp] = 1;

for(count=0; count<6; count++)

{

coor_data[(temp-1)*6+count] = point_data[position+1+count]; //璁板綍褰撳墠鎵嬫寚绱㈠紩锛屽苟瑁呰浇鍧愭爣鏁版嵁

}

}

else

{

dev_err(&(ts->client->dev),"Track Id error:%d\n ",0);

ts->bad_data = 1;

tmp ++;

ts->retry++;

#ifndef INT_PORT

goto COORDINATE_POLL;

#else

goto XFER_ERROR;

#endif

}

}

//coor_point = (uint16_t *)coor_data;



}



else

{

for(position=1;position < MAX_FINGER_NUM+1; position++)

{

finger_current[position] = 0;

}

}

coor_point = (uint16_t *)coor_data;

for(position=1;position < MAX_FINGER_NUM+1; position++)

{

if((finger_current[position] == 0)&&(finger_last[position] != 0))

{

input_report_abs(ts->input_dev, ABS_MT_POSITION_X, 0);

input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, 0);

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);

//printk("report error\n");

}

else if(finger_current[position])

{

input_report_abs(ts->input_dev, ABS_MT_POSITION_X, (*(coor_point+3*(position-1)))); //can change x-y!!!

input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, (*(coor_point+3*(position-1)+1)));

input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,1);

//input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, finger_list.pointer[0].pressure);

input_mt_sync(ts->input_dev);

// input_report_abs(ts->input_dev, ABS_X, finger_list.pointer[0].x);

// input_report_abs(ts->input_dev, ABS_Y, finger_list.pointer[0].y)

// input_report_abs(ts->input_dev, ABS_PRESSURE, finger_list.pointer[0].pressure);

// input_sync(ts->input_dev);

// printk("%d*",(*(coor_point+3*(position-1)))*SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT));

// printk("%d*",(*(coor_point+3*(position-1)+1))*SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH));

// printk("\n");

//printk("x=%d ",(*(coor_point+3*(position-1))));

//printk("y=%d ",(*(coor_point+3*(position-1)+1)));

printk("\n");

}



}

input_sync(ts->input_dev);



for(position=1;position<MAX_FINGER_NUM+1; position++)

{

finger_last[position] = finger_current[position];

}



#ifdef H***E_TOUCH_KEY

if((last_key == 0)&&(key == 0))

;

else

{

for(count = 0; count < 4; count++)

{

input_report_key(ts->input_dev, touch_key_array[count], !!(key&(0x01<<count)));

}

//printk("goodix key=%d \n",key);



}

last_key = key;

#endif

DATA_NO_READY:

XFER_ERROR:

i2c_end_cmd(ts);

if(ts->use_irq)

enable_irq(ts->client->irq);

}

/*******************************************************

鍔熻兘锛? 璁℃椂鍣ㄥ搷搴斿嚱鏁? 鐢辫鏃跺櫒瑙﹀彂锛岃皟搴﹁Е鎽稿睆宸ヤ綔鍑芥暟杩愯锛涗箣鍚庨噸鏂拌鏃?鍙傛暟锛? timer锛氬嚱鏁板叧鑱旂殑璁℃椂鍣?

return锛? 璁℃椂鍣ㄥ伐浣滄ā寮忥紝HRTIMER_NORESTART琛ㄧず涓嶉渶瑕佽嚜鍔ㄩ噸鍚?********************************************************/

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;

}

/*******************************************************

鍔熻兘锛? 涓柇鍝嶅簲鍑芥暟

鐢变腑鏂Е鍙戯紝璋冨害瑙︽懜灞忓鐞嗗嚱鏁拌繍琛?鍙傛暟锛? timer锛氬嚱鏁板叧鑱旂殑璁℃椂鍣?

return锛? 璁℃椂鍣ㄥ伐浣滄ā寮忥紝HRTIMER_NORESTART琛ㄧず涓嶉渶瑕佽嚜鍔ㄩ噸鍚?********************************************************/

static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)

{

struct goodix_ts_data *ts = dev_id;

//printk(KERN_INFO"-------------------ts_irq_handler------------------\n");

disable_irq_nosync(ts->client->irq);

queue_work(goodix_wq, &ts->work);



return IRQ_HANDLED;

}

/*******************************************************

鍔熻兘锛? 绠$悊GT801鐨勭數婧愶紝鍏佽GT801 PLUS杩涘叆鐫$湢鎴栧皢鍏跺敜閱?鍙傛暟锛? on: 0琛ㄧず浣胯兘鐫$湢锛?涓哄敜閱?return锛? 鏄惁璁剧疆鎴愬姛锛?涓烘垚鍔? 閿欒鐮侊細-1涓篿2c閿欒锛?2涓篏PIO閿欒锛?EINVAL涓哄弬鏁皁n閿欒

********************************************************/

//#if defined(INT_PORT)

static int goodix_ts_power(struct goodix_ts_data * ts, int on)

{

int ret = -1;

int retry = 50;//zsf add

unsigned char i2c_control_buf[3] = {0x06,0x92,0x01}; //suspend cmd



#ifdef INT_PORT

if(ts != NULL && !ts->use_irq)

return -2;

#endif

switch(on)

{

case 0:

i2c_pre_cmd(ts); //must

ret = i2c_write_bytes(ts->client, i2c_control_buf, 3);

printk(KERN_INFO"Send suspend cmd\n");

if(ret > 0) //failed

ret = 0;

i2c_end_cmd(ts); //must

return ret;



case 1:

//zsf add start

sndpw_retry:

retry--;

//zsf add end

#if 0 // #ifdef INT_PORT //suggest use INT PORT to wake up !!!

gpio_direction_output(gt818_gpio_tp_irq, 0);

msleep(20);

gpio_direction_output(gt818_gpio_tp_irq, 1);

msleep(20);

gpio_direction_output(gt818_gpio_tp_irq, 0);

gpio_free(gt818_gpio_tp_irq);

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE);

//if(ts->use_irq)

// s3c_gpio_cfgpin(gt818_gpio_tp_irq, int_cfg_num); //Set IO port as interrupt port

//else

gpio_direction_input(gt818_gpio_tp_irq);



#else

gpio_direction_output(gt818_gpio_tp_rst,0);

msleep(1);

gpio_direction_input(gt818_gpio_tp_rst);

#endif

msleep(40);

ret = goodix_init_panel(ts);

if(ret < 0&& retry>0)//zsf add

goto sndpw_retry;

return ret;



default:

printk(KERN_DEBUG "%s: Cant't support this command.", s3c_ts_name);

return -EINVAL;

}

}

/*******************************************************

鍔熻兘锛? 瑙︽懜灞忔帰娴嬪嚱鏁? 鍦ㄦ敞鍐岄┍鍔ㄦ椂璋冪敤(瑕佹眰瀛樺湪瀵瑰簲鐨刢lient)锛? 鐢ㄤ簬IO,涓柇绛夎祫婧愮敵璇凤紱璁惧娉ㄥ唽锛涜Е鎽稿睆鍒濆鍖栫瓑宸ヤ綔

鍙傛暟锛? client锛氬緟椹卞姩鐨勮澶囩粨鏋勪綋

id锛氳澶嘔D

return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

********************************************************/

static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

//TODO:鍦ㄦ祴璇曞け璐ュ悗闇€瑕侀噴鏀総s

int ret = 0;

int retry=0;

//unsigned short version_temp = 0;

unsigned char update_path[1] = {0};

#if defined(NO_DEFAULT_ID) && defined(INT_PORT)

uint8_t goodix_id[3] = {0,0xff,0};

#endif

char test_data = 1;

struct goodix_ts_data *ts;

struct goodix_i2c_rmi_platform_data *pdata;

dev_dbg(&client->dev,"Install touch driver.\n");

//Check I2C function

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; //used by Guitar_Update



#ifdef INT_PORT

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE);

#endif



#if defined(NO_DEFAULT_ID) && defined(INT_PORT)

for(retry=0;retry < 3; retry++)

{

gpio_direction_output(gt818_gpio_tp_rst,0);

msleep(1);

gpio_direction_input(gt818_gpio_tp_rst);

msleep(20);



ret =i2c_write_bytes(client, &test_data, 1); //Test I2C connection.

if (ret > 0)

break;

}

if(ret <= 0)

{

gpio_direction_output(gt818_gpio_tp_irq,0);

msleep(1);

gpio_direction_output(gt818_gpio_tp_rst,0);

msleep(20);

gpio_direction_input(gt818_gpio_tp_rst);

for(retry=0;retry < 80; retry++)

{

ret =i2c_write_bytes(client, &test_data, 1); //Test I2C connection.

if (ret > 0)

{

msleep(10);

ret =i2c_read_bytes(client, goodix_id, 3); //Test I2C connection.

if (ret > 0)

{

if(goodix_id[2] == 0x55)

{

gpio_direction_output(gt818_gpio_tp_irq,1);

msleep(1);

gpio_free(gt818_gpio_tp_irq);

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE);

msleep(10);

break;

}

}

}



}

}

#endif

//while(1)

for(retry=0;retry < 3; retry++)

{

gpio_direction_output(gt818_gpio_tp_rst,0);

msleep(1);

gpio_direction_input(gt818_gpio_tp_rst);

msleep(20);

//gt818_ts_reset();

ret =i2c_write_bytes(client, &test_data, 1); //Test I2C connection.

if (ret > 0)

break;

}



if(ret <= 0)

{

dev_err(&client->dev, "Warnning: I2C communication might be ERROR ret=%d!\n", ret);

goto err_i2c_failed;

}



INIT_WORK(&ts->work, goodix_ts_work_func); //init work_struct

ts->client = client;

i2c_set_clientdata(client, ts);

pdata = client->dev.platform_data;

#ifdef AUTO_UPDATE_GT818

i2c_pre_cmd(ts);

goodix_read_version(ts);

i2c_end_cmd(ts);



ret = gt818_downloader( ts, goodix_gt818_firmware, update_path);

if(ret < 0)

{

dev_err(&client->dev, "Warnning: GT818 update might be ERROR!\n");

//goto err_input_dev_alloc_failed;

}

#endif



ts->input_dev = input_allocate_device();

if (ts->input_dev == NULL) {

ret = -ENOMEM;

dev_dbg(&client->dev,"goodix_ts_probe: Failed to allocate input device\n");

goto err_input_dev_alloc_failed;

}

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 H***E_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, TOUCH_MAX_WIDTH, 0, 0);

input_set_abs_params(ts->input_dev, ABS_Y, 0, TOUCH_MAX_HEIGHT, 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, TOUCH_MAX_WIDTH, 0, 0);

input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, TOUCH_MAX_HEIGHT, 0, 0);

#endif

sprintf(ts->phys, "input/ts");

ts->input_dev->name = s3c_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;

// finger_list.length = 0;

#ifdef INT_PORT

client->irq=gt818_gpio_tp_irq_int_num; //If not defined in client

if (client->irq)

{

ret = gpio_request(gt818_gpio_tp_irq, "TS_INT"); //Request IO

if (ret < 0)

{

dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)gt818_gpio_tp_irq,ret);

goto err_gpio_request_failed;

}

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE); //ret > 0 ?

//s3c_gpio_cfgpin(gt818_gpio_tp_irq, int_cfg_num); //Set IO port function



#if INT_TRIGGER==1

#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_RISING

#elif INT_TRIGGER==0

#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_FALLING

// #elif INT_TRIGGER==2

// #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_LOW

// #elif INT_TRIGGER==3

// #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH

#endif

ret = request_irq(client->irq, goodix_ts_irq_handler , GT801_PLUS_IRQ_TYPE,

client->name, ts);

if (ret != 0) {

dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);

gpio_direction_input(gt818_gpio_tp_irq);

gpio_free(gt818_gpio_tp_irq);

goto err_gpio_request_failed;

}

else

{

disable_irq(client->irq);

ts->use_irq = 1;

dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n",gt818_gpio_tp_irq_int_num,gt818_gpio_tp_irq);

}

}

#endif

err_gpio_request_failed:



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);

}

i2c_pre_cmd(ts);

msleep(2);



for(retry=0; retry<3; retry++)

{

ret=goodix_init_panel(ts);

dev_info(&client->dev,"the config ret is :%d\n",ret);

msleep(2);

if(ret != 0) //Initiall failed

continue;

else

break;

}

if(ret != 0) {

ts->bad_data=1;

goto err_init_godix_ts;

}



if(ts->use_irq)

enable_irq(client->irq);



ts->power = goodix_ts_power;

goodix_read_version(ts);



#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

i2c_end_cmd(ts);

dev_info(&client->dev,"Start %s in %s mode\n",

ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");

return 0;

err_init_godix_ts:

i2c_end_cmd(ts);

if(ts->use_irq)

{

ts->use_irq = 0;

free_irq(client->irq,ts);

#ifdef INT_PORT

gpio_direction_input(gt818_gpio_tp_irq);

gpio_free(gt818_gpio_tp_irq);

#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;

}

/*******************************************************

鍔熻兘锛? 椹卞姩璧勬簮閲婃斁

鍙傛暟锛? client锛氳澶囩粨鏋勪綋

return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

********************************************************/

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

if (ts && ts->use_irq)

{

#ifdef INT_PORT

gpio_direction_input(gt818_gpio_tp_irq);

gpio_free(gt818_gpio_tp_irq);

#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) { /* 蹇呴』鍦ㄥ彇娑坵ork鍚庡啀鎵ц锛岄伩鍏嶅洜GPIO瀵艰嚧鍧愭爣澶勭悊浠g爜姝诲惊鐜?*/

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

/*

static int update_read_version(struct goodix_ts_data *ts, char **version)

{

int ret = -1, count = 0;

//unsigned char version_data[18];

char *version_data;

char *p;



*version = (char *)vmalloc(5);

version_data = *version;

if(!version_data)

return -ENOMEM;

p = version_data;

memset(version_data, 0, sizeof(version_data));

version_data[0]=0x07;

version_data[1]=0x17;

ret=i2c_read_bytes(ts->client,version_data, 4);

if (ret < 0)

return ret;

version_data[5]='\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;

}

*/

/**

@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] & SL***E_READY)

{

return 1;

}

msleep(1);

*timeout += 5;

}

return 0;

}

*/

static int goodix_update_write(struct file *filp, const char __user *buff, unsigned long len, void *data)

{

unsigned char cmd[120];

int ret = -1;

int retry = 0;

static unsigned char update_path[60];

struct goodix_ts_data *ts;



ts = i2c_get_clientdata(i2c_connect_client);

if(ts==NULL)

{

printk(KERN_INFO"goodix write to kernel via proc
file!@@@@@@\n");

return 0;

}



//printk(KERN_INFO"goodix write to kernel via proc
file!@@@@@@\n");

if(copy_from_user(&cmd, buff, len))

{

printk(KERN_INFO"goodix write to kernel via proc
file!@@@@@@\n");

return -EFAULT;

}

//printk(KERN_INFO"Write cmd is:%d,write len is:%ld\n",cmd[0], len);

switch(cmd[0])

{

case APK_UPDATE_TP:

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, 60);

strncpy(update_path, cmd+1, 60);



ret = gt818_downloader( ts, goodix_gt818_firmware, update_path);

if(ret < 0)

{

printk(KERN_INFO"Warnning: GT818 update might be ERROR!\n");

return 0;

}



i2c_pre_cmd(ts);

msleep(2);



for(retry=0; retry<3; retry++)

{

ret=goodix_init_panel(ts);

printk(KERN_INFO"the config ret is :%d\n",ret);



msleep(2);

if(ret != 0) //Initiall failed

continue;

else

break;

}



//if(ts->use_irq)

// s3c_gpio_cfgpin(gt818_gpio_tp_irq, int_cfg_num); //Set IO port as interrupt port

// else

gpio_direction_input(gt818_gpio_tp_irq);



i2c_end_cmd(ts);



if(ret != 0)

{

ts->bad_data=1;

return 1;

}

return 1;



case APK_READ_FUN: //functional command

if(cmd[1] == CMD_READ_VER)

{

printk(KERN_INFO"Read version!\n");

ts->read_mode = MODE_RD_VER;

}

else if(cmd[1] == CMD_READ_CFG)

{

printk(KERN_INFO"Read config info!\n");

ts->read_mode = MODE_RD_CFG;

}

return 1;



case APK_WRITE_CFG:

printk(KERN_INFO"Begin write config info!Config length:%d\n",cmd[1]);

i2c_pre_cmd(ts);

ret = i2c_write_bytes(ts->client, cmd+2, cmd[1]+2);

i2c_end_cmd(ts);

if(ret != 1)

{

printk("Write Config failed!return:%d\n",ret);

return -1;

}

return 1;



default:

return 0;

}

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;

unsigned char read_data[360] = {80, };

ts = i2c_get_clientdata(i2c_connect_client);

if(ts==NULL)

return 0;



printk("___READ__\n");

if(ts->read_mode == MODE_RD_VER) //read version data

{

i2c_pre_cmd(ts);

ret = goodix_read_version(ts);

i2c_end_cmd(ts);

if(ret <= 0)

{

printk(KERN_INFO"Read version data failed!\n");

return 0;

}



read_data[1] = (char)(ts->version&0xff);

read_data[0] = (char)((ts->version>>8)&0xff);

printk(KERN_INFO"Gt818 ROM version is:%x%x\n", read_data[0],read_data[1]);

memcpy(page, read_data, 2);

*eof = 1;

return 2;

}

else if(ts->read_mode == MODE_RD_CFG)

{

read_data[0] = 0x06;

read_data[1] = 0xa2; // cfg start address

printk("read config addr is:%x,%x\n", read_data[0],read_data[1]);

len = 106;

i2c_pre_cmd(ts);

ret = i2c_read_bytes(ts->client, read_data, len+2);

i2c_end_cmd(ts);

if(ret <= 0)

{

printk(KERN_INFO"Read config info failed!\n");

return 0;

}



memcpy(page, read_data+2, len);

return len;

}

return len;

}



#endif

//********************************************************************************************

static u8 is_equal( u8 *src , u8 *dst , int len )

{

int i;



for( i = 0 ; i < len ; i++ )

{

//printk(KERN_INFO"[%02X:%02X]\n", src[i], dst[i]);

}

for( i = 0 ; i < len ; i++ )

{

if ( src[i] != dst[i] )

{

return 0;

}

}



return 1;

}

static u8 gt818_nvram_store( struct goodix_ts_data *ts )

{

int ret;

int i;

u8 inbuf[3] = {REG_NVRCS_H,REG_NVRCS_L,0};

//u8 outbuf[3] = {};

ret = i2c_read_bytes( ts->client, inbuf, 3 );



if ( ret < 0 )

{

return 0;

}



if ( ( inbuf[2] & BIT_NVRAM_LOCK ) == BIT_NVRAM_LOCK )

{

return 0;

}



inbuf[2] = (1<<BIT_NVRAM_STROE); //store command



for ( i = 0 ; i < 300 ; i++ )

{

ret = i2c_write_bytes( ts->client, inbuf, 3 );



if ( ret < 0 )

break;

}



return ret;

}

static u8 gt818_nvram_recall( struct goodix_ts_data *ts )

{

int ret;

u8 inbuf[3] = {REG_NVRCS_H,REG_NVRCS_L,0};



ret = i2c_read_bytes( ts->client, inbuf, 3 );



if ( ret < 0 )

{

return 0;

}



if ( ( inbuf[2]&BIT_NVRAM_LOCK) == BIT_NVRAM_LOCK )

{

return 0;

}



inbuf[2] = ( 1 << BIT_NVRAM_RECALL ); //recall command

ret = i2c_write_bytes( ts->client , inbuf, 3);

return ret;

}

static int gt818_reset( struct goodix_ts_data *ts )

{

int ret = 1;

u8 retry;



unsigned char outbuf[3] = {0,0xff,0};

unsigned char inbuf[3] = {0,0xff,0};

//outbuf[1] = 1;

gpio_direction_output(gt818_gpio_tp_rst,0);

msleep(20);

gpio_direction_input(gt818_gpio_tp_rst);

msleep(100);

for(retry=0;retry < 80; retry++)

{

ret =i2c_write_bytes(ts->client, inbuf, 0); //Test I2C connection.

if (ret > 0)

{

msleep(10);

ret =i2c_read_bytes(ts->client, inbuf, 3); //Test I2C connection.

if (ret > 0)

{

if(inbuf[2] == 0x55)

{

ret =i2c_write_bytes(ts->client, outbuf, 3);

msleep(10);

break;

}

}

}



}

printk(KERN_INFO"Detect address %0X\n", ts->client->addr);

//msleep(500);

return ret;

}

static int gt818_set_address_2( struct goodix_ts_data *ts )

{

unsigned char inbuf[3] = {0,0,0};

int i;

for ( i = 0 ; i < 12 ; i++ )

{

if ( i2c_read_bytes( ts->client, inbuf, 3) )

{

printk(KERN_INFO"Got response\n");

return 1;

}

printk(KERN_INFO"wait for retry\n");

msleep(50);

}

return 0;

}

static u8 gt818_update_firmware( u8 *nvram, u16 length, struct goodix_ts_data *ts)

{

u8 ret,err,retry_time,i;

u16 cur_code_addr;

u16 cur_frame_num, total_frame_num, cur_frame_len;

u32 gt80x_update_rate;

unsigned char i2c_data_buf[PACK_SIZE+2] = {0,}; //私戮莼潞麓鐖? unsigned char i2c_chk_data_buf[PACK_SIZE+2] = {0,}; //私戮莼潞麓鐖? err = 0;

if( length > NVRAM_LEN - NVRAM_BOOT_SECTOR_LEN )

{

printk(KERN_INFO"length too big %d %d\n", length, NVRAM_LEN - NVRAM_BOOT_SECTOR_LEN );

return 0;

}



total_frame_num = ( length + PACK_SIZE - 1) / PACK_SIZE;

//gt80x_update_sta = _UPDATING;

gt80x_update_rate = 0;

for( cur_frame_num = 0 ; cur_frame_num < total_frame_num ; cur_frame_num++ )

{

retry_time = 5;



cur_code_addr = NVRAM_UPDATE_START_ADDR + cur_frame_num * PACK_SIZE;

i2c_data_buf[0] = (cur_code_addr>>8)&0xff;

i2c_data_buf[1] = cur_code_addr&0xff;



i2c_chk_data_buf[0] = i2c_data_buf[0];

i2c_chk_data_buf[1] = i2c_data_buf[1];



if( cur_frame_num == total_frame_num - 1 )

{

cur_frame_len = length - cur_frame_num * PACK_SIZE;

}

else

{

cur_frame_len = PACK_SIZE;

}



//strncpy(&i2c_data_buf[2], &nvram[cur_frame_num*PACK_SIZE], cur_frame_len);

for(i=0;i<cur_frame_len;i++)

{

i2c_data_buf[2+i] = nvram[cur_frame_num*PACK_SIZE+i];

}

do

{

err = 0;

//ret = gt818_i2c_write( guitar_i2c_address, cur_code_addr, &nvram[cur_frame_num*I2C_FRAME_MAX_LENGTH], cur_frame_len );

ret = i2c_write_bytes(ts->client, i2c_data_buf, (cur_frame_len+2));



if ( ret <= 0 )

{

printk(KERN_INFO"write fail\n");

err = 1;

}



ret = i2c_read_bytes(ts->client, i2c_chk_data_buf, (cur_frame_len+2));

// ret = gt818_i2c_read( guitar_i2c_address, cur_code_addr, inbuf, cur_frame_len);



if ( ret <= 0 )

{

printk(KERN_INFO"read fail\n");

err = 1;

}



if( is_equal( &i2c_data_buf[2], &i2c_chk_data_buf[2], cur_frame_len ) == 0 )

{

printk(KERN_INFO"not equal\n");

err = 1;

}



} while ( err == 1 && (--retry_time) > 0 );



if( err == 1 )

{

break;

}



gt80x_update_rate = ( cur_frame_num + 1 )*128/total_frame_num;



}

if( err == 1 )

{

printk(KERN_INFO"write nvram fail\n");

return 0;

}



ret = gt818_nvram_store(ts);



msleep( 20 );

if( ret == 0 )

{

printk(KERN_INFO"nvram store fail\n");

return 0;

}



ret = gt818_nvram_recall(ts);

msleep( 20 );



if( ret == 0 )

{

printk(KERN_INFO"nvram recall fail\n");

return 0;

}

for ( cur_frame_num = 0 ; cur_frame_num < total_frame_num ; cur_frame_num++ ) // read out all the code

{

cur_code_addr = NVRAM_UPDATE_START_ADDR + cur_frame_num*PACK_SIZE;

retry_time=5;

i2c_chk_data_buf[0] = (cur_code_addr>>8)&0xff;

i2c_chk_data_buf[1] = cur_code_addr&0xff;





if ( cur_frame_num == total_frame_num-1 )

{

cur_frame_len = length - cur_frame_num*PACK_SIZE;

}

else

{

cur_frame_len = PACK_SIZE;

}



do

{

err = 0;

//ret = gt818_i2c_read( guitar_i2c_address, cur_code_addr, inbuf, cur_frame_len);

ret = i2c_read_bytes(ts->client, i2c_chk_data_buf, (cur_frame_len+2));

if ( ret == 0 )

{

err = 1;

}



if( is_equal( &nvram[cur_frame_num*PACK_SIZE], &i2c_chk_data_buf[2], cur_frame_len ) == 0 )

{

err = 1;

}

} while ( err == 1 && (--retry_time) > 0 );



if( err == 1 )

{

break;

}



gt80x_update_rate = 127 + ( cur_frame_num + 1 )*128/total_frame_num;

}



gt80x_update_rate = 255;

//gt80x_update_sta = _UPDATECHKCODE;

if( err == 1 )

{

printk(KERN_INFO"nvram validate fail\n");

return 0;

}

//往0X00FF写0XCC表示烧录结束

i2c_chk_data_buf[0] = 0xff;

i2c_chk_data_buf[1] = 0x00;

i2c_chk_data_buf[2] = 0x0;

ret = i2c_write_bytes(ts->client, i2c_chk_data_buf, 3);



if( ret <= 0 )

{

printk(KERN_INFO"nvram validate fail\n");

return 0;

}



return 1;

}

static u8 gt818_update_proc( u8 *nvram, u16 length, struct goodix_ts_data *ts )

{

u8 ret;

u8 error = 0;

//struct tpd_info_t tpd_info;

GT818_SET_INT_PIN( 0 );

msleep( 20 );

ret = gt818_reset(ts);

if ( ret < 0 )

{

error = 1;

printk(KERN_INFO"reset fail\n");

goto end;

}

ret = gt818_set_address_2( ts );

if ( ret == 0 )

{

error = 1;

printk(KERN_INFO"set address fail\n");

goto end;

}

ret = gt818_update_firmware( nvram, length, ts);

if ( ret == 0 )

{

error=1;

printk(KERN_INFO"firmware update fail\n");

goto end;

}

end:

//GT818_SET_INT_PIN( 1 );

gpio_free(gt818_gpio_tp_irq);

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE);



msleep( 500 );

ret = gt818_reset(ts);

if ( ret < 0 )

{

error=1;

printk(KERN_INFO"final reset fail\n");

goto end;

}

if ( error == 1 )

{

return 0;

}

i2c_pre_cmd(ts);

while(goodix_read_version(ts)<0);



i2c_end_cmd(ts);

return 1;

}

static int gt818_downloader( struct goodix_ts_data *ts, unsigned char * data, unsigned char * path)

{

struct tpd_firmware_info_t *fw_info = (struct tpd_firmware_info_t *)data;

int i;

unsigned short checksum = 0;

unsigned char *data_ptr = &(fw_info->data);

int retry = 0,ret;

int err = 0;

struct file * file_data = NULL;

mm_segment_t old_fs;

//unsigned int rd_len;

unsigned int file_len = 0;

//unsigned char i2c_data_buf[PACK_SIZE] = {0,};



const int MAGIC_NUMBER_1 = 0x4D454449;

const int MAGIC_NUMBER_2 = 0x4154454B;



if(path[0] == 0)

{

printk(KERN_INFO"%s\n", __func__ );

printk(KERN_INFO"magic number 0x%08X 0x%08X\n", fw_info->magic_number_1, fw_info->magic_number_2 );

printk(KERN_INFO"magic number 0x%08X 0x%08X\n", MAGIC_NUMBER_1, MAGIC_NUMBER_2 );

printk(KERN_INFO"current version 0x%04X, target verion 0x%04X\n", ts->version, fw_info->version );

printk(KERN_INFO"size %d\n", fw_info->length );

printk(KERN_INFO"checksum %d\n", fw_info->checksum );

if ( fw_info->magic_number_1 != MAGIC_NUMBER_1 && fw_info->magic_number_2 != MAGIC_NUMBER_2 )

{

printk(KERN_INFO"Magic number not match\n");

err = 0;

goto exit_downloader;

}

if(((ts->version&0xff)> 0x99)||((ts->version&0xff) < 0x4a))

{

goto update_start;

}

if ( ts->version >= fw_info->version )

{

printk(KERN_INFO"No need to upgrade\n");

err = 0;

goto exit_downloader;

}

if ( get_chip_version( ts->version ) != get_chip_version( fw_info->version ) )

{

printk(KERN_INFO"Chip version incorrect");

err = 0;

goto exit_downloader;

}

update_start:

for ( i = 0 ; i < fw_info->length ; i++ )

checksum += data_ptr[i];

checksum = checksum%0xFFFF;

if ( checksum != fw_info->checksum )

{

printk(KERN_INFO"Checksum not match 0x%04X\n", checksum);

err = 0;

goto exit_downloader;

}

}

else

{

printk(KERN_INFO"Write cmd arg is:\n");

file_data = update_file_open(path, &old_fs);

printk(KERN_INFO"Write cmd arg is\n");

if(file_data == NULL) //file_data has been opened at the last time

{

err = -1;

goto exit_downloader;

}



file_len = (update_get_flen(path))-2;

printk(KERN_INFO"current length:%d\n", file_len);

ret = file_data->f_op->read(file_data, &data_ptr[0], file_len, &file_data->f_pos);



if(ret <= 0)

{

err = -1;

goto exit_downloader;

}



update_file_close(file_data, old_fs);



}

printk(KERN_INFO"STEP_0:\n");

//adapter = client->adapter;

gpio_free(gt818_gpio_tp_irq);

ret = gpio_request(gt818_gpio_tp_irq, "TS_INT"); //Request IO

if (ret < 0)

{

printk(KERN_INFO"Failed to request GPIO:%d, ERRNO:%d\n",(int)gt818_gpio_tp_irq,ret);

err = -1;

goto exit_downloader;

}

printk(KERN_INFO"STEP_1:\n");

err = -1;

while ( retry < 3 )

{

ret = gt818_update_proc( data_ptr, fw_info->length, ts);

if(ret == 1)

{

err = 1;

break;

}

retry++;

}



exit_downloader:

//mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);

// mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);

// gpio_direction_output(gt818_gpio_tp_irq,1);

// msleep(1);

gpio_free(gt818_gpio_tp_irq);

//s3c_gpio_setpull(gt818_gpio_tp_irq, S3C_GPIO_PULL_NONE);

return err;

}

//******************************End of firmware update surpport*******************************

//鍙敤浜庤椹卞姩鐨?璁惧鍚嶁€旇澶嘔D 鍒楄〃

//only one client

static const struct i2c_device_id goodix_ts_id[] = {

{ GOODIX_I2C_NAME, 0 },

{ }

};

//璁惧椹卞姩缁撴瀯浣?static struct i2c_driver goodix_ts_driver = {

.probe = goodix_ts_probe,

.remove = goodix_ts_remove,

#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,

},

};

/*******************************************************

鍔熻兘锛? 椹卞姩鍔犺浇鍑芥暟

return锛? 鎵ц缁撴灉鐮侊紝0琛ㄧず姝e父鎵ц

********************************************************/

static int __devinit goodix_ts_init(void)

{

// int ret;

printk("wax->%s\n",__FUNCTION__);

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;



}

printk("%s\n", __func__);



gt818_gpio_tp_irq_int_num=gt818_config_pins();

gt818_ts_setup.i2c_bus = 2;

gt818_ts_setup.i2c_address = GT818_TS_ADDR;

strcpy (gt818_ts_setup.type,GOODIX_I2C_NAME);

gt818_ts_setup.irq = gt818_gpio_tp_irq_int_num;

return gt818_sprd_add_i2c_device(>818_ts_setup, &goodix_ts_driver);

//ret=i2c_add_driver(&goodix_ts_driver);

//return ret;

}

/*******************************************************

鍔熻兘锛? 椹卞姩鍗歌浇鍑芥暟

鍙傛暟锛? client锛氳澶囩粨鏋勪綋

********************************************************/

static void __exit goodix_ts_exit(void)

{

printk(KERN_ALERT "Touchscreen driver of guitar exited.\n");

sprd_free_gpio_irq(gt818_gpio_tp_irq_int_num);

//i2c_del_driver(&goodix_ts_driver);

gt818_sprd_del_i2c_device(i2c_connect_client,&goodix_ts_driver);



if (goodix_wq)

destroy_workqueue(goodix_wq); //release our work queue

}

late_initcall(goodix_ts_init); //鏈€鍚庡垵濮嬪寲椹卞姩felix

module_exit(goodix_ts_exit);

MODULE_DESCRIPTION("Goodix Touchscreen Driver");

MODULE_LICENSE("GPL");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: