blob: b81f7260cb142e2be1e1cef78a5a01327750b66e [file] [log] [blame]
/* Himax Android Driver Sample Code for HX83112 chipset
*
* Copyright (C) 2017 Himax Corporation.
*
* 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.
*
*/
#include "himax_ic.h"
/*[Arima_8710][allen_yu] Fix TP I2C error in suspend 20180423 begin*/
#include "himax_common.h"
/*[Arima_8710][allen_yu] 20180423 end*/
extern int i2c_error_count;
/*[Arima_8710][allen_yu] Fix TP I2C error in suspend 20180419 begin*/
extern int reset_flag;
/*[Arima_8710][allen_yu] 20180419 end*/
extern unsigned long FW_VER_MAJ_FLASH_ADDR;
extern unsigned long FW_VER_MIN_FLASH_ADDR;
extern unsigned long CFG_VER_MAJ_FLASH_ADDR;
extern unsigned long CFG_VER_MIN_FLASH_ADDR;
extern unsigned long CID_VER_MAJ_FLASH_ADDR;
extern unsigned long CID_VER_MIN_FLASH_ADDR;
extern unsigned long FW_VER_MAJ_FLASH_LENG;
extern unsigned long FW_VER_MIN_FLASH_LENG;
extern unsigned long CFG_VER_MAJ_FLASH_LENG;
extern unsigned long CFG_VER_MIN_FLASH_LENG;
extern unsigned long CID_VER_MAJ_FLASH_LENG;
extern unsigned long CID_VER_MIN_FLASH_LENG;
#ifdef HX_AUTO_UPDATE_FW
extern int g_i_FW_VER;
extern int g_i_CFG_VER;
extern int g_i_CID_MAJ;
extern int g_i_CID_MIN;
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
//extern unsigned char i_CTPM_FW[];
extern unsigned char i_CTPM_FW_HX83112A[];
extern unsigned char i_CTPM_FW_HX83112B[];
/*[Arima_8710][allen_yu] 20180828 end*/
#endif
extern unsigned char IC_TYPE;
extern unsigned char IC_CHECKSUM;
extern bool DSRAM_Flag;
extern struct himax_ic_data* ic_data;
extern struct himax_ts_data *private_ts;
int himax_touch_data_size = 128;
#ifdef HX_TP_PROC_2T2R
bool Is_2T2R = false;
#endif
#ifdef HX_USB_DETECT_GLOBAL
//extern kal_bool upmu_is_chr_det(void);
extern void himax_cable_detect_func(bool force_renew);
#endif
int himax_get_touch_data_size(void)
{
return himax_touch_data_size;
}
#ifdef HX_RST_PIN_FUNC
extern void himax_rst_gpio_set(int pinnum, uint8_t value);
extern int himax_report_data_init(void);
extern u8 HX_HW_RESET_ACTIVATE;
void himax_pin_reset(void)
{
I("%s: Now reset the Touch chip.\n", __func__);
himax_rst_gpio_set(private_ts->rst_gpio, 0);
msleep(20);
himax_rst_gpio_set(private_ts->rst_gpio, 1);
/*[Arima_7947][allen_yu] Enter safe mode when i2c fail 20180129 begin*/
#if 0
msleep(20);
#endif
/*[Arima_7947][allen_yu] 20180129 end*/
}
void himax_reload_config(void)
{
if(himax_report_data_init())
E("%s: allocate data fail\n",__func__);
himax_sense_on(private_ts->client, 0x00);
}
void himax_irq_switch(int switch_on)
{
int ret = 0;
if(switch_on)
{
if (private_ts->use_irq)
himax_int_enable(private_ts->client->irq,switch_on);
else
hrtimer_start(&private_ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
}
else
{
if (private_ts->use_irq)
himax_int_enable(private_ts->client->irq,switch_on);
else
{
hrtimer_cancel(&private_ts->timer);
ret = cancel_work_sync(&private_ts->work);
}
}
}
void himax_ic_reset(uint8_t loadconfig,uint8_t int_off)
{
/*[Arima_8710][allen_yu] Fix TP I2C error in suspend 20180423 begin*/
#ifdef HX_RST_PIN_FUNC
if (reset_flag ==1){
/*[Arima_8710][allen_yu] 20180423 end*/
struct himax_ts_data *ts = private_ts;
HX_HW_RESET_ACTIVATE = 1;
I("%s,status: loadconfig=%d,int_off=%d\n",__func__,loadconfig,int_off);
if (ts->rst_gpio)
{
if(int_off)
{
himax_irq_switch(0);
}
himax_pin_reset();
if(loadconfig)
{
himax_reload_config();
}
if(int_off)
{
himax_irq_switch(1);
}
}
/*[Arima_8710][allen_yu] Fix TP I2C error in suspend 20180423 begin*/
}
#endif
/*[Arima_8710][allen_yu] 20180423 end*/
}
#endif
#if defined(HX_ESD_RECOVERY)
int g_zero_event_count = 0;
int himax_ic_esd_recovery(int hx_esd_event,int hx_zero_event,int length)
{
if(g_zero_event_count > 5)
{
g_zero_event_count = 0;
I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
goto checksum_fail;
}
if(hx_esd_event == length)
{
g_zero_event_count = 0;
goto checksum_fail;
}
else if(hx_zero_event == length)
{
g_zero_event_count++;
I("[HIMAX TP MSG]: ALL Zero event is %d times.\n",g_zero_event_count);
goto err_workqueue_out;
}
checksum_fail:
return CHECKSUM_FAIL;
err_workqueue_out:
return WORK_OUT;
}
void himax_esd_ic_reset(void)
{
/*Nothing to do in incell,need to follow display reset*/
}
#endif
int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C Fail
{
int result = 0;
return result;
}
void himax_idle_mode(struct i2c_client *client,int disable)
{
int retry = 20;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t switch_cmd = 0x00;
I("%s:entering\n",__func__);
do
{
I("%s,now %d times\n!",__func__,retry);
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x70;
tmp_addr[0] = 0x88;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
if(disable)
switch_cmd = 0x17;
else
switch_cmd = 0x1F;
tmp_data[0] = switch_cmd;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s:After turn ON/OFF IDLE Mode [0] = 0x%02X,[1] = 0x%02X,[2] = 0x%02X,[3] = 0x%02X\n", __func__,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
retry--;
msleep(10);
}
while((tmp_data[0] != switch_cmd) && retry > 0);
I("%s: setting OK!\n",__func__);
}
int himax_write_read_reg(struct i2c_client *client,uint8_t *tmp_addr,uint8_t *tmp_data,uint8_t hb,uint8_t lb)
{
int cnt = 0;
do
{
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(10);
himax_register_read(client, tmp_addr, 4, tmp_data, false);
//I("%s:Now tmp_data[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n",__func__,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
}
while((tmp_data[1] != hb && tmp_data[0] != lb) && cnt++ < 100);
if(cnt == 99)
return -1;
I("Now register 0x%08X : high byte=0x%02X,low byte=0x%02X\n",tmp_addr[3],tmp_data[1],tmp_data[0]);
return NO_ERR;
}
int himax_determin_diag_rawdata(int diag_command)
{
return diag_command%10;
}
int himax_determin_diag_storage(int diag_command)
{
return diag_command/10;
}
void himax_reload_disable(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
I("%s:entering\n",__func__);
tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x7F; tmp_addr[0] = 0x00;
tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xA5; tmp_data[0] = 0x5A;
himax_flash_write_burst(client, tmp_addr, tmp_data);
I("%s: setting OK!\n",__func__);
}
int himax_switch_mode(struct i2c_client *client,int mode)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t mode_wirte_cmd;
uint8_t mode_read_cmd;
int result = -1;
int retry = 200;
I("%s: Entering\n",__func__);
if(mode == 0) /*normal mode*/
{
mode_wirte_cmd = 0x00;
mode_read_cmd = 0x99;
}
else /*sorting mode*/
{
mode_wirte_cmd = 0xAA;
mode_read_cmd = 0xCC;
}
himax_sense_off(client);
//himax_interface_on(client);
/* */
/* clean up FW status */
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//msleep(30);
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x04;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = mode_wirte_cmd;
tmp_data[0] = mode_wirte_cmd;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//msleep(30);
himax_idle_mode(client,1);
himax_reload_disable(client);
// To stable the sorting //skip frames
if(mode)
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x70;
tmp_addr[0] = 0xF4;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x08;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
else
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x72;
tmp_addr[0] = 0x94;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x50;/*0x50 normal mode 80 frame*/
/* N Frame Sorting*/
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x70;
tmp_addr[0] = 0xF4;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x14;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
himax_sense_on(client,0x01);
I("mode_wirte_cmd(0)=0x%2.2X,mode_wirte_cmd(1)=0x%2.2X\n",tmp_data[0],tmp_data[1]);
while(retry!=0)
{
I("[%d]Read 10007F04!\n",retry);
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x04;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
msleep(100);
I("mode_read_cmd(0)=0x%2.2X,mode_read_cmd(1)=0x%2.2X\n",tmp_data[0],tmp_data[1]);
if(tmp_data[0] == mode_read_cmd && tmp_data[1] == mode_read_cmd)
{
I("Read OK!\n");
result = 0;
break;
}
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xA8;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
if(tmp_data[0] == 0x00 && tmp_data[1] == 0x00 && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
{
E("%s,: FW Stop!\n",__func__);
break;
}
retry--;
}
if(result == 0)
{
if(mode == 0)
return 1; //normal mode
else
return 2; //sorting mode
}
else
return -1; //change mode fail
}
void himax_return_event_stack(struct i2c_client *client)
{
int retry = 20;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
I("%s:entering\n",__func__);
do
{
I("%s,now %d times\n!",__func__,retry);
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_register_read(client, tmp_addr, 4, tmp_data, false);
retry--;
msleep(10);
}
while((tmp_data[1] != 0x00 && tmp_data[0] != 0x00) && retry > 0);
I("%s: End of setting!\n",__func__);
}
void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
I("diag_command = %d\n", diag_command );
himax_interface_on(client);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x02;
tmp_addr[1] = 0x04;
tmp_addr[0] = 0xB4;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = diag_command;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s: tmp_data[3]=0x%02X,tmp_data[2]=0x%02X,tmp_data[1]=0x%02X,tmp_data[0]=0x%02X!\n",
__func__,tmp_data[3],tmp_data[2],tmp_data[1],tmp_data[0]);
}
void himax_init_psl(struct i2c_client *client) //power saving level
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
//==============================================================
// SCU_Power_State_PW : 0x9000_00A0 ==> 0x0000_0000 (Reset PSL)
//==============================================================
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xA0;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
I("%s: power saving level reset OK!\n",__func__);
}
void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
{
uint8_t tmp_addr[4];
uint8_t buffer[256];
int page_prog_start = 0;
himax_sense_off(client);
himax_burst_enable(client, 1);
for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 128)
{
tmp_addr[0] = page_prog_start % 0x100;
tmp_addr[1] = (page_prog_start >> 8) % 0x100;
tmp_addr[2] = (page_prog_start >> 16) % 0x100;
tmp_addr[3] = page_prog_start / 0x1000000;
himax_register_read(client, tmp_addr,128,buffer,false);
memcpy(&flash_buffer[page_prog_start],buffer,128);
}
himax_burst_enable(client, 0);
himax_sense_on(client, 0x01);
return;
}
int himax_chip_self_test(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[128];
uint8_t self_test_info[24];
int pf_value=0x00;
uint8_t test_result_id = 0;
int i;
memset(tmp_addr, 0x00, sizeof(tmp_addr));
memset(tmp_data, 0x00, sizeof(tmp_data));
himax_interface_on(client);
himax_sense_off(client);
himax_burst_enable(client, 1);
// 0x10007f18 -> 0x00006AA6
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x18;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x6A;
tmp_data[0] = 0xA6;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*[Arima_8710][allen_yu] Set touch golden value for ATS 20180620 begin*/
//Set criteria 0x10007F1C [0,1]=aa/up,down=, [2-3]=key/up,down, [4-5]=avg/up,down
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x1C;
/*[20190822][TracyChui]Modify touch self test criteria for 0.9 glass start */
/*[20190815][TracyChui]Modify touch self test criteria start */
/*[Arima_8901][allen_yu] Modify touch golden value 20190527 begin*/
/*[Arima_8710][allen_yu] Dynamic detect touch golden value 20180929 begin*/
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
if(IC_TYPE == HX_83112A_SERIES_PWON)
{
tmp_data[3] = 0x00;
tmp_data[2] = 0x64;
tmp_data[1] = 0x08;
tmp_data[0] = 0x32;
tmp_data[7] = 0x00;
tmp_data[6] = 0x00;
tmp_data[5] = 0x00;
tmp_data[4] = 0x64;
}
else/*HX_83112B_SERIES_PWON*/
{
tmp_data[3] = 0x00;
tmp_data[2] = 0x64;
tmp_data[1] = 0x0F;
tmp_data[0] = 0x46;
tmp_data[7] = 0x00;
tmp_data[6] = 0x00;
tmp_data[5] = 0x00;
tmp_data[4] = 0x64;
}
/*[Arima_8710][allen_yu] 20180929 end*/
/*[Arima_8710][allen_yu] 20180828 end*/
/*[Arima_8901][allen_yu] 20190527 end*/
/*[20190815][TracyChui]Modify touch self test criteria end */
/*[20190822][TracyChui]Modify touch self test criteria for 0.9 glass end */
himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8);
/*[Arima_8710][allen_yu] 20180620 end*/
// 0x10007294 -> 0x0000190 //SET IIR_MAX FRAMES
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x01;
tmp_data[0] = 0x90;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//Disable IDLE Mode
himax_idle_mode(client,1);
// 0x10007f00 -> 0x0000A55A //Diable Flash Reload
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0xA5;
tmp_data[0] = 0x5A;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//start selftest // leave safe mode
himax_sense_on(client, 1);
//Hand shaking -> 0x100007f8 waiting 0xA66A
for(i = 0; i < 1000; i++)
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x18;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X, cnt=%d\n", __func__,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3],i);
msleep(10);
if(tmp_data[1] == 0xA6 && tmp_data[0] == 0x6A )
{
I("%s Data ready goto moving data\n", __func__);
break;
}
}
himax_sense_off(client);
msleep(20);
//=====================================
// Read test result ID : 0x10007f24 ==> bit[2][1][0] = [key][AA][avg] => 0xF = PASS
//=====================================
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x24;
himax_register_read(client, tmp_addr, 24, self_test_info, false);
test_result_id = self_test_info[0];
I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__
,test_result_id,self_test_info[0]);
I("raw top 1 = %d\n",self_test_info[3]*256+self_test_info[2]);
I("raw top 2 = %d\n",self_test_info[5]*256+self_test_info[4]);
I("raw top 3 = %d\n",self_test_info[7]*256+self_test_info[6]);
I("raw last 1 = %d\n",self_test_info[9]*256+self_test_info[8]);
I("raw last 2 = %d\n",self_test_info[11]*256+self_test_info[10]);
I("raw last 3 = %d\n",self_test_info[13]*256+self_test_info[12]);
I("raw key 1 = %d\n",self_test_info[15]*256+self_test_info[14]);
I("raw key 2 = %d\n",self_test_info[17]*256+self_test_info[16]);
I("raw key 3 = %d\n",self_test_info[19]*256+self_test_info[18]);
if (test_result_id==0xAA)
{
I("[Himax]: self-test pass\n");
pf_value = 0x1;
}
else
{
E("[Himax]: self-test fail\n");
/* E("[Himax]: bank_avg = %d, bank_max = %d,%d,%d, bank_min = %d,%d,%d, key = %d,%d,%d\n",
tmp_data[1],tmp_data[2],tmp_data[3],tmp_data[4],tmp_data[5],tmp_data[6],tmp_data[7],
tmp_data[8],tmp_data[9],tmp_data[10]); */
pf_value = 0x0;
}
//Enable IDLE Mode
himax_idle_mode(client,0);
// 0x10007f00 -> 0x00000000 //Enable Flash Reload //recovery
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_sense_on(client, 0);
msleep(120);
return pf_value;
}
void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable, bool suspended)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t back_data[4];
uint8_t retry_cnt = 0;
himax_sense_off(client);
//Enable:0x10007F14 = 0xA55AA55A
do
{
if(HSEN_enable)
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x14;
tmp_data[3] = 0xA5;
tmp_data[2] = 0x5A;
tmp_data[1] = 0xA5;
tmp_data[0] = 0x5A;
himax_flash_write_burst(client, tmp_addr, tmp_data);
back_data[3] = 0XA5;
back_data[2] = 0X5A;
back_data[1] = 0XA5;
back_data[0] = 0X5A;
}
else
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x14;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
back_data[3] = 0X00;
back_data[2] = 0X00;
back_data[1] = 0X00;
back_data[0] = 0x00;
}
himax_register_read(client, tmp_addr, 4, tmp_data, false);
//I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d \n", __func__, tmp_data[0],HSEN_enable,retry_cnt);
retry_cnt++;
}
while((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0] ) && retry_cnt < HIMAX_REG_RETRY_TIMES);
himax_sense_on(client,0);
}
int himax_palm_detect(uint8_t *buf)
{
return GESTURE_DETECT_FAIL;
}
void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable, bool suspended)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t back_data[4];
uint8_t retry_cnt = 0;
himax_sense_off(client);
//Enable:0x10007F10 = 0xA55AA55A
do
{
if(SMWP_enable)
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x10;
tmp_data[3] = 0xA5;
tmp_data[2] = 0x5A;
tmp_data[1] = 0xA5;
tmp_data[0] = 0x5A;
himax_flash_write_burst(client, tmp_addr, tmp_data);
back_data[3] = 0XA5;
back_data[2] = 0X5A;
back_data[1] = 0XA5;
back_data[0] = 0X5A;
}
else
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x10;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
back_data[3] = 0X00;
back_data[2] = 0X00;
back_data[1] = 0X00;
back_data[0] = 0x00;
}
himax_register_read(client, tmp_addr, 4, tmp_data, false);
//I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d \n", __func__, tmp_data[0],SMWP_enable,retry_cnt);
retry_cnt++;
}
while((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0] ) && retry_cnt < HIMAX_REG_RETRY_TIMES);
himax_sense_on(client,0);
}
void himax_usb_detect_set(struct i2c_client *client,uint8_t *cable_config)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
//Enable:0x10007F38 = 0xA55AA55A
if(cable_config[1] == 0x01)
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x38;
tmp_data[3] = 0xA5;
tmp_data[2] = 0x5A;
tmp_data[1] = 0xA5;
tmp_data[0] = 0x5A;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
else
{
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x7F;
tmp_addr[0] = 0x38;
tmp_data[3] = 0x77;
tmp_data[2] = 0x88;
tmp_data[1] = 0x77;
tmp_data[0] = 0x88;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
}
void himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
{
uint8_t tmp_data[4];
tmp_data[0] = 0x31;
if ( i2c_himax_write(client, 0x13,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
tmp_data[0] = (0x10 | auto_add_4_byte);
if ( i2c_himax_write(client, 0x0D,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
//isBusrtOn = true;
}
void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data, bool cfg_flag)
{
uint8_t tmp_data[4];
int i = 0;
int address = 0;
if(cfg_flag == false)
{
if(read_length>256)
{
E("%s: read len over 256!\n", __func__);
return;
}
if (read_length > 4)
himax_burst_enable(client, 1);
else
himax_burst_enable(client, 0);
address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0];
i = address;
tmp_data[0] = (uint8_t)i;
tmp_data[1] = (uint8_t)(i >> 8);
tmp_data[2] = (uint8_t)(i >> 16);
tmp_data[3] = (uint8_t)(i >> 24);
if ( i2c_himax_write(client, 0x00,tmp_data, 4, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
tmp_data[0] = 0x00;
if ( i2c_himax_write(client, 0x0C,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
if ( i2c_himax_read(client, 0x08,read_data, read_length, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
if (read_length > 4)
himax_burst_enable(client, 0);
}
else if(cfg_flag == true)
{
if(i2c_himax_read(client, read_addr[0], read_data,read_length,DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
}
else
{
E("%s: cfg_flag = %d, value is wrong!\n", __func__,cfg_flag);
return;
}
}
void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data)
{
uint8_t data_byte[8];
int i = 0, j = 0;
for (i = 0; i < 4; i++)
{
data_byte[i] = reg_byte[i];
}
for (j = 4; j < 8; j++)
{
data_byte[j] = write_data[j-4];
}
if ( i2c_himax_write(client, 0x00,data_byte, 8, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
}
void himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length)
{
uint8_t data_byte[256];
int i = 0, j = 0;
for (i = 0; i < 4; i++)
{
data_byte[i] = reg_byte[i];
}
for (j = 4; j < length + 4; j++)
{
data_byte[j] = write_data[j - 4];
}
if ( i2c_himax_write(client, 0x00,data_byte, length + 4, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
}
void himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data, bool cfg_flag)
{
int i =0, address = 0;
if(cfg_flag == false)
{
address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0];
for (i = address; i < address + write_length; i++)
{
if (write_length > 4)
{
himax_burst_enable(client, 1);
}
else
{
himax_burst_enable(client, 0);
}
himax_flash_write_burst_lenth(client, write_addr, write_data, write_length);
}
}
else if(cfg_flag == true)
{
if(i2c_himax_write(client, write_addr[0], write_data,write_length,DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
}
else
{
E("%s: cfg_flag = %d, value is wrong!\n", __func__,cfg_flag);
return;
}
}
bool himax_sense_off(struct i2c_client *client)
{
uint8_t cnt = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
/*[Arima_7947][allen_yu] Modify Int trigger way and upgrade himax fw to CID0404_D01_C02 20171228 begin*/
/*1225 for power on test*/
//=====================================
// FW ISR=0
//=====================================
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x5C;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0xA5;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(20);
/*1225 for power on test*/
/*[Arima_7947][allen_yu] 20171228 end*/
do
{
//===========================================
// 0x31 ==> 0x27
//===========================================
tmp_data[0] = 0x27;
if ( i2c_himax_write(client, 0x31,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
//===========================================
// 0x32 ==> 0x95
//===========================================
tmp_data[0] = 0x95;
if ( i2c_himax_write(client, 0x32,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
// ======================
// Check enter_save_mode
// ======================
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xA8;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s: Check enter_save_mode data[0]=%X \n", __func__,tmp_data[0]);
if (tmp_data[0] == 0x0C)
{
//=====================================
// Reset TCON
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x02;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1);
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Reset ADC
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x02;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x94;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1);
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
return true;
}
else
{
msleep(10);
#ifdef HX_RST_PIN_FUNC
himax_ic_reset(false,false);
#endif
}
}
while (cnt++ < 15);
return false;
}
/*[Arima_7947][allen_yu] Enter safe mode when i2c fail 20180129 begin*/
bool himax_enter_safe_mode(struct i2c_client *client)
{
uint8_t cnt = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
do
{
//===========================================
// 0x31 ==> 0x27
//===========================================
tmp_data[0] = 0x27;
if ( i2c_himax_write(client, 0x31,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
//===========================================
// 0x32 ==> 0x95
//===========================================
tmp_data[0] = 0x95;
if ( i2c_himax_write(client, 0x32,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
//===========================================
// 0x31 ==> 0x00
//===========================================
tmp_data[0] = 0x00;
if ( i2c_himax_write(client, 0x31,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
msleep(10);
//===========================================
// 0x31 ==> 0x27
//===========================================
tmp_data[0] = 0x27;
if ( i2c_himax_write(client, 0x31,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
//===========================================
// 0x32 ==> 0x95
//===========================================
tmp_data[0] = 0x95;
if ( i2c_himax_write(client, 0x32,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return false;
}
// ======================
// Check enter_save_mode
// ======================
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xA8;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s: Check enter_save_mode data[0]=%X \n", __func__,tmp_data[0]);
if (tmp_data[0] == 0x0C)
{
//=====================================
// Reset TCON
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x02;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1);
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Reset ADC
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x02;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x94;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1);
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
return true;
}
else
{
msleep(10);
#ifdef HX_RST_PIN_FUNC
himax_ic_reset(false,false);
#endif
}
}
while (cnt++ < 15);
return false;
}
/*[Arima_7947][allen_yu] 20180129 end*/
void himax_interface_on(struct i2c_client *client)
{
uint8_t tmp_data[5];
uint8_t tmp_data2[2];
int cnt = 0;
//Read a dummy register to wake up I2C.
if ( i2c_himax_read(client, 0x08, tmp_data,4,DEFAULT_RETRY_CNT) < 0) // to knock I2C
{
E("%s: i2c access fail!\n", __func__);
return;
}
do
{
//===========================================
// Enable continuous burst mode : 0x13 ==> 0x31
//===========================================
tmp_data[0] = 0x31;
if ( i2c_himax_write(client, 0x13,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
//===========================================
// AHB address auto +4 : 0x0D ==> 0x11
// Do not AHB address auto +4 : 0x0D ==> 0x10
//===========================================
tmp_data[0] = (0x10);
if ( i2c_himax_write(client, 0x0D,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
// Check cmd
i2c_himax_read(client, 0x13, tmp_data,1,DEFAULT_RETRY_CNT);
i2c_himax_read(client, 0x0D, tmp_data2,1,DEFAULT_RETRY_CNT);
if (tmp_data[0] == 0x31 && tmp_data2[0] == 0x10)
{
//isBusrtOn = true;
break;
}
msleep(1);
}
while (++cnt < 10);
if (cnt > 0)
I("%s:Polling burst mode: %d times", __func__,cnt);
}
bool wait_wip(struct i2c_client *client, int Timing)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t in_buffer[10];
//uint8_t out_buffer[20];
int retry_cnt = 0;
//=====================================
// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x10;
tmp_data[3] = 0x00;
tmp_data[2] = 0x02;
tmp_data[1] = 0x07;
tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
in_buffer[0] = 0x01;
do
{
//=====================================
// SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x42;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x03;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// SPI Command : 0x8000_0024 ==> 0x0000_0005
// read 0x8000_002C for 0x01, means wait success
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x05;
himax_flash_write_burst(client, tmp_addr, tmp_data);
in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF;
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x2C;
himax_register_read(client, tmp_addr, 4, in_buffer, false);
if ((in_buffer[0] & 0x01) == 0x00)
return true;
retry_cnt++;
if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00)
I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__,
retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]);
if (retry_cnt > 100)
{
E("%s: Wait wip error!\n", __func__);
return false;
}
msleep(Timing);
}
while ((in_buffer[0] & 0x01) == 0x01);
return true;
}
void himax_sense_on(struct i2c_client *client, uint8_t FlashMode)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
int retry = 0;
I("Enter %s \n", __func__);
himax_interface_on(client);
if(!FlashMode)
{
#ifdef HX_RST_PIN_FUNC
himax_ic_reset(false,false);
#else
//===AHBI2C_SystemReset==========
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x18;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x55;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
#endif
}
else
{
do
{
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x98;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x53;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
tmp_addr[0] = 0xE4;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s:Read status from IC = %X,%X\n", __func__, tmp_data[0],tmp_data[1]);
}
while((tmp_data[1] != 0x01 || tmp_data[0] != 0x00) && retry++ < 5);
if(retry >= 5)
{
E("%s: Fail:\n", __func__);
#ifdef HX_RST_PIN_FUNC
himax_ic_reset(false,false);
#else
//===AHBI2C_SystemReset==========
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x18;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x55;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
#endif
}
else
{
I("%s:OK and Read status from IC = %X,%X\n", __func__, tmp_data[0],tmp_data[1]);
/* reset code*/
tmp_data[0] = 0x00;
if ( i2c_himax_write(client, 0x31,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
}
if ( i2c_himax_write(client, 0x32,tmp_data, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
}
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x98;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
}
}
}
void himax_chip_erase(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
himax_interface_on(client);
/* init psl */
himax_init_psl(client);
//=====================================
// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x10;
tmp_data[3] = 0x00;
tmp_data[2] = 0x02;
tmp_data[1] = 0x07;
tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Chip Erase
// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
// 2. 0x8000_0024 ==> 0x0000_0006
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x47;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Chip Erase
// Erase Command : 0x8000_0024 ==> 0x0000_00C7
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0xC7;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(2000);
if (!wait_wip(client, 100))
E("%s:83112_Chip_Erase Fail\n", __func__);
}
bool himax_block_erase(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
himax_burst_enable(client, 0);
//=====================================
// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x10;
tmp_data[3] = 0x00;
tmp_data[2] = 0x02;
tmp_data[1] = 0x07;
tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Chip Erase
// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
// 2. 0x8000_0024 ==> 0x0000_0006
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x47;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=====================================
// Block Erase
// Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
// 0x8000_0020 ==> 0x6700_0000 //control
// 0x8000_0024 ==> 0x0000_0052 //BE
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x28;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x67;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x52;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1000);
if (!wait_wip(client, 100))
{
E("%s:83112_Erase Fail\n", __func__);
return false;
}
else
{
return true;
}
}
bool himax_sector_erase(struct i2c_client *client, int start_addr)
{
return true;
}
void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
{
}
bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size)
{
return true;
}
void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size)
{
int page_prog_start = 0;
int program_length = 48;
int i = 0, j = 0, k = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t buring_data[256]; // Read for flash data, 128K
// 4 bytes for 0x80002C padding
himax_interface_on(client);
//=====================================
// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x10;
tmp_data[3] = 0x00;
tmp_data[2] = 0x02;
tmp_data[1] = 0x07;
tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
{
//msleep(5);
//=====================================
// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
// 2. 0x8000_0024 ==> 0x0000_0006
//=====================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x47;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=================================
// SPI Transfer Control
// Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
// Set read start address : 0x8000_0028 ==> 0x0000_0000
//=================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
tmp_data[3] = 0x61;
tmp_data[2] = 0x0F;
tmp_data[1] = 0xF0;
tmp_data[0] = 0x00;
// data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000
// Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x28;
//tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000
if (page_prog_start < 0x100)
{
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
}
else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
{
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
{
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=================================
// Send 16 bytes data : 0x8000_002C ==> 16 bytes data
//=================================
buring_data[0] = 0x2C;
buring_data[1] = 0x00;
buring_data[2] = 0x00;
buring_data[3] = 0x80;
for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++) /// <------ bin file
{
buring_data[j + 4] = FW_content[i];
}
if ( i2c_himax_write(client, 0x00,buring_data, 20, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
//=================================
// Write command : 0x8000_0024 ==> 0x0000_0002
//=================================
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x24;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x02;
himax_flash_write_burst(client, tmp_addr, tmp_data);
//=================================
// Send 240 bytes data : 0x8000_002C ==> 240 bytes data
//=================================
for (j = 0; j < 5; j++)
{
for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) /// <------ bin file
{
buring_data[k+4] = FW_content[i];//(byte)i;
}
if ( i2c_himax_write(client, 0x00,buring_data, program_length+4, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return;
}
}
if (!wait_wip(client, 1))
E("%s:83112_Flash_Programming Fail\n", __func__);
}
}
bool himax_check_chip_version(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t ret_data = false;
int i = 0;
for (i = 0; i < 5; i++)
{
// Product ID
// Touch
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xD0;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3],tmp_data[2],tmp_data[1]);
if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && (tmp_data[1] == 0x2a))
{
IC_TYPE = HX_83112A_SERIES_PWON;
ret_data = true;
break;
}
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
else if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && (tmp_data[1] == 0x2b))
{
IC_TYPE = HX_83112B_SERIES_PWON;
ret_data = true;
break;
}
/*[Arima_8710][allen_yu] 20180828 end*/
else
{
ret_data = false;
E("%s:Read driver ID register Fail:\n", __func__);
}
}
return ret_data;
}
bool Calculate_CRC_with_AP(unsigned char *FW_content, int CRC_from_FW, int mode)
{
return true;
}
uint32_t himax_hw_check_CRC(struct i2c_client *client, uint8_t *start_addr, int reload_length)
{
uint32_t result = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
int cnt = 0;
int length = reload_length / 4;
//CRC4 // 0x8005_0020 <= from, 0x8005_0028 <= 0x0099_length
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x05;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x20;
//tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xFB; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, start_addr);
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x05;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x28;
tmp_data[3] = 0x00;
tmp_data[2] = 0x99;
tmp_data[1] = (length >> 8);
tmp_data[0] = length;
himax_flash_write_burst(client, tmp_addr, tmp_data);
cnt = 0;
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x05;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
do
{
himax_register_read(client, tmp_addr, 4, tmp_data, false);
if ((tmp_data[0] & 0x01) != 0x01)
{
tmp_addr[3] = 0x80;
tmp_addr[2] = 0x05;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x18;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s: tmp_data[3]=%X, tmp_data[2]=%X, tmp_data[1]=%X, tmp_data[0]=%X \n", __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]);
result = ((tmp_data[3] << 24) + (tmp_data[2] << 16) + (tmp_data[1] << 8) + tmp_data[0]);
break;
}
}
while (cnt++ < 100);
return result;
}
void himax_flash_page_write(struct i2c_client *client, uint8_t *write_addr, uint8_t *write_data)
{
}
void himax_set_reload_cmd(uint8_t *write_data, int idx, uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat)
{
int index = idx * 12;
int i;
for (i = 3; i >= 0; i--)
{
write_data[index + i] = (cmd_from >> (8 * i));
write_data[index + 4 + i] = (cmd_to >> (8 * i));
write_data[index + 8 + i] = (cmd_beat >> (8 * i));
}
}
bool himax_program_reload(struct i2c_client *client)
{
return true;
}
int fts_ctpm_fw_upgrade_with_sys_fs_32k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
{
/* Not use */
return 0;
}
int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
{
/* Not use */
return 0;
}
int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) //Alice - Un
{
//int CRC_from_FW = 0;
int burnFW_success = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
if (len != FW_SIZE_64k) //64k
{
E("%s: The file size is not 64K bytes\n", __func__);
return false;
}
#ifdef HX_RST_PIN_FUNC
himax_ic_reset(false,false);
#else
//===AHBI2C_SystemReset==========
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x18;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x55;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
#endif
/*[Arima_7947][allen_yu] Enter safe mode when i2c fail 20180129 begin*/
himax_enter_safe_mode(client);
/*[Arima_7947][allen_yu] 20180129 end*/
himax_chip_erase(client);
himax_flash_programming(client, fw, FW_SIZE_64k);
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
if(himax_hw_check_CRC(client,tmp_data, FW_SIZE_64k) == 0)
{
burnFW_success = 1;
}
else
{
burnFW_success = 0;
}
/*RawOut select initial*/
tmp_addr[3] = 0x80;tmp_addr[2] = 0x02;tmp_addr[1] = 0x04;tmp_addr[0] = 0xB4;
tmp_data[3] = 0x00;tmp_data[2] = 0x00;tmp_data[1] = 0x00;tmp_data[0] = 0x00;
himax_register_write(client,tmp_addr, 4, tmp_data, false);
/*DSRAM func initial*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x07;tmp_addr[0] = 0xFC;
tmp_data[3] = 0x00;tmp_data[2] = 0x00;tmp_data[1] = 0x00;tmp_data[0] = 0x00;
himax_register_write(client,tmp_addr, 4, tmp_data, false);
#ifdef HX_RST_PIN_FUNC
/*[Arima_7947][allen_yu] Upgrade himax fw to CID0404_D01_C06 and modify the node to access fw_ver 20180118 begin*/
himax_ic_reset(true,false);
/*[Arima_7947][allen_yu] 20180118 end*/
#else
//===AHBI2C_SystemReset==========
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x18;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x55;
himax_register_write(client, tmp_addr, 4, tmp_data, false);
#endif
/*[Arima_7947][allen_yu] Upgrade himax fw to CID0404_D01_C06 and modify the node to access fw_ver 20180118 begin*/
msleep(800);
himax_read_FW_ver(private_ts->client);
/*[Arima_7947][allen_yu] 20180118 end*/
return burnFW_success;
}
int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
{
/* Not use */
return 0;
}
int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
{
/* Not use */
return 0;
}
void himax_touch_information(struct i2c_client *client)
{
#ifndef HX_FIX_TOUCH_INFO
uint8_t cmd[4];
char data[12] = {0};
I("%s:IC_TYPE =%d\n", __func__,IC_TYPE);
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
//if(IC_TYPE == HX_83112A_SERIES_PWON)
if((IC_TYPE == HX_83112A_SERIES_PWON)||(IC_TYPE == HX_83112B_SERIES_PWON))
/*[Arima_8710][allen_yu] 20180828 end*/
{
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0xF4;
himax_register_read(client, cmd, 8, data, false);
ic_data->HX_RX_NUM = data[2];
ic_data->HX_TX_NUM = data[3];
ic_data->HX_MAX_PT = data[4];
//I("%s : HX_RX_NUM=%d,ic_data->HX_TX_NUM=%d,ic_data->HX_MAX_PT=%d\n",__func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0xFA;
himax_register_read(client, cmd, 4, data, false);
//I("%s : c_data->HX_XY_REVERSE=0x%2.2X\n",__func__,data[1]);
if((data[1] & 0x04) == 0x04)
{
ic_data->HX_XY_REVERSE = true;
}
else
{
ic_data->HX_XY_REVERSE = false;
}
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0xFC;
himax_register_read(client, cmd, 4, data, false);
ic_data->HX_Y_RES = data[0]*256;
ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[1];
ic_data->HX_X_RES = data[2]*256 + data[3];
//I("%s : ic_data->HX_Y_RES=%d,ic_data->HX_X_RES=%d \n",__func__,ic_data->HX_Y_RES,ic_data->HX_X_RES);
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0x89;
himax_register_read(client, cmd, 4, data, false);
//I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data[2]=0x%2.2X,data[3]=0x%2.2X\n",__func__,data[0],data[1],data[2],data[3]);
//I("data[0] & 0x01 = %d\n",(data[0] & 0x01));
if((data[0] & 0x01) == 1)
{
ic_data->HX_INT_IS_EDGE = true;
}
else
{
ic_data->HX_INT_IS_EDGE = false;
}
if (ic_data->HX_RX_NUM > 40)
ic_data->HX_RX_NUM = 32;
if (ic_data->HX_TX_NUM > 20)
ic_data->HX_TX_NUM = 18;
if (ic_data->HX_MAX_PT > 10)
ic_data->HX_MAX_PT = 10;
if (ic_data->HX_Y_RES > 2000)
ic_data->HX_Y_RES = 1280;
if (ic_data->HX_X_RES > 2000)
ic_data->HX_X_RES = 720;
/*Read number of MKey R100070E8H*/
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0xE8;
himax_register_read(client, cmd, 4,data, false);
//I("%s: data[0] = 0x%02X,data[1] = 0x%02X,data[2] = 0x%02X,data[3] = 0x%02X\n", __func__,data[0],data[1],data[2],data[3]);
ic_data->HX_BT_NUM = data[0] & 0x03;
}
else
{
ic_data->HX_RX_NUM = 0;
ic_data->HX_TX_NUM = 0;
ic_data->HX_BT_NUM = 0;
ic_data->HX_X_RES = 0;
ic_data->HX_Y_RES = 0;
ic_data->HX_MAX_PT = 0;
ic_data->HX_XY_REVERSE = false;
ic_data->HX_INT_IS_EDGE = false;
}
#else
/*[Arima_8710][allen_yu] Dynamic detect touch golden value 20180929 begin*/
if(IC_TYPE == HX_83112A_SERIES_PWON) {
ic_data->HX_RX_NUM = FIX_HX_RX_NUM;
ic_data->HX_TX_NUM = FIX_HX_TX_NUM;
ic_data->HX_BT_NUM = FIX_HX_BT_NUM;
ic_data->HX_X_RES = FIX_HX_X_RES;
ic_data->HX_Y_RES = FIX_HX_Y_RES;
ic_data->HX_MAX_PT = FIX_HX_MAX_PT;
ic_data->HX_XY_REVERSE = FIX_HX_XY_REVERSE;
ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE;
}
else {
ic_data->HX_RX_NUM = SEC_FIX_HX_RX_NUM;
ic_data->HX_TX_NUM = SEC_FIX_HX_TX_NUM;
ic_data->HX_BT_NUM = SEC_FIX_HX_BT_NUM;
ic_data->HX_X_RES = SEC_FIX_HX_X_RES;
ic_data->HX_Y_RES = SEC_FIX_HX_Y_RES;
ic_data->HX_MAX_PT = SEC_FIX_HX_MAX_PT;
ic_data->HX_XY_REVERSE = SEC_FIX_HX_XY_REVERSE;
ic_data->HX_INT_IS_EDGE = SEC_FIX_HX_INT_IS_EDGE;
}
/*[Arima_8710][allen_yu] 20180929 end*/
#endif
I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);
I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES);
I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE);
}
int himax_read_i2c_status(struct i2c_client *client)
{
return i2c_error_count; //
}
int himax_read_ic_trigger_type(struct i2c_client *client)
{
uint8_t cmd[4];
char data[12] = {0};
int trigger_type = false;
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0x89;
himax_register_read(client, cmd, 4, data, false);
if((data[0] & 0x01) == 1)
{
trigger_type = true;
}
else
{
trigger_type = false;
}
return trigger_type;
}
void himax_read_FW_ver(struct i2c_client *client)
{
uint8_t cmd[4];
uint8_t data[64];
/*[Arima_7947][allen_yu] Upgrade himax fw to CID0404_D01_C06 and modify the node to access fw_ver 20180118 begin*/
uint8_t cmd_2[4];
uint8_t data_2[64];
/*[Arima_7947][allen_yu] 20180118 end*/
/*[Arima_7947][allen_yu] Modify Int trigger way and upgrade himax fw to CID0404_D01_C02 20171228 begin*/
int retry = 20;
/*[Arima_7947][allen_yu] 20171228 end*/
int reload_status = 0;
while(reload_status == 0)
{
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x7f;
cmd[0] = 0x00;
himax_register_read(client, cmd, 4, data, false);
/*[Arima_7947][allen_yu] Upgrade himax fw to CID0404_D01_C06 and modify the node to access fw_ver 20180118 begin*/
cmd_2[3] = 0x10;
cmd_2[2] = 0x00;
cmd_2[1] = 0x72;
cmd_2[0] = 0xc0;
himax_register_read(client, cmd_2, 4, data_2, false);
if((data[3]==0x00 && data[2]==0x00 && data[1]==0x3A && data[0]==0xA3 )
||(data_2[3]==0x00 && data_2[2]==0x00 && data_2[1]==0x72 && data_2[0]==0xC0 ))
/*[Arima_7947][allen_yu] 20180118 end*/
{
I("reload OK! \n");
reload_status = 1;
break;
}
else if(retry == 0)
{
E("reload 20 times! fail \n");
ic_data->vendor_panel_ver = 0;
ic_data->vendor_fw_ver = 0;
ic_data->vendor_config_ver = 0;
ic_data->vendor_touch_cfg_ver = 0;
ic_data->vendor_display_cfg_ver = 0;
ic_data->vendor_cid_maj_ver = 0;
ic_data->vendor_cid_min_ver = 0;
return;
}
else
{
/*[Arima_7947][allen_yu] Upgrade himax fw to CID0404_D01_C06 and modify the node to access fw_ver 20180118 begin*/
I("%s: 0x10007f00, data[0]=%x,data[1]=%x,data[2]=%x,data[3]=%x \n", __func__, data[0],data[1],data[2],data[3]);
I("%s: 0x100072c0, data[0]=%x,data[1]=%x,data[2]=%x,data[3]=%x \n", __func__, data_2[0],data_2[1],data_2[2],data_2[3]);
cmd[3] = 0x90; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xA8;
himax_register_read(client, cmd, 4, data, false);
I("%s: 0x900000A8, data[0]=%x,data[1]=%x,data[2]=%x,data[3]=%x \n", __func__, data[0],data[1],data[2],data[3]);
cmd[3] = 0x90; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE4;
himax_register_read(client, cmd, 4, data, false);
I("%s: 0x900000E4, data[0]=%x,data[1]=%x,data[2]=%x,data[3]=%x \n", __func__, data[0],data[1],data[2],data[3]);
cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x7F; cmd[0] = 0x40;
himax_register_read(client, cmd, 4, data, false);
I("%s: 0x10007F40, data[0]=%x,data[1]=%x,data[2]=%x,data[3]=%x \n", __func__, data[0],data[1],data[2],data[3]);
/*[Arima_7947][allen_yu] 20180118 end*/
retry --;
msleep(10);
I("reload fail ,delay 10ms retry=%d\n",retry);
}
}
I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data[2]=0x%2.2X,data[3]=0x%2.2X\n",__func__,data[0],data[1],data[2],data[3]);
I("reload_status=%d\n",reload_status);
himax_sense_off(client);
//=====================================
// Read FW version : 0x1000_7004 but 05,06 are the real addr for FW Version
//=====================================
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0x04;
himax_register_read(client, cmd, 4, data, false);
ic_data->vendor_panel_ver = data[0];
ic_data->vendor_fw_ver = data[1] << 8 | data[2];
/*[Arima_8710][allen_yu] Modify the touch fw dynamic auto upgtade rule 20180830 begin*/
ic_data->vendor_hx_ic_id = data[3];
/*[Arima_8710][allen_yu] 20180830 end*/
I("PANEL_VER : %X \n",ic_data->vendor_panel_ver);
I("FW_VER : %X \n",ic_data->vendor_fw_ver);
/*[Arima_8710][allen_yu] Modify the touch fw dynamic auto upgtade rule 20180830 begin*/
I("IC_ID : %X \n",ic_data->vendor_hx_ic_id);
/*[Arima_8710][allen_yu] 20180830 end*/
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0x84;
himax_register_read(client, cmd, 4, data, false);
ic_data->vendor_config_ver = data[2] << 8 | data[3];
//I("CFG_VER : %X \n",ic_data->vendor_config_ver);
ic_data->vendor_touch_cfg_ver = data[2];
I("TOUCH_VER : %X \n",ic_data->vendor_touch_cfg_ver);
ic_data->vendor_display_cfg_ver = data[3];
I("DISPLAY_VER : %X \n",ic_data->vendor_display_cfg_ver);
cmd[3] = 0x10;
cmd[2] = 0x00;
cmd[1] = 0x70;
cmd[0] = 0x00;
himax_register_read(client, cmd, 4, data, false);
ic_data->vendor_cid_maj_ver = data[2] ;
ic_data->vendor_cid_min_ver = data[3];
I("CID_VER : %X \n",(ic_data->vendor_cid_maj_ver << 8 | ic_data->vendor_cid_min_ver));
return;
}
bool himax_ic_package_check(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t ret_data = 0x00;
int i = 0;
/*[Arima_7947][allen_yu] Enter safe mode when i2c fail 20180129 begin*/
himax_enter_safe_mode(client);
/*[Arima_7947][allen_yu] 20180129 end*/
for (i = 0; i < 5; i++)
{
// Product ID
// Touch
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0xD0;
himax_register_read(client, tmp_addr, 4, tmp_data, false);
I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3],tmp_data[2],tmp_data[1]);
if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && ((tmp_data[1] == 0x2a)||(tmp_data[1] == 0x2b)))
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
{
/*[Arima_8710][allen_yu] Modify the touch fw dynamic auto upgtade rule 20180830 begin*/
/*[Arima_8710][allen_yu] 20180828 end*/
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
//Himax: Set FW and CFG Flash Address
FW_VER_MAJ_FLASH_ADDR = 49157; //0x00C005
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 49158; //0x00C006
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 49408; //0x00C100
CFG_VER_MAJ_FLASH_LENG = 1;
CFG_VER_MIN_FLASH_ADDR = 49409; //0x00C101
CFG_VER_MIN_FLASH_LENG = 1;
CID_VER_MAJ_FLASH_ADDR = 49154; //0x00C002
CID_VER_MAJ_FLASH_LENG = 1;
CID_VER_MIN_FLASH_ADDR = 49155; //0x00C003
CID_VER_MIN_FLASH_LENG = 1;
//PANEL_VERSION_ADDR = 49156; //0x00C004
//PANEL_VERSION_LENG = 1;
/*[Arima_8710][allen_yu] 20180830 end*/
if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && (tmp_data[1] == 0x2a))
{
IC_TYPE = HX_83112A_SERIES_PWON;
#ifdef HX_AUTO_UPDATE_FW
g_i_FW_VER = i_CTPM_FW_HX83112A[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW_HX83112A[FW_VER_MIN_FLASH_ADDR];
g_i_CFG_VER = i_CTPM_FW_HX83112A[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW_HX83112A[CFG_VER_MIN_FLASH_ADDR];
g_i_CID_MAJ = i_CTPM_FW_HX83112A[CID_VER_MAJ_FLASH_ADDR];
g_i_CID_MIN = i_CTPM_FW_HX83112A[CID_VER_MIN_FLASH_ADDR];
#endif
}
else
{
IC_TYPE = HX_83112B_SERIES_PWON;
#ifdef HX_AUTO_UPDATE_FW
printk("%s: (%d)No need check 2nd ic package\n", __func__, __LINE__);
g_i_FW_VER = i_CTPM_FW_HX83112B[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW_HX83112B[FW_VER_MIN_FLASH_ADDR];
g_i_CFG_VER = i_CTPM_FW_HX83112B[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW_HX83112B[CFG_VER_MIN_FLASH_ADDR];
g_i_CID_MAJ = i_CTPM_FW_HX83112B[CID_VER_MAJ_FLASH_ADDR];
g_i_CID_MIN = i_CTPM_FW_HX83112B[CID_VER_MIN_FLASH_ADDR];
#endif
}
/*[Arima_8710][allen_yu] Modify the touch fw dynamic auto upgtade rule 20180830 begin*/
#if 0
/*[Arima_8710][allen_yu] 20180828 end*/
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
//Himax: Set FW and CFG Flash Address
FW_VER_MAJ_FLASH_ADDR = 49157; //0x00C005
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 49158; //0x00C006
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 49408; //0x00C100
CFG_VER_MAJ_FLASH_LENG = 1;
CFG_VER_MIN_FLASH_ADDR = 49409; //0x00C101
CFG_VER_MIN_FLASH_LENG = 1;
CID_VER_MAJ_FLASH_ADDR = 49154; //0x00C002
CID_VER_MAJ_FLASH_LENG = 1;
CID_VER_MIN_FLASH_ADDR = 49155; //0x00C003
CID_VER_MIN_FLASH_LENG = 1;
//PANEL_VERSION_ADDR = 49156; //0x00C004
//PANEL_VERSION_LENG = 1;
#endif
/*[Arima_8710][allen_yu] 20180830 end*/
/*[Arima_8710][allen_yu] Dynamic detect Yandex LCM/TP 2nd source and add PCBA node 20180828 begin*/
#if 0
g_i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR];
g_i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR];
g_i_CID_MAJ = i_CTPM_FW[CID_VER_MAJ_FLASH_ADDR];
g_i_CID_MIN = i_CTPM_FW[CID_VER_MIN_FLASH_ADDR];
#endif
/*[Arima_8710][allen_yu] 20180828 end*/
I("Himax IC package 83112_in\n");
ret_data = true;
/*[Arima_7947][allen_yu] Enter save mode when i2c fail 20180129 begin*/
himax_sense_on(client, 0);
/*[Arima_7947][allen_yu] 20180129 end*/
break;
}
else
{
ret_data = false;
E("%s:Read driver ID register Fail:\n", __func__);
}
}
return ret_data;
}
void himax_power_on_init(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
I("%s:\n", __func__);
himax_touch_information(client);
/*RawOut select initial*/
tmp_addr[3] = 0x80;tmp_addr[2] = 0x02;tmp_addr[1] = 0x04;tmp_addr[0] = 0xB4;
tmp_data[3] = 0x00;tmp_data[2] = 0x00;tmp_data[1] = 0x00;tmp_data[0] = 0x00;
himax_register_write(client,tmp_addr, 4, tmp_data, false);
/*DSRAM func initial*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x07;tmp_addr[0] = 0xFC;
tmp_data[3] = 0x00;tmp_data[2] = 0x00;tmp_data[1] = 0x00;tmp_data[0] = 0x00;
himax_register_write(client,tmp_addr, 4, tmp_data, false);
himax_sense_on(client, 0x00);
}
bool himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length) //Alice - Un
{
uint8_t cmd[4];
// AHB_I2C Burst Read Off
cmd[0] = 0x00;
if ( i2c_himax_write(client, 0x11,cmd, 1, DEFAULT_RETRY_CNT) < 0)
{
E("%s: i2c access fail!\n", __func__);
return 0;
}
i2c_himax_read(client, 0x30, buf, length,DEFAULT_RETRY_CNT);
// AHB_I2C Burst Read On
cmd[0] = 0x01;
if ( i2c_himax_write(client, 0x11,cmd, 1, 3) < 0)
{
E("%s: i2c access fail!\n", __func__);
return 0;
}
return 1;
}
void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data)
{
int i = 0;
//int cnt = 0;
unsigned char tmp_addr[4];
unsigned char tmp_data[4];
uint8_t max_i2c_size = 128;
uint8_t x_num = ic_data->HX_RX_NUM;
uint8_t y_num = ic_data->HX_TX_NUM;
int m_key_num = 0;
int total_size = (x_num * y_num + x_num + y_num) * 2 + 4;
int total_size_temp;
int mutual_data_size = x_num * y_num * 2;
int total_read_times = 0;
int address = 0;
uint8_t *temp_info_data; //max mkey size = 8
uint16_t check_sum_cal = 0;
int fw_run_flag = -1;
//uint16_t temp_check_sum_cal = 0;
temp_info_data = kzalloc(sizeof(uint8_t)*(total_size + 8),GFP_KERNEL);
/*1. Read number of MKey R100070E8H to determin data size*/
m_key_num = ic_data->HX_BT_NUM;
//I("%s,m_key_num=%d\n",__func__,m_key_num);
total_size += m_key_num*2;
/* 2. Start DSRAM Rawdata and Wait Data Ready */
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x5A;
tmp_data[0] = 0xA5;
fw_run_flag = himax_write_read_reg(client,tmp_addr,tmp_data,0xA5,0x5A);
if(fw_run_flag < 0)
{
I("%s Data NOT ready => bypass \n", __func__);
kfree(temp_info_data);
return;
}
/* 3. Read RawData */
total_size_temp = total_size;
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
if (total_size % max_i2c_size == 0)
{
total_read_times = total_size / max_i2c_size;
}
else
{
total_read_times = total_size / max_i2c_size + 1;
}
for (i = 0; i < (total_read_times); i++)
{
if ( total_size_temp >= max_i2c_size)
{
himax_register_read(client, tmp_addr, max_i2c_size, &temp_info_data[i*max_i2c_size], false);
total_size_temp = total_size_temp - max_i2c_size;
}
else
{
//I("last total_size_temp=%d\n",total_size_temp);
himax_register_read(client, tmp_addr, total_size_temp % max_i2c_size, &temp_info_data[i*max_i2c_size], false);
}
address = ((i+1)*max_i2c_size);
tmp_addr[1] = (uint8_t)((address>>8)&0x00FF);
tmp_addr[0] = (uint8_t)((address)&0x00FF);
}
/* 4. FW stop outputing */
//I("DSRAM_Flag=%d\n",DSRAM_Flag);
if(DSRAM_Flag == false)
{
//I("Return to Event Stack!\n");
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
else
{
//I("Continue to SRAM!\n");
tmp_addr[3] = 0x10;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = 0x00;
tmp_data[3] = 0x11;
tmp_data[2] = 0x22;
tmp_data[1] = 0x33;
tmp_data[0] = 0x44;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
/* 5. Data Checksum Check */
for (i = 2; i < total_size; i=i+2)/* 2:PASSWORD NOT included */
{
check_sum_cal += (temp_info_data[i+1]*256 + temp_info_data[i]);
}
if (check_sum_cal % 0x10000 != 0)
{
I("%s check_sum_cal fail=%2X \n", __func__, check_sum_cal);
kfree(temp_info_data);
return;
}
else
{
memcpy(info_data, &temp_info_data[4], mutual_data_size * sizeof(uint8_t));
//I("%s checksum PASS \n", __func__);
}
kfree(temp_info_data);
}
bool himax_calculateChecksum(struct i2c_client *client, bool change_iref)
{
uint8_t CRC_result = 0;
uint8_t tmp_data[4];
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = 0x00;
CRC_result = himax_hw_check_CRC(client,tmp_data, FW_SIZE_64k);
msleep(50);
return !CRC_result;
}
//ts_work
int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max)
{
int RawDataLen;
if (raw_cnt_rmd != 0x00)
{
RawDataLen = 128 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1;
}
else
{
RawDataLen = 128 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1;
}
return RawDataLen;
}
bool diag_check_sum( struct himax_report_data *hx_touch_data ) //return checksum value
{
uint16_t check_sum_cal = 0;
int i;
//Check 128th byte CRC
for (i = 0, check_sum_cal = 0; i < (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); i=i+2)
{
check_sum_cal += (hx_touch_data->hx_rawdata_buf[i+1]*256 + hx_touch_data->hx_rawdata_buf[i]);
}
if (check_sum_cal % 0x10000 != 0)
{
I("%s fail=%2X \n", __func__, check_sum_cal);
return 0;
//goto bypass_checksum_failed_packet;
}
return 1;
}
void diag_parse_raw_data(struct himax_report_data *hx_touch_data,int mul_num, int self_num,uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data)
{
int RawDataLen_word;
int index = 0;
int temp1, temp2,i;
if (hx_touch_data->hx_rawdata_buf[0] == 0x3A
&& hx_touch_data->hx_rawdata_buf[1] == 0xA3
&& hx_touch_data->hx_rawdata_buf[2] > 0
&& hx_touch_data->hx_rawdata_buf[3] == diag_cmd )
{
RawDataLen_word = hx_touch_data->rawdata_size/2;
index = (hx_touch_data->hx_rawdata_buf[2] - 1) * RawDataLen_word;
//I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
//I("RawDataLen=%d , RawDataLen_word=%d , hx_touch_info_size=%d\n", RawDataLen, RawDataLen_word, hx_touch_info_size);
for (i = 0; i < RawDataLen_word; i++)
{
temp1 = index + i;
if (temp1 < mul_num)
{
//mutual
mutual_data[index + i] = hx_touch_data->hx_rawdata_buf[i*2 + 4 + 1]*256 + hx_touch_data->hx_rawdata_buf[i*2 + 4]; //4: RawData Header, 1:HSB
}
else
{
//self
temp1 = i + index;
temp2 = self_num + mul_num;
if (temp1 >= temp2)
{
break;
}
self_data[i+index-mul_num] = hx_touch_data->hx_rawdata_buf[i*2 + 4]; //4: RawData Header
self_data[i+index-mul_num+1] = hx_touch_data->hx_rawdata_buf[i*2 + 4 + 1];
}
}
}
}
uint8_t himax_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data)
{
int cnt = 0;
uint8_t req_size = cmd_set[0];
uint8_t cmd_addr[4] = {0xFC, 0x00, 0x00, 0x90}; //0x900000FC -> cmd and hand shaking
uint8_t tmp_addr[4] = {0x80, 0x7F, 0x00, 0x10}; //0x10007F80 -> data space
cmd_set[3] = 0xAA;
himax_register_write(private_ts->client, cmd_addr, 4, cmd_set, 0);
I("%s: cmd_set[0] = 0x%02X,cmd_set[1] = 0x%02X,cmd_set[2] = 0x%02X,cmd_set[3] = 0x%02X\n", __func__,cmd_set[0],cmd_set[1],cmd_set[2],cmd_set[3]);
for (cnt = 0; cnt < 100; cnt++) //doing hand shaking 0xAA -> 0xBB
{
himax_register_read(private_ts->client, cmd_addr, 4, tmp_data, false);
//I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X, cnt=%d\n", __func__,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3],cnt);
msleep(10);
if(tmp_data[3] == 0xBB)
{
I("%s Data ready goto moving data\n", __func__);
break;
}
else if(cnt >= 99)
{
I("%s Data not ready in FW \n", __func__);
return FW_NOT_READY;
}
}
himax_register_read(private_ts->client, tmp_addr, req_size, tmp_data, false);
return NO_ERR;
}
int himax_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr)
{
uint8_t req_size = 0;
uint8_t status_addr[4] = {0x44, 0x7F, 0x00, 0x10}; //0x10007F44
uint8_t cmd_addr[4] = {0xF8, 0x00, 0x00, 0x90}; //0x900000F8
if(state_addr[0]==0x01)
{
state_addr[1]= 0x04;
state_addr[2]= status_addr[0];state_addr[3]= status_addr[1];state_addr[4]= status_addr[2];state_addr[5]= status_addr[3];
req_size = 0x04;
himax_sense_off(private_ts->client);
himax_register_read(private_ts->client, status_addr, req_size, tmp_addr, false);
himax_sense_on(private_ts->client,1);
}
else if(state_addr[0]==0x02)
{
state_addr[1]= 0x30;
state_addr[2]= cmd_addr[0];state_addr[3]= cmd_addr[1];state_addr[4]= cmd_addr[2];state_addr[5]= cmd_addr[3];
req_size = 0x30;
himax_register_read(private_ts->client, cmd_addr, req_size, tmp_addr, false);
}
return NO_ERR;
}
#if defined(HX_SMART_WAKEUP)||defined(HX_HIGH_SENSE)||defined(HX_USB_DETECT_GLOBAL)
void himax_resend_cmd_func(bool suspended)
{
struct himax_ts_data *ts;
ts = private_ts;
#ifdef HX_SMART_WAKEUP
himax_set_SMWP_enable(ts->client,ts->SMWP_enable,suspended);
#endif
#ifdef HX_HIGH_SENSE
himax_set_HSEN_enable(ts->client,ts->HSEN_enable,suspended);
#endif
#ifdef HX_USB_DETECT_GLOBAL
himax_cable_detect_func(true);
#endif
}
#endif
void himax_resume_ic_action(struct i2c_client *client)
{
return;
}
void himax_suspend_ic_action(struct i2c_client *client)
{
return;
}
#ifdef HX_ZERO_FLASH
int G_POWERONOF = 1;
void himax_sys_reset(void)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
// 0x10007f00 -> 0x0000A55A //Diable Flash Reload
tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x7F; tmp_addr[0] = 0x00;
tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x9A; tmp_data[0] = 0xA9;
himax_flash_write_burst(private_ts->client,tmp_addr, tmp_data);
msleep(100);
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18;
tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x55;
himax_register_write(private_ts->client,tmp_addr, 4, tmp_data, false);
}
void himax_clean_sram_0f(uint8_t *addr,int write_len,int type)
{
int total_read_times = 0;
int max_bus_size = 128;
int total_size_temp = 0;
int total_size = 0;
int address = 0;
int i = 0;
uint8_t fix_data = 0x00;
uint8_t tmp_addr[4];
uint8_t tmp_data[128]={0};
I("%s,Entering \n",__func__);
total_size = write_len;
total_size_temp = write_len;
I("[log]enable start!\n");
himax_burst_enable(private_ts->client,1);
I("[log]enable end!\n");
tmp_addr[3] = addr[3]; tmp_addr[2] = addr[2]; tmp_addr[1] = addr[1]; tmp_addr[0] = addr[0];
I("%s, write addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n",__func__,tmp_addr[3],tmp_addr[2],tmp_addr[1],tmp_addr[0]);
switch(type)
{
case 0:
fix_data = 0x00;
break;
case 1:
fix_data = 0xAA;
break;
case 2:
fix_data = 0xBB;
break;
}
for(i = 0;i<128;i++)
{
tmp_data[i] = fix_data;
}
I("%s, total size=%d\n",__func__,total_size);
if (total_size_temp % max_bus_size == 0)
{
total_read_times = total_size_temp / max_bus_size;
}
else
{
total_read_times = total_size_temp / max_bus_size + 1;
}
for (i = 0; i < (total_read_times); i++)
{
I("[log]write %d time start!\n",i);
if ( total_size_temp >= max_bus_size)
{
himax_flash_write_burst_lenth(private_ts->client,tmp_addr,tmp_data, max_bus_size);
total_size_temp = total_size_temp - max_bus_size;
}
else
{
I("last total_size_temp=%d\n",total_size_temp);
himax_flash_write_burst_lenth(private_ts->client,tmp_addr,tmp_data, total_size_temp % max_bus_size);
}
address = ((i+1)*max_bus_size);
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF);
tmp_addr[0] = addr[0] + (uint8_t)((address)&0x00FF);
msleep(10);
}
I("%s,END \n",__func__);
}
void himax_write_sram_0f(const struct firmware *fw_entry,uint8_t *addr,int start_index,int write_len)
{
int total_read_times = 0;
int max_bus_size = 128;
int total_size_temp = 0;
int total_size = 0;
int address = 0;
int i = 0;
uint8_t tmp_addr[4];
uint8_t *tmp_data;
uint32_t now_addr;
I("%s,Entering \n",__func__);
total_size = 65536;
total_size_temp = write_len;
I("[log]enable start!\n");
himax_burst_enable(private_ts->client,1);
I("[log]enable end!\n");
tmp_addr[3] = addr[3]; tmp_addr[2] = addr[2]; tmp_addr[1] = addr[1]; tmp_addr[0] = addr[0];
I("%s, write addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n",__func__,tmp_addr[3],tmp_addr[2],tmp_addr[1],tmp_addr[0]);
now_addr = (addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0];
I("now addr= 0x%08X\n",now_addr);
I("%s, total size=%d\n",__func__,total_size);
//I("[log]locate start!\n");
tmp_data = kzalloc(sizeof(uint8_t)*total_size,GFP_KERNEL);
//I("[log]enable end!\n");
//I("[log]memcpy start!\n");
memcpy(tmp_data,fw_entry->data,total_size);
//I("[log]memcpy end!\n");
I("tmp_data size=%d\n",(int)sizeof(tmp_data));
for(i = 0;i<10;i++)
{
I("[%d] 0x%2.2X",i,tmp_data[i]);
}
I("\n");
if (total_size_temp % max_bus_size == 0)
{
total_read_times = total_size_temp / max_bus_size;
}
else
{
total_read_times = total_size_temp / max_bus_size + 1;
}
for (i = 0; i < (total_read_times); i++)
{
I("[log]write %d time start!\n",i);
if ( total_size_temp >= max_bus_size)
{
himax_flash_write_burst_lenth(private_ts->client,tmp_addr,&(tmp_data[start_index+i*max_bus_size]), max_bus_size);
total_size_temp = total_size_temp - max_bus_size;
}
else
{
I("last total_size_temp=%d\n",total_size_temp);
himax_flash_write_burst_lenth(private_ts->client,tmp_addr,&(tmp_data[start_index+i*max_bus_size]), total_size_temp % max_bus_size);
}
I("[log]write %d time end!\n",i);
address = ((i+1)*max_bus_size);
tmp_addr[0] = addr[0] + (uint8_t)((address)&0x00FF);
if(tmp_addr[0] < addr[0])
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF) + 1;
else
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF);
msleep(10);
}
I("%s,END \n",__func__);
kfree(tmp_data);
}
void himax_firmware_update_0f(const struct firmware *fw_entry)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
I("%s,Entering \n",__func__);
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18;
tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x55;
himax_register_write(private_ts->client,tmp_addr, 4, tmp_data, false);
himax_sense_off(private_ts->client);
himax_chip_erase(private_ts->client);
/* first 48K */
tmp_addr[3] = 0x08;tmp_addr[2] = 0x00;tmp_addr[1] = 0x00;tmp_addr[0] = 0x00;
himax_write_sram_0f(fw_entry,tmp_addr,0,0xC000);
/* clean */
if(G_POWERONOF == 1)
{
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x00;tmp_addr[0] = 0x00;
himax_clean_sram_0f(tmp_addr,32768,0);
}
/*last 16k*/
/*config info*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x70;tmp_addr[0] = 0x00;
if(G_POWERONOF == 1)
himax_write_sram_0f(fw_entry,tmp_addr,0xC000,132);
else
himax_clean_sram_0f(tmp_addr,132,2);
/*FW config*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x70;tmp_addr[0] = 0x84;
if(G_POWERONOF == 1)
himax_write_sram_0f(fw_entry,tmp_addr,0xC0FE,512); //0xc100-2
else
himax_clean_sram_0f(tmp_addr,512,1);
/*ADC config*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x78;tmp_addr[0] = 0x00;
if(G_POWERONOF == 1)
himax_write_sram_0f(fw_entry,tmp_addr,0xD000,376);
else
himax_clean_sram_0f(tmp_addr,376,2);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x79;tmp_addr[0] = 0x78;
if(G_POWERONOF == 1)
himax_write_sram_0f(fw_entry,tmp_addr,0xD178,376);
else
himax_clean_sram_0f(tmp_addr,376,2);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x7A;tmp_addr[0] = 0xF0;
if(G_POWERONOF == 1)
himax_write_sram_0f(fw_entry,tmp_addr,0xD000,376);
else
himax_clean_sram_0f(tmp_addr,376,2);
//G_POWERONOF = 0;
I("%s,END \n",__func__);
}
void himax_0f_operation(struct work_struct *work)
{
int err = NO_ERR;
const struct firmware *fw_entry = NULL;
char *firmware_name = "himax.bin";
uint8_t tmp_data[4];
I("%s,Entering \n",__func__);
I("file name = %s\n",firmware_name);
err = request_firmware(&fw_entry, firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",__func__,__LINE__,err);
//goto err_request_firmware;
return ;
}
himax_firmware_update_0f(fw_entry);
release_firmware(fw_entry);
tmp_data[0] = 0x00;tmp_data[1] = 0x00;tmp_data[2] = 0x00;tmp_data[3] = 0x08;
if(himax_hw_check_CRC(private_ts->client,tmp_data, 0xC000) == 0)
{
I("%s,HW CRC OK!\n",__func__);
}
else
{
E("%s,HW CRC FAIL!\n",__func__);
}
msleep(100);
himax_sys_reset();
msleep(100);
himax_int_enable(private_ts->client->irq,1);
I("%s,END \n",__func__);
return ;
}
#ifdef HX_0F_DEBUG
void himax_read_sram_0f(const struct firmware *fw_entry,uint8_t *addr,int start_index,int read_len)
{
int total_read_times = 0;
int max_i2c_size = 128;
int total_size_temp = 0;
int total_size = 0;
int address = 0;
int i = 0,j = 0;
int not_same = 0;
uint8_t tmp_addr[4];
uint8_t *temp_info_data;
int *not_same_buff;
I("%s,Entering \n",__func__);
himax_burst_enable(private_ts->client,1);
total_size = read_len;
total_size_temp = read_len;
temp_info_data = kzalloc(sizeof(uint8_t)*total_size,GFP_KERNEL);
not_same_buff = kzalloc(sizeof(int)*total_size,GFP_KERNEL);
tmp_addr[3] = addr[3]; tmp_addr[2] = addr[2]; tmp_addr[1] = addr[1]; tmp_addr[0] = addr[0];
I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n",__func__,tmp_addr[3],tmp_addr[2],tmp_addr[1],tmp_addr[0]);
I("%s, total size=%d\n",__func__,total_size);
himax_burst_enable(private_ts->client,1);
if (total_size % max_i2c_size == 0)
{
total_read_times = total_size / max_i2c_size;
}
else
{
total_read_times = total_size / max_i2c_size + 1;
}
for (i = 0; i < (total_read_times); i++)
{
if ( total_size_temp >= max_i2c_size)
{
himax_register_read(private_ts->client,tmp_addr, max_i2c_size, &temp_info_data[i*max_i2c_size], false);
total_size_temp = total_size_temp - max_i2c_size;
}
else
{
//I("last total_size_temp=%d\n",total_size_temp);
himax_register_read(private_ts->client,tmp_addr, total_size_temp % max_i2c_size, &temp_info_data[i*max_i2c_size], false);
}
address = ((i+1)*max_i2c_size);
tmp_addr[0] = addr[0] + (uint8_t)((address)&0x00FF);
if(tmp_addr[0] < addr[0])
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF) + 1;
else
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF);
msleep(10);
}
I("%s,READ Start \n",__func__);
I("%s,start_index = %d \n",__func__,start_index);
j = start_index;
for(i = 0;i < read_len;i++,j++)
{
if(fw_entry->data[j] != temp_info_data[i])
{
not_same++;
not_same_buff[i] = 1;
}
I("0x%2.2X,",temp_info_data[i]);
if (i > 0 && i%16 == 15)
printk("\n");
}
I("%s,READ END \n",__func__);
I("%s,Not Same count=%d\n",__func__,not_same);
if(not_same != 0)
{
j = start_index;
for(i = 0;i<read_len;i++,j++)
{
if(not_same_buff[i] == 1)
I("bin = [%d] 0x%2.2X\n",i,fw_entry->data[j]);
}
for(i = 0;i<read_len;i++,j++)
{
if(not_same_buff[i] == 1)
I("sram = [%d] 0x%2.2X \n",i,temp_info_data[i]);
}
}
I("%s,END \n",__func__);
kfree(temp_info_data);
}
void himax_read_all_sram(uint8_t *addr,int read_len)
{
int total_read_times = 0;
int max_bus_size = 128;
int total_size_temp = 0;
int total_size = 0;
int address = 0;
int i = 0;
struct file *fn;
uint8_t tmp_addr[4];
uint8_t *temp_info_data;
I("%s,Entering \n",__func__);
himax_burst_enable(private_ts->client,1);
total_size = read_len;
total_size_temp = read_len;
temp_info_data = kzalloc(sizeof(uint8_t)*total_size,GFP_KERNEL);
tmp_addr[3] = addr[3]; tmp_addr[2] = addr[2]; tmp_addr[1] = addr[1]; tmp_addr[0] = addr[0];
I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n",__func__,tmp_addr[3],tmp_addr[2],tmp_addr[1],tmp_addr[0]);
I("%s, total size=%d\n",__func__,total_size);
if (total_size % max_bus_size == 0)
{
total_read_times = total_size / max_bus_size;
}
else
{
total_read_times = total_size / max_bus_size + 1;
}
for (i = 0; i < (total_read_times); i++)
{
if ( total_size_temp >= max_bus_size)
{
himax_register_read(private_ts->client,tmp_addr, max_bus_size, &temp_info_data[i*max_bus_size], false);
total_size_temp = total_size_temp - max_bus_size;
}
else
{
//I("last total_size_temp=%d\n",total_size_temp);
himax_register_read(private_ts->client,tmp_addr, total_size_temp % max_bus_size, &temp_info_data[i*max_bus_size], false);
}
address = ((i+1)*max_bus_size);
tmp_addr[1] = addr[1] + (uint8_t)((address>>8)&0x00FF);
tmp_addr[0] = addr[0] + (uint8_t)((address)&0x00FF);
msleep(10);
}
I("%s, NOW addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n",__func__,tmp_addr[3],tmp_addr[2],tmp_addr[1],tmp_addr[0]);
/*for(i = 0;i<read_len;i++)
{
I("0x%2.2X,",temp_info_data[i]);
if (i > 0 && i%16 == 15)
printk("\n");
}*/
I("Now Write File start!\n");
fn = filp_open("/sdcard/dump_dsram.txt",O_CREAT | O_WRONLY ,0);
if (!IS_ERR(fn))
{
I("%s create file and ready to write\n",__func__);
fn->f_op->write(fn,temp_info_data,read_len*sizeof(uint8_t),&fn->f_pos);
filp_close(fn,NULL);
}
I("Now Write File End!\n");
I("%s,END \n",__func__);
kfree(temp_info_data);
}
void himax_firmware_read_0f(const struct firmware *fw_entry)
{
uint8_t tmp_addr[4];
I("%s,Entering \n",__func__);
/* first 48K */
tmp_addr[3] = 0x08;tmp_addr[2] = 0x00;tmp_addr[1] = 0x00;tmp_addr[0] = 0x00;
himax_read_sram_0f(fw_entry,tmp_addr,0,0xC000);
/*last 16k*/
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x70;tmp_addr[0] = 0x00;
himax_read_sram_0f(fw_entry,tmp_addr,0xC000,132);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x70;tmp_addr[0] = 0x84;
himax_read_sram_0f(fw_entry,tmp_addr,0xC0FE,512);//0xc100-2
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x78;tmp_addr[0] = 0x00;
himax_read_sram_0f(fw_entry,tmp_addr,0xD000,376);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x79;tmp_addr[0] = 0x78;
himax_read_sram_0f(fw_entry,tmp_addr,0xD178,376);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x7A;tmp_addr[0] = 0xF0;
himax_read_sram_0f(fw_entry,tmp_addr,0xD000,376);
tmp_addr[3] = 0x10;tmp_addr[2] = 0x00;tmp_addr[1] = 0x00;tmp_addr[0] = 0x00;
himax_read_all_sram(tmp_addr,32768);
I("%s,END \n",__func__);
}
void himax_0f_operation_check(void)
{
int err = NO_ERR;
const struct firmware *fw_entry = NULL;
char *firmware_name = "himax.bin";
I("%s,Entering \n",__func__);
I("file name = %s\n",firmware_name);
err = request_firmware(&fw_entry, firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",__func__,__LINE__,err);
//goto err_request_firmware;
return ;
}
I("first 4 bytes 0x%2X,0x%2X,0x%2X,0x%2X !\n",fw_entry->data[0],fw_entry->data[1],fw_entry->data[2],fw_entry->data[3]);
I("next 4 bytes 0x%2X,0x%2X,0x%2X,0x%2X !\n",fw_entry->data[4],fw_entry->data[5],fw_entry->data[6],fw_entry->data[7]);
I("and next 4 bytes 0x%2X,0x%2X,0x%2X,0x%2X !\n",fw_entry->data[8],fw_entry->data[9],fw_entry->data[10],fw_entry->data[11]);
himax_firmware_read_0f(fw_entry);
release_firmware(fw_entry);
I("%s,END \n",__func__);
return ;
}
#endif
#endif