/*
* drivers/input/touchscreen/ft5x06_ex_fun.c
*
* FocalTech ft5x0x 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 "ft5x06_ex_fun.h"
#include <linux/i2c/ft5x06_ts.h>
#include <linux/mount.h>
#include <linux/netdevice.h>
struct Upgrade_Info{
u16 delay_aa; /*delay of write FT_UPGRADE_AA*/
u16 delay_55; /*delay of write FT_UPGRADE_55*/
u8 upgrade_id_1; /*upgrade id 1*/
u8 upgrade_id_2; /*upgrade id 2*/
u16 delay_readid; /*delay of read id*/
};
int fts_ctpm_fw_upgrade(struct i2c_client * client, u8* pbt_buf, u32 dw_lenth);
static unsigned char CTPM_FW[]=
{
#include "ft5336_app.i"
};
static struct mutex g_device_mutex;
int ft5x0x_write_reg(struct i2c_client * client, u8 regaddr, u8 regvalue)
{
unsigned char buf[2] = {0};
buf[0] = regaddr;
buf[1] = regvalue;
return ft5x0x_i2c_Write(client, buf, sizeof(buf));
}
int ft5x0x_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue)
{
return ft5x0x_i2c_Read(client, ®addr, 1, regvalue, 1);
}
int fts_ctpm_auto_clb(struct i2c_client * client)
{
unsigned char uc_temp;
unsigned char i ;
/*start auto CLB*/
msleep(200);
ft5x0x_write_reg(client, 0, 0x40);
msleep(100); /*make sure already enter factory mode*/
ft5x0x_write_reg(client, 2, 0x4); /*write command to start calibration*/
msleep(300);
if (DEVICE_IC_TYPE == IC_FT5X36) {
for(i=0;i<100;i++)
{
ft5x0x_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++)
{
ft5x0x_read_reg(client, 0, &uc_temp);
if (0x0 == ((uc_temp&0x70)>>4)) /*return to normal mode, calibration finish*/
{
break;
}
msleep(20);
}
}
/*calibration OK*/
ft5x0x_write_reg(client, 0, 0x40); /*goto factory mode for store*/
msleep(200); /*make sure already enter factory mode*/
ft5x0x_write_reg(client, 2, 0x5); /*store CLB result*/
msleep(300);
ft5x0x_write_reg(client, 0, 0x0); /*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_len<8 || fw_len>32*1024)
{
pr_err("FW length error\n");
return -EIO;
}
if((CTPM_FW[fw_len-8]^CTPM_FW[fw_len-6])==0xFF
&& (CTPM_FW[fw_len-7]^CTPM_FW[fw_len-5])==0xFF
&& (CTPM_FW[fw_len-3]^CTPM_FW[fw_len-4])==0xFF)
{
/*FW upgrade*/
pbt_buf = CTPM_FW;
/*call the upgrade function*/
i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, sizeof(CTPM_FW));
if (i_ret != 0)
{
dev_err(&client->dev, "[FTS] upgrade failed. err=%d.\n", i_ret);
}
else
{
#ifdef AUTO_CLB
fts_ctpm_auto_clb(client); /*start auto CLB*/
#endif
}
}
else
{
dev_err(&client->dev, "FW format error\n");
return -EBADFD;
}
return i_ret;
}
u8 fts_ctpm_get_i_file_ver(void)
{
u16 ui_sz;
ui_sz = sizeof(CTPM_FW);
if (ui_sz > 2)
{
return CTPM_FW[ui_sz - 2];
}
else
{
return 0x00; /*default value*/
}
}
int fts_ctpm_auto_upgrade(struct i2c_client * client)
{
u8 uc_host_fm_ver=FT5x0x_REG_FW_VER;
u8 uc_tp_fm_ver;
int i_ret;
ft5x0x_read_reg(client, FT5x0x_REG_FW_VER, &uc_tp_fm_ver);
uc_host_fm_ver = fts_ctpm_get_i_file_ver();
if ( uc_tp_fm_ver == FT5x0x_REG_FW_VER || /*the firmware in touch panel maybe corrupted*/
uc_tp_fm_ver < uc_host_fm_ver /*the firmware in host flash is new, need upgrade*/
)
{
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
{
dev_err(&client->dev, "[FTS] upgrade failed ret=%d.\n", i_ret);
return -EIO;
}
}
return 0;
}
/*
*get upgrade information depend on the ic type
*/
static void fts_get_upgrade_info(struct Upgrade_Info * upgrade_info)
{
switch(DEVICE_IC_TYPE)
{
case IC_FT5X06:
upgrade_info->delay_55 = FT5X06_UPGRADE_55_DELAY;
upgrade_info->delay_aa = FT5X06_UPGRADE_AA_DELAY;
upgrade_info->upgrade_id_1 = FT5X06_UPGRADE_ID_1;
upgrade_info->upgrade_id_2 = FT5X06_UPGRADE_ID_2;
upgrade_info->delay_readid = FT5X06_UPGRADE_READID_DELAY;
break;
case IC_FT5606:
upgrade_info->delay_55 = FT5606_UPGRADE_55_DELAY;
upgrade_info->delay_aa = FT5606_UPGRADE_AA_DELAY;
upgrade_info->upgrade_id_1 = FT5606_UPGRADE_ID_1;
upgrade_info->upgrade_id_2 = FT5606_UPGRADE_ID_2;
upgrade_info->delay_readid = FT5606_UPGRADE_READID_DELAY;
break;
case IC_FT5316:
upgrade_info->delay_55 = FT5316_UPGRADE_55_DELAY;
upgrade_info->delay_aa = FT5316_UPGRADE_AA_DELAY;
upgrade_info->upgrade_id_1 = FT5316_UPGRADE_ID_1;
upgrade_info->upgrade_id_2 = FT5316_UPGRADE_ID_2;
upgrade_info->delay_readid = FT5316_UPGRADE_READID_DELAY;
break;
case IC_FT5X36:
upgrade_info->delay_55 = FT5X36_UPGRADE_55_DELAY;
upgrade_info->delay_aa = FT5X36_UPGRADE_AA_DELAY;
upgrade_info->upgrade_id_1 = FT5X36_UPGRADE_ID_1;
upgrade_info->upgrade_id_2 = FT5X36_UPGRADE_ID_2;
upgrade_info->delay_readid = FT5X36_UPGRADE_READID_DELAY;
break;
default:
break;
}
}
#define FTS_UPGRADE_LOOP 3
int ft5x36_read_project_code(struct i2c_client * client, char * pProjectCode) {
u8 reg_val[2] = {0};
u32 i = 0;
u32 j;
u32 temp;
u8 packet_buf[4];
u8 auc_i2c_write_buf[10];
int i_ret;
u8 is_5336_new_bootloader = 0;
struct Upgrade_Info upgradeinfo;
fts_get_upgrade_info(&upgradeinfo);
for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
/*********Step 1:Reset CTPM *****/
/*write 0xaa to register 0xfc*/
ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA);
msleep(upgradeinfo.delay_aa);
/*write 0x55 to register 0xfc*/
ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55);
msleep(upgradeinfo.delay_55);
/*********Step 2:Enter upgrade mode *****/
auc_i2c_write_buf[0] = FT_UPGRADE_55;
auc_i2c_write_buf[1] = FT_UPGRADE_AA;
i_ret = ft5x0x_i2c_Write(client, auc_i2c_write_buf, 2);
/*********Step 3:check READ-ID***********************/
msleep(upgradeinfo.delay_readid);
auc_i2c_write_buf[0] = 0x90;
auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] = 0x00;
ft5x0x_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
if (reg_val[0] == upgradeinfo.upgrade_id_1
&& reg_val[1] == upgradeinfo.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]);
break;
}
else
{
dev_err(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
continue;
}
}
if (i >= FTS_UPGRADE_LOOP)
return -EIO;
auc_i2c_write_buf[0] = 0xcd;
ft5x0x_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
if (reg_val[0] > 4)
is_5336_new_bootloader = 1;