From: 蔡枫 Date: Wed, 13 Jul 2011 14:13:05 +0000 (+0800) Subject: newton:optimize ft5406,modify supend and resume for ft5406 and gt819 X-Git-Tag: firefly_0821_release~10137 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=8e46094df6dcd7acf26508c6d432d33a70b33134;p=firefly-linux-kernel-4.4.55.git newton:optimize ft5406,modify supend and resume for ft5406 and gt819 --- diff --git a/arch/arm/mach-rk29/board-rk29-newton.c b/arch/arm/mach-rk29/board-rk29-newton.c index 2beda0781255..2b0f35733607 100755 --- a/arch/arm/mach-rk29/board-rk29-newton.c +++ b/arch/arm/mach-rk29/board-rk29-newton.c @@ -571,16 +571,12 @@ struct platform_device rk29_device_newton = { } }; #endif -#if defined (CONFIG_TOUCHSCREEN_FT5406)|| defined (CONFIG_TOUCHSCREEN_GOODIX_NEWTON) +#if defined (CONFIG_TOUCHSCREEN_FT5406) #define TOUCH_RESET_PIN RK29_PIN6_PC3 #define TOUCH_INT_PIN RK29_PIN0_PA2 - -//#define TOUCH_POER_PIN RK29_PIN6_PB2 - int ft5406_init_platform_hw(void) { - printk("ft5406_init_platform_hw\n"); - + printk("ft5406_init_platform_hw\n"); if(gpio_request(TOUCH_RESET_PIN,NULL) != 0){ gpio_free(TOUCH_RESET_PIN); printk("ft5406_init_platform_hw gpio_request error\n"); @@ -593,49 +589,109 @@ int ft5406_init_platform_hw(void) return -EIO; } - // if(gpio_request(TOUCH_POER_PIN,NULL) != 0){ - // gpio_free(TOUCH_POER_PIN); - // printk("ft5406_init_platform_hw gpio_power error\n"); -// return -EIO; - // } - -#if 1 - gpio_direction_output(TOUCH_RESET_PIN, 0); - gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); - msleep(100); + gpio_direction_output(TOUCH_RESET_PIN, 0); gpio_direction_output(TOUCH_INT_PIN, 0); - gpio_set_value(TOUCH_INT_PIN,GPIO_LOW); - mdelay(10); -// gpio_direction_output(TOUCH_POER_PIN, 0); -// gpio_set_value(TOUCH_POER_PIN,GPIO_HIGH); - - //msleep(3000); - msleep(50); //harry 2011.04.20 - + gpio_set_value(TOUCH_INT_PIN,GPIO_HIGH); gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); - msleep(100); - gpio_direction_output(TOUCH_INT_PIN, 1); gpio_pull_updown(TOUCH_INT_PIN, 0); -#endif + return 0; +} +int ft5406_exit_platform_hw(void) +{ + printk("ft5406_exit_platform_hw\n"); + gpio_free(TOUCH_RESET_PIN); + gpio_free(TOUCH_INT_PIN); + return 0; +} - return 0; +int ft5406_platform_sleep(void) +{ + printk("ft5406_platform_sleep\n"); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + return 0; } -#endif -#if defined (CONFIG_TOUCHSCREEN_FT5406) +int ft5406_platform_wakeup(void) +{ + printk("ft5406_platform_wakeup\n"); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); + return 0; +} struct ft5406_platform_data ft5406_info = { .init_platform_hw= ft5406_init_platform_hw, + .exit_platform_hw= ft5406_exit_platform_hw, + .platform_sleep = ft5406_platform_sleep, + .platform_wakeup = ft5406_platform_wakeup, }; #endif #if defined(CONFIG_TOUCHSCREEN_GOODIX_NEWTON) +#define TOUCH_RESET_PIN RK29_PIN6_PC3 +#define TOUCH_INT_PIN RK29_PIN0_PA2 +int gt819_init_platform_hw(void) +{ + printk("gt819_init_platform_hw\n"); + if(gpio_request(TOUCH_RESET_PIN,NULL) != 0){ + gpio_free(TOUCH_RESET_PIN); + printk("gt819_init_platform_hw gpio_request error\n"); + return -EIO; + } + + if(gpio_request(TOUCH_INT_PIN,NULL) != 0){ + gpio_free(TOUCH_INT_PIN); + printk("gt819_init_platform_hw gpio_request error\n"); + return -EIO; + } + gpio_direction_output(TOUCH_RESET_PIN, 0); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + msleep(100); + gpio_direction_output(TOUCH_INT_PIN, 0); + gpio_set_value(TOUCH_INT_PIN,GPIO_LOW); + mdelay(10); + msleep(50); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); + msleep(100); + gpio_direction_output(TOUCH_INT_PIN, 1); + gpio_pull_updown(TOUCH_INT_PIN, 0); + return 0; +} + + +int gt819_exit_platform_hw(void) +{ + printk("gt819_exit_platform_hw\n"); + gpio_free(TOUCH_RESET_PIN); + gpio_free(TOUCH_INT_PIN); + return 0; +} + +int gt819_platform_sleep(void) +{ + printk("gt819_platform_sleep\n"); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + return 0; +} + +int gt819_platform_wakeup(void) +{ + printk("gt819_platform_wakeup\n"); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); + msleep(5); + gpio_set_value(TOUCH_INT_PIN, GPIO_LOW); + msleep(20); + gpio_set_value(TOUCH_INT_PIN, GPIO_HIGH); + return 0; +} struct goodix_platform_data goodix_info = { - .init_platform_hw= ft5406_init_platform_hw, + .init_platform_hw= gt819_init_platform_hw, + .exit_platform_hw= gt819_exit_platform_hw, + .platform_sleep = gt819_platform_sleep, + .platform_wakeup = gt819_platform_wakeup, }; #endif @@ -962,37 +1018,23 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = { .platform_data = &eeti_egalax_info, }, #endif - - #if defined (CONFIG_TOUCHSCREEN_GOODIX_NEWTON) { - .type = "Goodix-TS", + .type = "Goodix-TS", .addr = 0x55, .flags =0, - //.irq =RK29_PIN0_PA2, + .irq =RK29_PIN0_PA2, .platform_data = &goodix_info, }, #endif - - - #if defined (CONFIG_TOUCHSCREEN_FT5406) { - .type ="ft5x0x_ts", + .type ="ft5x0x_ts", .addr = 0x38, //0x70, .flags =0, - //.irq =RK29_PIN0_PA2, // support goodix tp detect, 20110706 + .irq =RK29_PIN0_PA2, // support goodix tp detect, 20110706 .platform_data = &ft5406_info, }, - //added by koffu - { - .type ="ft_rw_iic_drv", - .addr = 0x38, //0x70, - .flags =0, - //.irq =RK29_PIN0_PA2, - //.platform_data = &ft5406_info, - }, - #endif }; #endif diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index 7f1460d04b67..e2b47210fc82 100755 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -224,16 +224,16 @@ struct it7260_platform_data { struct ft5406_platform_data { int (*get_pendown_state)(void); int (*init_platform_hw)(void); - int (*ft5406_platform_sleep)(void); - int (*ft5406_platform_wakeup)(void); + int (*platform_sleep)(void); + int (*platform_wakeup)(void); 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); + int (*platform_sleep)(void); + int (*platform_wakeup)(void); void (*exit_platform_hw)(void); }; diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile old mode 100644 new mode 100755 index 77af57fbfa5f..d87e0bdef0c3 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -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 +obj-$(CONFIG_TOUCHSCREEN_GOODIX_NEWTON) += gt819.o diff --git a/drivers/input/touchscreen/ft5406_ts.c b/drivers/input/touchscreen/ft5406_ts.c index a7be67db1e56..4812aac4b396 100755 --- a/drivers/input/touchscreen/ft5406_ts.c +++ b/drivers/input/touchscreen/ft5406_ts.c @@ -35,15 +35,6 @@ #include #include #include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include #include #include #include @@ -51,8 +42,6 @@ #ifdef CONFIG_ANDROID_POWER #include #endif - - #include #include #include @@ -60,7 +49,6 @@ #include #include #include - #include #include #include @@ -71,25 +59,35 @@ #include /* ddl@rock-chips.com : camera support */ #include #include - #ifdef CONFIG_HAS_EARLYSUSPEND #include -#endif - -//#include -#include "ft5406_ts.h" - - -#ifdef CONFIG_HAS_EARLYSUSPEND static struct early_suspend ft5406_early_suspend; #endif -static struct i2c_client *this_client; #define CONFIG_FT5X0X_MULTITOUCH 1 -#define TOUCH_RESET_PIN RK29_PIN6_PC3 +#define MAX_POINT 5 +#define FT5406_IIC_SPEED 400*1000 //300*1000 +#define TOUCH_RESET_PIN RK29_PIN6_PC3 +#define FT5X0X_REG_THRES 0x80 /* Thresshold, the threshold be low, the sensitivy will be high */ +#define FT5X0X_REG_REPORT_RATE 0x88 /* **************report rate, in unit of 10Hz **************/ +#define FT5X0X_REG_PMODE 0xA5 /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */ +#define FT5X0X_REG_FIRMID 0xA6 /* ***************firmware version **********************/ +#define FT5X0X_REG_NOISE_MODE 0xb2 /* to enable or disable power noise, 1 -- enable, 0 -- disable */ +#define SCREEN_MAX_X 800 +#define SCREEN_MAX_Y 480 +#define PRESS_MAX 255 +#define FT5X0X_NAME "ft5x0x_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"// +#define TOUCH_MAJOR_MAX 200 +#define WIDTH_MAJOR_MAX 200 +//FT5X0X_REG_PMODE +#define PMODE_ACTIVE 0x00 +#define PMODE_MONITOR 0x01 +#define PMODE_STANDBY 0x02 +#define PMODE_HIBERNATE 0x03 + struct ts_event { u16 x1; @@ -103,564 +101,37 @@ struct ts_event { u16 x5; u16 y5; u16 pressure; - s16 touch_ID1; + s16 touch_ID1; s16 touch_ID2; - s16 touch_ID3; - s16 touch_ID4; + s16 touch_ID3; + s16 touch_ID4; s16 touch_ID5; u8 touch_point; u8 status; }; +struct tp_event { + u16 x; + u16 y; + s16 id; + u16 pressure; + u8 touch_point; + u8 flag; +}; + struct ft5x0x_ts_data { struct i2c_client *client; struct input_dev *input_dev; - int irq; + int irq; struct ts_event event; struct work_struct pen_event_work; struct workqueue_struct *ts_workqueue; }; - -static int fts_ctpm_fw_upgrade_with_i_file(void); - - - -//#define FT5X0X_I2C_ADDR 0x70 -#define MAX_POINT 5 -/* -static int ft5x0x_ts_probe(struct i2c_adapter *bus, int address, int kind); -static unsigned short ft5x0x_normal_i2c[] = {FT5X0X_I2C_ADDR>>1, I2C_CLIENT_END}; -static unsigned short ft5x0x_ignore = I2C_CLIENT_END; -static struct i2c_client_address_data ft5x0x_addr_data={ - .normal_i2c = ft5x0x_normal_i2c, - .probe = &ft5x0x_ignore, - .ignore =&ft5x0x_ignore, -}; - -static int ft5x0x_attach_adapter(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &ft5x0x_addr_data, ft5x0x_ts_probe); -} - -static struct i2c_driver ft5x0x_ts_driver = { - .driver = { - .name = FT5X0X_NAME, - .owner = THIS_MODULE, - }, - .id = FT5X0X_I2C_ADDR, - .attach_adapter = &ft5x0x_attach_adapter, -}; - - - - -static struct i2c_client ft5x0x_client = { - .driver = &ft5x0x_ts_driver, - .name = "ft5x0x", -}; -*/ -/*read the it7260 register ,used i2c bus*/ - -#define FT5406_IIC_SPEED 200*1000 //300*1000 -static int ft5406_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len) -{ - int ret; - ret = i2c_master_reg8_recv(client, reg, buf, len, FT5406_IIC_SPEED); - return ret; -} - - -/* set the it7260 registe,used i2c bus*/ -static int ft5406_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], unsigned short len) -{ - int ret; - ret = i2c_master_reg8_send(client, reg, buf, (int)len, FT5406_IIC_SPEED); - return ret; -} - - - - -/* -static int ft5x0x_i2c_rxdata(u8 reg, u8 rxdata[], int length) -{ - int ret; - struct i2c_msg msg[1]; - - msg->addr = ft5x0x_client.addr; - msg->flags |= I2C_M_RD; - msg->buf = rxdata; - msg->len = length; - - //printk("ft50x0_client.addr = 0x%x\n", ft5x0x_client.addr); - rxdata[0] = reg; - - ret = i2c_transfer(ft5x0x_client.adapter, msg, 1); - if (ret< 0) - { - printk("error at ft5x0x_read_regs !!! \n"); - } - return ret; - -} - -static int ft5x0x_i2c_txdata(u8 reg, u8 txdata[], int length) -{ - int ret; - struct i2c_msg msg[1]; - static u8 i2c_buf[128]; - - msg->addr = ft5x0x_client.addr; - msg->flags = 0; - msg->buf = i2c_buf; - msg->len = length + 1; - - - i2c_buf[0] = reg; - memcpy(&i2c_buf[1], &txdata[0], length); - ret = i2c_transfer(ft5x0x_client.adapter, msg, 1); - if (ret< 0) - { - printk("error at gt800_write_regs !!! \n"); - } - return ret; - -} - -*/ -static void ft5x0x_ts_release(struct ft5x0x_ts_data *data) -{ - //struct ft5x0x_ts_data *data = i2c_get_clientdata(&ft5x0x_client); - //struct ts_event *event = &data->event; - -#if CONFIG_FT5X0X_MULTITOUCH // #ifdef - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 0); -#else - input_report_abs(data->input_dev, ABS_PRESSURE, 0); - input_report_key(data->input_dev, BTN_TOUCH, 0); -#endif - input_sync(data->input_dev); -} - -static int ft5x0x_read_data(struct ft5x0x_ts_data *data ) -{ - //struct ft5x0x_ts_data *data = i2c_get_clientdata(&ft5x0x_client); - struct ts_event *event = &data->event; - u8 start_reg=0x0; - u8 buf[32] = {0}; - int ret = -1; - //int i = 0; - int status = 0; - int cnt = 0; - -#if 0 - start_reg = 0xa6; - ret = ft5x0x_i2c_rxdata(start_reg, buf, 2); - if (ret < 0) { - printk("%s read_data i2c_rxdata failed: %d\n", __func__, ret); - return ret; - } - for (i=0; i<2; i++) { - printk("=========buf[%d] = 0x%x \n", i, buf[i]); - } -#endif - - - start_reg = 0; - - - -#if CONFIG_FT5X0X_MULTITOUCH // #ifdef - if (MAX_POINT == 5) { - ret = ft5406_read_regs(data->client,start_reg, buf, 31); - } else { - ret = ft5406_read_regs(data->client,start_reg, buf, 13); - } -#else - ret = ft5406_read_regs(data->client,start_reg, buf, 7); -#endif - if (ret < 0) { - // printk("%s read_data i2c_rxdata failed: %d\n", __func__, ret); - return ret; - } -#if 0 - for (i=0; i<32; i++) { - printk("buf[%d] = 0x%x \n", i, buf[i]); - } -#endif - - memset(event, 0, sizeof(struct ts_event)); - - if (MAX_POINT == 5) { - event->touch_point = buf[2] & 0x07;// 000 0111 - } else { - event->touch_point = buf[2] & 0x03;// 0000 0011 - } - -// printk("touch_point = %d\n", event->touch_point); - if (event->touch_point == 0) { - // printk("release point !!!!!!!!!!!!!!!!!\n"); - ft5x0x_ts_release(data); - return 1; - } - cnt =0; -#if CONFIG_FT5X0X_MULTITOUCH // #ifdef - switch (event->touch_point) { - if (MAX_POINT == 5) { - case 5: - event->x5 = (s16)(buf[0x1b] & 0x0F)<<8 | (s16)buf[0x1c]; - event->y5 = (s16)(buf[0x1d] & 0x0F)<<8 | (s16)buf[0x1e]; - status = (s16)((buf[0x1b] & 0xc0) >> 6); - event->touch_ID5=(s16)(buf[0x1D] & 0xF0)>>4; - if(event->x5 > 1024) - cnt ++; - // printk("read ID5 = %d\n",event->touch_ID5,status); - // printk("read status5= %d\n",status); - #if 0 - if (status == 1) { - printk("point 5 release!\n"); - ft5x0x_ts_release(data); - } - #endif - case 4: - event->x4 = (s16)(buf[0x15] & 0x0F)<<8 | (s16)buf[0x16]; - event->y4 = (s16)(buf[0x17] & 0x0F)<<8 | (s16)buf[0x18]; - status = (s16)((buf[0x15] & 0xc0) >> 6); - //event->touch_ID4=(s16)(buf[0x17] & 0xF0); - event->touch_ID4=(s16)(buf[0x17] & 0xF0)>>4; - // printk("read ID4 = %d,read status4 = %d\n",event->touch_ID4,status); - #if 0 - if (status == 1) { - printk("point 4 release!\n"); - ft5x0x_ts_release(data); - } - #endif - if(event->x4 >1024) - cnt ++; - case 3: - event->x3 = (s16)(buf[0x0f] & 0x0F)<<8 | (s16)buf[0x10]; - event->y3 = (s16)(buf[0x11] & 0x0F)<<8 | (s16)buf[0x12]; - status = (s16)((buf[0x0f] & 0xc0) >> 6); - // event->touch_ID3=(s16)(buf[0x11] & 0xF0); - event->touch_ID3=(s16)(buf[0x11] & 0xF0)>>4; - // printk("read ID3 = %d,read status3 = %d\n",event->touch_ID3,status); - #if 0 - if (status == 1) { - printk("point 3 release!\n"); - ft5x0x_ts_release(data); - } - #endif - if(event->x3 > 1024) - cnt ++; - } - case 2: - event->x2 = (s16)(buf[9] & 0x0F)<<8 | (s16)buf[10]; - event->y2 = (s16)(buf[11] & 0x0F)<<8 | (s16)buf[12]; - status = (s16)((buf[0x9] & 0xc0) >> 6); - // event->touch_ID2=(s16)(buf[0x0b] & 0xF0); - event->touch_ID2=(s16)(buf[0x0b] & 0xF0)>>4; - // printk("read ID2 = %d,read status2 = %d\n",event->touch_ID2,status); - #if 0 - if (status == 1) { - printk("point 2 release!\n"); - ft5x0x_ts_release(data); - } - #endif - if(event->x2 > 1024) - cnt ++; - case 1: - event->x1 = (s16)(buf[3] & 0x0F)<<8 | (s16)buf[4]; - event->y1 = (s16)(buf[5] & 0x0F)<<8 | (s16)buf[6]; - status = ((buf[0x3] & 0xc0) >> 6); - event->status= status ; - // event->touch_ID1=(s16)(buf[5] & 0xF0); - event->touch_ID1=(s16)(buf[0x05] & 0xF0)>>4; - //printk("status1= %d\n",event->status); - #if 0 - if (status == 1) { - printk("point 1 release!\n"); - ft5x0x_ts_release(data); - } - #endif - if(event->x1 >1024) - cnt ++; - - break; - default: - return -1; - } - -/* - if((event->touch_point ==1) - &&((event->y1y2>MENU_KEY_MAX))) - { - ft5x0x_ts_release(data); - return 1; - } - - if(((event->touch_point - cnt) ==0)&&(event->touch_point >1)) - { - ft5x0x_ts_release(data); - return 1; - } -*/ -#else - if (event->touch_point == 1) { - event->x1 = (s16)(buf[3] & 0x0F)<<8 | (s16)buf[4]; - event->y1 = (s16)(buf[5] & 0x0F)<<8 | (s16)buf[6]; - } -#endif - event->pressure =200; //200; - - // printk("status2= %d\n",event->status); - - return 0; -} - -static void ft5x0x_report_value(struct ft5x0x_ts_data *data ) -{ - //struct ft5x0x_ts_data *data = i2c_get_clientdata(&ft5x0x_client); - struct ts_event *event = &data->event; - -#if CONFIG_FT5X0X_MULTITOUCH //#ifdef - switch(event->touch_point) { - if (MAX_POINT == 5){ - case 5: - - if(event->x5 <= 1024) - { - input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID5); - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x5); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y5); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); - input_mt_sync(data->input_dev); - } - // printk("===x5 = %d,y5 = %d ====\n",event->x5,event->y5); - case 4: - if(event->x4 <= 1024) - { - input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID4); - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x4); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y4); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); - input_mt_sync(data->input_dev); - } - // printk("===x4 = %d,y4 = %d ====\n",event->x4, event->y4); - case 3: - if(event->x3 <= 1024) - { - input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID3); - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x3); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y3); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); - input_mt_sync(data->input_dev); - } - // printk("===x3 = %d,y3 = %d ====\n",event->x3, event->y3); - } - case 2: - if(event->x2 <= 1024) - { - input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID2); - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x2); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y2); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); - input_mt_sync(data->input_dev); - } - // printk("===x2 = %d,y2 = %d ====\n",event->x2,event->y2); - case 1: - input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID1); - input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x1); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y1); - input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); - input_mt_sync(data->input_dev); - // printk("===x1 = %d,y1 = %d ====\n",event->x1,event->y1); - default: - // printk("==touch_point default =\n"); - // printk("read status0= %d\n",event->status); - // if (event->status== 1) { - // printk("point 0 release!\n"); - // ft5x0x_ts_release(data); - // } - break; - } -#else /* CONFIG_FT5X0X_MULTITOUCH*/ - //if (event->touch_point == 1) { - input_report_abs(data->input_dev, ABS_X, event->x1); - 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); -#endif /* CONFIG_FT5X0X_MULTITOUCH*/ - input_sync(data->input_dev); - - // printk("status3= %d\n",event->status); - - -} /*end ft5x0x_report_value*/ - -static void ft5x0x_ts_pen_irq_work(struct work_struct *work) -{ - int ret = -1; -// printk("==work 1=\n"); - - struct ft5x0x_ts_data *ft5x0x_ts = - container_of(work, struct ft5x0x_ts_data, pen_event_work); - - - ret = ft5x0x_read_data(ft5x0x_ts); - if (ret == 0) { - ft5x0x_report_value(ft5x0x_ts); - // printk("==work 2=\n"); - } -// else printk("data package read error\n"); -// printk("==work 2=\n"); -// msleep(1); - enable_irq(ft5x0x_ts->irq); - //enable_irq(7); -// gpio_irq_enable(TOUCH_INT_IOPIN); -} - -static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id) -{ - - struct ft5x0x_ts_data *ft5x0x_ts = dev_id; - - //printk("ft5x0x_ts irq =%d",ft5x0x_ts->irq); - - disable_irq_nosync(ft5x0x_ts->irq); - // disable_irq(ft5x0x_ts->irq); -// disable_irq(7); - //gpio_irq_disable(ft5x0x_ts->irq); - - if (!work_pending(&ft5x0x_ts->pen_event_work)) - { - queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work); - // printk("ft5x0x_ts_work!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - return IRQ_HANDLED; -} - - -static int __devexit ft5406_remove(struct i2c_client *client) -{ - struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); - - // printk("==ft5x0x_ts_remove=\n"); - -// free_irq(client->irq, ft5x0x_ts); -// free_irq(7, ft5x0x_ts); - free_irq(ft5x0x_ts->irq, ft5x0x_ts); - - input_unregister_device(ft5x0x_ts->input_dev); - kfree(ft5x0x_ts); - cancel_work_sync(&ft5x0x_ts->pen_event_work); - destroy_workqueue(ft5x0x_ts->ts_workqueue); - i2c_set_clientdata(client, NULL); -#ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&ft5406_early_suspend); -#endif - this_client = NULL; - - return 0; -} - - -#ifdef CONFIG_HAS_EARLYSUSPEND -static int ft5x0x_ts_suspend(struct early_suspend *h) -{ - -u8 buf[1]; -//u8 buf_r[1]; -int read_data=5; -int err = 0; - -// printk("==ft5x0x_ts_suspend=\n"); - - -// struct ft5x0x_ts_data *ts; -// ts = container_of(handler, struct ft5x0x_ts_data, early_suspend); - #if 0 - struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - enable_irq_wake(ft5x0x_ts->irq); - #endif -// disable_irq(ft5x0x_client->irq); -// cancel_work_sync(&ts->pen_event_work); -// flush_workqueue(ts->ts_workqueue); -// ==set mode ==, - disable_irq(102); - #if 1 - buf[0]=PMODE_HIBERNATE; - while(read_data) - { - err=ft5406_set_regs(this_client,FT5X0X_REG_PMODE, buf,1); - // printk("==ft5406 suspend write 111=%d\n",buf[0]); - if(err==1) - { - read_data=0; - } - else - { - read_data--; - // printk("==ft5406 suspend write222=%d\n",buf[0]); - ft5406_set_regs(this_client,FT5X0X_REG_PMODE, buf,1); - } - } - - // printk("==ft5406 suspend write=%d\n",buf[0]); - // printk("==ft5406 suspend write err=%d\n",err); - // msleep(50); //harry 2011.04.20 - // err = ft5406_read_regs(this_client,FT5X0X_REG_PMODE,buf_r,1); - // printk("==ft5406 suspend read=%d\n",buf_r[0]); - // printk("==ft5406 suspend read err=%d\n",err); - - #endif - - - return 0; - -} - - -static int ft5x0x_ts_resume(struct early_suspend *h) -{ - //printk("==ft5x0x_ts_resume=\n"); - #if 0 - struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - disable_irq_wake(ft5x0x_ts->irq); - #endif - // wake the mode -// __gpio_as_output(GPIO_FT5X0X_WAKE); -// __gpio_clear_pin(GPIO_FT5X0X_WAKE); //set wake = 0,base on system -// msleep(100); -// __gpio_set_pin(GPIO_FT5X0X_WAKE); //set wake = 1,base on system -// msleep(100); -// enable_irq(IRQ_EINT(6)); - enable_irq(102); - #if 1 - gpio_direction_output(TOUCH_RESET_PIN, 0); - gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); - msleep(20); //harry 2011.04.20 - gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); - #endif - - return 0; -} -#endif +static struct i2c_client *this_client; /***********************************************************************/ #define FTS_PACKET_LENGTH 128 -static bool i2c_write_interface(u8* pbt_buf, int dw_lenth); static u8 CTPM_FW[]= @@ -1065,32 +536,164 @@ unsigned char fts_ctpm_get_upg_ver(void) } +/*read the it7260 register ,used i2c bus*/ +static int ft5406_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len) +{ + int ret; + ret = i2c_master_reg8_recv(client, reg, buf, len, FT5406_IIC_SPEED); + return ret; +} + + +/* set the it7260 registe,used i2c bus*/ +static int ft5406_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], unsigned short len) +{ + int ret; + ret = i2c_master_reg8_send(client, reg, buf, (int)len, FT5406_IIC_SPEED); + return ret; +} + +static void ft5406_queue_work(struct work_struct *work) +{ + struct ft5x0x_ts_data *data = container_of(work, struct ft5x0x_ts_data, pen_event_work); + struct tp_event event; + u8 start_reg=0x0; + u8 buf[32] = {0}; + int ret,i,offset,points; + +#if CONFIG_FT5X0X_MULTITOUCH + ret = ft5406_read_regs(data->client,start_reg, buf, 6*MAX_POINT+1); +#else + ret = ft5406_read_regs(data->client,start_reg, buf, 7); +#endif + if (ret < 0) { + dev_err(&data->client->dev, "ft5406_read_regs fail:%d!\n",ret); + return; + } +#if 0 + for (i=0; i<32; i++) { + printk("buf[%d] = 0x%x \n", i, buf[i]); + } +#endif + + points = buf[2] & 0x07; + //dev_info(&data->client->dev, "ft5406_read_and_report_data points = %d\n",points); + if (points == 0) { +#if CONFIG_FT5X0X_MULTITOUCH + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 0); + //input_mt_sync(data->input_dev); +#else + input_report_abs(data->input_dev, ABS_PRESSURE, 0); + input_report_key(data->input_dev, BTN_TOUCH, 0); +#endif + input_sync(data->input_dev); + enable_irq(data->irq); + dev_info(&data->client->dev, "ft5406 touch release\n"); + return; + } + memset(&event, 0, sizeof(struct tp_event)); +#if CONFIG_FT5X0X_MULTITOUCH + for(i=0;i>4; + event.flag = ((buf[offset+0] & 0xc0) >> 6); + event.pressure = 200; + if(event.x<=SCREEN_MAX_X && event.y<=SCREEN_MAX_Y){ + //dev_info(&data->client->dev, + // "ft5406 multiple report event[%d]:x = %d,y = %d,id = %d,flag = %d,pressure = %d\n", + // i,event.x,event.y,event.id,event.flag,event.pressure); + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(data->input_dev, ABS_MT_POSITION_X, event.x); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event.y); + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event.id); + input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); + input_mt_sync(data->input_dev); + } + } +#else + event.x = (s16)(buf[3] & 0x0F)<<8 | (s16)buf[4]; + event.y = (s16)(buf[5] & 0x0F)<<8 | (s16)buf[6]; + event.pressure =200; + input_report_abs(data->input_dev, ABS_X, event.x); + input_report_abs(data->input_dev, ABS_Y, event.y); + input_report_abs(data->input_dev, ABS_PRESSURE, event.pressure); + input_report_key(data->input_dev, BTN_TOUCH, 1); + //dev_info(&data->client->dev, "ft5406 single report event:x = %d,y = %d\n",event.x,event.y); +#endif + //dev_info(&data->client->dev, "ft5406 sync\n",event.x,event.y); + input_sync(data->input_dev); + enable_irq(data->irq); + return; +} + +static irqreturn_t ft5406_interrupt(int irq, void *dev_id) +{ + struct ft5x0x_ts_data *ft5x0x_ts = dev_id; -#define FT5X0X_REG_THRES 0x80 /* Thresshold, the threshold be low, the sensitivy will be high */ -#define FT5X0X_REG_REPORT_RATE 0x88 /* **************report rate, in unit of 10Hz **************/ -#define FT5X0X_REG_PMODE 0xA5 /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */ -#define FT5X0X_REG_FIRMID 0xA6 /* ***************firmware version **********************/ -#define FT5X0X_REG_NOISE_MODE 0xb2 /* to enable or disable power noise, 1 -- enable, 0 -- disable */ + disable_irq_nosync(ft5x0x_ts->irq); + if (!work_pending(&ft5x0x_ts->pen_event_work)) + queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work); + return IRQ_HANDLED; +} + +static int ft5406_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); + struct ft5406_platform_data *pdata = client->dev.platform_data; + + if (pdata->platform_sleep) + pdata->platform_sleep(); + disable_irq(ft5x0x_ts->irq); + return 0; +} +static int ft5406_resume(struct i2c_client *client) +{ + struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); + struct ft5406_platform_data *pdata = client->dev.platform_data; + + enable_irq(ft5x0x_ts->irq); + if (pdata->platform_wakeup) + pdata->platform_wakeup(); + return 0; +} + +static int __devexit ft5406_remove(struct i2c_client *client) +{ + struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client); + + free_irq(ft5x0x_ts->irq, ft5x0x_ts); + input_unregister_device(ft5x0x_ts->input_dev); + kfree(ft5x0x_ts); + cancel_work_sync(&ft5x0x_ts->pen_event_work); + destroy_workqueue(ft5x0x_ts->ts_workqueue); + i2c_set_clientdata(client, NULL); +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&ft5406_early_suspend); +#endif + this_client = NULL; + return 0; +} + static int ft5406_probe(struct i2c_client *client ,const struct i2c_device_id *id) { struct ft5x0x_ts_data *ft5x0x_ts; struct input_dev *input_dev; - struct ft5406_platform_data *pdata = pdata = client->dev.platform_data; - + struct ft5406_platform_data *pdata = client->dev.platform_data; 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; - //printk("==ft5x0x_ts_probe=\n"); - + dev_info(&client->dev, "ft5x0x_ts_probe!\n"); if (!pdata) { dev_err(&client->dev, "platform data is required!\n"); return -EINVAL; @@ -1099,106 +702,58 @@ static int ft5406_probe(struct i2c_client *client ,const struct i2c_device_id * if (pdata->init_platform_hw) pdata->init_platform_hw(); - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - return -EIO; - + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){ + dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n"); + return -ENODEV; + } ft5x0x_ts = kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL); if (!ft5x0x_ts) { - err = -ENOMEM; - goto exit_alloc_data_failed; - } -/* - ft5x0x_client.adapter = bus; - ft5x0x_client.addr= address; - ft5x0x_client.mode = NORMALMODE; //NORMALNOSTOPMODE;// DIRECTMODE; - ft5x0x_client.Channel = I2C_CH0; - ft5x0x_client.speed = 300; - ft5x0x_client.addressBit=I2C_7BIT_ADDRESS_8BIT_REG; - ft5x0x_ts->client=&ft5x0x_client; - - i2c_set_clientdata(&ft5x0x_client, ft5x0x_ts); - - err = i2c_attach_client(&ft5x0x_client); - if (err < 0) - { - printk("ft5x0x attach client failed!!!!\n"); - goto exit_alloc_data_failed; + return -ENOMEM; } - INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work); - ft5x0x_ts->ts_workqueue = create_singlethread_workqueue("ft5x0x_ts"); - if (!ft5x0x_ts->ts_workqueue) { - err = -ESRCH; - goto exit_create_singlethread; - } - - rockchip_mux_api_set(TOUCH_INT_IOMUX_PINNAME,TOUCH_INT_IOMUX_PINDIR); - GPIOSetPinDirection(TOUCH_INT_IOPIN, GPIO_IN); - GPIOPullUpDown(TOUCH_INT_IOPIN, GPIOPullUp); - err = request_gpio_irq(TOUCH_INT_IOPIN, ft5x0x_ts_interrupt, GPIOEdgelFalling, ft5x0x_ts); - if(err < 0) - { - printk("ft5x0x_probe: request irq failed\n"); - goto exit_irq_request_failed; - } -*/ - input_dev = input_allocate_device(); - if (!input_dev) { - err = -ENOMEM; - printk("failed to allocate input device\n"); - goto exit_input_dev_alloc_failed; - } - - this_client = client; - while(retry < 5) { - ret=ft5406_set_regs(this_client,FT5X0X_REG_PMODE, buf_test,1); + ret=ft5406_set_regs(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; + err = -ENODEV; + goto exit_i2c_test_fail; } - ft5x0x_ts->client = client; + + input_dev = input_allocate_device(); + if (!input_dev) { + err = -ENOMEM; + printk("failed to allocate input device\n"); + goto exit_input_dev_alloc_failed; + } + ft5x0x_ts->client = this_client = client; ft5x0x_ts->irq = client->irq; ft5x0x_ts->input_dev = input_dev; - #if CONFIG_FT5X0X_MULTITOUCH //#ifdef - set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit); + #if CONFIG_FT5X0X_MULTITOUCH set_bit(ABS_MT_POSITION_X, input_dev->absbit); set_bit(ABS_MT_POSITION_Y, input_dev->absbit); + set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit); + set_bit(ABS_MT_TRACKING_ID, input_dev->absbit); set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit); - - //input_dev->evbit[0] = BIT_MASK(EV_ABS)|BIT_MASK(EV_KEY)|BIT_MASK(EV_SYN); //harry 03.21 - #ifdef CONFIG_TOUCH_PANEL_KEY - set_bit(KEY_HOME, input_dev->keybit); - set_bit(KEY_MENU, input_dev->keybit); - set_bit(KEY_BACK, input_dev->keybit); - #endif - - input_set_abs_params(input_dev, - ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0); - input_set_abs_params(input_dev, - ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0); - input_set_abs_params(input_dev, - ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0); - input_set_abs_params(input_dev, - ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 10, 0, 0); + input_set_abs_params(input_dev,ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0); + input_set_abs_params(input_dev,ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0); + input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR, 0, TOUCH_MAJOR_MAX, 0, 0); + input_set_abs_params(input_dev,ABS_MT_TRACKING_ID, 0, MAX_POINT, 0, 0); + input_set_abs_params(input_dev,ABS_MT_WIDTH_MAJOR, 0, WIDTH_MAJOR_MAX, 0, 0); #else set_bit(ABS_X, input_dev->absbit); set_bit(ABS_Y, input_dev->absbit); set_bit(ABS_PRESSURE, input_dev->absbit); set_bit(BTN_TOUCH, input_dev->keybit); - input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0); - input_set_abs_params(input_dev, - ABS_PRESSURE, 0, PRESS_MAX, 0 , 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, PRESS_MAX, 0 , 0); #endif @@ -1208,24 +763,20 @@ static int ft5406_probe(struct i2c_client *client ,const struct i2c_device_id * input_dev->name = FT5X0X_NAME; //dev_name(&client->dev) err = input_register_device(input_dev); if (err) { - // printk("ft5x0x_ts_probe: failed to register input device: \n"); + printk("ft5x0x_ts_probe: failed to register input device: \n"); goto exit_input_register_device_failed; } -// printk("==probe over =\n"); - - ft5x0x_ts->irq = RK29_PIN0_PA2; if (!ft5x0x_ts->irq) { - dev_dbg(&ft5x0x_ts->client->dev, "no IRQ?\n"); - return -ENODEV; + err = -ENODEV; + dev_err(&ft5x0x_ts->client->dev, "no IRQ?\n"); + goto exit_no_irq_fail; }else{ ft5x0x_ts->irq = gpio_to_irq(ft5x0x_ts->irq); } -//printk("ft5x0x_ts irq =%d", ft5x0x_ts->irq); - - - INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work); + //INIT_WORK(&ft5x0x_ts->pen_event_work, ft5406_ts_pen_irq_work); + INIT_WORK(&ft5x0x_ts->pen_event_work, ft5406_queue_work); ft5x0x_ts->ts_workqueue = create_singlethread_workqueue("ft5x0x_ts"); if (!ft5x0x_ts->ts_workqueue) { err = -ESRCH; @@ -1244,7 +795,6 @@ static int ft5406_probe(struct i2c_client *client ,const struct i2c_device_id * fts_register_read(FT5X0X_REG_NOISE_MODE, ®_value,1); printk("[TSP]nosie mode = 0x%2x\n", reg_value); -#if 1 if (fts_ctpm_get_upg_ver() != reg_version) { printk("[TSP] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver()); @@ -1259,74 +809,48 @@ static int ft5406_probe(struct i2c_client *client ,const struct i2c_device_id * } else { - printk("[TSP] ugrade fail err=%d, line = %d.\n", - err, __LINE__); + printk("[TSP] ugrade fail err=%d, line = %d.\n",err, __LINE__); } msleep(4000); } -#endif - - //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); - + ret = request_irq(ft5x0x_ts->irq, ft5406_interrupt, IRQF_TRIGGER_FALLING, client->dev.driver->name, ft5x0x_ts); if (ret < 0) { dev_err(&client->dev, "irq %d busy?\n", ft5x0x_ts->irq); - goto fail3; + goto exit_irq_request_fail; } - //harry 03.23 - #if 0 - ret = input_register_device(input_dev); - if(ret<0) - { - // printk("ft5406 register input device failed!!!!\n"); - goto exit_irq_request_failed; - } - #endif - -#ifdef CONFIG_HAS_EARLYSUSPEND - ft5406_early_suspend.suspend =ft5x0x_ts_suspend; - ft5406_early_suspend.resume =ft5x0x_ts_resume; - ft5406_early_suspend.level = 0x2; - register_early_suspend(&ft5406_early_suspend); + + i2c_set_clientdata(client, ft5x0x_ts); +#if 0//def CONFIG_HAS_EARLYSUSPEND + ft5406_early_suspend.suspend =ft5406_ts_suspend; + ft5406_early_suspend.resume =ft5406_ts_resume; + ft5406_early_suspend.level = 0x2; + register_early_suspend(&ft5406_early_suspend); #endif - //buf_w[0] = 6; //harry 04.07 buf_w[0] = 6; - err = ft5406_set_regs(client,0x88,buf_w,1); - //ft5x0x_i2c_txdata(0x88, buf_w, 1); /* adjust frequency 60Hz */ - buf_r[0] = 0; err = ft5406_read_regs(client,0x88,buf_r,1); - //ft5x0x_i2c_rxdata(0x88, buf_r, 1); // printk("read buf[0x88] = %d\n", buf_r[0]); - return 0; -fail3: - free_irq(ft5x0x_ts->irq,ft5x0x_ts); - i2c_set_clientdata(client, NULL); //harry - destroy_workqueue(ft5x0x_ts->ts_workqueue); //harry -exit_input_register_device_failed: - input_free_device(input_dev); -// i2c_set_clientdata(client, NULL); -// kfree(ft5x0x_ts); -exit_input_dev_alloc_failed: -// free_irq(7, ft5x0x_ts); - free_irq(ft5x0x_ts->irq, ft5x0x_ts); -exit_irq_request_failed: -exit_platform_data_null: + i2c_set_clientdata(client, NULL); + free_irq(ft5x0x_ts->irq,ft5x0x_ts); +exit_irq_request_fail: 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"); +exit_no_irq_fail: + input_unregister_device(input_dev); +exit_input_register_device_failed: + input_free_device(input_dev); +exit_input_dev_alloc_failed: +exit_i2c_test_fail: + if (pdata->exit_platform_hw) + pdata->exit_platform_hw(); kfree(ft5x0x_ts); -exit_alloc_data_failed: return err; } @@ -1345,29 +869,28 @@ static struct i2c_driver ft5406_driver = { .name = FT5X0X_NAME }, .id_table = ft5406_idtable, - .probe = ft5406_probe, -#ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = ft5x0x_ts_suspend, - .resume = ft5x0x_ts_resume, -#endif + .probe = ft5406_probe, + .suspend = ft5406_suspend, + .resume = ft5406_resume, .remove = __devexit_p(ft5406_remove), }; -static int __init ft5x0x_ts_init(void) +static int __init ft5406_ts_init(void) { return i2c_add_driver(&ft5406_driver); } -static void __exit ft5x0x_ts_exit(void) +static void __exit ft5406_ts_exit(void) { + printk("Touchscreen driver of ft5406 exited.\n"); i2c_del_driver(&ft5406_driver); } /***********************************************************************/ -module_init(ft5x0x_ts_init); -module_exit(ft5x0x_ts_exit); +module_init(ft5406_ts_init); +module_exit(ft5406_ts_exit); MODULE_AUTHOR(""); MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver"); diff --git a/drivers/input/touchscreen/ft5406_ts.h b/drivers/input/touchscreen/ft5406_ts.h deleted file mode 100755 index b1f1cd2ff1de..000000000000 --- a/drivers/input/touchscreen/ft5406_ts.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __LINUX_FT5X0X_TS_H__ -#define __LINUX_FT5X0X_TS_H__ - -#define SCREEN_MAX_X 800 -#define SCREEN_MAX_Y 480 -#define PRESS_MAX 255 - -#define FT5X0X_NAME "ft5x0x_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"// - -struct ft5x0x_ts_platform_data{ - u16 intr; /* irq number */ -}; - -enum ft5x0x_ts_regs { - FT5X0X_REG_PMODE = 0xA5, /* Power Consume Mode */ -}; - -//FT5X0X_REG_PMODE -#define PMODE_ACTIVE 0x00 -#define PMODE_MONITOR 0x01 -#define PMODE_STANDBY 0x02 -#define PMODE_HIBERNATE 0x03 - - - #ifndef ABS_MT_TOUCH_MAJOR - #define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */ - #define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */ - #define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */ - #define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */ - #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ - #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ - #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ - #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ - #define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */ - #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ - - #endif /* ABS_MT_TOUCH_MAJOR */ - - -#endif - diff --git a/drivers/input/touchscreen/goodix_touch_newton.c b/drivers/input/touchscreen/goodix_touch_newton.c deleted file mode 100755 index e34812725d91..000000000000 --- a/drivers/input/touchscreen/goodix_touch_newton.c +++ /dev/null @@ -1,1905 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -//#include -#include -#include -#include -#include -#include "goodix_touch_newton.h" - -#include -#include -#include -#include -#include - -#include - -/******************************************************* -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 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<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<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; iclient, 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>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; i83)&&(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; iclient, 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 deleted file mode 100755 index 6b16a13e5868..000000000000 --- a/drivers/input/touchscreen/goodix_touch_newton.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 -#include -#include -#include - -//*************************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 */ diff --git a/drivers/input/touchscreen/gt819.c b/drivers/input/touchscreen/gt819.c new file mode 100755 index 000000000000..bb376f322af4 --- /dev/null +++ b/drivers/input/touchscreen/gt819.c @@ -0,0 +1,426 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GOODIX_I2C_NAME "Goodix-TS" +//define default resolution of the touchscreen +#define GOODIX_MULTI_TOUCH +#define GT819_IIC_SPEED 400*1000 //400*1000 +#define TOUCH_MAX_WIDTH 800 +#define TOUCH_MAX_HEIGHT 480 +#define TOUCH_MAJOR_MAX 200 +#define WIDTH_MAJOR_MAX 200 +#define MAX_POINT 10 +#define INT_TRIGGER_EDGE_RISING 0 +#define INT_TRIGGER_EDGE_FALLING 1 +#define INT_TRIGGER_EDGE_LOW 2 +#define INT_TRIGGER_EDGE_HIGH 3 +#define INT_TRIGGER INT_TRIGGER_EDGE_FALLING +#define I2C_DELAY 0x0f +struct goodix_ts_data { + struct workqueue_struct *goodix_wq; + struct i2c_client *client; + struct input_dev *input_dev; + struct work_struct work; + int irq; + int irq_gpio; + uint16_t abs_x_max; + uint16_t abs_y_max; + uint8_t max_touch_num; + uint8_t int_trigger_type; +}; + +static const char *goodix_ts_name = "Goodix Capacitive TouchScreen"; + +static int gt819_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len) +{ + int ret; + ret = i2c_master_reg8_recv(client, reg, buf, len, GT819_IIC_SPEED); + return ret; +} + + +static int gt819_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], unsigned short len) +{ + int ret; + ret = i2c_master_reg8_send(client, reg, buf, (int)len, GT819_IIC_SPEED); + return ret; +} + +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 x,y,w; + + ret = gt819_read_regs(ts->client,1, point_data, 1); + if (ret < 0) { + dev_err(&ts->client->dev, "i2c_read_bytes fail:%d!\n",ret); + return; + } + + points = point_data[0] & 0x1f; + //dev_info(&ts->client->dev, "points = %d\n",points); + if (points == 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(data->input_dev); + input_sync(ts->input_dev); + enable_irq(ts->irq); + dev_info(&ts->client->dev, "touch release\n"); + return; + } + for(i=0;0!=points;i++) + points>>=1; + points = i; + ret = gt819_read_regs(ts->client,3, point_data, points*5); + if (ret < 0) { + dev_err(&ts->client->dev, "i2c_read_bytes fail:%d!\n",ret); + return; + } + for(i=0;iclient->dev, "goodix multiple report event[%d]:x = %d,y = %d,w = %d\n",i,x,y,w); + if(x<=TOUCH_MAX_WIDTH && y<=TOUCH_MAX_HEIGHT){ + //dev_info(&ts->client->dev, "goodix multiple report event[%d]:x = %d,y = %d,w = %d\n",i,x,y,w); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); + input_mt_sync(ts->input_dev); + } + } + input_sync(ts->input_dev); + enable_irq(ts->irq); + return; +} + +/******************************************************* +Description: + External interrupt service routine. + +Parameter: + irq: interrupt number. + dev_id: private data pointer. + +return: + irq execute status. +*******************************************************/ +static irqreturn_t gt819_irq_handler(int irq, void *dev_id) +{ + struct goodix_ts_data *ts = dev_id; + + disable_irq_nosync(ts->client->irq); + queue_work(ts->goodix_wq, &ts->work); + return IRQ_HANDLED; +} + +static int gt819_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct goodix_platform_data *pdata = client->dev.platform_data; + dev_info(&client->dev,"gt819_suspend\n"); + + if (pdata->platform_sleep) + pdata->platform_sleep(); + disable_irq(client->irq); + return 0; +} + +static int gt819_resume(struct i2c_client *client) +{ + struct goodix_platform_data *pdata = client->dev.platform_data; + dev_info(&client->dev,"gt819_resume\n"); + + enable_irq(client->irq); + if (pdata->platform_wakeup) + pdata->platform_wakeup(); + return 0; +} + + +/******************************************************* +Description: + Goodix touchscreen driver release function. + +Parameter: + client: i2c device struct. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int gt819_remove(struct i2c_client *client) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(client); +#ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP + 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); + 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); + kfree(ts); + return 0; +} + +static int gt819_init_panel(struct goodix_ts_data *ts) +{ + int ret,I2cDelay; + uint8_t rd_cfg_buf[10]; + #if 0 + int i; + uint8_t config_info[] = { + 0x02,(TOUCH_MAX_WIDTH>>8),(TOUCH_MAX_WIDTH&0xff), + (TOUCH_MAX_HEIGHT>>8),(TOUCH_MAX_HEIGHT&0xff),MAX_POINT,(0xa0 | INT_TRIGGER), + 0x20,0x00,0x32,0x0f,0x20,0x08,0x14,0x00, + 0x00,0x20,0x00,0x00,0x88,0x88,0x88,0x00,0x37,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0xff,0xff,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0xff,0xff,0xff,0x00,0x00,0x3c,0x64,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 + }; + ret = gt819_set_regs(ts->client, 101, config_info, sizeof(config_info)); + for (i=0; iclient, 101, rd_cfg_buf, 10); + if (ret < 0) + return ret; + ts->abs_x_max = ((((uint16_t)rd_cfg_buf[1])<<8)|rd_cfg_buf[2]); + ts->abs_y_max = ((((uint16_t)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; + I2cDelay = rd_cfg_buf[9]&0x0f; + dev_info(&ts->client->dev,"X_MAX = %d,Y_MAX = %d,MAX_TOUCH_NUM = %d,INT_TRIGGER = %d,I2cDelay = %x\n", + ts->abs_x_max,ts->abs_y_max,ts->max_touch_num,ts->int_trigger_type,I2cDelay); + if((ts->abs_x_max!=TOUCH_MAX_WIDTH)||(ts->abs_y_max!=TOUCH_MAX_HEIGHT)|| + (MAX_POINT!=ts->max_touch_num)||INT_TRIGGER!=ts->int_trigger_type || I2C_DELAY!=I2cDelay){ + ts->abs_x_max = TOUCH_MAX_WIDTH; + ts->abs_y_max = TOUCH_MAX_HEIGHT; + ts->max_touch_num = MAX_POINT; + ts->int_trigger_type = INT_TRIGGER; + rd_cfg_buf[1] = ts->abs_x_max>>8; + rd_cfg_buf[2] = ts->abs_x_max&0xff; + rd_cfg_buf[3] = ts->abs_y_max>>8; + rd_cfg_buf[4] = ts->abs_y_max&0xff; + rd_cfg_buf[5] = ts->max_touch_num; + rd_cfg_buf[6] = ((rd_cfg_buf[6]&0xfc) | INT_TRIGGER); + rd_cfg_buf[9] = ((rd_cfg_buf[9]&0xf0) | I2C_DELAY); + ret = gt819_set_regs(ts->client, 101, rd_cfg_buf, 10); + if (ret < 0) + return ret; + dev_info(&ts->client->dev,"set config\n"); + } + return 0; +} + +/******************************************************* +Description: + Goodix touchscreen probe function. + +Parameter: + client: i2c device struct. + id:device id. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int gt819_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + struct goodix_ts_data *ts; + struct goodix_platform_data *pdata = client->dev.platform_data; + const char irq_table[4] = {IRQ_TYPE_EDGE_RISING, + IRQ_TYPE_EDGE_FALLING, + IRQ_TYPE_LEVEL_LOW, + IRQ_TYPE_LEVEL_HIGH}; + + dev_info(&client->dev,"Install touch driver\n"); + + 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)) { + dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n"); + return -ENODEV; + } + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts == NULL) { + return -ENOMEM; + } + ts->client = client; + + ret = gt819_init_panel(ts); + if(ret != 0){ + dev_err(&client->dev,"init panel fail,ret = %d\n",ret); + goto err_init_panel_fail; + } + + if (!client->irq){ + dev_err(&client->dev,"no irq fail\n"); + ret = -ENODEV; + goto err_no_irq_fail; + } + ts->irq_gpio = client->irq; + ts->irq = client->irq = gpio_to_irq(client->irq); + ret = request_irq(client->irq, gt819_irq_handler, irq_table[ts->int_trigger_type],client->name, ts); + if (ret != 0) { + dev_err(&client->dev,"request_irq fail:%d\n", ret); + goto err_irq_request_fail; + } + + ts->goodix_wq = create_workqueue("goodix_wq"); + if (!ts->goodix_wq) { + printk(KERN_ALERT "creat workqueue faiked\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(); + if (ts->input_dev == NULL) { + ret = -ENOMEM; + dev_err(&client->dev,"Failed to allocate input device\n"); + goto err_input_dev_alloc_failed; + } + + set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit); + set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit); + set_bit(ABS_MT_TOUCH_MAJOR, ts->input_dev->absbit); + set_bit(ABS_MT_TRACKING_ID, ts->input_dev->absbit); + set_bit(ABS_MT_WIDTH_MAJOR, ts->input_dev->absbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); + 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); + input_set_abs_params(ts->input_dev,ABS_MT_TOUCH_MAJOR, 0, TOUCH_MAJOR_MAX, 0, 0); + input_set_abs_params(ts->input_dev,ABS_MT_TRACKING_ID, 0, MAX_POINT, 0, 0); + input_set_abs_params(ts->input_dev,ABS_MT_WIDTH_MAJOR, 0, WIDTH_MAJOR_MAX, 0, 0); + + ts->input_dev->name = goodix_ts_name; + 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; + } + i2c_set_clientdata(client, ts); + + return 0; + i2c_set_clientdata(client, NULL); + input_unregister_device(ts->input_dev); +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_input_dev_alloc_failed: + destroy_workqueue(ts->goodix_wq); +err_create_work_queue_fail: + free_irq(client->irq,ts); +err_irq_request_fail: +err_no_irq_fail: +err_init_panel_fail: + if (pdata->exit_platform_hw) + pdata->exit_platform_hw(); + kfree(ts); + return ret; +} + + + +static const struct i2c_device_id gt819_id[] = { + { GOODIX_I2C_NAME, 0 }, + { } +}; + +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, + .owner = THIS_MODULE, + }, +}; + +/******************************************************* +Description: + Driver Install function. +return: + Executive Outcomes. 0---succeed. +********************************************************/ +static int __devinit gt819_init(void) +{ + int ret; + + ret=i2c_add_driver(>819_driver); + return ret; +} + +/******************************************************* +Description: + Driver uninstall function. +return: + Executive Outcomes. 0---succeed. +********************************************************/ +static void __exit gt819_exit(void) +{ + printk(KERN_ALERT "Touchscreen driver of guitar exited.\n"); + i2c_del_driver(>819_driver); +} + +late_initcall(gt819_init); +module_exit(gt819_exit); + +MODULE_DESCRIPTION("Goodix Touchscreen Driver"); +MODULE_LICENSE("GPL");