/* Himax Android Driver Sample Code for HMX83100 chipset
*
* Copyright (C) 2015 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"

const struct firmware *i_TP_CRC_FW_128K;
const struct firmware *i_TP_CRC_FW_64K;
const struct firmware *i_TP_CRC_FW_124K;
const struct firmware *i_TP_CRC_FW_60K;

unsigned long FW_VER_MAJ_FLASH_ADDR;
unsigned long FW_VER_MAJ_FLASH_LENG;
unsigned long FW_VER_MIN_FLASH_ADDR;
unsigned long FW_VER_MIN_FLASH_LENG;
unsigned long CFG_VER_MAJ_FLASH_ADDR;
unsigned long CFG_VER_MAJ_FLASH_LENG;
unsigned long CFG_VER_MIN_FLASH_ADDR;
unsigned long CFG_VER_MIN_FLASH_LENG;

unsigned char IC_TYPE;
unsigned char IC_CHECKSUM;

 /*0:Running, 1:Stop, 2:I2C Fail*/
int himax_hand_shaking(struct i2c_client *client)
{
	int ret, result;
	uint8_t hw_reset_check[1];
	uint8_t hw_reset_check_2[1];
	uint8_t buf0[2];
	uint8_t	IC_STATUS_CHECK = 0xAA;

	memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
	memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));

	buf0[0] = 0xF2;
	if (IC_STATUS_CHECK == 0xAA) {
		buf0[1] = 0xAA;
		IC_STATUS_CHECK = 0x55;
	} else {
		buf0[1] = 0x55;
		IC_STATUS_CHECK = 0xAA;
	}

	ret = i2c_himax_master_write(client,
	buf0, 2, HIMAX_I2C_RETRY_TIMES);
	if (ret < 0) {
		E("[Himax]:write 0xF2 failed line: %d\n", __LINE__);
		goto work_func_send_i2c_msg_fail;
	}
	msleep(50);

	buf0[0] = 0xF2;
	buf0[1] = 0x00;
	ret = i2c_himax_master_write(client,
	buf0, 2, HIMAX_I2C_RETRY_TIMES);
	if (ret < 0) {
		E("[Himax]:write 0x92 failed line: %d\n", __LINE__);
		goto work_func_send_i2c_msg_fail;
	}
	usleep_range(1999, 2000);

	ret = i2c_himax_read(client, 0xD1,
	hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
	if (ret < 0) {
		E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__);
		goto work_func_send_i2c_msg_fail;
	}

	if (IC_STATUS_CHECK != hw_reset_check[0]) {
		usleep_range(1999, 2000);
		ret = i2c_himax_read(client, 0xD1,
		hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
		if (ret < 0) {
			E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n",
			__LINE__);
			goto work_func_send_i2c_msg_fail;
		}

		if (hw_reset_check[0] == hw_reset_check_2[0])
			result = 1;
		else
			result = 0;

	} else {
		result = 0;
	}

	return result;

work_func_send_i2c_msg_fail:
	return 2;
}

void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];

	if (diag_command != 0)
		diag_command = diag_command + 5;

	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
	tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
	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);
}

void himax_flash_dump_func(struct i2c_client *client,
uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
{
	/*struct himax_ts_data *ts =
	container_of(work, struct himax_ts_data, flash_work);*/
	/*uint8_t sector = 0;*/
	/*uint8_t page = 0;*/
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];
	uint8_t out_buffer[20];
	uint8_t in_buffer[260];
	int page_prog_start = 0;
	int i = 0;

	himax_sense_off(client);
	himax_burst_enable(client, 0);
	/*=============Dump Flash Start=============*/
	/*=====================================*/
	/* 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 < Flash_Size;
		page_prog_start = page_prog_start + 256) {
		/*=====================================
		SPI Transfer Control
		Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
		Set read start address  : 0x8000_0028 ==> 0x0000_0000
		Set command			   : 0x8000_0024 ==> 0x0000_003B
		=====================================*/
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
		tmp_data[3] = 0x69; tmp_data[2] = 0x40;
		tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
		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;
		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);

		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] = 0x3B;
		himax_flash_write_burst(client, tmp_addr, tmp_data);

		/*=====================================
		AHB_I2C Burst Read
		Set SPI data register : 0x8000_002C ==> 0x00
		=====================================*/
		out_buffer[0] = 0x2C;
		out_buffer[1] = 0x00;
		out_buffer[2] = 0x00;
		out_buffer[3] = 0x80;
		i2c_himax_write(client, 0x00, out_buffer, 4, 3);

		/*=====================================
		Read access : 0x0C ==> 0x00
		=====================================*/
		out_buffer[0] = 0x00;
		i2c_himax_write(client, 0x0C, out_buffer, 1, 3);

		/*=====================================
		Read 128 bytes two times
		=====================================*/
		i2c_himax_read(client, 0x08, in_buffer, 128, 3);
		for (i = 0 ; i < 128 ; i++)
			flash_buffer[i + page_prog_start]
			= in_buffer[i];

		i2c_himax_read(client, 0x08 , in_buffer, 128, 3);
		for (i = 0 ; i < 128 ; i++)
			flash_buffer[(i + 128) + page_prog_start]
			= in_buffer[i];

		I("%s:Verify Progress: %x\n", __func__, page_prog_start);
	}

/*=============Dump Flash End=============*/
		/*//msleep(100);
		for( i=0 ; i<8 ;i++)
		{
			for(j=0 ; j<64 ; j++)
			{
				setFlashDumpProgress(i*32 + j);
			}
		}
		*/
	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];
	int pf_value = 0x00;
	uint8_t test_result_id = 0;
	int j;

	memset(tmp_addr, 0x00, sizeof(tmp_addr));
	memset(tmp_data, 0x00, sizeof(tmp_data));

	himax_interface_on(client);
	himax_sense_off(client);

	/*Set criteria*/
	himax_burst_enable(client, 1);

	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
	tmp_data[3] = 0x14; tmp_data[2] = 0xC8;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	tmp_data[7] = 0x13; tmp_data[6] = 0x60;
	tmp_data[5] = 0x0A; tmp_data[4] = 0x99;

	himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8);

	/*start selftest*/
	/* 0x9008_805C ==> 0x0000_0001*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
	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);

	himax_sense_on(client, 1);

	msleep(2000);

	himax_sense_off(client);
	msleep(20);

	/*=====================================
	Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
	=====================================*/
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
	himax_register_read(client, tmp_addr, 1, tmp_data);

	test_result_id = tmp_data[0];

	I("%s: check test result, test_result_id=%x, test_result=%x\n",
	__func__ , test_result_id, tmp_data[0]);

	if (test_result_id == 0xF) {
		I("[Himax]: self-test pass\n");
		pf_value = 0x1;
	} else {
		E("[Himax]: self-test fail\n");
		pf_value = 0x0;
	}
	himax_burst_enable(client, 1);

	for (j = 0 ; j < 10 ; j++) {
		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
		tmp_addr[3] = 0x90; tmp_addr[2] = 0x06;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
		himax_register_read(client, tmp_addr, 1, tmp_data);
		I("[Himax]: 9006000C = %d\n", tmp_data[0]);
		if (tmp_data[0] != 0) {
			tmp_data[3] = 0x90; tmp_data[2] = 0x06;
			tmp_data[1] = 0x00; tmp_data[0] = 0x00;
			if (i2c_himax_write(client, 0x00,
			tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
				E("%s: i2c access fail!\n", __func__);
			}
			tmp_data[0] = 0x00;
			if (i2c_himax_write(client, 0x0C,
			tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
				E("%s: i2c access fail!\n", __func__);
			}
				i2c_himax_read(client, 0x08,
				tmp_data, 124, HIMAX_I2C_RETRY_TIMES);
		} else {
			break;
		}
	}

	himax_sense_on(client, 1);
	msleep(120);

	return pf_value;
}

void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];

	himax_burst_enable(client, 0);
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
	himax_flash_write_burst(client, tmp_addr, tmp_data);
}
void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data)
{
	uint8_t tmp_addr[4];

	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
	himax_register_read(client, tmp_addr, 1, tmp_data);
}

void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];

	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
	himax_flash_write_burst(client, tmp_addr, tmp_data);
}

void himax_get_SMWP_enable(struct i2c_client *client,
uint8_t *tmp_data)
{
	uint8_t tmp_addr[4];

	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
	himax_register_read(client, tmp_addr, 1, tmp_data);
}

int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
{
	uint8_t tmp_data[4];
	int err = -1;

	tmp_data[0] = 0x31;

	if (i2c_himax_write(client, 0x13,
	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return err;
	}

	tmp_data[0] = (0x10 | auto_add_4_byte);
	if (i2c_himax_write(client, 0x0D,
	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return err;
	}
	return 0;

}

void himax_register_read(struct i2c_client *client,
uint8_t *read_addr, int read_length, uint8_t *read_data)
{
	uint8_t tmp_data[4];
	int i = 0;
	int address = 0;

	if (read_length > 256) {
		E("%s: read len over 256!\n", __func__);
		return;
	}
	if (read_length > 1)
		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, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}
	tmp_data[0] = 0x00;
	if (i2c_himax_write(client, 0x0C,
	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}
	if (i2c_himax_read(client, 0x08,
	read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}
	if (read_length > 1)
		himax_burst_enable(client, 0);
}

void himax_flash_read(struct i2c_client *client,
uint8_t *reg_byte, uint8_t *read_data)
{
	uint8_t tmpbyte[2];

	if (i2c_himax_write(client, 0x00,
	&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(client, 0x01,
	&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(client, 0x02,
	&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(client, 0x03,
	&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	tmpbyte[0] = 0x00;
	if (i2c_himax_write(client, 0x0C,
	&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_read(client, 0x08,
	&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_read(client, 0x09,
	&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_read(client, 0x0A,
	&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_read(client, 0x0B,
	&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_read(client, 0x18,
	&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	} /* No bus request*/

	if (i2c_himax_read(client, 0x0F,
	&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	} /* idle state*/

}

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, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

}

int himax_flash_write_burst_length(struct i2c_client *client,
uint8_t *reg_byte, uint8_t *write_data, int length)
{
	uint8_t data_byte[256];
	int i = 0, j = 0, err = -1;

	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, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return err;
	}
	return 0;
}

int himax_register_write(struct i2c_client *client,
uint8_t *write_addr, int write_length, uint8_t *write_data)
{
	int i = 0, address = 0;
	int ret = 0, err = -1;

	address = (write_addr[3] << 24) +
				(write_addr[2] << 16) +
				(write_addr[1] << 8) +
				write_addr[0];

	for (i = address ; i < address + write_length * 4;
		i = i + 4) {
		if (write_length > 1) {
			ret = himax_burst_enable(client, 1);
			if (ret)
				return err;
		} else {
			ret = himax_burst_enable(client, 0);
			if (ret)
				return err;
		}
	ret = himax_flash_write_burst_length(client,
		write_addr, write_data, write_length * 4);
	if (ret < 0)
		return err;
	}

	return 0;
}

void himax_sense_off(struct i2c_client *client)
{
	uint8_t wdt_off = 0x00;
	uint8_t tmp_addr[4];
	uint8_t tmp_data[5];

	himax_burst_enable(client, 0);

	while (wdt_off == 0x00) {
		/* 0x9000_800C ==> 0x0000_AC53*/
		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
		tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
		himax_flash_write_burst(client, tmp_addr, tmp_data);

		/*=====================================*/
		/* Read Watch Dog disable password :
		0x9000_800C ==> 0x0000_AC53 */
		/*=====================================*/
		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
		himax_register_read(client, tmp_addr, 1, tmp_data);

		/*Check WDT*/
		if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC
		&& tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
			wdt_off = 0x01;
		else
			wdt_off = 0x00;
	}

	/* VCOM		//0x9008_806C ==> 0x0000_0001*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
	tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
	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);

	msleep(20);

	/* 0x9000_0010 ==> 0x0000_00DA*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
	himax_flash_write_burst(client, tmp_addr, tmp_data);

	/*=====================================
	Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
	=====================================*/
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
	himax_register_read(client, tmp_addr, 1, tmp_data);
	I("%s: CPU clock off password data[0]=%x",
	__func__, tmp_data[0]);
	I(" data[1]=%x data[2]=%x data[3]=%x\n",
	tmp_data[1], tmp_data[2], tmp_data[3]);

}

void himax_interface_on(struct i2c_client *client)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[5];

    /*=====================================
	Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
	=====================================*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
	himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/
}

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, 1, in_buffer);

		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, ",
			__func__, retry_cnt, in_buffer[0]);
			I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n",
			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[128];

	himax_interface_on(client);
	himax_burst_enable(client, 0);
	/*CPU reset*/
	/* 0x9000_0014 ==> 0x0000_00CA*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
	himax_flash_write_burst(client, tmp_addr, tmp_data);

	/*=====================================
	Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
	=====================================*/
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
	himax_register_read(client, tmp_addr, 1, tmp_data);

	I("%s: check pull low CPU reset signal  data[0]=%x data[1]=%x ",
	__func__, tmp_data[0], tmp_data[1]);
	I("data[2]=%x data[3]=%x\n",
	tmp_data[2], tmp_data[3]);

	/* 0x9000_0014 ==> 0x0000_0000*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; 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);

	/*=====================================
	Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
	=====================================*/
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
	himax_register_read(client, tmp_addr, 1, tmp_data);

	I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ",
	__func__, tmp_data[0], tmp_data[1]);
	I("data[2]=%x data[3]=%x\n",
	tmp_data[2], tmp_data[3]);

	/*=====================================
	Reset TCON
	=====================================*/
	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
	tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
	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);
	usleep_range(9999, 10000);
	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
	tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
	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);

	if (FlashMode == 0x00) { /*SRAM*/
		/*=====================================
					Re-map
		=====================================*/
		tmp_addr[3] = 0x90; 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] = 0xF1;
		himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
		I("%s:83100_Chip_Re-map ON\n", __func__);
	} else {
		/*=====================================
					Re-map off
		=====================================*/
		tmp_addr[3] = 0x90; 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_length(client, tmp_addr, tmp_data, 4);
		I("%s:83100_Chip_Re-map OFF\n", __func__);
	}
	/*=====================================
				CPU clock on
	=====================================*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
	himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);

}

void himax_chip_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);

	/*=====================================
	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:83100_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:83100_Erase Fail\n", __func__);
		return false;
	} else {
		return true;
	}

}

bool himax_sector_erase(struct i2c_client *client, int start_addr)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];
	int page_prog_start = 0;

	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);
	for (page_prog_start = start_addr;
	page_prog_start < start_addr + 0x0F000;
	page_prog_start = page_prog_start + 0x1000) {
		/*=====================================
		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);

		/*=====================================
		Sector Erase
		Erase Command :
		0x8000_0028 ==> 0x0000_0000 //SPI addr
		0x8000_0020 ==> 0x6700_0000 //control
		0x8000_0024 ==> 0x0000_0020 //SE
		=====================================*/
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
		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);

		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] = 0x20;
		himax_flash_write_burst(client, tmp_addr, tmp_data);

		msleep(200);

		if (!wait_wip(client, 100)) {
			E("%s:83100_Erase Fail\n", __func__);
			return false;
		}
	}
	return true;
}

void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
{
	int i = 0;
	uint8_t tmp_addr[4];
	uint8_t tmp_data[64];
	int FW_length = 0x4000; /* 0x4000 = 16K bin file */

	/*himax_sense_off(client);*/

	for (i = 0; i < FW_length; i = i + 64) {
		himax_burst_enable(client, 1);

		if (i < 0x100) {
			tmp_addr[3] = 0x08;
			tmp_addr[2] = 0x00;
			tmp_addr[1] = 0x00;
			tmp_addr[0] = i;
		} else if (i >= 0x100 && i < 0x10000) {
			tmp_addr[3] = 0x08;
			tmp_addr[2] = 0x00;
			tmp_addr[1] = (i >> 8);
			tmp_addr[0] = i;
		}

		memcpy(&tmp_data[0], &FW_content[i], 64);
		himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64);

	}

	if (!wait_wip(client, 100))
		E("%s:83100_Sram_Write Fail\n", __func__);
}

bool himax_sram_verify(struct i2c_client *client,
uint8_t *FW_File, int FW_Size)
{
	int i = 0;
	uint8_t out_buffer[20];
	uint8_t in_buffer[128];
	uint8_t *get_fw_content;

	get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL);

	for (i = 0 ; i < 0x4000 ; i = i + 128) {
		himax_burst_enable(client, 1);

		/*=====================================
				AHB_I2C Burst Read
		=====================================*/
		if (i < 0x100) {
			out_buffer[3] = 0x08;
			out_buffer[2] = 0x00;
			out_buffer[1] = 0x00;
			out_buffer[0] = i;
		} else if (i >= 0x100 && i < 0x10000) {
			out_buffer[3] = 0x08;
			out_buffer[2] = 0x00;
			out_buffer[1] = (i >> 8);
			out_buffer[0] = i;
		}

		if (i2c_himax_write(client, 0x00, out_buffer,
		4, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return false;
		}

		out_buffer[0] = 0x00;
		if (i2c_himax_write(client, 0x0C, out_buffer,
		1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return false;
		}

		if (i2c_himax_read(client, 0x08, in_buffer,
		128, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return false;
		}
		memcpy(&get_fw_content[i], &in_buffer[0], 128);
	}

	for (i = 0 ; i < FW_Size ; i++) {
		if (FW_File[i] != get_fw_content[i]) {
			E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n",
			__func__, i, get_fw_content[i], FW_File[i]);
			return false;
		}
	}

	kfree(get_fw_content);

	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];
	/* // Read for flash data, 128K //4 bytes for 0x80002C padding */
	uint8_t buring_data[256];

	/*himax_interface_on(client);*/
	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);

	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, HIMAX_I2C_RETRY_TIMES) < 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,
				HIMAX_I2C_RETRY_TIMES) < 0) {
				E("%s: i2c access fail!\n", __func__);
				return;
			}

		}

		if (!wait_wip(client, 1))
			E("%s:83100_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 = 0x00;
	int i = 0;
	int ret = 0;

	himax_sense_off(client);

	for (i = 0 ; i < 5 ; i++) {
		/* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
		(Lock register R/W from driver) */
		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
		tmp_data[1] = 0x00; tmp_data[0] = 0x01;
		ret = himax_register_write(client, tmp_addr, 1, tmp_data);
		if (ret)
			return false;

		/* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
		tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
		ret = himax_register_write(client, tmp_addr, 1, tmp_data);
		if (ret)
			return false;

		/* 3. Read driver ID register RF4H 1 byte (0x8001_F401)
		//	  Driver register RF4H 1 byte value = 0x84H,
		read back value will become 0x84848484 */
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
		tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
		himax_register_read(client, tmp_addr, 1, tmp_data);
		ret_data = tmp_data[0];

		I("%s:Read driver IC ID = %X\n", __func__, ret_data);
		if (ret_data == 0x84) {
			IC_TYPE         = HX_83100_SERIES_PWON;
			/*himax_sense_on(client, 0x01);*/
			ret_data = true;
			break;

		} else {
			ret_data = false;
			E("%s:Read driver ID register Fail:\n", __func__);
		}
	}
	/* 4. After read finish, set DDREG_Req = 0
	(0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/
	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
	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_register_write(client, tmp_addr, 1, tmp_data);
	/*himax_sense_on(client, 0x01);*/
	return ret_data;
}

/*#if 1*/
int himax_check_CRC(struct i2c_client *client, int mode)
{
	bool burnFW_success = false;
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];
	int tmp_value;
	int CRC_value = 0;

	memset(tmp_data, 0x00, sizeof(tmp_data));
	if (i_TP_CRC_FW_60K == NULL) {
		I("%s: i_TP_CRC_FW_60K = NULL\n", __func__);
		return 0;
	} else if (i_TP_CRC_FW_64K == NULL) {
		I("%s: i_TP_CRC_FW_64K = NULL\n", __func__);
		return 0;
	} else if (i_TP_CRC_FW_124K == NULL) {
		I("%s: i_TP_CRC_FW_124K = NULL\n", __func__);
		return 0;
	} else if (i_TP_CRC_FW_128K == NULL) {
		I("%s: i_TP_CRC_FW_128K = NULL\n", __func__);
		return 0;
	}

	if (1) {
		if (mode == fw_image_60k) {
			himax_sram_write(client,
			(unsigned char *)i_TP_CRC_FW_60K->data);
			burnFW_success = himax_sram_verify(client,
			(unsigned char *)i_TP_CRC_FW_60K->data, 0x4000);
		} else if (mode == fw_image_64k) {
			himax_sram_write(client,
			(unsigned char *)i_TP_CRC_FW_64K->data);
			burnFW_success = himax_sram_verify(client,
			(unsigned char *)i_TP_CRC_FW_64K->data, 0x4000);
		} else if (mode == fw_image_124k) {
			himax_sram_write(client,
			(unsigned char *)i_TP_CRC_FW_124K->data);
			burnFW_success = himax_sram_verify(client,
			(unsigned char *)i_TP_CRC_FW_124K->data, 0x4000);
		} else if (mode == fw_image_128k) {
			himax_sram_write(client,
			(unsigned char *)i_TP_CRC_FW_128K->data);
			burnFW_success = himax_sram_verify(client,
			(unsigned char *)i_TP_CRC_FW_128K->data, 0x4000);
		}
		if (burnFW_success) {
			I("%s: Start to do CRC FW mode=%d\n", __func__, mode);
			himax_sense_on(client, 0x00);	/* run CRC firmware*/

			while (true) {
				msleep(100);
				tmp_addr[3] = 0x90;
				tmp_addr[2] = 0x08;
				tmp_addr[1] = 0x80;
				tmp_addr[0] = 0x94;
				himax_register_read(client,
				tmp_addr, 1, tmp_data);

				I("%s: CRC from firmware is %x, %x, %x, %x\n",
				__func__, tmp_data[3], tmp_data[2],
				tmp_data[1], tmp_data[0]);
/*
				if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF
				&& tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) {
				} else
					break;
				*/
				if (!(tmp_data[3] == 0xFF
				&& tmp_data[2] == 0xFF
				&& tmp_data[1] == 0xFF
				&& tmp_data[0] == 0xFF)) {
					break;
				}
			}

			CRC_value = tmp_data[3];

			tmp_value = tmp_data[2] << 8;
			CRC_value += tmp_value;

			tmp_value = tmp_data[1] << 16;
			CRC_value += tmp_value;

			tmp_value = tmp_data[0] << 24;
			CRC_value += tmp_value;

			I("%s: CRC Value is %x\n", __func__, CRC_value);

			/*Close Remapping*/
			/*=====================================
			Re-map close
			=====================================*/
			tmp_addr[3] = 0x90; 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_length(client,
			tmp_addr, tmp_data, 4);
			return CRC_value;

		} else {
			E("%s: SRAM write fail\n", __func__);
			return 0;
		}
	} else
		I("%s: NO CRC Check File\n", __func__);

	return 0;
}

bool Calculate_CRC_with_AP(unsigned char *FW_content,
int CRC_from_FW, int mode)
{
	uint8_t tmp_data[4];
	int i, j;
	int fw_data;
	int fw_data_2;
	int CRC = 0xFFFFFFFF;
	int PolyNomial = 0x82F63B78;
	int length = 0;

	if (mode == fw_image_128k)
		length = 0x8000;
	else if (mode == fw_image_124k)
		length = 0x7C00;
	else if (mode == fw_image_64k)
		length = 0x4000;
	else /*if (mode == fw_image_60k)*/
		length = 0x3C00;

	for (i = 0 ; i < length ; i++) {
		fw_data = FW_content[i * 4];

		for (j = 1 ; j < 4 ; j++) {
			fw_data_2 = FW_content[i * 4 + j];
			fw_data += (fw_data_2) << (8 * j);
		}

		CRC = fw_data ^ CRC;

		for (j = 0 ; j < 32 ; j++) {
			if ((CRC % 2) != 0)
				CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
			else
				CRC = (((CRC >> 1) ^ 0x7FFFFFFF) & 0x7FFFFFFF);
		}
	}

	I("%s: CRC calculate from bin file is %x\n", __func__, CRC);

	tmp_data[0] = (uint8_t)(CRC >> 24);
	tmp_data[1] = (uint8_t)(CRC >> 16);
	tmp_data[2] = (uint8_t)(CRC >> 8);
	tmp_data[3] = (uint8_t) CRC;

	CRC = tmp_data[0];
	CRC += tmp_data[1] << 8;
	CRC += tmp_data[2] << 16;
	CRC += tmp_data[3] << 24;

	I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC);
	I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW);
	if (CRC_from_FW == CRC)
		return true;
	else
		return false;
}
/*#endif*/

int himax_load_CRC_bin_file(struct i2c_client *client)
{
	int err = 0;
	char *CRC_60_firmware_name = "HX_CRC_60.bin";
	char *CRC_64_firmware_name = "HX_CRC_64.bin";
	char *CRC_124_firmware_name = "HX_CRC_124.bin";
	char *CRC_128_firmware_name = "HX_CRC_128.bin";

	I("%s,Entering\n", __func__);
	if (i_TP_CRC_FW_60K == NULL)	{
		I("load file name = %s\n", CRC_60_firmware_name);
		err = request_firmware(&i_TP_CRC_FW_60K,
		CRC_60_firmware_name, private_ts->dev);
		if (err < 0) {
			E("%s,fail in line%d error code=%d\n",
			__func__, __LINE__, err);
			err = -1;
			goto request_60k_fw_fail;
		}
	} else
		I("%s already load i_TP_CRC_FW_60K\n", __func__);

	if (i_TP_CRC_FW_64K == NULL)	{
		I("load file name = %s\n", CRC_64_firmware_name);
		err = request_firmware(&i_TP_CRC_FW_64K,
		CRC_64_firmware_name, private_ts->dev);
		if (err < 0) {
			E("%s,fail in line%d error code=%d\n",
			__func__, __LINE__, err);
			err = -2;
			goto request_64k_fw_fail;
		}
	} else
		I("%s already load i_TP_CRC_FW_64K\n", __func__);

	if (i_TP_CRC_FW_124K == NULL) {
		I("load file name = %s\n", CRC_124_firmware_name);
		err = request_firmware(&i_TP_CRC_FW_124K,
		CRC_124_firmware_name, private_ts->dev);
		if (err < 0) {
			E("%s,fail in line%d error code=%d\n",
			__func__, __LINE__, err);
			err = -3;
			goto request_124k_fw_fail;
		}
	} else
		I("%s already load i_TP_CRC_FW_124K\n", __func__);

	if (i_TP_CRC_FW_128K == NULL) {
		I("load file name = %s\n", CRC_128_firmware_name);
		err = request_firmware(&i_TP_CRC_FW_128K,
		CRC_128_firmware_name, private_ts->dev);
		if (err < 0) {
			E("%s,fail in line%d error code=%d\n",
			__func__, __LINE__, err);
			err = -4;
			goto request_128k_fw_fail;
		}
	} else
		I("%s already load  i_TP_CRC_FW_128K\n", __func__);

	return err;

request_128k_fw_fail:
	release_firmware(i_TP_CRC_FW_124K);
request_124k_fw_fail:
	release_firmware(i_TP_CRC_FW_64K);
request_64k_fw_fail:
	release_firmware(i_TP_CRC_FW_60K);
request_60k_fw_fail:
	return err;
}
int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
	int CRC_from_FW = 0;
	int burnFW_success = 0;

	if (len != 0x10000) {/*64k*/
		E("%s: The file size is not 64K bytes\n", __func__);
		return false;
	}
	himax_sense_off(client);
	msleep(500);
	himax_interface_on(client);
	if (!himax_sector_erase(client, 0x00000)) {
		E("%s:Sector erase fail!Please restart the IC.\n", __func__);
		return false;
	}
	himax_flash_programming(client, fw, 0x0F000);

	/*burnFW_success = himax_83100_Verify(fw, len);
	if(burnFW_success==false)
		return burnFW_success;*/

	CRC_from_FW = himax_check_CRC(client, fw_image_60k);
	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k);
	/*himax_sense_on(client, 0x01);*/
	return burnFW_success;
}

int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
	int CRC_from_FW = 0;
	int burnFW_success = 0;

	if (len != 0x10000) {   /*64k*/
		E("%s: The file size is not 64K bytes\n", __func__);
		return false;
	}
	himax_sense_off(client);
	msleep(500);
	himax_interface_on(client);
	himax_chip_erase(client);
	himax_flash_programming(client, fw, len);

	/*burnFW_success = himax_83100_Verify(fw, len);
	if(burnFW_success==false)
		return burnFW_success;*/

	CRC_from_FW = himax_check_CRC(client, fw_image_64k);
	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k);
	/*himax_sense_on(client, 0x01);*/
	return burnFW_success;
}

int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
	int CRC_from_FW = 0;
	int burnFW_success = 0;

	if (len != 0x20000) {   /*128k*/
		E("%s: The file size is not 128K bytes\n", __func__);
		return false;
	}
	himax_sense_off(client);
	msleep(500);
	himax_interface_on(client);
	if (!himax_block_erase(client)) {
		E("%s:Block erase fail!Please restart the IC.\n", __func__);
		return false;
	}
	if (!himax_sector_erase(client, 0x10000)) {
		E("%s:Sector erase fail!Please restart the IC.\n", __func__);
		return false;
	}
	himax_flash_programming(client, fw, 0x1F000);

	/*burnFW_success = himax_83100_Verify(fw, len);
	if(burnFW_success==false)
		return burnFW_success;*/

	CRC_from_FW = himax_check_CRC(client, fw_image_124k);
	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k);
	/*himax_sense_on(client, 0x01);*/
	return burnFW_success;
}

int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
	int CRC_from_FW = 0;
	int burnFW_success = 0;

	if (len != 0x20000) {   /*128k*/
		E("%s: The file size is not 128K bytes\n", __func__);
		return false;
	}
	himax_sense_off(client);
	msleep(500);
	himax_interface_on(client);
	himax_chip_erase(client);

	himax_flash_programming(client, fw, len);

	/*burnFW_success = himax_83100_Verify(fw, len);
	if(burnFW_success==false)
		return burnFW_success;*/

	CRC_from_FW = himax_check_CRC(client, fw_image_128k);
	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k);
	/*himax_sense_on(client, 0x01); */
	return burnFW_success;
}

void himax_touch_information(struct i2c_client *client)
{
	uint8_t cmd[4];
	char data[12] = {0};

	I("%s:IC_TYPE =%d\n", __func__, IC_TYPE);

	if (IC_TYPE == HX_83100_SERIES_PWON) {
		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
		himax_register_read(client, cmd, 1, data);

		ic_data->HX_RX_NUM				= data[1];
		ic_data->HX_TX_NUM				= data[2];
		ic_data->HX_MAX_PT				= data[3];

		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
		himax_register_read(client, cmd, 1, data);

		if ((data[1] & 0x04) == 0x04)
			ic_data->HX_XY_REVERSE = true;
		else
			ic_data->HX_XY_REVERSE = false;

		ic_data->HX_Y_RES = data[3]*256;
		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
		himax_register_read(client, cmd, 1, data);
		ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[0];
		ic_data->HX_X_RES = data[1]*256 + data[2];
		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
		himax_register_read(client, cmd, 1, data);
		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 = 29;
		if (ic_data->HX_TX_NUM > 20)
			ic_data->HX_TX_NUM = 16;
		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;
#ifdef HX_EN_MUT_BUTTON
		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
		himax_register_read(client, cmd, 1, data);
		ic_data->HX_BT_NUM				= data[3];
#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);
	} 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;
	}
}

void himax_read_FW_ver(struct i2c_client *client)
{
	uint8_t cmd[4];
	uint8_t data[64];

	/*=====================================
	Read FW version : 0x0000_E303
	=====================================*/
	cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
	himax_register_read(client, cmd, 1, data);

	ic_data->vendor_config_ver = data[3] << 8;

	cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
	himax_register_read(client, cmd, 1, data);

	ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
	I("CFG_VER : %X\n", ic_data->vendor_config_ver);

	cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
	himax_register_read(client, cmd, 1, data);

	ic_data->vendor_fw_ver = data[0]<<8 | data[1];
	I("FW_VER : %X\n", ic_data->vendor_fw_ver);

}

bool himax_ic_package_check(struct i2c_client *client)
{
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
	uint8_t cmd[3];
	uint8_t data[3];

	memset(cmd, 0x00, sizeof(cmd));
	memset(data, 0x00, sizeof(data));

	if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
		return false;

	if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
		return false;

	if ((data[0] == 0x85 && data[1] == 0x29)) {
		IC_TYPE = HX_85XX_F_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 64901;  /*0xFD85*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 64902;  /*0xFD86*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 64928;   /*0xFDA0*/
		CFG_VER_MAJ_FLASH_LENG = 12;
		CFG_VER_MIN_FLASH_ADDR = 64940;   /*0xFDAC*/
		CFG_VER_MIN_FLASH_LENG = 12;
		I("Himax IC package 852x F\n");
	}
	if ((data[0] == 0x85 && data[1] == 0x30)
		|| (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) {
		IC_TYPE = HX_85XX_E_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 133;	/*0x0085*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 160;	/*0x00A0*/
		CFG_VER_MAJ_FLASH_LENG = 12;
		CFG_VER_MIN_FLASH_ADDR = 172;	/*0x00AC*/
		CFG_VER_MIN_FLASH_LENG = 12;
		I("Himax IC package 852x E\n");
	} else if ((data[0] == 0x85 && data[1] == 0x31)) {
		IC_TYPE = HX_85XX_ES_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 133;  /*0x0085*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 160;   /*0x00A0*/
		CFG_VER_MAJ_FLASH_LENG = 12;
		CFG_VER_MIN_FLASH_ADDR = 172;   /*0x00AC*/
		CFG_VER_MIN_FLASH_LENG = 12;
		I("Himax IC package 852x ES\n");
	} else if ((data[0] == 0x85 && data[1] == 0x28)
		|| (cmd[0] == 0x04 && cmd[1] == 0x85
		&& (cmd[2] == 0x26 || cmd[2] == 0x27
		|| cmd[2] == 0x28))) {
		IC_TYPE = HX_85XX_D_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 133;    /*0x0085*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 134;   /*0x0086*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 160;  /*0x00A0*/
		CFG_VER_MAJ_FLASH_LENG = 12;
		CFG_VER_MIN_FLASH_ADDR = 172;  /* 0x00AC*/
		CFG_VER_MIN_FLASH_LENG = 12;
		I("Himax IC package 852x D\n");
	} else if ((data[0] == 0x85 && data[1] == 0x23) ||
		(cmd[0] == 0x03 && cmd[1] == 0x85 &&
		(cmd[2] == 0x26 || cmd[2] == 0x27 ||
		cmd[2] == 0x28 || cmd[2] == 0x29))) {
		IC_TYPE = HX_85XX_C_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 134;                   /*0x0086*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 135;                   /*0x0087*/
		CFG_VER_MAJ_FLASH_LENG = 12;
		CFG_VER_MIN_FLASH_ADDR = 147;                   /*0x0093*/
		CFG_VER_MIN_FLASH_LENG = 12;
		I("Himax IC package 852x C\n");
	} else if ((data[0] == 0x85 && data[1] == 0x26) ||
		(cmd[0] == 0x02 && cmd[1] == 0x85 &&
		(cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
		IC_TYPE                = HX_85XX_B_SERIES_PWON;
		IC_CHECKSUM            = HX_TP_BIN_CHECKSUM_SW;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 728;                   /*0x02D8*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 692;                   /*0x02B4*/
		CFG_VER_MAJ_FLASH_LENG = 3;
		CFG_VER_MIN_FLASH_ADDR = 704;                   /*0x02C0*/
		CFG_VER_MIN_FLASH_LENG = 3;
		I("Himax IC package 852x B\n");
	} else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
		cmd[1] == 0x85 && cmd[2] == 0x19)) {
		IC_TYPE     = HX_85XX_A_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
		I("Himax IC package 852x A\n");
	} else {
		E("Himax IC package incorrect!!\n");
	}
#else
		IC_TYPE = HX_83100_SERIES_PWON;
		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
		/*Himax: Set FW and CFG Flash Address*/
		FW_VER_MAJ_FLASH_ADDR = 57384;   /*0xE028*/
		FW_VER_MAJ_FLASH_LENG = 1;
		FW_VER_MIN_FLASH_ADDR = 57385;   /*0xE029*/
		FW_VER_MIN_FLASH_LENG = 1;
		CFG_VER_MAJ_FLASH_ADDR = 58115;  /*0xE303*/
		CFG_VER_MAJ_FLASH_LENG = 1;
		CFG_VER_MIN_FLASH_ADDR = 58116;  /*0xE304*/
		CFG_VER_MIN_FLASH_LENG = 1;
		I("Himax IC package 83100_in\n");

#endif
	return true;
}

void himax_read_event_stack(struct i2c_client *client,
uint8_t *buf, uint8_t length)
{
	uint8_t cmd[4];

	cmd[3] = 0x90; cmd[2] = 0x06;
	cmd[1] = 0x00; cmd[0] = 0x00;
	if (i2c_himax_write(client, 0x00,
		cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
	}

	cmd[0] = 0x00;
	if (i2c_himax_write(client, 0x0C,
		cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
	}

	i2c_himax_read(client, 0x08,
	buf, length, HIMAX_I2C_RETRY_TIMES);
}

/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data)
{
	uint8_t tmpbyte[2];

	if (i2c_himax_write(private_ts->client, 0x00,
		&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client, 0x01,
		&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client, 0x02,
		&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client,
		0x03, &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client,
		0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client,
		0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client,
		0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client,
		0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (isBusrtOn == false) {
		tmpbyte[0] = 0x01;
		if (i2c_himax_write(private_ts->client,
			0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return;
		}
	}
}
#endif
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static void himax_83100_Flash_Burst_Write
(uint8_t *reg_byte, uint8_t *write_data)
{
    /*uint8_t tmpbyte[2];*/
	int i = 0;

	if (i2c_himax_write(private_ts->client, 0x00,
		&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client, 0x01,
		&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client, 0x02,
		&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

	if (i2c_himax_write(private_ts->client, 0x03,
		&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
	}

    /*Write 256 bytes with continue burst mode*/
	for (i = 0 ; i < 256 ; i = i + 4) {
		if (i2c_himax_write(private_ts->client,
			0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return;
		}

		if (i2c_himax_write(private_ts->client, 0x05,
			&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return;
		}

		if (i2c_himax_write(private_ts->client, 0x06,
			&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return;
		}

		if (i2c_himax_write(private_ts->client, 0x07,
			&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
			E("%s: i2c access fail!\n", __func__);
			return;
		}
	}

    /*if (isBusrtOn == false)
    {
       tmpbyte[0] = 0x01;
		if (i2c_himax_write(private_ts->client,
		0x0C, &tmpbyte[0], 1, 3) < 0) {
		E("%s: i2c access fail!\n", __func__);
		return;
    }*/

}
#endif

/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
{
	uint8_t tmp_addr[4];
	uint8_t tmp_data[4];
	uint8_t out_buffer[20];
	uint8_t in_buffer[260];

	int fail_addr = 0, fail_cnt = 0;
	int page_prog_start = 0;
	int i = 0;

	himax_interface_on(private_ts->client);
	himax_burst_enable(private_ts->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_83100_Flash_Write(tmp_addr, tmp_data);

	for (page_prog_start = 0; page_prog_start < FW_Size;
	page_prog_start = page_prog_start + 256) {
		/*=====================================
		SPI Transfer Control
		Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
		Set read start address  : 0x8000_0028 ==> 0x0000_0000
		Set command			   : 0x8000_0024 ==> 0x0000_003B
		=====================================*/
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
		tmp_data[3] = 0x69; tmp_data[2] = 0x40;
		tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
		himax_83100_Flash_Write(tmp_addr, tmp_data);

		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
		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_83100_Flash_Write(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] = 0x3B;
		himax_83100_Flash_Write(tmp_addr, tmp_data);

		/*==================================
		AHB_I2C Burst Read
		Set SPI data register : 0x8000_002C ==> 0x00
		==================================*/
		out_buffer[0] = 0x2C;
		out_buffer[1] = 0x00;
		out_buffer[2] = 0x00;
		out_buffer[3] = 0x80;
		i2c_himax_write(private_ts->client, 0x00,
		out_buffer, 4, HIMAX_I2C_RETRY_TIMES);

		/*==================================
		Read access : 0x0C ==> 0x00
		==================================*/
		out_buffer[0] = 0x00;
		i2c_himax_write(private_ts->client, 0x0C,
		out_buffer, 1, HIMAX_I2C_RETRY_TIMES);

		/*==================================
		Read 128 bytes two times
		==================================*/
		i2c_himax_read(private_ts->client, 0x08,
		in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
		for (i = 0; i < 128; i++)
			flash_buffer[i + page_prog_start] = in_buffer[i];

		i2c_himax_read(private_ts->client, 0x08,
		in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
		for (i = 0; i < 128; i++)
			flash_buffer[(i + 128)
			+ page_prog_start] = in_buffer[i];

		/*tmp_addr[3] = 0x80;
		tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
		himax_register_read(tmp_addr, 32, out in_buffer);
		for (int i = 0; i < 128; i++)
			  flash_buffer[i + page_prog_start] = in_buffer[i];
		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
		tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
		himax_register_read(tmp_addr, 32, out in_buffer);
		for (int i = 0; i < 128; i++)
			  flash_buffer[i + page_prog_start] = in_buffer[i];
		*/
		I("%s:Verify Progress: %x\n", __func__, page_prog_start);
	}

	fail_cnt = 0;
	for (i = 0; i < FW_Size; i++) {
		if (FW_File[i] != flash_buffer[i]) {
			if (fail_cnt == 0)
				fail_addr = i;

			fail_cnt++;
			/*E("%s Fail Block:%x\n", __func__, i);
			return false;*/
		}
	}
	if (fail_cnt > 0) {
		E("%s:Start Fail Block:%x and fail block count=%x\n",
		__func__, fail_addr, fail_cnt);
		return false;
	}

	I("%s:Byte read verify pass.\n", __func__);
	return true;

}
#endif

void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data)
{
	int i;
	int cnt = 0;
	unsigned char tmp_addr[4];
	unsigned char tmp_data[4];
	uint8_t max_i2c_size = 32;
	int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
	int total_size_4bytes = total_size / 4;
	int total_read_times = 0;
	unsigned long address = 0x08000468;

	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
	tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
	himax_flash_write_burst(client, tmp_addr, tmp_data);
	do {
		cnt++;
		himax_register_read(client, tmp_addr, 1, tmp_data);
		usleep_range(9999, 10000);
	} while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
	if (total_size_4bytes % max_i2c_size == 0)
		total_read_times = total_size_4bytes / max_i2c_size;
	else
		total_read_times = total_size_4bytes / max_i2c_size + 1;

	for (i = 0 ; i < (total_read_times) ; i++) {
		if (total_size_4bytes >= max_i2c_size) {
			himax_register_read(client, tmp_addr,
			max_i2c_size,
			&info_data[i*max_i2c_size*4]);
			total_size_4bytes = total_size_4bytes - max_i2c_size;
		} else {
			himax_register_read(client, tmp_addr,
			total_size_4bytes % max_i2c_size,
			&info_data[i*max_i2c_size*4]);
		}
		address += max_i2c_size * 4;
		tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF);
		tmp_addr[0] = (uint8_t)((address) & 0x00FF);
	}
	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
	tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
	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);
}
/*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 = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1;
	else
		RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1;

	return RawDataLen;
}

bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length)
{
	uint8_t cmd[4];

	if (length > 56)
		length = 124;
	/*=====================
	AHB I2C Burst Read
	=====================*/
	cmd[0] = 0x31;
	if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		goto err_workqueue_out;
	}

	cmd[0] = 0x10;
	if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		goto err_workqueue_out;
	}
	/*=====================
	Read event stack
	=====================*/
	cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
	if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		goto err_workqueue_out;
	}

	cmd[0] = 0x00;
	if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
		E("%s: i2c access fail!\n", __func__);
		goto err_workqueue_out;
	}
	i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
	return 1;

err_workqueue_out:
	return 0;
}

bool post_read_event_stack(struct i2c_client *client)
{
	return 1;
}
bool diag_check_sum(uint8_t hx_touch_info_size,
uint8_t *buf) /*return checksum value*/
{
	uint16_t check_sum_cal = 0;
	int i;

	/*Check 124th byte CRC*/
	for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2)
		check_sum_cal += (buf[i + 1] * 256 + buf[i]);

	if (check_sum_cal % 0x10000 != 0) {
		I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n",
		__func__, check_sum_cal, hx_touch_info_size);
		return 0;
	}
	return 1;
}

void diag_parse_raw_data(int hx_touch_info_size,
int RawDataLen, int mul_num, int self_num, uint8_t *buf,
uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
{
	int RawDataLen_word;
	int index = 0;
	int temp1, temp2, i;

	if (buf[hx_touch_info_size] == 0x3A &&
		buf[hx_touch_info_size + 1] == 0xA3 &&
		buf[hx_touch_info_size + 2] > 0 &&
		buf[hx_touch_info_size + 3] == diag_cmd + 5) {
		RawDataLen_word = RawDataLen / 2;
		index = (buf[hx_touch_info_size + 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);*/
		for (i = 0; i < RawDataLen_word; i++) {
			temp1 = index + i;

			if (temp1 < mul_num) { /*mutual*/
					/*4: RawData Header, 1:HSB */
					mutual_data[index + i]
					= buf[i*2 + hx_touch_info_size + 4 + 1]
					* 256
					+ buf[i * 2 + hx_touch_info_size + 4];
			} else { /*self*/
				temp1 = i + index;
				temp2 = self_num + mul_num;

				if (temp1 >= temp2)
					break;

				/*4: RawData Header*/
				self_data[i + index - mul_num]
				= buf[i * 2 + hx_touch_info_size + 4];
				self_data[i + index - mul_num + 1]
				= buf[i * 2 + hx_touch_info_size + 4 + 1];
			}
		}
	} else {
		I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
			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);
	}
}
