From f936c4437f99ea667924c068bb4e472f7777e4f7 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 7 Nov 2013 14:56:24 +0530 Subject: [PATCH 1/8] input: touchscreen: Code clean-up for Goodix driver Fix errors and warnings found by checkpatch script in goodix_tool.c and gt9xx_update.c. Correct debug messages in goodix_update.c. Remove magic numbers for read-write flags with macros in goodix_tool.c Change-Id: I3a00fb46106f859128f0fa9b8c99b5d6ba24bc7b Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/goodix_tool.c | 415 ++++---- drivers/input/touchscreen/gt9xx/gt9xx.c | 20 +- drivers/input/touchscreen/gt9xx/gt9xx.h | 74 +- .../input/touchscreen/gt9xx/gt9xx_update.c | 930 +++++++----------- 4 files changed, 624 insertions(+), 815 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c index 63fad6c46836..99a29401b36f 100644 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c @@ -23,16 +23,15 @@ #include "gt9xx.h" #include +#include +#include #define DATA_LENGTH_UINT 512 -#define CMD_HEAD_LENGTH (sizeof(st_cmd_head) - sizeof(u8 *)) +#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *)) static char procname[20] = {0}; -#define UPDATE_FUNCTIONS - -#pragma pack(1) -struct { - u8 wr; /* write read flag٬0:R 1:W 2:PID 3: */ +struct st_cmd_head { + u8 wr; /* write read flag 0:R 1:W 2:PID 3: */ u8 flag; /* 0:no need flag/int 1: need flag 2:need int */ u8 flag_addr[2];/* flag address */ u8 flag_val; /* flag val */ @@ -46,9 +45,9 @@ struct { u8 addr[2]; /* address */ u8 res[3]; /* reserved */ u8 *data; /* data pointer */ -} st_cmd_head; -#pragma pack() -st_cmd_head cmd_head; +} __packed; + +static struct st_cmd_head cmd_head; static struct i2c_client *gt_client; @@ -56,15 +55,11 @@ static struct proc_dir_entry *goodix_proc_entry; static struct mutex lock; -static s32 goodix_tool_write(struct file *filp, const char __user *buff, - unsigned long len, void *data); -static s32 goodix_tool_read(char *page, char **start, off_t off, int count, - int *eof, void *data); static s32 (*tool_i2c_read)(u8 *, u16); static s32 (*tool_i2c_write)(u8 *, u16); -s32 DATA_LENGTH; -s8 IC_TYPE[16] = {0}; +s32 data_length; +s8 ic_type[16] = {0}; static void tool_set_proc_name(char *procname) { @@ -113,7 +108,7 @@ static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) } if (i == cmd_head.retry) { - dev_err(&client->dev, "I2C read retry limit over.\n"); + dev_err(>_client->dev, "I2C read retry limit over\n"); ret = -EIO; } @@ -138,7 +133,7 @@ static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) } if (i == cmd_head.retry) { - dev_err(&client->dev, "I2C write retry limit over.\n"); + dev_err(>_client->dev, "I2C write retry limit over\n"); ret = -EIO; } @@ -173,17 +168,17 @@ static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) static void register_i2c_func(void) { - if (strcmp(IC_TYPE, "GT8110") && strcmp(IC_TYPE, "GT8105") - && strcmp(IC_TYPE, "GT801") && strcmp(IC_TYPE, "GT800") - && strcmp(IC_TYPE, "GT801PLUS") && strcmp(IC_TYPE, "GT811") - && strcmp(IC_TYPE, "GTxxx")) { + if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105") + && strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800") + && strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811") + && strcmp(ic_type, "GTxxx")) { tool_i2c_read = tool_i2c_read_with_extra; tool_i2c_write = tool_i2c_write_with_extra; - pr_debug("I2C function: with pre and end cmd!\n"); + pr_debug("I2C function: with pre and end cmd\n"); } else { tool_i2c_read = tool_i2c_read_no_extra; tool_i2c_write = tool_i2c_write_no_extra; - pr_info("I2C function: without pre and end cmd!\n"); + pr_info("I2C function: without pre and end cmd\n"); } } @@ -191,57 +186,14 @@ static void unregister_i2c_func(void) { tool_i2c_read = NULL; tool_i2c_write = NULL; - pr_info("I2C function: unregister i2c transfer function!\n"); -} - -s32 init_wr_node(struct i2c_client *client) -{ - u8 i; - - gt_client = client; - memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_head.data = NULL; - - i = 5; - while ((!cmd_head.data) && i) { - cmd_head.data = devm_kzalloc(&client->dev, - i * DATA_LENGTH_UINT, GFP_KERNEL); - if (cmd_head.data) - break; - i--; - } - if (i) { - DATA_LENGTH = i * DATA_LENGTH_UINT; - dev_dbg(&client->dev, "Applied memory size:%d.", DATA_LENGTH); - } else { - pr_err("Apply for memory failed.\n"); - return FAIL; - } - - cmd_head.addr_len = 2; - cmd_head.retry = 5; - - register_i2c_func(); - - mutex_init(&lock); - tool_set_proc_name(procname); - goodix_proc_entry = create_proc_entry(procname, 0660, NULL); - if (goodix_proc_entry == NULL) { - pr_err("Couldn't create proc entry!\n"); - return FAIL; - } - GTP_INFO("Create proc entry success!"); - goodix_proc_entry->write_proc = goodix_tool_write; - dix_proc_entry->read_proc = goodix_tool_read; - - return SUCCESS; + pr_info("I2C function: unregister i2c transfer function\n"); } void uninit_wr_node(void) { cmd_head.data = NULL; unregister_i2c_func(); - remove_proc_entry(procname, NULL); + proc_remove(goodix_proc_entry); } static u8 relation(u8 src, u8 dst, u8 rlt) @@ -256,7 +208,7 @@ static u8 relation(u8 src, u8 dst, u8 rlt) case 1: ret = (src == dst) ? true : false; - pr_debug("equal:src:0x%02x dst:0x%02x ret:%d.\n", + pr_debug("equal:src:0x%02x dst:0x%02x ret:%d\n", src, dst, (s32)ret); break; @@ -298,23 +250,18 @@ static u8 comfirm(void) s32 i = 0; u8 buf[32]; -/* memcpy(&buf[GTP_ADDR_LENGTH - cmd_head.addr_len], - * &cmd_head.flag_addr, cmd_head.addr_len); - * memcpy(buf, &cmd_head.flag_addr, cmd_head.addr_len); - * //Modified by Scott, 2012-02-17 - */ memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); for (i = 0; i < cmd_head.times; i++) { if (tool_i2c_read(buf, 1) <= 0) { - pr_err("Read flag data failed!\n"); + dev_err(>_client->dev, "Read flag data failed"); return FAIL; } if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, cmd_head.flag_relation)) { - pr_debug("value at flag addr:0x%02x.\n", + pr_debug("value at flag addr:0x%02x\n", buf[GTP_ADDR_LENGTH]); - pr_debug("flag value:0x%02x.\n", cmd_head.flag_val); + pr_debug("flag value:0x%02x\n", cmd_head.flag_val); break; } @@ -322,89 +269,99 @@ static u8 comfirm(void) } if (i >= cmd_head.times) { - pr_debug("Didn't get the flag to continue!\n"); + dev_err(>_client->dev, "Didn't get the flag to continue"); return FAIL; } return SUCCESS; } -/******************************************************** +#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE +static s32 fill_update_info(char __user *user_buf, + size_t count, loff_t *ppos) +{ + u8 buf[4]; + + buf[0] = show_len >> 8; + buf[1] = show_len & 0xff; + buf[2] = total_len >> 8; + buf[3] = total_len & 0xff; + return simple_read_from_buffer(user_buf, count, ppos, + buf, sizeof(buf)); +} +#else +static s32 fill_update_info(char __user *user_buf, + size_t count, loff_t *ppos) +{ + return -ENODEV; +} +#endif + +/* * Function: * Goodix tool write function. * Input: * standard proc write function param. * Output: * Return write length. - ******************************************************* */ -static s32 goodix_tool_write(struct file *filp, const char __user *buff, - unsigned long len, void *data) +static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) { s32 ret = 0; mutex_lock(&lock); - ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); + ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); if (ret) { - pr_err("copy_from_user failed.\n"); - ret = -EACCES; + dev_err(>_client->dev, "copy_from_user failed"); + ret = -EFAULT; goto exit; } - pr_debug("wr :0x%02x.\n", cmd_head.wr); - pr_debug("flag:0x%02x.\n", cmd_head.flag); - pr_debug("flag addr:0x%02x%02x.\n", cmd_head.flag_addr[0], - cmd_head.flag_addr[1]); - pr_debug("flag val:0x%02x.\n", cmd_head.flag_val); - pr_debug("flag rel:0x%02x.\n", cmd_head.flag_relation); - pr_debug("circle :%d.\n", (s32)cmd_head.circle); - pr_debug("times :%d.\n", (s32)cmd_head.times); - pr_debug("retry :%d.\n", (s32)cmd_head.retry); - pr_debug("delay :%d.\n", (s32)cmd_head.delay); - pr_debug("data len:%d.\n", (s32)cmd_head.data_len); - pr_debug("addr len:%d.\n", (s32)cmd_head.addr_len); - pr_debug("addr:0x%02x%02x.\n", cmd_head.addr[0], cmd_head.addr[1]); - pr_debug("len:%d.\n", (s32)len); - pr_debug("buf[20]:0x%02x.\n", buff[CMD_HEAD_LENGTH]); + dev_dbg(>_client->dev, "wr:0x%02x, flag:0x%02x, flag addr:0x%02x%02x, + flag val:0x%02x, flag rel:0x%02x,", cmd_headd.wr, + cmd_head.flag, cmd_head.flag_addr[0], + cmd_head.flag_addr[1], cmd_head.flag_val, + cmd_head.flag_relation); + dev_dbg(>_client->dev, "circle:%d, times:%d, retry:%d, delay:%d, + data len:%d, addr len:%d, addr:0x%02x%02x, write len: %d", + (s32)cmd_head.circle, (s32)cmd_head.times, (s32)cmd_head.retry, + (s32)cmd_head.delay, (s32)cmd_head.data_len, + (s32)cmd_head.addr_len, cmd_head.addr[0], cmd_head.addr[1], + (s32)count); - if (cmd_head.data_len > (DATA_LENGTH - GTP_ADDR_LENGTH)) { - pr_debug("data len %d > data buff %d, rejected!\n", - cmd_head.data_len, (DATA_LENGTH - GTP_ADDR_LENGTH)); - ret = -EINVAL; - goto exit; - } - if (cmd_head.addr_len > GTP_ADDR_LENGTH) { - pr_debug(" addr len %d > data buff %d, rejected!\n", - cmd_head.addr_len, GTP_ADDR_LENGTH); + if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) { + dev_err(>_client->dev, "data len %d > data buff %d, rejected\n", + cmd_head.data_len, (data_length - GTP_ADDR_LENGTH)); ret = -EINVAL; goto exit; } - if (cmd_head.wr == 1) { - /* copy_from_user(&cmd_head.data[cmd_head.addr_len], - * &buff[CMD_HEAD_LENGTH], cmd_head.data_len); - */ + if (cmd_head.wr == GTP_RW_WRITE) { ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], - &buff[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) - pr_err("copy_from_user failed.\n"); + &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed"); + ret = -EFAULT; + goto exit; + } memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); - if (cmd_head.flag == 1) { - if (comfirm() == FAIL) { - pr_err("[WRITE]Comfirm fail!\n"); + if (cmd_head.flag == GTP_NEED_FLAG) { + if (comfirm() == FAIL) { + dev_err(>_client->dev, "Confirm fail"); ret = -EINVAL; goto exit; } - } else if (cmd_head.flag == 2) { + } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { /* Need interrupt! */ } if (tool_i2c_write( &cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len) <= 0) { - pr_err("[WRITE]Write data failed!\n"); + dev_err(>_client->dev, "Write data failed"); ret = -EIO; goto exit; } @@ -414,32 +371,33 @@ static s32 goodix_tool_write(struct file *filp, const char __user *buff, ret = cmd_head.data_len + CMD_HEAD_LENGTH; goto exit; - } else if (cmd_head.wr == 3) { /* Write ic type */ - - ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], + } else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) { /* Write ic type */ + ret = copy_from_user(&cmd_head.data[0], + &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) - pr_err("copy_from_user failed.\n"); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed"); + ret = -EFAULT; + goto exit; + } - if (cmd_head.data_len > sizeof(IC_TYPE)) { - pr_debug("<<-GTP->> data len %d > data buff %d, rejected!\n", - cmd_head.data_len, sizeof(IC_TYPE)); + if (cmd_head.data_len > sizeof(ic_type)) { + dev_err(>_client->dev, + "data len %d > data buff %d, rejected\n", + cmd_head.data_len, sizeof(ic_type)); ret = -EINVAL; goto exit; } - memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); + memcpy(ic_type, cmd_head.data, cmd_head.data_len); register_i2c_func(); ret = cmd_head.data_len + CMD_HEAD_LENGTH; goto exit; - } else if (cmd_head.wr == 5) { - - /* memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); */ - + } else if (cmd_head.wr == GTP_RW_NO_WRITE) { ret = cmd_head.data_len + CMD_HEAD_LENGTH; goto exit; - } else if (cmd_head.wr == 7) { /* disable irq! */ + } else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */ gtp_irq_disable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT @@ -447,7 +405,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *buff, #endif ret = CMD_HEAD_LENGTH; goto exit; - } else if (cmd_head.wr == 9) { /* enable irq! */ + } else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */ gtp_irq_enable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT @@ -455,41 +413,45 @@ static s32 goodix_tool_write(struct file *filp, const char __user *buff, #endif ret = CMD_HEAD_LENGTH; goto exit; - } else if (cmd_head.wr == 17) { + } else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) { struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], - &buff[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) - pr_debug("copy_from_user failed.\n"); + &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed"); + goto exit; + } if (cmd_head.data[GTP_ADDR_LENGTH]) { - pr_debug("gtp enter rawdiff.\n"); + pr_debug("gtp enter rawdiff\n"); ts->gtp_rawdiff_mode = true; } else { ts->gtp_rawdiff_mode = false; - pr_debug("gtp leave rawdiff.\n"); + pr_debug("gtp leave rawdiff\n"); } ret = CMD_HEAD_LENGTH; goto exit; - } -#ifdef UPDATE_FUNCTIONS - else if (cmd_head.wr == 11) { /* Enter update mode! */ - if (gup_enter_update_mode(gt_client) == FAIL) + } else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) { + /* Enter update mode! */ + if (gup_enter_update_mode(gt_client) == FAIL) { ret = -EBUSY; goto exit; - } else if (cmd_head.wr == 13) { /* Leave update mode! */ - gup_leave_update_mode(); - } else if (cmd_head.wr == 15) { /* Update firmware! */ + } + } else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) { + /* Leave update mode! */ + gup_leave_update_mode(gt_client); + } else if (cmd_head.wr == GTP_RW_UPDATE_FW) { + /* Update firmware! */ show_len = 0; total_len = 0; - if (cmd_head.data_len + 1 > DATA_LENGTH) { - pr_debug("<<-GTP->> data len %d > data buff %d, rejected!\n", - cmd_head.data_len + 1, DATA_LENGTH); + if (cmd_head.data_len + 1 > data_length) { + dev_err(>_client->dev, "data len %d > data buff %d, rejected\n", + cmd_head.data_len + 1, data_length); ret = -EINVAL; goto exit; } memset(cmd_head.data, 0, cmd_head.data_len + 1); - memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], + memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); if (gup_update_proc((void *)cmd_head.data) == FAIL) { @@ -497,7 +459,6 @@ static s32 goodix_tool_write(struct file *filp, const char __user *buff, goto exit; } } -#endif ret = CMD_HEAD_LENGTH; exit: @@ -505,37 +466,37 @@ exit: return ret; } -/******************************************************* +/* * Function: * Goodix tool read function. * Input: * standard proc read function param. * Output: * Return read length. - ******************************************************* -*/ -static s32 goodix_tool_read(char *page, char **start, off_t off, int count, - int *eof, void *data) + */ +static s32 goodix_tool_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) { + u16 data_len = 0; s32 ret; + u8 buf[32]; mutex_lock(&lock); - if (cmd_head.wr % 2) { - pr_err("<< [READ]command head wrong\n"); + if (cmd_head.wr & 0x1) { + dev_err(>_client->dev, "command head wrong\n"); ret = -EINVAL; goto exit; - } else if (!cmd_head.wr) { - u16 len = 0; - s16 data_len = 0; - u16 loc = 0; + } - if (cmd_head.flag == 1) { + switch (cmd_head.wr) { + case GTP_RW_READ: + if (cmd_head.flag == GTP_NEED_FLAG) { if (comfirm() == FAIL) { - pr_err("[READ]Comfirm fail!\n"); + dev_err(>_client->dev, "Confirm fail"); ret = -EINVAL; goto exit; } - } else if (cmd_head.flag == 2) { + } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { /* Need interrupt! */ } @@ -550,54 +511,86 @@ static s32 goodix_tool_read(char *page, char **start, off_t off, int count, msleep(cmd_head.delay); data_len = cmd_head.data_len; - while (data_len > 0) { - if (data_len > DATA_LENGTH) - len = DATA_LENGTH; - else - len = data_len; - - data_len -= len; - - if (tool_i2c_read(cmd_head.data, len) <= 0) { - pr_err("[READ]Read data failed!\n"); - ret = -EINVAL; - goto exit; - } - memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH], - len); - loc += len; + if (data_len <= 0 || (data_len > data_length)) { + dev_err(>_client->dev, "Invalid data length %d\n", + data_len); + ret = -EINVAL; + goto exit; } - } else if (cmd_head.wr == 2) { - /* memcpy(page, "gt8", cmd_head.data_len); - * memcpy(page, "GT818", 5); - * page[5] = 0; - */ + if (data_len > count) + data_len = count; - pr_debug("Return ic type:%s len:%d.\n", page, - (s32)cmd_head.data_len); - ret = cmd_head.data_len; - goto exit; - /* return sizeof(IC_TYPE_NAME); */ - } else if (cmd_head.wr == 4) { - page[0] = show_len >> 8; - page[1] = show_len & 0xff; - page[2] = total_len >> 8; - page[3] = total_len & 0xff; - } else if (cmd_head.wr == 6) { - /* Read error code! */ - } else if (cmd_head.wr == 8) { /*Read driver version */ - /* memcpy(page, GTP_DRIVER_VERSION, - * strlen(GTP_DRIVER_VERSION)); - */ - s32 tmp_len; - - tmp_len = strlen(GTP_DRIVER_VERSION); - memcpy(page, GTP_DRIVER_VERSION, tmp_len); - page[tmp_len] = 0; + if (tool_i2c_read(cmd_head.data, data_len) <= 0) { + dev_err(>_client->dev, "Read data failed\n"); + ret = -EIO; + goto exit; + } + ret = simple_read_from_buffer(user_buf, count, ppos, + &cmd_head.data[GTP_ADDR_LENGTH], data_len); + break; + case GTP_RW_FILL_INFO: + ret = fill_update_info(user_buf, count, ppos); + break; + case GTP_RW_READ_VERSION: + /* Read driver version */ + data_len = scnprintf(buf, sizeof(buf), "%s\n", + GTP_DRIVER_VERSION); + ret = simple_read_from_buffer(user_buf, count, ppos, + buf, data_len); + break; + default: + ret = -EINVAL; + break; } - ret = cmd_head.data_len; exit: mutex_unlock(&lock); return ret; } + +static const struct file_operations goodix_proc_fops = { + .write = goodix_tool_write, + .read = goodix_tool_read, + .open = simple_open, + .owner = THIS_MODULE, +}; + +s32 init_wr_node(struct i2c_client *client) +{ + u8 i; + + gt_client = client; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.data = NULL; + + i = GTP_I2C_RETRY_5; + while ((!cmd_head.data) && i) { + cmd_head.data = devm_kzalloc(&client->dev, + i * DATA_LENGTH_UINT, GFP_KERNEL); + if (cmd_head.data) + break; + i--; + } + if (i) { + data_length = i * DATA_LENGTH_UINT; + dev_dbg(&client->dev, "Applied memory size:%d", data_length); + } + + cmd_head.addr_len = 2; + cmd_head.retry = GTP_I2C_RETRY_5; + + register_i2c_func(); + + mutex_init(&lock); + tool_set_proc_name(procname); + goodix_proc_entry = proc_create(procname, + S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, + goodix_proc_entry, + &goodix_proc_fops); + if (goodix_proc_entry == NULL) { + dev_err(&client->dev, "Couldn't create proc entry"); + return FAIL; + } + + return SUCCESS; +} diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index bc0ff0e4e7ac..2c7c338e566f 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -44,7 +44,8 @@ #include "gt9xx.h" #include - +#include +#include #include #define GOODIX_DEV_NAME "Goodix-CTP" @@ -52,10 +53,6 @@ #define GOODIX_COORDS_ARR_SIZE 4 #define MAX_BUTTONS 4 -/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ -#define GTP_I2C_ADDRESS_HIGH 0x14 -#define GTP_I2C_ADDRESS_LOW 0x5D - #define GOODIX_VTG_MIN_UV 2600000 #define GOODIX_VTG_MAX_UV 3300000 #define GOODIX_I2C_VTG_MIN_UV 1800000 @@ -79,7 +76,6 @@ static const u16 touch_key_array[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK}; #endif -static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); static void gtp_int_sync(struct goodix_ts_data *ts, int ms); static int gtp_i2c_test(struct i2c_client *client); static int goodix_power_off(struct goodix_ts_data *ts); @@ -98,7 +94,6 @@ static struct delayed_work gtp_esd_check_work; static struct workqueue_struct *gtp_esd_check_workqueue; static void gtp_esd_check_func(struct work_struct *work); static int gtp_init_ext_watchdog(struct i2c_client *client); -struct i2c_client *i2c_connect_client; #endif #if GTP_SLIDE_WAKEUP @@ -113,6 +108,7 @@ static s8 gtp_enter_doze(struct goodix_ts_data *ts); bool init_done; static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */ u8 grp_cfg_version; +struct i2c_client *i2c_connect_client; /******************************************************* Function: @@ -264,7 +260,7 @@ Output: result of i2c write operation. > 0: succeed, otherwise: failed *********************************************************/ -static int gtp_send_cfg(struct goodix_ts_data *ts) +int gtp_send_cfg(struct goodix_ts_data *ts) { int ret; #if GTP_DRIVER_SEND_CFG @@ -656,7 +652,7 @@ Input: Output: None. *******************************************************/ -static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) +void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) { /* This reset sequence will selcet I2C slave address */ gpio_direction_output(ts->pdata->reset_gpio, 0); @@ -1791,7 +1787,7 @@ static int goodix_ts_probe(struct i2c_client *client, strlcpy(ts->fw_name, pdata->fw_name, strlen(pdata->fw_name) + 1); -#if GTP_AUTO_UPDATE +#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE ret = gup_init_update_proc(ts); if (ret < 0) { dev_err(&client->dev, @@ -1851,7 +1847,7 @@ static int goodix_ts_probe(struct i2c_client *client, if (ts->use_irq) gtp_irq_enable(ts); -#if GTP_CREATE_WR_NODE +#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG init_wr_node(client); #endif @@ -1927,7 +1923,7 @@ static int goodix_ts_remove(struct i2c_client *client) #endif mutex_destroy(&ts->lock); -#if GTP_CREATE_WR_NODE +#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG uninit_wr_node(); #endif diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index 56e561ab3925..1379bd847705 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -22,18 +22,9 @@ #include #include -#include -#include -#include -#include #include -#include -#include #include -#include -#include -#include -#include +#include #if defined(CONFIG_FB) #include @@ -116,14 +107,11 @@ extern u16 total_len; #define GTP_DRIVER_SEND_CFG 1 #define GTP_HAVE_TOUCH_KEY 1 -/* auto updated by .bin file as default */ -#define GTP_AUTO_UPDATE 0 /* auto updated by head_fw_array in gt9xx_firmware.h, * function together with GTP_AUTO_UPDATE */ #define GTP_HEADER_FW_UPDATE 0 -#define GTP_CREATE_WR_NODE 0 #define GTP_ESD_PROTECT 0 #define GTP_WITH_PEN 0 @@ -132,26 +120,14 @@ extern u16 total_len; /* double-click wakeup, function together with GTP_SLIDE_WAKEUP */ #define GTP_DBL_CLK_WAKEUP 0 -/*************************** PART2:TODO define *******************************/ -/* STEP_1(REQUIRED): Define Configuration Information Group(s) */ -/* Sensor_ID Map: */ -/* sensor_opt1 sensor_opt2 Sensor_ID - * GND GND 0 - * VDDIO GND 1 - * NC GND 2 - * GND NC/300K 3 - * VDDIO NC/300K 4 - * NC NC/300K 5 - */ - -#define GTP_IRQ_TAB {\ +#define GTP_IRQ_TAB {\ IRQ_TYPE_EDGE_RISING,\ IRQ_TYPE_EDGE_FALLING,\ IRQ_TYPE_LEVEL_LOW,\ IRQ_TYPE_LEVEL_HIGH\ } -/* STEP_3(optional): Specify your special config info if needed */ + #define GTP_IRQ_TAB_RISING 0 #define GTP_IRQ_TAB_FALLING 1 #if GTP_CUSTOM_CFG @@ -197,16 +173,52 @@ extern u16 total_len; #define RESOLUTION_LOC 3 #define TRIGGER_LOC 8 +/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ +#define GTP_I2C_ADDRESS_HIGH 0x14 +#define GTP_I2C_ADDRESS_LOW 0x5D + +/* GTP CM_HEAD RW flags */ +#define GTP_RW_READ 0 +#define GTP_RW_WRITE 1 +#define GTP_RW_READ_IC_TYPE 2 +#define GTP_RW_WRITE_IC_TYPE 3 +#define GTP_RW_FILL_INFO 4 +#define GTP_RW_NO_WRITE 5 +#define GTP_RW_READ_ERROR 6 +#define GTP_RW_DISABLE_IRQ 7 +#define GTP_RW_READ_VERSION 8 +#define GTP_RW_ENABLE_IRQ 9 +#define GTP_RW_ENTER_UPDATE_MODE 11 +#define GTP_RW_LEAVE_UPDATE_MODE 13 +#define GTP_RW_UPDATE_FW 15 +#define GTP_RW_CHECK_RAWDIFF_MODE 17 + +/* GTP need flag or interrupt */ +#define GTP_NO_NEED 0 +#define GTP_NEED_FLAG 1 +#define GTP_NEED_INTERRUPT 2 + /*****************************End of Part III********************************/ void gtp_esd_switch(struct i2c_client *client, int on); -#if GTP_CREATE_WR_NODE -extern s32 init_wr_node(struct i2c_client *client); -extern void uninit_wr_node(void); +int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, + u8 *rxbuf, int len); +int gtp_send_cfg(struct goodix_ts_data *ts); +void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); +void gtp_irq_disable(struct goodix_ts_data *ts); +void gtp_irq_enable(struct goodix_ts_data *ts); + +#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG +s32 init_wr_node(struct i2c_client *client); +void uninit_wr_node(void); #endif -#if GTP_AUTO_UPDATE +#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE extern u8 gup_init_update_proc(struct goodix_ts_data *ts); +s32 gup_enter_update_mode(struct i2c_client *client); +void gup_leave_update_mode(struct i2c_client *client); +s32 gup_update_proc(void *dir); +extern struct i2c_client *i2c_connect_client; #endif #endif /* _GOODIX_GT9XX_H_ */ diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c index c991bfd3ffdf..b04f65708d7e 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c @@ -32,6 +32,9 @@ * By Meta, 2013/03/11 */ #include "gt9xx.h" +#include +#include +#include #if GTP_HEADER_FW_UPDATE #include @@ -39,16 +42,14 @@ #include "gt9xx_firmware.h" #endif +#define FIRMWARE_NAME_LEN_MAX 256 + #define GUP_REG_HW_INFO 0x4220 #define GUP_REG_FW_MSG 0x41E4 #define GUP_REG_PID_VID 0x8140 -#define GUP_SEARCH_FILE_TIMES 50 -#define UPDATE_FILE_PATH_2 "/data/_goodix_update_.bin" -#define UPDATE_FILE_PATH_1 "/sdcard/_goodix_update_.bin" - -#define CONFIG_FILE_PATH_1 "/data/_goodix_config_.cfg" -#define CONFIG_FILE_PATH_2 "/sdcard/_goodix_config_.cfg" +#define GOODIX_FIRMWARE_FILE_NAME "_goodix_update_.bin" +#define GOODIX_CONFIG_FILE_NAME "_goodix_config_.cfg" #define FW_HEAD_LENGTH 14 #define FW_SECTION_LENGTH 0x2000 @@ -72,24 +73,22 @@ #define FAIL 0 #define SUCCESS 1 -#pragma pack(1) -struct { +struct st_fw_head { u8 hw_info[4]; /* hardware info */ u8 pid[8]; /* product id */ u16 vid; /* version id */ -} st_fw_head; -#pragma pack() +} __packed; -struct { +struct st_update_msg { u8 force_update; u8 fw_flag; - struct file *file; - struct file *cfg_file; - st_fw_head ic_fw_msg; - mm_segment_t old_fs; -} st_update_msg; + bool need_free; + u8 *fw_data; + u32 fw_len; + struct st_fw_head ic_fw_msg; +}; -st_update_msg update_msg; +static struct st_update_msg update_msg; u16 show_len; u16 total_len; u8 got_file_flag; @@ -106,7 +105,7 @@ Output: numbers of i2c_msgs to transfer: 2: succeed, otherwise: failed *********************************************************/ -s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len) +static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len) { s32 ret = -1; u8 retries = 0; @@ -171,7 +170,7 @@ s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len) } if (retries == 5) { - dev_err(&client->dev, "I2C write retry limit over.\n"); + dev_err(&client->dev, "I2C write retry limit over\n"); ret = -EIO; } @@ -180,112 +179,92 @@ s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len) static s32 gup_init_panel(struct goodix_ts_data *ts) { + struct i2c_client *client = ts->client; + u8 *config_data; s32 ret = 0; s32 i = 0; u8 check_sum = 0; u8 opr_buf[16]; u8 sensor_id = 0; - u8 cfg_info_group1[] = CTP_CFG_GROUP1; - u8 cfg_info_group2[] = CTP_CFG_GROUP2; - u8 cfg_info_group3[] = CTP_CFG_GROUP3; - u8 cfg_info_group4[] = CTP_CFG_GROUP4; - u8 cfg_info_group5[] = CTP_CFG_GROUP5; - u8 cfg_info_group6[] = CTP_CFG_GROUP6; - u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3, - cfg_info_group4, cfg_info_group5, cfg_info_group6}; - u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1), - CFG_GROUP_LEN(cfg_info_group2), - CFG_GROUP_LEN(cfg_info_group3), - CFG_GROUP_LEN(cfg_info_group4), - CFG_GROUP_LEN(cfg_info_group5), - CFG_GROUP_LEN(cfg_info_group6)}; + for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) + if (ts->pdata->config_data_len[i]) + break; - if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && - (!cfg_info_len[3]) && (!cfg_info_len[4]) && - (!cfg_info_len[5])) { + if (i == GOODIX_MAX_CFG_GROUP) { sensor_id = 0; } else { - ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, + ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, &sensor_id, 1); if (ret == SUCCESS) { - if (sensor_id >= 0x06) { - pr_err("Invalid sensor_id(0x%02X), No Config Sent!\n", + if (sensor_id >= GOODIX_MAX_CFG_GROUP) { + pr_err("Invalid sensor_id(0x%02X), No Config Sent", sensor_id); return -EINVAL; } } else { - pr_err("Failed to get sensor_id, No config sent!\n"); + pr_err("Failed to get sensor_id, No config sent\n"); return -EINVAL; } } - pr_debug("Sensor_ID: %d\n", sensor_id); + pr_debug("Sensor ID selected: %d", sensor_id); - ts->gtp_cfg_len = cfg_info_len[sensor_id]; - - if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) { - pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n", - sensor_id); + if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH || + !ts->pdata->config_data_len[sensor_id]) { + pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP", + sensor_id); return -EINVAL; } - ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, + ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1); - if (ret == SUCCESS) { - pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d\n", - sensor_id+1, send_cfg_buf[sensor_id][0], opr_buf[0]); + pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d", + sensor_id + 1, + ts->pdata->config_data[sensor_id][0], + opr_buf[0]); - send_cfg_buf[sensor_id][0] = opr_buf[0]; + ts->pdata->config_data[sensor_id][0] = opr_buf[0]; ts->fixed_cfg = 0; - /* - * if (opr_buf[0] < 90) { - * grp_cfg_version = send_cfg_buf[sensor_id][0]; - * *** backup group config version *** - * send_cfg_buf[sensor_id][0] = 0x00; - * ts->fixed_cfg = 0; - * } else { *** treated as fixed config, not send config *** - * pr_info("Ic fixed config with config version(%d)", - * opr_buf[0]); - * ts->fixed_cfg = 1; - * } - */ + } else { + pr_err("Failed to get ic config version. No config sent"); return -EINVAL; } - memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); - memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], - ts->gtp_cfg_len); + config_data = ts->pdata->config_data[sensor_id]; + ts->config_data = ts->pdata->config_data[sensor_id]; + ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id]; pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x\n", ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); - config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; - config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); - config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; - config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); + config_data[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; + config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); + config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; + config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); if (GTP_INT_TRIGGER == 0) /* RISING */ - config[TRIGGER_LOC] &= 0xfe; + config_data[TRIGGER_LOC] &= 0xfe; else if (GTP_INT_TRIGGER == 1) /* FALLING */ - config[TRIGGER_LOC] |= 0x01; + config_data[TRIGGER_LOC] |= 0x01; check_sum = 0; for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) - check_sum += config[i]; + check_sum += config_data[i]; - config[ts->gtp_cfg_len] = (~check_sum) + 1; + config_data[ts->gtp_cfg_len] = (~check_sum) + 1; - ret = gtp_send_cfg(ts->client); + ret = gtp_send_cfg(ts); if (ret < 0) - pr_err("Send config error.\n"); + pr_err("Send config error\n"); + ts->config_data = NULL; + ts->gtp_cfg_len = 0; msleep(20); return 0; } - static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) { u8 i = 0; @@ -298,7 +277,7 @@ static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) break; if (i >= 5) { - pr_err("Read data from 0x%02x%02x failed!\n", msg[0], msg[1]); + pr_err("Read data from 0x%02x%02x failed\n", msg[0], msg[1]); return FAIL; } @@ -319,7 +298,7 @@ static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val) break; if (i >= 5) { - pr_err("Set data to 0x%02x%02x failed!\n", msg[0], msg[1]); + pr_err("Set data to 0x%02x%02x failed\n", msg[0], msg[1]); return FAIL; } @@ -337,7 +316,7 @@ static u8 gup_get_ic_fw_msg(struct i2c_client *client) ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, &buf[GTP_ADDR_LENGTH], 4); if (ret == FAIL) { - pr_err("[get_ic_fw_msg]get hw_info failed,exit\n"); + pr_err("get hw_info failed,exit"); return FAIL; } @@ -356,14 +335,14 @@ static u8 gup_get_ic_fw_msg(struct i2c_client *client) for (retry = 0; retry < 2; retry++) { ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1); if (ret == FAIL) { - pr_err("Read firmware message fail.\n"); + pr_err("Read firmware message fail\n"); return ret; } update_msg.force_update = buf[GTP_ADDR_LENGTH]; if ((update_msg.force_update != 0xBE) && (!retry)) { - pr_info("The check sum in ic is error.\n"); - pr_info("The IC will be updated by force.\n"); + pr_info("The check sum in ic is error\n"); + pr_info("The IC will be updated by force\n"); continue; } break; @@ -374,7 +353,7 @@ static u8 gup_get_ic_fw_msg(struct i2c_client *client) ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, &buf[GTP_ADDR_LENGTH], 6); if (ret == FAIL) { - pr_err("[get_ic_fw_msg]get pid & vid failed,exit\n"); + pr_err("get pid & vid failed,exit"); return FAIL; } @@ -413,17 +392,19 @@ s32 gup_enter_update_mode(struct i2c_client *client) s32 ret = -1; u8 retry = 0; u8 rd_buf[3]; + struct goodix_ts_data *ts = i2c_get_clientdata(client); /* step1:RST output low last at least 2ms */ - GTP_GPIO_OUTPUT(GTP_RST_PORT, 0); - msleep(20); + gpio_direction_output(ts->pdata->reset_gpio, 0); + usleep(20000); /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */ - GTP_GPIO_OUTPUT(GTP_INT_PORT, (client->addr == 0x14)); + gpio_direction_output(ts->pdata->irq_gpio, + (client->addr == GTP_I2C_ADDRESS_HIGH)); msleep(20); /* step3:RST output high reset guitar */ - GTP_GPIO_OUTPUT(GTP_RST_PORT, 1); + gpio_direction_output(ts->pdata->reset_gpio, 1); /* 20121211 modify start */ msleep(20); @@ -449,7 +430,7 @@ s32 gup_enter_update_mode(struct i2c_client *client) rd_buf[GTP_ADDR_LENGTH]); } if (retry >= 200) { - pr_err("Enter update Hold ss51 failed.\n"); + pr_err("Enter update Hold ss51 failed\n"); return FAIL; } @@ -460,12 +441,13 @@ s32 gup_enter_update_mode(struct i2c_client *client) return ret; } -void gup_leave_update_mode(void) +void gup_leave_update_mode(struct i2c_client *client) { - GTP_GPIO_AS_INT(GTP_INT_PORT); + struct goodix_ts_data *ts = i2c_get_clientdata(client); - pr_debug("[leave_update_mode]reset chip.\n"); - gtp_reset_guitar(i2c_connect_client, 20); + gpio_direction_input(ts->pdata->irq_gpio); + pr_debug("reset chip"); + gtp_reset_guitar(ts, 20); } /* Get the correct nvram data @@ -486,7 +468,8 @@ void gup_leave_update_mode(void) * 3. IC PID == 91XX || File PID == 91XX */ -static u8 gup_enter_update_judge(st_fw_head *fw_head) +static u8 gup_enter_update_judge(struct i2c_client *client, + struct st_fw_head *fw_head) { u16 u16_tmp; s32 i = 0; @@ -510,9 +493,9 @@ static u8 gup_enter_update_judge(st_fw_head *fw_head) /* First two conditions */ if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, sizeof(update_msg.ic_fw_msg.hw_info))) { - pr_debug("Get the same hardware info.\n"); + pr_debug("Get the same hardware info\n"); if (update_msg.force_update != 0xBE) { - pr_info("FW chksum error,need enter update.\n"); + pr_info("FW chksum error,need enter update\n"); return SUCCESS; } @@ -535,67 +518,48 @@ static u8 gup_enter_update_judge(st_fw_head *fw_head) (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) || (!memcmp(fw_head->pid, "91XX", 4))) { if (!memcmp(fw_head->pid, "91XX", 4)) - pr_debug("Force none same pid update mode.\n"); + pr_debug("Force none same pid update mode\n"); else - pr_debug("Get the same pid.\n"); + pr_debug("Get the same pid\n"); /* The third condition */ if (fw_head->vid > update_msg.ic_fw_msg.vid) { - pr_info("Need enter update."); + pr_info("Need enter update"); return SUCCESS; } - pr_err("Don't meet the third condition.\n"); - pr_err("File VID <= Ic VID, update aborted!\n"); + pr_err("Don't meet the third condition\n"); + pr_err("File VID <= Ic VID, update aborted\n"); } else { - pr_err("File PID != Ic PID, update aborted!\n"); + pr_err("File PID != Ic PID, update aborted\n"); } } else { - pr_err("Different Hardware, update aborted!\n"); + pr_err("Different Hardware, update aborted\n"); } return FAIL; } -static u8 ascii2hex(u8 a) +static s8 gup_update_config(struct i2c_client *client, + const struct firmware *cfg) { - s8 value = 0; - - if (a >= '0' && a <= '9') - value = a - '0'; - else if (a >= 'A' && a <= 'F') - value = a - 'A' + 0x0A; - else if (a >= 'a' && a <= 'f') - value = a - 'a' + 0x0A; - else - value = 0xff; - - return value; -} - -static s8 gup_update_config(struct i2c_client *client) -{ - u32 file_len = 0; s32 ret = 0; s32 i = 0; s32 file_cfg_len = 0; u32 chip_cfg_len = 0; s32 count = 0; u8 *buf; - u8 *pre_buf; u8 *file_config; - /* u8 checksum = 0; */ u8 pid[8]; + u8 high, low; - if (update_msg.cfg_file == NULL) { - pr_err("[update_cfg]No need to upgrade config!\n"); + if (!cfg || !cfg->data) { + pr_err("No need to upgrade config"); return FAIL; } - file_len = update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, - 0, SEEK_END); ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6); if (ret == FAIL) { - pr_err("[update_cfg]Read product id & version id fail.\n"); + pr_err("Read product id & version id fail"); return FAIL; } pid[5] = '\0'; @@ -603,339 +567,207 @@ static s8 gup_update_config(struct i2c_client *client) chip_cfg_len = 186; if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) { + !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) || + !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) { chip_cfg_len = 228; } - pr_debug("[update_cfg]config file len:%d\n", file_len); - pr_debug("[update_cfg]need config len:%d\n", chip_cfg_len); - if ((file_len+5) < chip_cfg_len*5) { + pr_debug("config file ASCII len:%d", cfg->size); + pr_debug("need config binary len:%d", chip_cfg_len); + if ((cfg->size + 5) < chip_cfg_len * 5) { pr_err("Config length error"); return -EINVAL; } - buf = devm_kzalloc(&client->dev, file_len, GFP_KERNEL); + buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL); if (!buf) return -ENOMEM; - pre_buf = devm_kzalloc(&client->dev, file_len, GFP_KERNEL); - if (!pre_buf) - return -ENOMEM; - file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH, GFP_KERNEL); if (!file_config) return -ENOMEM; - update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_SET); - - pr_debug("[update_cfg]Read config from file.\n"); - ret = update_msg.cfg_file->f_op->read(update_msg.cfg_file, - (char *)pre_buf, file_len, &update_msg.cfg_file->f_pos); - if (ret < 0) { - pr_err("[update_cfg]Read config file failed.\n"); - return ret; - } - - pr_debug("[update_cfg]Delete illegal character.\n"); - for (i = 0, count = 0; i < file_len; i++) { - if (pre_buf[i] == ' ' || pre_buf[i] == '\r' - || pre_buf[i] == '\n') + pr_debug("Delete illegal character"); + for (i = 0, count = 0; i < cfg->size; i++) { + if (cfg->data[i] == ' ' || cfg->data[i] == '\r' + || cfg->data[i] == '\n') continue; - buf[count++] = pre_buf[i]; + buf[count++] = cfg->data[i]; } - pr_debug("[update_cfg]Ascii to hex.\n"); + pr_debug("Ascii to hex"); file_config[0] = GTP_REG_CONFIG_DATA >> 8; file_config[1] = GTP_REG_CONFIG_DATA & 0xff; - for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i + = 5) { - if ((buf[i] == '0') && ((buf[i+1] == 'x') || - (buf[i+1] == 'X'))) { - u8 high, low; - - high = ascii2hex(buf[i+2]); - low = ascii2hex(buf[i+3]); + for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) { + if ((buf[i] == '0') && ((buf[i + 1] == 'x') || + (buf[i + 1] == 'X'))) { + ret = hex2bin(&high, &buf[i + 2], 1); + if (ret) { + pr_err("Failed to convert high address from hex2bin"); + return ret; + } + ret = hex2bin(&low, &buf[i + 3], 1); + if (ret) { + pr_err("Failed to convert low address from hex2bin"); + return ret; + } if ((high == 0xFF) || (low == 0xFF)) { ret = 0; - pr_err("[update_cfg]Illegal config file.\n"); + pr_err("Illegal config file"); return ret; } file_config[file_cfg_len++] = (high<<4) + low; } else { ret = 0; - pr_err("[update_cfg]Illegal config file.\n"); + pr_err("Illegal config file"); return ret; } } - /* cal checksum */ - /* for (i=GTP_ADDR_LENGTH; i 0) { - pr_info("[update_cfg]Send config SUCCESS.\n"); + if (ret > 0) break; - } - pr_err("[update_cfg]Send config i2c error.\n"); + pr_err("Send config i2c error"); } return ret; } #if GTP_HEADER_FW_UPDATE -static u8 gup_check_fs_mounted(char *path_name) +static u32 gup_get firmware_file(struct i2c_client, + struct st_update_msg *msg, u8 *path) { - struct path root_path; - struct path path; - int err; - - err = kern_path("/", LOOKUP_FOLLOW, &root_path); - - if (err) { - pr_debug("\"/\" NOT Mounted: %d\n", err); - return FAIL; + if (sizeiof(header_fw_array) < (FW_HEAD_LENGTH + + FW_SECTION_LENGTH * 4 + + FW_DSP_ISP_LENGTH + + FW_DSP_LENGTH + + FW_BOOT_LENGTH)) { + dev_err(&client->dev, + "INVALID header_fw_array"); + return -EINVAL; } - err = kern_path(path_name, LOOKUP_FOLLOW, &path); + msg->fw_data = (u8 *)header_fw_array; + msg->fw_len = sizeof(header_fw_array); + dev_dbg(&client->dev, "Found firmware from header file, len=%d", + msg->fw_len); + return 0; +} +#else +static s32 gup_get_firmware_file(struct i2c_client *client, + struct st_update_msg *msg, u8 *path) +{ + s32 ret; + const struct firmware *fw = NULL; - if (err) { - pr_debug("/data/ NOT Mounted: %d\n", err); - return FAIL; + ret = request_firmware(&fw, path, &client->dev); + if (ret < 0) { + dev_info(&client->dev, "Cannot get firmware - %s (%d)\n", + path, ret); + return -EEXIST; } - return SUCCESS; + dev_dbg(&client->dev, "Config File: %s size=%d", path, fw->size); + msg->fw_data = + devm_kzalloc(&client->dev, fw->size, GFP_KERNEL); + if (!msg->fw_data) { + release_firmware(fw); + return -ENOMEM; + } - /* if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) - * return FAIL; - * else - * return SUCCESS; - */ + memcpy(msg->fw_data, fw->data, fw->size); + msg->fw_len = fw->size; + msg->need_free = true; + release_firmware(fw); + return 0; } #endif -static u8 gup_check_update_file(struct i2c_client *client, st_fw_head *fw_head, - u8 *path) +static u8 gup_check_firmware_name(struct i2c_client *client, + u8 **path_p) +{ + u8 len; + u8 *fname; + + if (!(*path_p)) { + *path_p = GOODIX_FIRMWARE_FILE_NAME; + return 0; + } + + len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX); + if (len >= FIRMWARE_NAME_LEN_MAX) { + dev_err(&client->dev, "firmware name too long"); + return -EINVAL; + } + + fname = strrchr(*path_p, '/'); + if (fname) { + fname = fname + 1; + *path_p = fname; + } + return 0; +} + +static u8 gup_check_update_file(struct i2c_client *client, + struct st_fw_head *fw_head, u8 *path) { s32 ret = 0; s32 i = 0; s32 fw_checksum = 0; - u8 buf[FW_HEAD_LENGTH]; + u16 temp; + const struct firmware *fw = NULL; - if (path) { - pr_debug("Update File path:%s, %d\n", path, strlen(path)); - update_msg.file = file_open(path, O_RDONLY, 0); - - if (IS_ERR(update_msg.file)) { - pr_err("Open update file(%s) error!\n", path); - return FAIL; - } - } else { -#if GTP_HEADER_FW_UPDATE - for (i = 0; i < (GUP_SEARCH_FILE_TIMES); i++) { - pr_debug("Waiting for /data mounted [%d]\n", i); - - if (gup_check_fs_mounted("/data") == SUCCESS) { - pr_debug("/data Mounted!\n"); - break; - } - msleep(3000); - } - if (i >= (GUP_SEARCH_FILE_TIMES)) { - pr_err("Wait for /data mounted timeout!\n"); - return FAIL; - } - - /* update config */ - update_msg.cfg_file = file_open(CONFIG_FILE_PATH_1, - O_RDONLY, 0); - - if (IS_ERR(update_msg.cfg_file)) { - pr_debug("%s is unavailable\n", CONFIG_FILE_PATH_1); - } else { - pr_info("Update Config File: %s\n", CONFIG_FILE_PATH_1); - ret = gup_update_config(client); - if (ret <= 0) - pr_err("Update config failed.\n"); - filp_close(update_msg.cfg_file, NULL); - } - - if (sizeof(header_fw_array) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH - *4 + FW_DSP_ISP_LENGTH+FW_DSP_LENGTH + FW_BOOT_LENGTH)) { - pr_err("INVALID header_fw_array, check your gt9xx_firmware.h file!\n"); - return FAIL; - } - update_msg.file = file_open(UPDATE_FILE_PATH_2, O_CREAT | - O_RDWR, 0666); - if ((IS_ERR(update_msg.file))) { - pr_err("Failed to Create file: %s for fw_header!\n", - UPDATE_FILE_PATH_2); - return FAIL; - } - update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); - update_msg.file->f_op->write(update_msg.file, - (char *)header_fw_array, sizeof(header_fw_array), - &update_msg.file->f_pos); - file_close(update_msg.file, NULL); - update_msg.file = file_open(UPDATE_FILE_PATH_2, O_RDONLY, 0); -#else - u8 fp_len = max(sizeof(UPDATE_FILE_PATH_1), - sizeof(UPDATE_FILE_PATH_2)); - u8 cfp_len = max(sizeof(CONFIG_FILE_PATH_1), - sizeof(CONFIG_FILE_PATH_2)); - - u8 *search_update_path = devm_kzalloc(&client->dev, fp_len, - GFP_KERNEL); - if (!search_update_path) - goto load_failed; - - u8 *search_cfg_path = devm_kzalloc(&client->dev, cfp_len, - GFP_KERNEL); - if (!search_cfg_path) - goto load_failed; - /* Begin to search update file,the config file & firmware - * file must be in the same path,single or double. - */ - searching_file = 1; - for (i = 0; i < GUP_SEARCH_FILE_TIMES; i++) { - if (searching_file == 0) { - pr_info(".bin/.cfg update file search forcely terminated!\n"); - return FAIL; - } - if (i % 2) { - memcpy(search_update_path, UPDATE_FILE_PATH_1, - sizeof(UPDATE_FILE_PATH_1)); - memcpy(search_cfg_path, CONFIG_FILE_PATH_1, - sizeof(CONFIG_FILE_PATH_1)); - } else { - memcpy(search_update_path, UPDATE_FILE_PATH_2, - sizeof(UPDATE_FILE_PATH_2)); - memcpy(search_cfg_path, CONFIG_FILE_PATH_2, - sizeof(CONFIG_FILE_PATH_2)); - } - - if (!(got_file_flag&0x0F)) { - update_msg.file = file_open(search_update_path, - O_RDONLY, 0); - if (!IS_ERR(update_msg.file)) { - pr_debug("Find the bin file\n"); - got_file_flag |= 0x0F; - } - } - if (!(got_file_flag & 0xF0)) { - update_msg.cfg_file = file_open(search_cfg_path, - O_RDONLY, 0); - if (!IS_ERR(update_msg.cfg_file)) { - pr_debug("Find the cfg file\n"); - got_file_flag |= 0xF0; - } - } - - if (got_file_flag) { - if (got_file_flag == 0xFF) - break; - i += 4; - } - pr_debug("%3d:Searching %s %s file...\n", i, - (got_file_flag & 0x0F) ? "" : "bin", - (got_file_flag & 0xF0) ? "" : "cfg"); - - msleep(3000); - } - - searching_file = 0; - - if (!got_file_flag) { - pr_err("Can't find update file.\n"); - goto load_failed; - } - - if (got_file_flag & 0xF0) { - pr_debug("Got the update config file.\n"); - ret = gup_update_config(client); - if (ret <= 0) - pr_err("Update config failed.\n"); - filp_close(update_msg.cfg_file, NULL); - msleep(500); /* waiting config to be stored in FLASH. */ - } - if (got_file_flag & 0x0F) { - pr_debug("Got the update firmware file.\n"); - } else { - pr_err("No need to upgrade firmware.\n"); - goto load_failed; - } -#endif - } - - update_msg.old_fs = get_fs(); - set_fs(KERNEL_DS); - - update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); - /* update_msg.file->f_pos = 0; */ - - ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, - FW_HEAD_LENGTH, &update_msg.file->f_pos); + ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev); if (ret < 0) { - pr_err("Read firmware head in update file error.\n"); - goto load_failed; + dev_info(&client->dev, "Cannot get config file - %s (%d)\n", + GOODIX_CONFIG_FILE_NAME, ret); + } else { + dev_dbg(&client->dev, + "Update config File: %s", GOODIX_CONFIG_FILE_NAME); + ret = gup_update_config(client, fw); + if (ret <= 0) + dev_err(&client->dev, "Update config failed"); + release_firmware(fw); } - memcpy(fw_head, buf, FW_HEAD_LENGTH); + + update_msg.need_free = false; + update_msg.fw_len = 0; + + if (gup_check_firmware_name(client, &path)) + goto load_failed; + + if (gup_get_firmware_file(client, &update_msg, path)) + goto load_failed; + + memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH); /* check firmware legality */ fw_checksum = 0; for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH + - FW_DSP_LENGTH + FW_BOOT_LENGTH; i + = 2) { - u16 temp; - - ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, - 2, &update_msg.file->f_pos); - if (ret < 0) { - pr_err("Read firmware file error.\n"); - goto load_failed; - } - temp = (buf[0]<<8) + buf[1]; + FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) { + temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) + + update_msg.fw_data[FW_HEAD_LENGTH + i + 1]; fw_checksum += temp; } - pr_debug("firmware checksum:%x\n", fw_checksum&0xFFFF); + pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF); if (fw_checksum & 0xFFFF) { - pr_err("Illegal firmware file.\n"); + dev_err(&client->dev, "Illegal firmware file"); goto load_failed; } return SUCCESS; load_failed: - set_fs(update_msg.old_fs); + if (update_msg.need_free) { + devm_kfree(&client->dev, update_msg.fw_data); + update_msg.need_free = false; + } return FAIL; } -#if 0 -static u8 gup_check_update_header(struct i2c_client *client, - st_fw_head *fw_head) -{ - const u8 *pos; - int i = 0; - u8 mask_num = 0; - s32 ret = 0; - - pos = HEADER_UPDATE_DATA; - - memcpy(fw_head, pos, FW_HEAD_LENGTH); - pos += FW_HEAD_LENGTH; - - ret = gup_enter_update_judge(fw_head); - if (ret == SUCCESS) - return SUCCESS; - return FAIL; -} -#endif - static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, u16 total_length) { @@ -947,7 +779,7 @@ static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; u8 retry = 0; - pr_debug("Begin burn %dk data to addr 0x%x\n", (total_length/1024), + pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024), start_addr); while (burn_length < total_length) { pr_debug("B/T:%04d/%04d", burn_length, total_length); @@ -964,26 +796,26 @@ static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, ret = gup_i2c_write(client, wr_buf, GTP_ADDR_LENGTH + frame_length); if (ret <= 0) { - pr_err("Write frame data i2c error.\n"); + pr_err("Write frame data i2c error\n"); continue; } ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH + frame_length); if (ret <= 0) { - pr_err("Read back frame data i2c error.\n"); + pr_err("Read back frame data i2c error\n"); continue; } if (memcmp(&wr_buf[GTP_ADDR_LENGTH], &rd_buf[GTP_ADDR_LENGTH], frame_length)) { - pr_err("Check frame data fail,not equal.\n"); + pr_err("Check frame data fail,not equal\n"); continue; } else { break; } } if (retry >= MAX_FRAME_CHECK_TIME) { - pr_err("Burn frame data time out,exit.\n"); + pr_err("Burn frame data time out,exit\n"); return FAIL; } burn_length += frame_length; @@ -994,20 +826,15 @@ static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length) { - s32 ret = 0; - - if (update_msg.file == NULL) { - pr_err("cannot find update file,load section file fail.\n"); - return FAIL; - } - update_msg.file->f_pos = FW_HEAD_LENGTH + offset; - - ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, length, - &update_msg.file->f_pos); - if (ret < 0) { - pr_err("Read update file fail.\n"); + if (!update_msg.fw_data || + update_msg.fw_len < FW_HEAD_LENGTH + offset + length) { + pr_err( + "<<-GTP->> cannot load section data. fw_len=%d read end=%d\n", + update_msg.fw_len, + FW_HEAD_LENGTH + offset + length); return FAIL; } + memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length); return SUCCESS; } @@ -1032,20 +859,20 @@ static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src, if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length], frame_length)) { - pr_err("Recall frame data fail,not equal.\n"); + pr_err("Recall frame data fail,not equal\n"); return FAIL; } recall_length += frame_length; recall_addr += frame_length; } - pr_debug("Recall check %dk firmware success.\n", (chk_length/1024)); + pr_debug("Recall check %dk firmware success\n", (chk_length/1024)); return SUCCESS; } static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, - u16 start_addr, u8 bank_cmdi) + u16 start_addr, u8 bank_cmd) { s32 ret = 0; u8 rd_buf[5]; @@ -1053,14 +880,14 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, /* step1:hold ss51 & dsp */ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); if (ret <= 0) { - pr_err("[burn_fw_section]hold ss51 & dsp fail.\n"); + pr_err("hold ss51 & dsp fail"); return FAIL; } /* step2:set scramble */ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); if (ret <= 0) { - pr_err("[burn_fw_section]set scramble fail.\n"); + pr_err("set scramble fail"); return FAIL; } @@ -1068,7 +895,7 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); if (ret <= 0) { - pr_err("[burn_fw_section]select bank %d fail.\n", + pr_err("select bank %d fail", (bank_cmd >> 4)&0x0F); return FAIL; } @@ -1076,21 +903,21 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, /* step4:enable accessing code */ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); if (ret <= 0) { - pr_err("[burn_fw_section]enable accessing code fail.\n"); + pr_err("enable accessing code fail"); return FAIL; } /* step5:burn 8k fw section */ ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_section]burn fw_section fail.\n"); + pr_err("burn fw_section fail"); return FAIL; } /* step6:hold ss51 & release dsp */ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); if (ret <= 0) { - pr_err("[burn_fw_section]hold ss51 & release dsp fail.\n"); + pr_err("hold ss51 & release dsp fail"); return FAIL; } /* must delay */ @@ -1099,14 +926,14 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, /* step7:send burn cmd to move data to flash from sram */ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f); if (ret <= 0) { - pr_err("[burn_fw_section]send burn cmd fail.\n"); + pr_err("send burn cmd fail"); return FAIL; } - pr_debug("[burn_fw_section]Wait for the burn is complete......\n"); + pr_debug("Wait for the burn is complete"); do { ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); if (ret <= 0) { - pr_err("[burn_fw_section]Get burn state fail\n"); + pr_err("Get burn state fail"); return FAIL; } msleep(20); @@ -1116,7 +943,7 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); if (ret <= 0) { - pr_err("[burn_fw_section]select bank %d fail.\n", + pr_err("select bank %d fail", (bank_cmd >> 4)&0x0F); return FAIL; } @@ -1124,7 +951,7 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, /* step9:enable accessing code */ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); if (ret <= 0) { - pr_err("[burn_fw_section]enable accessing code fail.\n"); + pr_err("enable accessing code fail"); return FAIL; } @@ -1132,14 +959,14 @@ static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, ret = gup_recall_check(client, fw_section, start_addr, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_section]recall check 8k firmware fail.\n"); + pr_err("recall check 8k firmware fail"); return FAIL; } /* step11:disable accessing code */ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00); if (ret <= 0) { - pr_err("[burn_fw_section]disable accessing code fail.\n"); + pr_err("disable accessing code fail"); return FAIL; } @@ -1152,101 +979,97 @@ static u8 gup_burn_dsp_isp(struct i2c_client *client) u8 *fw_dsp_isp = NULL; u8 retry = 0; - pr_debug("[burn_dsp_isp]Begin burn dsp isp---->>\n"); + pr_debug("Begin burn dsp isp"); /* step1:alloc memory */ - pr_debug("[burn_dsp_isp]step1:alloc memory\n"); + pr_debug("step1:alloc memory"); while (retry++ < 5) { fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH, GFP_KERNEL); if (fw_dsp_isp == NULL) { continue; } else { - pr_info("[burn_dsp_isp]Alloc %dk byte memory success.\n", - (FW_DSP_ISP_LENGTH/1024)); break; } } - if (retry == 5) { - pr_err("[burn_dsp_isp]Alloc memory fail,exit.\n"); + if (retry == 5) return FAIL; - } /* step2:load dsp isp file data */ - pr_debug("[burn_dsp_isp]step2:load dsp isp file data\n"); + pr_debug("step2:load dsp isp file data"); ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH + FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH); if (ret == FAIL) { - pr_err("[burn_dsp_isp]load firmware dsp_isp fail.\n"); + pr_err("load firmware dsp_isp fail"); return FAIL; } /* step3:disable wdt,clear cache enable */ - pr_debug("[burn_dsp_isp]step3:disable wdt,clear cache enable\n"); + pr_debug("step3:disable wdt,clear cache enable"); ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); if (ret <= 0) { - pr_err("[burn_dsp_isp]disable wdt fail.\n"); + pr_err("disable wdt fail"); return FAIL; } ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); if (ret <= 0) { - pr_err("[burn_dsp_isp]clear cache enable fail.\n"); + pr_err("clear cache enable fail"); return FAIL; } /* step4:hold ss51 & dsp */ - pr_debug("[burn_dsp_isp]step4:hold ss51 & dsp\n"); + pr_debug("step4:hold ss51 & dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); if (ret <= 0) { - pr_err("[burn_dsp_isp]hold ss51 & dsp fail.\n"); + pr_err("hold ss51 & dsp fail"); return FAIL; } /* step5:set boot from sram */ - pr_debug("[burn_dsp_isp]step5:set boot from sram\n"); + pr_debug("step5:set boot from sram"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); if (ret <= 0) { - pr_err("[burn_dsp_isp]set boot from sram fail.\n"); + pr_err("set boot from sram fail"); return FAIL; } /* step6:software reboot */ - pr_debug("[burn_dsp_isp]step6:software reboot\n"); + pr_debug("step6:software reboot"); ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); if (ret <= 0) { - pr_err("[burn_dsp_isp]software reboot fail.\n"); + pr_err("software reboot fail"); return FAIL; } /* step7:select bank2 */ - pr_debug("[burn_dsp_isp]step7:select bank2\n"); + pr_debug("step7:select bank2"); ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); if (ret <= 0) { - pr_err("[burn_dsp_isp]select bank2 fail.\n"); + pr_err("select bank2 fail"); return FAIL; } /* step8:enable accessing code */ - pr_debug("[burn_dsp_isp]step8:enable accessing code\n"); + pr_debug("step8:enable accessing code"); ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); if (ret <= 0) { - pr_err("[burn_dsp_isp]enable accessing code fail.\n"); + pr_err("enable accessing code fail"); return FAIL; } /* step9:burn 4k dsp_isp */ - pr_debug("[burn_dsp_isp]step9:burn 4k dsp_isp\n"); + pr_debug("step9:burn 4k dsp_isp"); ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH); if (ret == FAIL) { - pr_err("[burn_dsp_isp]burn dsp_isp fail.\n"); + pr_err("burn dsp_isp fail"); return FAIL; } /* step10:set scramble */ - pr_debug("[burn_dsp_isp]step10:set scramble\n"); + pr_debug("step10:set scramble"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); if (ret <= 0) { - pr_err("[burn_dsp_isp]set scramble fail.\n"); + pr_err("set scramble fail"); return FAIL; } @@ -1259,98 +1082,94 @@ static u8 gup_burn_fw_ss51(struct i2c_client *client) u8 retry = 0; s32 ret = 0; - pr_debug("[burn_fw_ss51]Begin burn ss51 firmware---->>\n"); + pr_debug("Begin burn ss51 firmware"); /* step1:alloc memory */ - pr_debug("[burn_fw_ss51]step1:alloc memory\n"); + pr_debug("step1:alloc memory"); while (retry++ < 5) { fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH, GFP_KERNEL); if (fw_ss51 == NULL) { continue; } else { - pr_info("[burn_fw_ss51]Alloc %dk byte memory success.\n", - (FW_SECTION_LENGTH/1024)); break; } } - if (retry == 5) { - pr_err("[burn_fw_ss51]Alloc memory fail,exit.\n"); + if (retry == 5) return FAIL; - } /* step2:load ss51 firmware section 1 file data */ - pr_debug("[burn_fw_ss51]step2:load ss51 firmware section 1 file data\n"); + pr_debug("step2:load ss51 firmware section 1 file data"); ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 1 fail.\n"); + pr_err("load ss51 firmware section 1 fail"); return FAIL; } /* step3:clear control flag */ - pr_debug("[burn_fw_ss51]step3:clear control flag\n"); + pr_debug("step3:clear control flag"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); if (ret <= 0) { - pr_err("[burn_fw_ss51]clear control flag fail.\n"); + pr_err("clear control flag fail"); return FAIL; } /* step4:burn ss51 firmware section 1 */ - pr_debug("[burn_fw_ss51]step4:burn ss51 firmware section 1\n"); + pr_debug("step4:burn ss51 firmware section 1"); ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); if (ret == FAIL) { - pr_err("[burn_fw_ss51]burn ss51 firmware section 1 fail.\n"); + pr_err("burn ss51 firmware section 1 fail"); return FAIL; } /* step5:load ss51 firmware section 2 file data */ - pr_debug("[burn_fw_ss51]step5:load ss51 firmware section 2 file data\n"); + pr_debug("step5:load ss51 firmware section 2 file data"); ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail.\n"); + pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail\n"); return FAIL; } /* step6:burn ss51 firmware section 2 */ - pr_debug("[burn_fw_ss51]step6:burn ss51 firmware section 2\n"); + pr_debug("step6:burn ss51 firmware section 2"); ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02); if (ret == FAIL) { - pr_err("[burn_fw_ss51]burn ss51 firmware section 2 fail.\n"); + pr_err("burn ss51 firmware section 2 fail"); return FAIL; } /* step7:load ss51 firmware section 3 file data */ - pr_debug("[burn_fw_ss51]step7:load ss51 firmware section 3 file data\n"); + pr_debug("step7:load ss51 firmware section 3 file data"); ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 3 fail.\n"); + pr_err("load ss51 firmware section 3 fail"); return FAIL; } /* step8:burn ss51 firmware section 3 */ - pr_debug("[burn_fw_ss51]step8:burn ss51 firmware section 3\n"); + pr_debug("step8:burn ss51 firmware section 3"); ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13); if (ret == FAIL) { - pr_err("[burn_fw_ss51]burn ss51 firmware section 3 fail.\n"); + pr_err("burn ss51 firmware section 3 fail"); return FAIL; } /* step9:load ss51 firmware section 4 file data */ - pr_debug("[burn_fw_ss51]step9:load ss51 firmware section 4 file data\n"); + pr_debug("step9:load ss51 firmware section 4 file data"); ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 4 fail.\n"); + pr_err("load ss51 firmware section 4 fail"); return FAIL; } /* step10:burn ss51 firmware section 4 */ - pr_debug("[burn_fw_ss51]step10:burn ss51 firmware section 4\n"); + pr_debug("step10:burn ss51 firmware section 4"); ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14); if (ret == FAIL) { - pr_err("[burn_fw_ss51]burn ss51 firmware section 4 fail.\n"); + pr_err("burn ss51 firmware section 4 fail"); return FAIL; } @@ -1364,101 +1183,97 @@ static u8 gup_burn_fw_dsp(struct i2c_client *client) u8 retry = 0; u8 rd_buf[5]; - pr_debug("[burn_fw_dsp]Begin burn dsp firmware---->>\n"); + pr_debug("Begin burn dsp firmware"); /* step1:alloc memory */ - pr_debug("[burn_fw_dsp]step1:alloc memory\n"); + pr_debug("step1:alloc memory"); while (retry++ < 5) { fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH, GFP_KERNEL); if (fw_dsp == NULL) { continue; } else { - pr_info("[burn_fw_dsp]Alloc %dk byte memory success.\n", - (FW_SECTION_LENGTH/1024)); break; } } - if (retry == 5) { - pr_err("[burn_fw_dsp]Alloc memory fail,exit.\n"); + if (retry == 5) return FAIL; - } /* step2:load firmware dsp */ - pr_debug("[burn_fw_dsp]step2:load firmware dsp\n"); + pr_debug("step2:load firmware dsp"); ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_dsp]load firmware dsp fail.\n"); + pr_err("load firmware dsp fail"); return ret; } /* step3:select bank3 */ - pr_debug("[burn_fw_dsp]step3:select bank3\n"); + pr_debug("step3:select bank3"); ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); if (ret <= 0) { - pr_err("[burn_fw_dsp]select bank3 fail.\n"); + pr_err("select bank3 fail"); return FAIL; } /* Step4:hold ss51 & dsp */ - pr_debug("[burn_fw_dsp]step4:hold ss51 & dsp\n"); + pr_debug("step4:hold ss51 & dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); if (ret <= 0) { - pr_err("[burn_fw_dsp]hold ss51 & dsp fail.\n"); + pr_err("hold ss51 & dsp fail"); return FAIL; } /* step5:set scramble */ - pr_debug("[burn_fw_dsp]step5:set scramble\n"); + pr_debug("step5:set scramble"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); if (ret <= 0) { - pr_err("[burn_fw_dsp]set scramble fail.\n"); + pr_err("set scramble fail"); return FAIL; } /* step6:release ss51 & dsp */ - pr_debug("[burn_fw_dsp]step6:release ss51 & dsp\n"); + pr_debug("step6:release ss51 & dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); if (ret <= 0) { - pr_err("[burn_fw_dsp]release ss51 & dsp fail.\n"); + pr_err("release ss51 & dsp fail"); return FAIL; } /* must delay */ msleep(20); /* step7:burn 4k dsp firmware */ - pr_debug("[burn_fw_dsp]step7:burn 4k dsp firmware\n"); + pr_debug("step7:burn 4k dsp firmware"); ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_dsp]burn fw_section fail.\n"); + pr_err("[burn_fw_dsp]burn fw_section fail\n"); return ret; } /* step8:send burn cmd to move data to flash from sram */ - pr_debug("[burn_fw_dsp]step8:send burn cmd to move data to flash from sram\n"); + pr_debug("step8:send burn cmd to move data to flash from sram"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05); if (ret <= 0) { - pr_err("[burn_fw_dsp]send burn cmd fail.\n"); + pr_err("send burn cmd fail"); return ret; } - pr_debug("[burn_fw_dsp]Wait for the burn is complete......\n"); + pr_debug("Wait for the burn is complete"); do { ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); if (ret <= 0) { - pr_err("[burn_fw_dsp]Get burn state fail\n"); + pr_err("Get burn state fail"); return ret; } msleep(20); } while (rd_buf[GTP_ADDR_LENGTH]); /* step9:recall check 4k dsp firmware */ - pr_debug("[burn_fw_dsp]step9:recall check 4k dsp firmware\n"); + pr_debug("step9:recall check 4k dsp firmware"); ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_dsp]recall check 4k dsp firmware fail.\n"); + pr_err("recall check 4k dsp firmware fail"); return ret; } - ret = SUCCESS; + return SUCCESS; } static u8 gup_burn_fw_boot(struct i2c_client *client) @@ -1468,115 +1283,111 @@ static u8 gup_burn_fw_boot(struct i2c_client *client) u8 retry = 0; u8 rd_buf[5]; - pr_debug("[burn_fw_boot]Begin burn bootloader firmware---->>\n"); + pr_debug("Begin burn bootloader firmware"); /* step1:Alloc memory */ - pr_debug("[burn_fw_boot]step1:Alloc memory\n"); + pr_debug("step1:Alloc memory"); while (retry++ < 5) { fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH, GFP_KERNEL); if (fw_boot == NULL) { continue; } else { - pr_info("[burn_fw_boot]Alloc %dk byte memory success.\n", - (FW_BOOT_LENGTH/1024)); break; } } - if (retry == 5) { - pr_err("[burn_fw_boot]Alloc memory fail,exit.\n"); + if (retry == 5) return FAIL; - } /* step2:load firmware bootloader */ - pr_debug("[burn_fw_boot]step2:load firmware bootloader\n"); + pr_debug("step2:load firmware bootloader"); ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH + FW_DSP_LENGTH), FW_BOOT_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_boot]load firmware dsp fail.\n"); + pr_err("load firmware dsp fail"); return ret; } /* step3:hold ss51 & dsp */ - pr_debug("[burn_fw_boot]step3:hold ss51 & dsp\n"); + pr_debug("step3:hold ss51 & dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); if (ret <= 0) { - pr_err("[burn_fw_boot]hold ss51 & dsp fail.\n"); + pr_err("hold ss51 & dsp fail"); return FAIL; } /* step4:set scramble */ - pr_debug("[burn_fw_boot]step4:set scramble\n"); + pr_debug("step4:set scramble"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); if (ret <= 0) { - pr_err("[burn_fw_boot]set scramble fail.\n"); + pr_err("set scramble fail"); return FAIL; } /* step5:release ss51 & dsp */ - pr_debug("[burn_fw_boot]step5:release ss51 & dsp\n"); + pr_debug("step5:release ss51 & dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); if (ret <= 0) { - pr_err("[burn_fw_boot]release ss51 & dsp fail.\n"); + pr_err("release ss51 & dsp fail"); return FAIL; } /* must delay */ msleep(20); /* step6:select bank3 */ - pr_debug("[burn_fw_boot]step6:select bank3\n"); + pr_debug("step6:select bank3"); ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); if (ret <= 0) { - pr_err("[burn_fw_boot]select bank3 fail.\n"); + pr_err("select bank3 fail"); return FAIL; } /* step7:burn 2k bootloader firmware */ - pr_debug("[burn_fw_boot]step7:burn 2k bootloader firmware\n"); + pr_debug("step7:burn 2k bootloader firmware"); ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_boot]burn fw_section fail.\n"); + pr_err("burn fw_section fail"); return ret; } /* step7:send burn cmd to move data to flash from sram */ - pr_debug("[burn_fw_boot]step7:send burn cmd to move data to flash from sram\n"); + pr_debug("step7:send burn cmd to flash data from sram"); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06); if (ret <= 0) { - pr_err("[burn_fw_boot]send burn cmd fail.\n"); + pr_err("send burn cmd fail"); return ret; } - pr_debug("[burn_fw_boot]Wait for the burn is complete......\n"); + pr_debug("Wait for the burn is complete"); do { ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); if (ret <= 0) { - pr_err("[burn_fw_boot]Get burn state fail\n"); + pr_err("Get burn state fail"); return ret; } msleep(20); } while (rd_buf[GTP_ADDR_LENGTH]); /* step8:recall check 2k bootloader firmware */ - pr_debug("[burn_fw_boot]step8:recall check 2k bootloader firmware\n"); + pr_debug("step8:recall check 2k bootloader firmware"); ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH); if (ret == FAIL) { - pr_err("[burn_fw_boot]recall check 4k dsp firmware fail.\n"); + pr_err("recall check 4k dsp firmware fail"); return ret; } /* step9:enable download DSP code */ - pr_debug("[burn_fw_boot]step9:enable download DSP code\n"); + pr_debug("step9:enable download DSP code "); ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99); if (ret <= 0) { - pr_err("[burn_fw_boot]enable download DSP code fail.\n"); + pr_err("enable download DSP code fail"); return FAIL; } /* step10:release ss51 & hold dsp */ - pr_debug("[burn_fw_boot]step10:release ss51 & hold dsp\n"); + pr_debug("step10:release ss51 & hold dsp"); ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08); if (ret <= 0) { - pr_err("[burn_fw_boot]release ss51 & hold dsp fail.\n"); + pr_err("release ss51 & hold dsp fail"); return FAIL; } @@ -1586,46 +1397,47 @@ static u8 gup_burn_fw_boot(struct i2c_client *client) s32 gup_update_proc(void *dir) { s32 ret = 0; - u8 retry = 0; - st_fw_head fw_head; + u8 retry = 0; + struct st_fw_head fw_head; struct goodix_ts_data *ts = NULL; - pr_debug("[update_proc]Begin update ......\n"); + pr_debug("Begin update."); + + if (!i2c_connect_client) { + pr_err("No i2c connect client for %s\n", __func__); + return -EIO; + } show_len = 1; total_len = 100; - if (dir == NULL) - /* wait main thread to be completed */ - msleep(3000); ts = i2c_get_clientdata(i2c_connect_client); if (searching_file) { /* exit .bin update file searching */ searching_file = 0; - pr_info("Exiting searching .bin update file...\n"); + pr_info("Exiting searching .bin update file."); /* wait for auto update quitted completely */ while ((show_len != 200) && (show_len != 100)) msleep(100); } - update_msg.file = NULL; ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir); if (ret == FAIL) { - pr_err("[update_proc]check update file fail.\n"); + pr_err("check update file fail"); goto file_fail; } /* gtp_reset_guitar(i2c_connect_client, 20); */ ret = gup_get_ic_fw_msg(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]get ic message fail.\n"); + pr_err("get ic message fail"); goto file_fail; } - ret = gup_enter_update_judge(&fw_head); + ret = gup_enter_update_judge(ts->client, &fw_head); if (ret == FAIL) { - pr_err("[update_proc]Check *.bin file fail.\n"); + pr_err("Check *.bin file fail"); goto file_fail; } @@ -1636,7 +1448,7 @@ s32 gup_update_proc(void *dir) #endif ret = gup_enter_update_mode(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]enter update mode fail.\n"); + pr_err("enter update mode fail"); goto update_fail; } @@ -1645,53 +1457,46 @@ s32 gup_update_proc(void *dir) total_len = 100; ret = gup_burn_dsp_isp(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]burn dsp isp fail.\n"); + pr_err("burn dsp isp fail"); continue; } show_len += 10; ret = gup_burn_fw_ss51(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]burn ss51 firmware fail.\n"); + pr_err("burn ss51 firmware fail"); continue; } show_len += 40; ret = gup_burn_fw_dsp(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]burn dsp firmware fail.\n"); + pr_err("burn dsp firmware fail"); continue; } show_len += 20; ret = gup_burn_fw_boot(i2c_connect_client); if (ret == FAIL) { - pr_err("[update_proc]burn bootloader fw fail.\n"); + pr_err("burn bootloader fw fail"); continue; } show_len += 10; - pr_info("[update_proc]UPDATE SUCCESS.\n"); + pr_info("UPDATE SUCCESS"); break; } if (retry >= 5) { - pr_err("[update_proc]retry timeout,UPDATE FAIL.\n"); + pr_err("retry timeout,UPDATE FAIL"); goto update_fail; } - pr_debug("[update_proc]leave update mode.\n"); - gup_leave_update_mode(); + pr_debug("leave update mode"); + gup_leave_update_mode(i2c_connect_client); msleep(100); - /* - * ret = gtp_send_cfg(i2c_connect_client); - * if(ret < 0) { - * pr_err("[update_proc]send config fail."); - * } - */ - if (ts->fw_error) { - pr_info("firmware error auto update, resent config!\n"); + pr_info("firmware error auto update, resent config\n"); gup_init_panel(ts); } show_len = 100; @@ -1702,7 +1507,11 @@ s32 gup_update_proc(void *dir) #if GTP_ESD_PROTECT gtp_esd_switch(ts->client, SWITCH_ON); #endif - filp_close(update_msg.file, NULL); + if (update_msg.need_free) { + devm_kfree(&ts->client->dev, update_msg.fw_data); + update_msg.need_free = false; + } + return SUCCESS; update_fail: @@ -1714,11 +1523,12 @@ update_fail: #endif file_fail: - if (update_msg.file && !IS_ERR(update_msg.file)) - filp_close(update_msg.file, NULL); - show_len = 200; total_len = 100; + if (update_msg.need_free) { + devm_kfree(&ts->client->dev, update_msg.fw_data); + update_msg.need_free = false; + } return FAIL; } @@ -1728,7 +1538,6 @@ static void gup_update_work(struct work_struct *work) pr_err("Goodix update work fail\n"); } -#if GTP_AUTO_UPDATE u8 gup_init_update_proc(struct goodix_ts_data *ts) { dev_dbg(&ts->client->dev, "Ready to run update work\n"); @@ -1739,4 +1548,3 @@ u8 gup_init_update_proc(struct goodix_ts_data *ts) return 0; } -#endif From 740bb381f6998d34eac9547b26c3ab17a72a9821 Mon Sep 17 00:00:00 2001 From: Sudhakar Manapati Date: Tue, 18 Aug 2015 19:00:11 +0530 Subject: [PATCH 2/8] msm: reap unused kernel files This change removes source files from the kernel tree that were not being used during make. Change-Id: I5132854367330a9b47f678409cbe6a45f2b5abb3 Signed-off-by: Sudhakar Manapati --- drivers/input/touchscreen/gt9xx/gt9xx_firmware.h | 6 ------ drivers/input/touchscreen/gt9xx/gt9xx_update.c | 1 - 2 files changed, 7 deletions(-) delete mode 100644 drivers/input/touchscreen/gt9xx/gt9xx_firmware.h diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_firmware.h b/drivers/input/touchscreen/gt9xx/gt9xx_firmware.h deleted file mode 100644 index 81e3affe62e9..000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx_firmware.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * make sense only when GTP_HEADER_FW_UPDATE & GTP_AUTO_UPDATE are enabled - * define your own firmware array here -*/ -const unsigned char header_fw_array[] = { -}; diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c index b04f65708d7e..8f093923bacd 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c @@ -39,7 +39,6 @@ #if GTP_HEADER_FW_UPDATE #include #include -#include "gt9xx_firmware.h" #endif #define FIRMWARE_NAME_LEN_MAX 256 From cf29d5ea8207fd31e15fe1c4dad06cecde2a352e Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Wed, 13 Nov 2013 20:12:16 +0530 Subject: [PATCH 3/8] input: touchscreen: Add debugfs support for suspend/resume. Add debugfs entry for suspend/resume that allow suspending/ resuming of Goodix CTP driver from userspace. Also change the return type of goodix_ts_resume and goodix_ts_suspend functions and set the status of gtp_is_suspended in the last of above functions. Change-Id: Ic2b1b2562b63ccecdf15bdc64ad7e45996d196d3 Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/gt9xx.c | 83 +++++++++++++++++++++++-- drivers/input/touchscreen/gt9xx/gt9xx.h | 1 + 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index 2c7c338e566f..b214ca358e39 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -47,6 +47,7 @@ #include #include #include +#include #define GOODIX_DEV_NAME "Goodix-CTP" #define CFG_MAX_TOUCH_POINTS 5 @@ -83,7 +84,9 @@ static int goodix_power_on(struct goodix_ts_data *ts); #if defined(CONFIG_FB) static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); + unsigned long event, void *data); +static int goodix_ts_suspend(struct device *dev); +static int goodix_ts_resume(struct device *dev); #elif defined(CONFIG_HAS_EARLYSUSPEND) static void goodix_ts_early_suspend(struct early_suspend *h); static void goodix_ts_late_resume(struct early_suspend *h); @@ -110,6 +113,9 @@ static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */ u8 grp_cfg_version; struct i2c_client *i2c_connect_client; +#define GTP_DEBUGFS_DIR "ts_debug" +#define GTP_DEBUGFS_FILE_SUSPEND "suspend" + /******************************************************* Function: Read data from the i2c slave device. @@ -1556,6 +1562,56 @@ static const struct attribute_group gtp_attr_grp = { .attrs = gtp_attrs, }; +static int gtp_debug_suspend_set(void *_data, u64 val) +{ + struct goodix_ts_data *ts = _data; + + mutex_lock(&ts->input_dev->mutex); + if (val) + goodix_ts_suspend(&ts->client->dev); + else + goodix_ts_resume(&ts->client->dev); + mutex_unlock(&ts->input_dev->mutex); + + return 0; +} + +static int gtp_debug_suspend_get(void *_data, u64 *val) +{ + struct goodix_ts_data *ts = _data; + + mutex_lock(&ts->input_dev->mutex); + *val = ts->gtp_is_suspend; + mutex_unlock(&ts->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get, + gtp_debug_suspend_set, "%lld\n"); + +static int gtp_debugfs_init(struct goodix_ts_data *data) +{ + data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL); + + if (IS_ERR_OR_NULL(data->debug_base)) { + pr_err("Failed to create debugfs dir\n"); + return -EINVAL; + } + + if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND, + S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, + data->debug_base, + data, + &debug_suspend_fops)))) { + pr_err("Failed to create suspend file\n"); + debugfs_remove_recursive(data->debug_base); + return -EINVAL; + } + + return 0; +} + static int goodix_ts_get_dt_coords(struct device *dev, char *name, struct goodix_ts_platform_data *pdata) { @@ -1860,6 +1916,10 @@ static int goodix_ts_probe(struct i2c_client *client, goto exit_free_irq; } + ret = gtp_debugfs_init(ts); + if (ret != 0) + goto exit_remove_sysfs; + init_done = true; return 0; exit_free_irq: @@ -1884,6 +1944,8 @@ exit_free_irq: input_free_device(ts->input_dev); ts->input_dev = NULL; } +exit_remove_sysfs: + sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp); exit_free_inputdev: kfree(ts->config_data); exit_power_off: @@ -1958,6 +2020,7 @@ static int goodix_ts_remove(struct i2c_client *client) goodix_power_deinit(ts); i2c_set_clientdata(client, NULL); } + debugfs_remove_recursive(ts->debug_base); return 0; } @@ -1976,9 +2039,13 @@ static int goodix_ts_suspend(struct device *dev) struct goodix_ts_data *ts = dev_get_drvdata(dev); int ret = 0, i; + if (ts->gtp_is_suspend) { + dev_dbg(&ts->client->dev, "Already in suspend state\n"); + return 0; + } + mutex_lock(&ts->lock); #if GTP_ESD_PROTECT - ts->gtp_is_suspend = 1; gtp_esd_switch(ts->client, SWITCH_OFF); #endif @@ -1998,12 +2065,13 @@ static int goodix_ts_suspend(struct device *dev) ret = gtp_enter_sleep(ts); #endif if (ret <= 0) - dev_err(&ts->client->dev, "GTP early suspend failed.\n"); + dev_err(&ts->client->dev, "GTP early suspend failed\n"); /* to avoid waking up while not sleeping, * delay 48 + 10ms to ensure reliability */ msleep(58); mutex_unlock(&ts->lock); + ts->gtp_is_suspend = 1; return ret; } @@ -2021,6 +2089,11 @@ static int goodix_ts_resume(struct device *dev) struct goodix_ts_data *ts = dev_get_drvdata(dev); int ret = 0; + if (!ts->gtp_is_suspend) { + dev_dbg(&ts->client->dev, "Already in awake state\n"); + return 0; + } + mutex_lock(&ts->lock); ret = gtp_wakeup_sleep(ts); @@ -2029,7 +2102,7 @@ static int goodix_ts_resume(struct device *dev) #endif if (ret <= 0) - dev_err(&ts->client->dev, "GTP resume failed.\n"); + dev_err(&ts->client->dev, "GTP resume failed\n"); if (ts->use_irq) gtp_irq_enable(ts); @@ -2038,10 +2111,10 @@ static int goodix_ts_resume(struct device *dev) ktime_set(1, 0), HRTIMER_MODE_REL); #if GTP_ESD_PROTECT - ts->gtp_is_suspend = 0; gtp_esd_switch(ts->client, SWITCH_ON); #endif mutex_unlock(&ts->lock); + ts->gtp_is_suspend = 0; return ret; } diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index 1379bd847705..a61858853742 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -96,6 +96,7 @@ struct goodix_ts_data { #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif + struct dentry *debug_base; }; extern u16 show_len; From 1758da06e73793a52ebc4774d8694099432347c4 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 21 Nov 2013 20:50:46 +0530 Subject: [PATCH 4/8] input: touchscreen: Add threaded irq support to Goodix driver Add threaded irq support to Goodix touchscreen driver to reduce the time spent with interrupts diabled to a bare minimum by pushing the processing out into the kernel thread. Change-Id: I3ade13181957d327ad9d0266b1999a4b0f2d8d1a Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/gt9xx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index b214ca358e39..87f63ebe29ff 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -1198,7 +1198,11 @@ static int gtp_request_irq(struct goodix_ts_data *ts) int ret; const u8 irq_table[] = GTP_IRQ_TAB; - ret = request_irq(ts->client->irq, goodix_ts_irq_handler, + GTP_DEBUG("INT trigger type:%x, irq=%d", ts->int_trigger_type, + ts->client->irq); + + ret = request_threaded_irq(ts->client->irq, NULL, + goodix_ts_irq_handler, irq_table[ts->int_trigger_type], ts->client->name, ts); if (ret) { From e172c0da0e5495a16cfeff7c7ba6a40dabf68968 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Wed, 18 Dec 2013 19:50:28 +0530 Subject: [PATCH 5/8] input: touchscreen: Remove irq polling from Goodix driver Remove irq polling from Goodix driver. Use interrupt based mechanism to process interrupts from touch controller. Change-Id: I0a9037eac6e30a6319919043dd2ef1c226663af9 Signed-off-by: Shantanu Jain Signed-off-by: Sudhakar Manapati --- drivers/input/touchscreen/gt9xx/gt9xx.c | 49 +++++-------------------- 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index 87f63ebe29ff..0e8f3da34dee 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -595,26 +595,6 @@ exit_work_func: return; } -/******************************************************* -Function: - Timer interrupt service routine for polling mode. -Input: - timer: timer struct pointer -Output: - Timer work mode. - HRTIMER_NORESTART: no restart mode -*********************************************************/ -static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer) -{ - struct goodix_ts_data - *ts = container_of(timer, struct goodix_ts_data, timer); - - queue_work(ts->goodix_wq, &ts->work); - hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000), - HRTIMER_MODE_REL); - return HRTIMER_NORESTART; -} - /******************************************************* Function: External interrupt service routine for interrupt mode. @@ -1206,15 +1186,6 @@ static int gtp_request_irq(struct goodix_ts_data *ts) irq_table[ts->int_trigger_type], ts->client->name, ts); if (ret) { - dev_err(&ts->client->dev, "Request IRQ failed!ERRNO:%d.\n", - ret); - gpio_direction_input(ts->pdata->irq_gpio); - - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - ts->timer.function = goodix_ts_timer_handler; - hrtimer_start(&ts->timer, ktime_set(1, 0), - HRTIMER_MODE_REL); ts->use_irq = false; return ret; } @@ -1750,7 +1721,7 @@ static int goodix_parse_dt(struct device *dev, prop->value, pdata->config_data_len[i]); read_cfg_num++; } - dev_dbg(dev, "%d config data read from device tree.\n", read_cfg_num); + dev_dbg(dev, "%d config data read from device tree\n", read_cfg_num); return 0; } @@ -1839,7 +1810,7 @@ static int goodix_ts_probe(struct i2c_client *client, ret = gtp_i2c_test(client); if (ret != 2) { - dev_err(&client->dev, "I2C communication ERROR!\n"); + dev_err(&client->dev, "I2C communication ERROR\n"); goto exit_power_off; } @@ -1890,18 +1861,18 @@ static int goodix_ts_probe(struct i2c_client *client, INIT_WORK(&ts->work, goodix_ts_work_func); ret = gtp_request_irq(ts); - if (ret < 0) - dev_info(&client->dev, "GTP works in polling mode.\n"); + if (ret) + dev_info(&client->dev, "GTP request irq failed %d\n", ret); else - dev_info(&client->dev, "GTP works in interrupt mode.\n"); + dev_info(&client->dev, "GTP works in interrupt mode\n"); ret = gtp_read_fw_version(client, &version_info); if (ret != 2) - dev_err(&client->dev, "GTP firmware version read failed.\n"); + dev_err(&client->dev, "GTP firmware version read failed\n"); ret = gtp_check_product_id(client); if (ret != 0) { - dev_err(&client->dev, "GTP Product id doesn't match.\n"); + dev_err(&client->dev, "GTP Product id doesn't match\n"); goto exit_free_irq; } if (ts->use_irq) @@ -1916,7 +1887,7 @@ static int goodix_ts_probe(struct i2c_client *client, #endif ret = sysfs_create_group(&client->dev.kobj, >p_attr_grp); if (ret < 0) { - dev_err(&client->dev, "sys file creation failed.\n"); + dev_err(&client->dev, "sys file creation failed\n"); goto exit_free_irq; } @@ -1931,7 +1902,7 @@ exit_free_irq: #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, - "Error occurred while unregistering fb_notifier.\n"); + "Error occurred while unregistering fb_notifier\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif @@ -1983,7 +1954,7 @@ static int goodix_ts_remove(struct i2c_client *client) #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, - "Error occurred while unregistering fb_notifier.\n"); + "Error occurred while unregistering fb_notifier\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif From 12e637fc796d426df937bf00c187ef8ef40f47d0 Mon Sep 17 00:00:00 2001 From: Himanshu Aggarwal Date: Sun, 24 Nov 2013 19:15:01 +0530 Subject: [PATCH 6/8] input: touchscreen: Remove redundant code from Goodix driver Remove code that reads firmware from the header file, this feature is not supported. Change-Id: I6c18e153ddf18667ca83d47df20c71bce6dbfa21 Signed-off-by: Himanshu Aggarwal --- drivers/input/touchscreen/gt9xx/gt9xx.h | 5 ---- .../input/touchscreen/gt9xx/gt9xx_update.c | 26 ------------------- 2 files changed, 31 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index a61858853742..38487eea7b10 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -108,11 +108,6 @@ extern u16 total_len; #define GTP_DRIVER_SEND_CFG 1 #define GTP_HAVE_TOUCH_KEY 1 -/* auto updated by head_fw_array in gt9xx_firmware.h, - * function together with GTP_AUTO_UPDATE - */ -#define GTP_HEADER_FW_UPDATE 0 - #define GTP_ESD_PROTECT 0 #define GTP_WITH_PEN 0 diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c index 8f093923bacd..4660b27d156c 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c @@ -36,11 +36,6 @@ #include #include -#if GTP_HEADER_FW_UPDATE -#include -#include -#endif - #define FIRMWARE_NAME_LEN_MAX 256 #define GUP_REG_HW_INFO 0x4220 @@ -635,26 +630,6 @@ static s8 gup_update_config(struct i2c_client *client, return ret; } -#if GTP_HEADER_FW_UPDATE -static u32 gup_get firmware_file(struct i2c_client, - struct st_update_msg *msg, u8 *path) -{ - if (sizeiof(header_fw_array) < (FW_HEAD_LENGTH + - FW_SECTION_LENGTH * 4 + - FW_DSP_ISP_LENGTH + - FW_DSP_LENGTH + - FW_BOOT_LENGTH)) { - dev_err(&client->dev, - "INVALID header_fw_array"); - return -EINVAL; - } - msg->fw_data = (u8 *)header_fw_array; - msg->fw_len = sizeof(header_fw_array); - dev_dbg(&client->dev, "Found firmware from header file, len=%d", - msg->fw_len); - return 0; -} -#else static s32 gup_get_firmware_file(struct i2c_client *client, struct st_update_msg *msg, u8 *path) { @@ -682,7 +657,6 @@ static s32 gup_get_firmware_file(struct i2c_client *client, release_firmware(fw); return 0; } -#endif static u8 gup_check_firmware_name(struct i2c_client *client, u8 **path_p) From 80fa7e9893d4b5b04a2d2d3dcc249f8f3813f319 Mon Sep 17 00:00:00 2001 From: Himanshu Aggarwal Date: Mon, 23 Dec 2013 21:16:12 +0530 Subject: [PATCH 7/8] input: touchscreen: Fix issues in suspend path Fix issues in suspend path in Goodix driver. Change-Id: I280f2201c69838ad4da8eb94e9f10768f54ed457 Signed-off-by: Himanshu Aggarwal 4 Signed-off-by: Sudhakar Manapati --- drivers/input/touchscreen/gt9xx/gt9xx.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index 0e8f3da34dee..c3223a49b21b 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -712,16 +712,13 @@ static s8 gtp_enter_doze(struct goodix_ts_data *ts) return ret; } #else -/******************************************************* -Function: - Enter sleep mode. -Input: - ts: private data. -Output: - Executive outcomes. - >0: succeed, otherwise failed. -*******************************************************/ -static s8 gtp_enter_sleep(struct goodix_ts_data *ts) +/** + * gtp_enter_sleep - Enter sleep mode + * @ts: driver private data + * + * Returns zero on success, else an error. + */ +static u8 gtp_enter_sleep(struct goodix_ts_data *ts) { int ret = -1; s8 retry = 0; @@ -743,16 +740,16 @@ static s8 gtp_enter_sleep(struct goodix_ts_data *ts) ret = goodix_power_off(ts); if (ret) { dev_err(&ts->client->dev, "GTP power off failed.\n"); - return 0; + return ret; } - return 1; + return 0; } usleep(5000); while (retry++ < GTP_I2C_RETRY_5) { ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); if (ret == 1) { dev_dbg(&ts->client->dev, "GTP enter sleep!"); - return ret; + return 0; } msleep(20); } @@ -2039,7 +2036,7 @@ static int goodix_ts_suspend(struct device *dev) ret = gtp_enter_sleep(ts); #endif - if (ret <= 0) + if (ret < 0) dev_err(&ts->client->dev, "GTP early suspend failed\n"); /* to avoid waking up while not sleeping, * delay 48 + 10ms to ensure reliability From 4bfc4cac73016ee9e05add0acdb6726a0caefebb Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 21 Nov 2013 14:01:04 +0530 Subject: [PATCH 8/8] input: touchscreen: Change dev_pm_ops for Goodix driver Convert the driver to dev_pm_ops from SIMPLE_DEV_PM_OPS in Goodix TS driver to reduce suspend/resume latency. Change-Id: I45690b239c73f636538b864f0c4a7e539a02eedb Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/gt9xx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index c3223a49b21b..a9d7666a6d6f 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -2277,8 +2277,15 @@ static void gtp_esd_check_func(struct work_struct *work) } #endif -static SIMPLE_DEV_PM_OPS(goodix_ts_dev_pm_ops, goodix_ts_suspend, - goodix_ts_resume); +#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) +static const struct dev_pm_ops goodix_ts_dev_pm_ops = { + .suspend = goodix_ts_suspend, + .resume = goodix_ts_resume, +}; +#else +static const struct dev_pm_ops goodix_ts_dev_pm_ops = { +}; +#endif static const struct i2c_device_id goodix_ts_id[] = { { GTP_I2C_NAME, 0 },