diff options
Diffstat (limited to 'drivers/input/touchscreen/focaltech/focaltech_ex_fun.c')
| -rw-r--r-- | drivers/input/touchscreen/focaltech/focaltech_ex_fun.c | 1321 |
1 files changed, 1321 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/focaltech/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech/focaltech_ex_fun.c new file mode 100644 index 00000000..6ec67594 --- /dev/null +++ b/drivers/input/touchscreen/focaltech/focaltech_ex_fun.c @@ -0,0 +1,1321 @@ +/* + *drivers/input/touchscreen/ft5x06_ex_fun.c + * + *FocalTech IC driver expand function for debug. + * + *Copyright (c) 2010 Focal tech Ltd. + * + *This software is licensed under the terms of the GNU General Public + *License version 2, as published by the Free Software Foundation, and + *may be copied, distributed, and modified under those terms. + * + *This program is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + *GNU General Public License for more details. + * + *Note:the error code of EIO is the general error in this file. + */ + +//#include "tpd.h" +//#include "tpd_custom_fts.h" +#include <linux/netdevice.h> +#include <linux/mount.h> +//#include <linux/netdevice.h> +#include <linux/proc_fs.h> +#include <linux/i2c/focaltech.h> +#include <linux/i2c/focaltech_ex_fun.h> +#include <linux/i2c/focaltech_ctl.h> + +static struct mutex g_device_mutex; +extern void mt65xx_eint_unmask(unsigned int line); +extern void mt65xx_eint_mask(unsigned int line); + +u8 *I2CDMABuf_va = NULL; +volatile u32 I2CDMABuf_pa = NULL; + +extern struct Upgrade_Info fts_updateinfo_curr; + +int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf, + u32 dw_lenth); + +static unsigned char FT6306_FW[] = { +#include "FT6x06_4Column_Ver0x12_20150227_app.h" +}; + +static unsigned char FT5316_FW[] = { +#include "Ft5x16_720P_Ver0x23_test_app.h" +}; + +static unsigned char FT_FW_NULL[] = { +}; + +static unsigned char *CTPM_FW = FT_FW_NULL; +static u32 fw_size = 0; + +static DEFINE_MUTEX(g_device_mutex); + +/* +*fts_i2c_Read-read data and write data by i2c +*@client: handle of i2c +*@writebuf: Data that will be written to the slave +*@writelen: How many bytes to write +*@readbuf: Where to store data read from slave +*@readlen: How many bytes to read +* +*Returns negative errno, else the number of messages executed +* +* +*/ +int fts_i2c_Read(struct i2c_client *client, char *writebuf, + int writelen, char *readbuf, int readlen) +{ + int ret; + +#if 1//for normal I2c transfer + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + { + .addr = client->addr, + .flags = 1, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + dev_err(&client->dev, "f%s: i2c read error.\n", + __func__); + } else { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 1, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) + dev_err(&client->dev, "%s:i2c read error.\n", __func__); + } +#else// for DMA I2c transfer + if(writelen!=0) + { + //DMA Write + if(0)//if(writelen < 8 ) + { + + //MSE_ERR("Sensor non-dma write timing is %x!\r\n", this_client->timing); + ret= i2c_master_send(client, writebuf, writelen); + } + else + { + for(i = 0 ; i < writelen; i++) + { + I2CDMABuf_va[i] = writebuf[i]; + } + + client->addr = client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG; + + if((ret=i2c_master_send(client, (unsigned char *)I2CDMABuf_pa, writelen))!=writelen) + dev_err(&client->dev, "###%s i2c write len=%x,buffaddr=%x\n", __func__,ret,I2CDMABuf_pa); + //MSE_ERR("Sensor dma timing is %x!\r\n", this_client->timing); + //return ret; + client->addr = client->addr & I2C_MASK_FLAG &(~ I2C_DMA_FLAG); + + } + } + //DMA Read + if(readlen!=0) + { + if(0)//if (readlen <8) { + { + ret = i2c_master_recv(client, (unsigned char *)readbuf, readlen); + } + else + { + + client->addr = client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG; + ret = i2c_master_recv(client, (unsigned char *)I2CDMABuf_pa, readlen); + + for(i = 0; i < readlen; i++) + { + readbuf[i] = I2CDMABuf_va[i]; + } + client->addr = client->addr & I2C_MASK_FLAG &(~ I2C_DMA_FLAG); + + } + } + #endif + return ret; +} +/*write data by i2c*/ + +int fts_i2c_Write(struct i2c_client *client, char *writebuf, int writelen) +{ + int ret; + + //int i = 0; + + + //printk("fts_i2c_Write %d %x %x %x %x",writelen,writebuf,I2CDMABuf_va,I2CDMABuf_pa,client); + + // client->addr = client->addr & I2C_MASK_FLAG; + // client->ext_flag |= I2C_DIRECTION_FLAG; + // client->timing = 100; + #if 1 + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + }; + + ret = i2c_transfer(client->adapter, msg, 1); + if (ret < 0) + dev_err(&client->dev, "%s i2c write error.\n", __func__); + #else + + if(0)//if(writelen < 8) + { + + //MSE_ERR("Sensor non-dma write timing is %x!\r\n", this_client->timing); + ret = i2c_master_send(client, writebuf, writelen); + } + else + { + for(i = 0 ; i < writelen; i++) + { + I2CDMABuf_va[i] = writebuf[i]; + } + + client->addr = client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG; + + if((ret=i2c_master_send(client, (unsigned char *)I2CDMABuf_pa, writelen))!=writelen) + dev_err(&client->dev, "###%s i2c write len=%x,buffaddr=%x\n", __func__,ret,I2CDMABuf_pa); + //MSE_ERR("Sensor dma timing is %x!\r\n", this_client->timing); + client->addr = client->addr & I2C_MASK_FLAG &(~ I2C_DMA_FLAG); + + } + #endif + return ret; + +} + +int fts_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue) +{ + unsigned char buf[2] = {0}; + buf[0] = regaddr; + buf[1] = regvalue; + + return fts_i2c_Write(client, buf, sizeof(buf)); +} + + +int fts_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue) +{ + return fts_i2c_Read(client, ®addr, 1, regvalue, 1); +} + +int fts_ctpm_auto_clb(struct i2c_client *client) +{ + unsigned char uc_temp = 0x00; + unsigned char i = 0; + + /*start auto CLB */ + msleep(200); + + fts_write_reg(client, 0, FTS_FACTORYMODE_VALUE); + /*make sure already enter factory mode */ + msleep(100); + /*write command to start calibration */ + fts_write_reg(client, 2, 0x4); + msleep(300); + if ((fts_updateinfo_curr.CHIP_ID==0x11) ||(fts_updateinfo_curr.CHIP_ID==0x12) ||(fts_updateinfo_curr.CHIP_ID==0x13) ||(fts_updateinfo_curr.CHIP_ID==0x14)) //5x36,5x36i + { + for(i=0;i<100;i++) + { + fts_read_reg(client, 0x02, &uc_temp); + if (0x02 == uc_temp || + 0xFF == uc_temp) + { + /*if 0x02, then auto clb ok, else 0xff, auto clb failure*/ + break; + } + msleep(20); + } + } else { + for(i=0;i<100;i++) + { + fts_read_reg(client, 0, &uc_temp); + if (0x0 == ((uc_temp&0x70)>>4)) /*return to normal mode, calibration finish*/ + { + break; + } + msleep(20); + } + } + /*calibration OK*/ + fts_write_reg(client, 0, 0x40); /*goto factory mode for store*/ + msleep(200); /*make sure already enter factory mode*/ + fts_write_reg(client, 2, 0x5); /*store CLB result*/ + msleep(300); + fts_write_reg(client, 0, FTS_WORKMODE_VALUE); /*return to normal mode */ + msleep(300); + + /*store CLB result OK */ + return 0; +} + + +/* +upgrade with *.i file +*/ +int fts_ctpm_fw_upgrade_with_i_file(struct i2c_client *client) +{ + u8 *pbt_buf = NULL; + int i_ret; + //int fw_len = sizeof(CTPM_FW); + + /*judge the fw that will be upgraded + * if illegal, then stop upgrade and return. + */ + if (fw_size < 8 || fw_size > 32 * 1024) { + dev_err(&client->dev, "%s:FW length error\n", __func__); + return -EIO; + } + + if ((CTPM_FW[fw_size - 8] ^ CTPM_FW[fw_size - 6]) == 0xFF + && (CTPM_FW[fw_size - 7] ^ CTPM_FW[fw_size - 5]) == 0xFF + && (CTPM_FW[fw_size - 3] ^ CTPM_FW[fw_size - 4]) == 0xFF) { + /*FW upgrade */ + pbt_buf = CTPM_FW; + /*call the upgrade function */ + i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, fw_size); + if (i_ret != 0) + dev_err(&client->dev, "%s:upgrade failed. err.\n", + __func__); + else if(fts_updateinfo_curr.AUTO_CLB==AUTO_CLB_NEED) + fts_ctpm_auto_clb(client); /*start auto CLB */ + + } else { + dev_err(&client->dev, "%s:FW format error\n", __func__); + return -EBADFD; + } + + return i_ret; +} + +u8 fts_ctpm_get_i_file_ver(void) +{ + u16 ui_sz; + //ui_sz = sizeof(CTPM_FW); + ui_sz = fw_size; + if (ui_sz > 2) + return CTPM_FW[ui_sz - 2]; + + return 0x00; /*default value */ +} + +/*update project setting +*only update these settings for COB project, or for some special case +*/ +int fts_ctpm_update_project_setting(struct i2c_client *client) +{ + u8 uc_i2c_addr; /*I2C slave address (7 bit address)*/ + u8 uc_io_voltage; /*IO Voltage 0---3.3v; 1----1.8v*/ + u8 uc_panel_factory_id; /*TP panel factory ID*/ + u8 buf[FTS_SETTING_BUF_LEN]; + u8 reg_val[2] = {0}; + u8 auc_i2c_write_buf[10] = {0}; + u8 packet_buf[FTS_SETTING_BUF_LEN + 6]; + u32 i = 0; + int i_ret; + + uc_i2c_addr = client->addr; + uc_io_voltage = 0x0; + uc_panel_factory_id = 0x5a; + + + /*Step 1:Reset CTPM + *write 0xaa to register 0xfc + */ + fts_write_reg(client, 0xfc, 0xaa); + msleep(50); + + /*write 0x55 to register 0xfc */ + fts_write_reg(client, 0xfc, 0x55); + msleep(30); + + /*********Step 2:Enter upgrade mode *****/ + auc_i2c_write_buf[0] = 0x55; + auc_i2c_write_buf[1] = 0xaa; + do { + i++; + i_ret = fts_i2c_Write(client, auc_i2c_write_buf, 2); + msleep(5); + } while (i_ret <= 0 && i < 5); + + + /*********Step 3:check READ-ID***********************/ + auc_i2c_write_buf[0] = 0x90; + auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] = + 0x00; + + fts_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2); + + if (reg_val[0] == 0x79 && reg_val[1] == 0x3) + dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + reg_val[0], reg_val[1]); + else + return -EIO; + + auc_i2c_write_buf[0] = 0xcd; + fts_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1); + dev_dbg(&client->dev, "bootloader version = 0x%x\n", reg_val[0]); + + /*--------- read current project setting ---------- */ + /*set read start address */ + buf[0] = 0x3; + buf[1] = 0x0; + buf[2] = 0x78; + buf[3] = 0x0; + + fts_i2c_Read(client, buf, 4, buf, FTS_SETTING_BUF_LEN); + dev_dbg(&client->dev, "[FTS] old setting: uc_i2c_addr = 0x%x,\ + uc_io_voltage = %d, uc_panel_factory_id = 0x%x\n", + buf[0], buf[2], buf[4]); + + /*--------- Step 4:erase project setting --------------*/ + auc_i2c_write_buf[0] = 0x63; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + msleep(100); + + /*---------- Set new settings ---------------*/ + buf[0] = uc_i2c_addr; + buf[1] = ~uc_i2c_addr; + buf[2] = uc_io_voltage; + buf[3] = ~uc_io_voltage; + buf[4] = uc_panel_factory_id; + buf[5] = ~uc_panel_factory_id; + packet_buf[0] = 0xbf; + packet_buf[1] = 0x00; + packet_buf[2] = 0x78; + packet_buf[3] = 0x0; + packet_buf[4] = 0; + packet_buf[5] = FTS_SETTING_BUF_LEN; + + for (i = 0; i < FTS_SETTING_BUF_LEN; i++) + packet_buf[6 + i] = buf[i]; + + fts_i2c_Write(client, packet_buf, FTS_SETTING_BUF_LEN + 6); + msleep(100); + + /********* reset the new FW***********************/ + auc_i2c_write_buf[0] = 0x07; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + + msleep(200); + return 0; +} + +int fts_ctpm_auto_upgrade(struct i2c_client *client) +{ + u8 uc_host_fm_ver = FT_REG_FW_VER; + u8 uc_tp_fm_ver; + int i_ret; + unsigned char uc_reg_value; + + fts_read_reg(client, FT5X0X_REG_CIPHER, &uc_reg_value); + printk("[FTS] read chip id is %x\n",uc_reg_value); +#ifdef CONFIG_TOUCHSCREEN_FIRMWARE_UPGRADE +/*the chip id of FT6306 is 0x06*/ + if (uc_reg_value == 0x06) + { + CTPM_FW = FT6306_FW; + fw_size = sizeof(FT6306_FW); + } + if (uc_reg_value == 0x0a) + { + CTPM_FW = FT5316_FW; + fw_size = sizeof(FT5316_FW); + } +#endif + fts_read_reg(client, FT_REG_FW_VER, &uc_tp_fm_ver); + uc_host_fm_ver = fts_ctpm_get_i_file_ver(); + + printk("[FTS] uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x\n",uc_tp_fm_ver, uc_host_fm_ver); +/* +*avoid the old module about 500pcs to upgrade the firmware, +*the firmware version of old module is from 0x01 to 0x03, +*but the new module firmware version is more than 0x10. +*bug385939 +*/ + if (uc_reg_value == 0x06) { + if (uc_tp_fm_ver < 0x04) + return 0; + } + + if (/*the firmware in touch panel maybe corrupted */ + uc_tp_fm_ver == FT_REG_FW_VER || + /*the firmware in host flash is new, need upgrade */ + uc_tp_fm_ver < uc_host_fm_ver + ) { + msleep(100); + dev_dbg(&client->dev, "[FTS] uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x\n", + uc_tp_fm_ver, uc_host_fm_ver); + i_ret = fts_ctpm_fw_upgrade_with_i_file(client); + if (i_ret == 0) { + msleep(300); + uc_host_fm_ver = fts_ctpm_get_i_file_ver(); + dev_dbg(&client->dev, "[FTS] upgrade to new version 0x%x\n", + uc_host_fm_ver); + } else { + pr_err("[FTS] upgrade failed ret=%d.\n", i_ret); + return -EIO; + } + } + + return 0; +} + +void delay_qt_ms(unsigned long w_ms) +{ + unsigned long i; + unsigned long j; + + for (i = 0; i < w_ms; i++) + { + for (j = 0; j < 1000; j++) + { + udelay(1); + } + } +} + +extern void focaltech_get_upgrade_array(struct i2c_client *client); + +int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf, + u32 dw_lenth) +{ + u8 reg_val[2] = {0}; + u32 i = 0; + u8 is_5336_new_bootloader = 0; + u8 is_5336_fwsize_30 = 0; + u32 packet_number; + u32 j=0; + u32 temp; + u32 lenght; + u8 packet_buf[FTS_PACKET_LENGTH + 6]; + u8 auc_i2c_write_buf[10]; + u8 bt_ecc; + int i_ret; + // struct Upgrade_Info upgradeinfo; + + //fts_get_upgrade_info(&upgradeinfo); + + focaltech_get_upgrade_array(client); + + if(*(pbt_buf+dw_lenth-12) == 30) + { + is_5336_fwsize_30 = 1; + } + else + { + is_5336_fwsize_30 = 0; + } + for (i = 0; i < FTS_UPGRADE_LOOP; i++) + { + msleep(100); + printk("[FTS] Step 1:Reset CTPM\n"); + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + //if (DEVICE_IC_TYPE == IC_FT6208 || DEVICE_IC_TYPE == IC_FT6x06) + if(fts_updateinfo_curr.CHIP_ID==0x05 || fts_updateinfo_curr.CHIP_ID==0x06 ) + fts_write_reg(client, 0xbc, FT_UPGRADE_AA); + else + fts_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(fts_updateinfo_curr.delay_aa); + + + /*write 0x55 to register 0xfc */ + //if(DEVICE_IC_TYPE == IC_FT6208 || DEVICE_IC_TYPE == IC_FT6x06) + if(fts_updateinfo_curr.CHIP_ID==0x05 || fts_updateinfo_curr.CHIP_ID==0x06 ) + fts_write_reg(client, 0xbc, FT_UPGRADE_55); + else + fts_write_reg(client, 0xfc, FT_UPGRADE_55); + if(i<=15) + { + msleep(fts_updateinfo_curr.delay_55+i*3); + } + else + { + msleep(fts_updateinfo_curr.delay_55-(i-15)*2); + } + + + /*********Step 2:Enter upgrade mode *****/ + printk("[FTS] Step 2:Enter upgrade mode \n"); + #if 0 + auc_i2c_write_buf[0] = FT_UPGRADE_55; + auc_i2c_write_buf[1] = FT_UPGRADE_AA; + do { + j++; + i_ret = fts_i2c_Write(client, auc_i2c_write_buf, 2); + msleep(5); + } while (i_ret <= 0 && j < 5); + #else + auc_i2c_write_buf[0] = FT_UPGRADE_55; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + msleep(5); + auc_i2c_write_buf[0] = FT_UPGRADE_AA; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + #endif + +#if 1 + /*********Step 3:check READ-ID***********************/ + msleep(fts_updateinfo_curr.delay_readid); + auc_i2c_write_buf[0] = 0x90; + auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] =0x00; + fts_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2); + + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0], reg_val[1]); + if (reg_val[0] == fts_updateinfo_curr.upgrade_id_1 + && reg_val[1] == fts_updateinfo_curr.upgrade_id_2) { + //dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + //reg_val[0], reg_val[1]); + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + reg_val[0], reg_val[1]); + break; + } else { + dev_err(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + reg_val[0], reg_val[1]); + } +#endif + } + if (i >= FTS_UPGRADE_LOOP) + return -EIO; + + auc_i2c_write_buf[0] = 0xcd; + fts_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1); + /*********0705 mshl ********************/ + /*if (reg_val[0] > 4) + is_5336_new_bootloader = 1;*/ + + if (reg_val[0] <= 4) + { + is_5336_new_bootloader = BL_VERSION_LZ4 ; + } + else if(reg_val[0] == 7) + { + is_5336_new_bootloader = BL_VERSION_Z7 ; + } + else if(reg_val[0] >= 0x0f && ((fts_updateinfo_curr.CHIP_ID==0x11) ||(fts_updateinfo_curr.CHIP_ID==0x12) ||(fts_updateinfo_curr.CHIP_ID==0x13) ||(fts_updateinfo_curr.CHIP_ID==0x14))) + { + is_5336_new_bootloader = BL_VERSION_GZF ; + } + else + { + is_5336_new_bootloader = BL_VERSION_LZ4 ; + } + + + printk("[FTS] Step 4:erase app and panel paramenter area\n"); + /*Step 4:erase app and panel paramenter area*/ + printk("Step 4:erase app and panel paramenter area\n"); + auc_i2c_write_buf[0] = 0x61; + fts_i2c_Write(client, auc_i2c_write_buf, 1); /*erase app area */ + msleep(fts_updateinfo_curr.delay_earse_flash); + /*erase panel parameter area */ + if(is_5336_fwsize_30) + { + auc_i2c_write_buf[0] = 0x63; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + } + msleep(100); + + printk("[FTS] Step 5:write firmware(FW) to ctpm flash\n"); + /*********Step 5:write firmware(FW) to ctpm flash*********/ + bt_ecc = 0; + printk("Step 5:write firmware(FW) to ctpm flash\n"); + + //dw_lenth = dw_lenth - 8; + if(is_5336_new_bootloader == BL_VERSION_LZ4 || is_5336_new_bootloader == BL_VERSION_Z7 ) + { + dw_lenth = dw_lenth - 8; + } + else if(is_5336_new_bootloader == BL_VERSION_GZF) + { + dw_lenth = dw_lenth - 14; + } + packet_number = (dw_lenth) / FTS_PACKET_LENGTH; + packet_buf[0] = 0xbf; + packet_buf[1] = 0x00; + + for (j = 0; j < packet_number; j++) { + temp = j * FTS_PACKET_LENGTH; + packet_buf[2] = (u8) (temp >> 8); + packet_buf[3] = (u8) temp; + lenght = FTS_PACKET_LENGTH; + packet_buf[4] = (u8) (lenght >> 8); + packet_buf[5] = (u8) lenght; + + for (i = 0; i < FTS_PACKET_LENGTH; i++) { + packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i]; + bt_ecc ^= packet_buf[6 + i]; + } + + fts_i2c_Write(client, packet_buf, FTS_PACKET_LENGTH + 6); + msleep(FTS_PACKET_LENGTH / 6 + 1); + if((((j+1) * FTS_PACKET_LENGTH)%1024)==0) + printk("write bytes:0x%04x\n", (j+1) * FTS_PACKET_LENGTH); + //delay_qt_ms(FTS_PACKET_LENGTH / 6 + 1); + } + + if ((dw_lenth) % FTS_PACKET_LENGTH > 0) { + temp = packet_number * FTS_PACKET_LENGTH; + packet_buf[2] = (u8) (temp >> 8); + packet_buf[3] = (u8) temp; + temp = (dw_lenth) % FTS_PACKET_LENGTH; + packet_buf[4] = (u8) (temp >> 8); + packet_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + packet_buf[6 + i] = pbt_buf[packet_number * FTS_PACKET_LENGTH + i]; + bt_ecc ^= packet_buf[6 + i]; + } + + fts_i2c_Write(client, packet_buf, temp + 6); + msleep(20); + } +#if 0 + /*send the last six byte*/ + for (i = 0; i<6; i++) + { + if (is_5336_new_bootloader && ((fts_updateinfo_curr.CHIP_ID==0x11) ||(fts_updateinfo_curr.CHIP_ID==0x12) ||(fts_updateinfo_curr.CHIP_ID==0x13) ||(fts_updateinfo_curr.CHIP_ID==0x14)))//5x36,5x36i + temp = 0x7bfa + i; + else + temp = 0x6ffa + i; + packet_buf[2] = (u8)(temp>>8); + packet_buf[3] = (u8)temp; + temp =1; + packet_buf[4] = (u8)(temp>>8); + packet_buf[5] = (u8)temp; + packet_buf[6] = pbt_buf[ dw_lenth + i]; + bt_ecc ^= packet_buf[6]; + fts_i2c_Write(client, packet_buf, 7); + msleep(20); + } +#else + /*send the last six byte*/ + if(is_5336_new_bootloader == BL_VERSION_LZ4 || is_5336_new_bootloader == BL_VERSION_Z7 ) + { + for (i = 0; i<6; i++) + { + if (is_5336_new_bootloader == BL_VERSION_Z7 ) + { + temp = 0x7bfa + i; + } + else if(is_5336_new_bootloader == BL_VERSION_LZ4) + { + temp = 0x6ffa + i; + } + packet_buf[2] = (u8)(temp>>8); + packet_buf[3] = (u8)temp; + temp =1; + packet_buf[4] = (u8)(temp>>8); + packet_buf[5] = (u8)temp; + packet_buf[6] = pbt_buf[ dw_lenth + i]; + bt_ecc ^= packet_buf[6]; + + fts_i2c_Write(client, packet_buf, 7); + msleep(20); + } + } + else if(is_5336_new_bootloader == BL_VERSION_GZF) + { + + for (i = 0; i<12; i++) + { + if (is_5336_fwsize_30) + { + temp = 0x7ff4 + i; + } + else + { + temp = 0x7bf4 + i; + } + packet_buf[2] = (u8)(temp>>8); + packet_buf[3] = (u8)temp; + temp =1; + packet_buf[4] = (u8)(temp>>8); + packet_buf[5] = (u8)temp; + packet_buf[6] = pbt_buf[ dw_lenth + i]; + bt_ecc ^= packet_buf[6]; + + fts_i2c_Write(client, packet_buf, 7); + msleep(20); + + } + } + +#endif + printk("[FTS] Step 6: read out checksum\n"); + /*********Step 6: read out checksum***********************/ + /*send the opration head */ + printk("Step 6: read out checksum\n"); + auc_i2c_write_buf[0] = 0xcc; + fts_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1); + if (reg_val[0] != bt_ecc) { + dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n", + reg_val[0], + bt_ecc); + return -EIO; + } + + printk("[FTS] Step 7: reset the new FW\n"); + /*********Step 7: reset the new FW***********************/ + printk("Step 7: reset the new FW\n"); + auc_i2c_write_buf[0] = 0x07; + fts_i2c_Write(client, auc_i2c_write_buf, 1); + msleep(300); /*make sure CTP startup normally */ + + return 0; +} +/*sysfs debug*/ + +/* +*get firmware size + +@firmware_name:firmware name +*note:the firmware default path is sdcard. + if you want to change the dir, please modify by yourself. +*/ +static int fts_GetFirmwareSize(char *firmware_name) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize = 0; + char filepath[128]; + memset(filepath, 0, sizeof(filepath)); + + sprintf(filepath, "%s", firmware_name); + + if (NULL == pfile) + pfile = filp_open(filepath, O_RDONLY, 0); + + if (IS_ERR(pfile)) { + pr_err("error occured while opening file %s.\n", filepath); + return -EIO; + } + + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + filp_close(pfile, NULL); + return fsize; +} + + + +/* +*read firmware buf for .bin file. + +@firmware_name: fireware name +@firmware_buf: data buf of fireware + +note:the firmware default path is sdcard. + if you want to change the dir, please modify by yourself. +*/ +static int fts_ReadFirmware(char *firmware_name, + unsigned char *firmware_buf) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize; + char filepath[128]; + loff_t pos; + mm_segment_t old_fs; + + memset(filepath, 0, sizeof(filepath)); + sprintf(filepath, "%s", firmware_name); + if (NULL == pfile) + pfile = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(pfile)) { + pr_err("error occured while opening file %s.\n", filepath); + return -EIO; + } + + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(pfile, firmware_buf, fsize, &pos); + filp_close(pfile, NULL); + set_fs(old_fs); + + return 0; +} + + + +/* +upgrade with *.bin file +*/ + +int fts_ctpm_fw_upgrade_with_app_file(struct i2c_client *client, + char *firmware_name) +{ + u8 *pbt_buf = NULL; + int i_ret=0; + int fwsize = fts_GetFirmwareSize(firmware_name); + + if (fwsize <= 0) { + dev_err(&client->dev, "%s ERROR:Get firmware size failed\n", + __func__); + return -EIO; + } + + if (fwsize < 8 || fwsize > 32 * 1024) { + dev_dbg(&client->dev, "%s:FW length error\n", __func__); + return -EIO; + } + + + /*=========FW upgrade========================*/ + pbt_buf = kmalloc(fwsize + 1, GFP_ATOMIC); + + if (fts_ReadFirmware(firmware_name, pbt_buf)) { + dev_err(&client->dev, "%s() - ERROR: request_firmware failed\n", + __func__); + kfree(pbt_buf); + pbt_buf = NULL; + //return -EIO; + i_ret = -EIO; + goto err_ret; + } + + /*call the upgrade function */ + i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, fwsize); + if (i_ret != 0) + dev_err(&client->dev, "%s() - ERROR:[FTS] upgrade failed..\n", + __func__); + else if(fts_updateinfo_curr.AUTO_CLB==AUTO_CLB_NEED) + fts_ctpm_auto_clb(client); + +err_ret: + + + if(pbt_buf != NULL) + kfree(pbt_buf); + + return i_ret; +} + +static ssize_t fts_tpfwver_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t num_read_chars = 0; + u8 fwver = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + mutex_lock(&g_device_mutex); + + if (fts_read_reg(client, FT_REG_FW_VER, &fwver) < 0) + num_read_chars = snprintf(buf, PAGE_SIZE, + "get tp fw version fail!\n"); + else + num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver); + + mutex_unlock(&g_device_mutex); + + return num_read_chars; +} + +static ssize_t fts_tpfwver_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + /*place holder for future use*/ + return -EPERM; +} + + + +static ssize_t fts_tprwreg_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /*place holder for future use*/ + return -EPERM; +} + +static ssize_t fts_tprwreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + ssize_t num_read_chars = 0; + int retval; + long unsigned int wmreg = 0; + u8 regaddr = 0xff, regvalue = 0xff; + u8 valbuf[5] = {0}; + + memset(valbuf, 0, sizeof(valbuf)); + mutex_lock(&g_device_mutex); + num_read_chars = count - 1; + + if (num_read_chars != 2) { + if (num_read_chars != 4) { + pr_info("please input 2 or 4 character\n"); + goto error_return; + } + } + + memcpy(valbuf, buf, num_read_chars); + retval = strict_strtoul(valbuf, 16, &wmreg); + + if (0 != retval) { + dev_err(&client->dev, "%s() - ERROR: Could not convert the "\ + "given input to a number." \ + "The given input was: \"%s\"\n", + __func__, buf); + goto error_return; + } + + if (2 == num_read_chars) { + /*read register*/ + regaddr = wmreg; + if (fts_read_reg(client, regaddr, ®value) < 0) + dev_err(&client->dev, "Could not read the register(0x%02x)\n", + regaddr); + else + pr_info("the register(0x%02x) is 0x%02x\n", + regaddr, regvalue); + } else { + regaddr = wmreg >> 8; + regvalue = wmreg; + if (fts_write_reg(client, regaddr, regvalue) < 0) + dev_err(&client->dev, "Could not write the register(0x%02x)\n", + regaddr); + else + dev_err(&client->dev, "Write 0x%02x into register(0x%02x) successful\n", + regvalue, regaddr); + } + +error_return: + mutex_unlock(&g_device_mutex); + + return count; +} + +static ssize_t fts_fwupdate_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /* place holder for future use */ + return -EPERM; +} + +/*upgrade from *.i*/ +static ssize_t fts_fwupdate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + //struct fts_ts_data *data = NULL; + u8 uc_host_fm_ver; + int i_ret; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + //data = (struct fts_ts_data *)i2c_get_clientdata(client); + + mutex_lock(&g_device_mutex); + + disable_irq(client->irq); + //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); + i_ret = fts_ctpm_fw_upgrade_with_i_file(client); + if (i_ret == 0) { + msleep(300); + uc_host_fm_ver = fts_ctpm_get_i_file_ver(); + pr_info("%s [FTS] upgrade to new version 0x%x\n", __func__, + uc_host_fm_ver); + } else + dev_err(&client->dev, "%s ERROR:[FTS] upgrade failed.\n", + __func__); + + enable_irq(client->irq); + //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); + mutex_unlock(&g_device_mutex); + + return count; +} + +static ssize_t fts_fwupgradeapp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /*place holder for future use*/ + return -EPERM; +} + + +/*upgrade from app.bin*/ +static ssize_t fts_fwupgradeapp_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t num_read_chars = 0; + char fwname[128]; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + memset(fwname, 0, sizeof(fwname)); + sprintf(fwname, "%s", buf); + fwname[count - 1] = '\0'; + + mutex_lock(&g_device_mutex); + disable_irq(client->irq); + //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); + if(0==fts_ctpm_fw_upgrade_with_app_file(client, fwname)) + { + num_read_chars = snprintf(buf, PAGE_SIZE, + "FTP firmware upgrade success!\n"); + } + else + { + num_read_chars = snprintf(buf, PAGE_SIZE, + "FTP firmware upgrade fail!\n"); + } + + enable_irq(client->irq); + //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); + mutex_unlock(&g_device_mutex); + + return num_read_chars; +} + + +/*sysfs */ +/*get the fw version +*example:cat ftstpfwver +*/ +static DEVICE_ATTR(ftstpfwver, S_IRUGO | S_IWUSR, fts_tpfwver_show, + fts_tpfwver_store); + +/*upgrade from *.i +*example: echo 1 > ftsfwupdate +*/ +static DEVICE_ATTR(ftsfwupdate, S_IRUGO | S_IWUSR, fts_fwupdate_show, + fts_fwupdate_store); + +/*read and write register +*read example: echo 88 > ftstprwreg ---read register 0x88 +*write example:echo 8807 > ftstprwreg ---write 0x07 into register 0x88 +* +*note:the number of input must be 2 or 4.if it not enough,please fill in the 0. +*/ +static DEVICE_ATTR(ftstprwreg, S_IRUGO | S_IWUSR, fts_tprwreg_show, + fts_tprwreg_store); + + +/*upgrade from app.bin +*example:echo "*_app.bin" > ftsfwupgradeapp +*/ +static DEVICE_ATTR(ftsfwupgradeapp, S_IRUGO | S_IWUSR, fts_fwupgradeapp_show, + fts_fwupgradeapp_store); + + +/*add your attr in here*/ +static struct attribute *fts_attributes[] = { + &dev_attr_ftstpfwver.attr, + &dev_attr_ftsfwupdate.attr, + &dev_attr_ftstprwreg.attr, + &dev_attr_ftsfwupgradeapp.attr, + NULL +}; + +static struct attribute_group fts_attribute_group = { + .attrs = fts_attributes +}; + +/*create sysfs for debug*/ +int fts_create_sysfs(struct i2c_client *client) +{ + int err; + + err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group); + if (0 != err) { + dev_err(&client->dev, + "%s() - ERROR: sysfs_create_group() failed.\n", + __func__); + sysfs_remove_group(&client->dev.kobj, &fts_attribute_group); + return -EIO; + } else { + mutex_init(&g_device_mutex); + pr_info("ft6x06:%s() - sysfs_create_group() succeeded.\n", + __func__); + } + return err; +} + +void fts_release_sysfs(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fts_attribute_group); + mutex_destroy(&g_device_mutex); + + +} +/*create apk debug channel*/ + +#define PROC_UPGRADE 0 +#define PROC_READ_REGISTER 1 +#define PROC_WRITE_REGISTER 2 +#define PROC_RAWDATA 3 +#define PROC_AUTOCLB 4 + +#define PROC_NAME "ft5x0x-debug" +static unsigned char proc_operate_mode = PROC_RAWDATA; +static struct proc_dir_entry *ft5x0x_proc_entry; +/*interface of write proc*/ +static ssize_t ft5x0x_debug_write(struct file *filp, const char __user *buff, size_t len, loff_t *ops) +{ + struct i2c_client *client = (struct i2c_client *)PDE_DATA(file_inode(filp)); + unsigned char writebuf[FTS_PACKET_LENGTH]; + int buflen = len; + int writelen = 0; + int ret = 0; + + if (copy_from_user(&writebuf, buff, buflen)) { + dev_err(&client->dev, "%s:copy from user error\n", __func__); + return -EFAULT; + } + proc_operate_mode = writebuf[0]; + + switch (proc_operate_mode) { + case PROC_UPGRADE: + { + char upgrade_file_path[128]; + memset(upgrade_file_path, 0, sizeof(upgrade_file_path)); + sprintf(upgrade_file_path, "%s", writebuf + 1); + upgrade_file_path[buflen-1] = '\0'; + printk("%s\n", upgrade_file_path); + disable_irq(client->irq); + + ret = fts_ctpm_fw_upgrade_with_app_file(client, upgrade_file_path); + + enable_irq(client->irq); + if (ret < 0) { + dev_err(&client->dev, "%s:upgrade failed.\n", __func__); + return ret; + } + } + break; + case PROC_READ_REGISTER: + writelen = 1; + printk("%s:register addr=0x%02x\n", __func__, writebuf[1]); + ret = fts_i2c_Write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_WRITE_REGISTER: + writelen = 2; + ret = fts_i2c_Write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_RAWDATA: + break; + case PROC_AUTOCLB: + fts_ctpm_auto_clb(client); + break; + + default: + break; + } + + + return len; +} + +/*interface of read proc*/ +static ssize_t ft5x0x_debug_read(struct file *filp, char __user *page, size_t len, loff_t *pos) +{ + struct i2c_client *client = (struct i2c_client *)PDE_DATA(file_inode(filp)); + int ret = 0; + + //u8 tx = 0, rx = 0; + //int i, j; + + unsigned char buf[PAGE_SIZE]; + int num_read_chars = 0; + int readlen = 0; + u8 regvalue = 0x00, regaddr = 0x00; + switch (proc_operate_mode) { + case PROC_UPGRADE: + /*after calling ft5x0x_debug_write to upgrade*/ + regaddr = 0xA6; + ret = fts_read_reg(client, regaddr, ®value); + if (ret < 0) + num_read_chars = sprintf(buf, "%s", "get fw version failed.\n"); + else + num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue); + break; + case PROC_READ_REGISTER: + readlen = 1; + ret = fts_i2c_Read(client, NULL, 0, buf, readlen); + if (ret < 0) { + dev_err(&client->dev, "%s:read iic error\n", __func__); + return ret; + } else + printk("%s:value=0x%02x\n", __func__, buf[0]); + num_read_chars = 1; + break; + case PROC_RAWDATA: + break; + default: + break; + } + + memcpy(page, buf, num_read_chars); + + return num_read_chars; +} +static struct file_operations proc_ops = { + .read = ft5x0x_debug_read, + .write = ft5x0x_debug_write, +}; +int ft5x0x_create_apk_debug_channel(struct i2c_client * client) +{ + ft5x0x_proc_entry = proc_create_data(PROC_NAME, 0777 | S_IFREG, NULL, &proc_ops, (void *)client); + if (NULL == ft5x0x_proc_entry) { + dev_err(&client->dev, "Couldn't create proc entry!\n"); + return -ENOMEM; + } + return 0; +} + +void ft5x0x_release_apk_debug_channel(void) +{ +#if 0 + if (ft5x0x_proc_entry) + remove_proc_entry(PROC_NAME, NULL); +#endif +} + |
