bool fimc_is_ois_read_userdata(struct fimc_is_core *core)
{
	u8 SendData[2], RcvData[256];
	struct i2c_client *client = core->client1;

	if (core->use_ois_hsi2c) {
	    fimc_is_ois_i2c_config(core->client1, true);
	}

	fimc_is_ois_i2c_write(client ,0x000F, 0x40);
	SendData[0] = 0x00;
	SendData[1] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x0010, SendData, 4);
	fimc_is_ois_i2c_write(client ,0x000E, 0x04);

	fimc_is_ois_i2c_read(client, 0x000E, &RcvData[0]);
	if (RcvData[0] == 0x14) {
		fimc_is_ois_i2c_read_multi(client, 0x0100, RcvData, FW_TRANS_SIZE);
		if (core->use_ois_hsi2c) {
			fimc_is_ois_i2c_config(core->client1, false);
		}
		memcpy(ois_uinfo.header_ver, RcvData, 6);
		return true;
	} else {
		if (core->use_ois_hsi2c) {
			fimc_is_ois_i2c_config(core->client1, false);
		}
		return false;
	}
}
bool fimc_is_ois_diff_test(struct fimc_is_core *core, int *x_diff, int *y_diff)
{
	int ret = 0;
	u8 val = 0, x = 0, y = 0;
	u16 x_min = 0, y_min = 0, x_max = 0, y_max = 0;
	int retries = 20, default_diff = 1100;
	u8 read_x[2], read_y[2];
	struct exynos_platform_fimc_is *core_pdata = NULL;

	core_pdata = dev_get_platdata(fimc_is_dev);
	if (!core_pdata) {
		err("core->pdata is null");
		return false;
	}

#ifdef CONFIG_AF_HOST_CONTROL
	fimc_is_af_move_lens(core);
	msleep(30);
#endif

	info("(%s) : E\n", __FUNCTION__);
	if (core_pdata->use_ois_hsi2c) {
		fimc_is_ois_i2c_config(core->client1, true);
	}

	ret = fimc_is_ois_i2c_read_multi(core->client1, 0x021A, read_x, 2);
	ret |= fimc_is_ois_i2c_read_multi(core->client1, 0x021C, read_y, 2);
	if (ret) {
		err("i2c read fail\n");
	}

	ret = fimc_is_ois_i2c_write_multi(core->client1, 0x0022, read_x, 4);
	ret |= fimc_is_ois_i2c_write_multi(core->client1, 0x0024, read_y, 4);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0002, 0x02);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x01);
	if (ret) {
		err("i2c write fail\n");
	}
	msleep(400);
	info("(%s) : OIS Position = Center\n", __FUNCTION__);

	ret = fimc_is_ois_i2c_write(core->client1, 0x0000, 0x00);
	if (ret) {
		err("i2c write fail\n");
	}

	do {
		ret = fimc_is_ois_i2c_read(core->client1, 0x0001, &val);
		if (ret != 0) {
			break;
		}
		msleep(10);
		if (--retries < 0) {
			err("Read register failed!!!!, data = 0x%04x\n", val);
			break;
		}
	} while (val != 1);

	ret = fimc_is_ois_i2c_write(core->client1, 0x0034, 0x64);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0230, 0x64);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0231, 0x00);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0232, 0x64);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0233, 0x00);
	if (ret) {
		err("i2c write fail\n");
	}

	ret = fimc_is_ois_i2c_read(core->client1, 0x0034, &val);
	info("OIS[read_val_0x0034::0x%04x]\n", val);
	ret |= fimc_is_ois_i2c_read(core->client1, 0x0230, &val);
	info("OIS[read_val_0x0230::0x%04x]\n", val);
	ret |= fimc_is_ois_i2c_read(core->client1, 0x0231, &val);
	info("OIS[read_val_0x0231::0x%04x]\n", val);
	ret |= fimc_is_ois_i2c_read(core->client1, 0x0232, &val);
	info("OIS[read_val_0x0232::0x%04x]\n", val);
	ret |= fimc_is_ois_i2c_read(core->client1, 0x0233, &val);
	info("OIS[read_val_0x0233::0x%04x]\n", val);
	if (ret) {
		err("i2c read fail\n");
	}

	ret = fimc_is_ois_i2c_write(core->client1, 0x020E, 0x00);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x020F, 0x00);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0210, 0x50);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0211, 0x50);
	if (ret) {
		err("i2c write fail\n");
	}
	ret = fimc_is_ois_i2c_write(core->client1, 0x0013, 0x01);
	if (ret) {
		err("i2c write fail\n");
	}

#if 0
	ret = fimc_is_ois_i2c_write(core->client1, 0x0012, 0x01);
	if (ret) {
		err("i2c write fail\n");
	}

	retries = 30;
	do { //polarity check
		ret = fimc_is_ois_i2c_read(core->client1, 0x0012, &val);
		if (ret != 0) {
			break;
		}
		msleep(100);
		if (--retries < 0) {
			err("Polarity check is not done or not [read_val_0x0012::0x%04x]\n", val);
			break;
		}
	} while (val);
	fimc_is_ois_i2c_read(core->client1, 0x0200, &val);
	err("OIS[read_val_0x0200::0x%04x]\n", val);
#endif

	retries = 120;
	do {
		ret = fimc_is_ois_i2c_read(core->client1, 0x0013, &val);
		if (ret != 0) {
			break;
		}
		msleep(100);
		if (--retries < 0) {
			err("Read register failed!!!!, data = 0x%04x\n", val);
			break;
		}
	} while (val);

	fimc_is_ois_i2c_read(core->client1, 0x0004, &val);
	info("OIS[read_val_0x0004::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0005, &val);
	info("OIS[read_val_0x0005::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0006, &val);
	info("OIS[read_val_0x0006::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0022, &val);
	info("OIS[read_val_0x0022::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0023, &val);
	info("OIS[read_val_0x0023::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0024, &val);
	info("OIS[read_val_0x0024::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0025, &val);
	info("OIS[read_val_0x0025::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0200, &val);
	info("OIS[read_val_0x0200::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x020E, &val);
	info("OIS[read_val_0x020E::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x020F, &val);
	info("OIS[read_val_0x020F::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0210, &val);
	info("OIS[read_val_0x0210::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0211, &val);
	info("OIS[read_val_0x0211::0x%04x]\n", val);

	fimc_is_ois_i2c_read(core->client1, 0x0212, &val);
	x = val;
	info("OIS[read_val_0x0212::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0213, &val);
	x_max = (val << 8) | x;
	info("OIS[read_val_0x0213::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0214, &val);
	x = val;
	info("OIS[read_val_0x0214::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0215, &val);
	x_min = (val << 8) | x;
	info("OIS[read_val_0x0215::0x%04x]\n", val);

	fimc_is_ois_i2c_read(core->client1, 0x0216, &val);
	y = val;
	info("OIS[read_val_0x0216::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0217, &val);
	y_max = (val << 8) | y;
	info("OIS[read_val_0x0217::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0218, &val);
	y = val;
	info("OIS[read_val_0x0218::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x0219, &val);
	y_min = (val << 8) | y;
	info("OIS[read_val_0x0219::0x%04x]\n", val);

	fimc_is_ois_i2c_read(core->client1, 0x021A, &val);
	info("OIS[read_val_0x021A::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x021B, &val);
	info("OIS[read_val_0x021B::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x021C, &val);
	info("OIS[read_val_0x021C::0x%04x]\n", val);
	fimc_is_ois_i2c_read(core->client1, 0x021D, &val);
	info("OIS[read_val_0x021D::0x%04x]\n", val);

	*x_diff = abs(x_max - x_min);
	*y_diff = abs(y_max - y_min);

	info("(%s) : X (default_diff:%d)(%d,%d)\n", __FUNCTION__,
			default_diff, *x_diff, *y_diff);

	ret = fimc_is_ois_i2c_read_multi(core->client1, 0x021A, read_x, 2);
	ret |= fimc_is_ois_i2c_read_multi(core->client1, 0x021C, read_y, 2);
	if (ret) {
		err("i2c read fail\n");
	}

	ret = fimc_is_ois_i2c_write_multi(core->client1, 0x0022, read_x, 4);
	ret |= fimc_is_ois_i2c_write_multi(core->client1, 0x0024, read_y, 4);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0002, 0x02);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x01);
	msleep(400);
	ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x00);
	if (ret) {
		err("i2c write fail\n");
	}

	if (core_pdata->use_ois_hsi2c) {
		fimc_is_ois_i2c_config(core->client1, false);
	}

	if (*x_diff > default_diff  && *y_diff > default_diff) {
		return true;
	} else {
		return false;
	}
}
void fimc_is_ois_fw_update(struct fimc_is_core *core)
{
	u8 SendData[256], RcvData;
	u16 RcvDataShort = 0;
	u8 data[2] = {0, };
	int block, i, position = 0;
	u16 checkSum;
	u8 *buf = NULL;
	int ret = 0, sum_size = 0, retry_count = 3;
	int module_ver = 0, binary_ver = 0;
	u8 error_status = 0;
	bool forced_update = false, crc_result = false;
	bool need_reset = false;
	struct i2c_client *client = core->client1;
	struct exynos_platform_fimc_is *core_pdata = NULL;

	core_pdata = dev_get_platdata(fimc_is_dev);
	if (!core_pdata) {
		err("core->pdata is null");
		return;
	}

	/* OIS Status Check */
	error_status = fimc_is_ois_read_status(core);
	if (error_status == 0x01) {
		forced_update = true;
	}

	ret = fimc_is_ois_fw_version(core);
	if (!ret) {
		err("Failed to read ois fw version.");
		return;
	}
	fimc_is_ois_read_userdata(core);

	if (ois_minfo.header_ver[0] == '6') {
		if (ois_minfo.header_ver[2] == 'C' || ois_minfo.header_ver[2] == 'E'
			|| ois_minfo.header_ver[2] == 'G' || ois_minfo.header_ver[2] == 'I') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
		} else if (ois_minfo.header_ver[2] == 'D' || ois_minfo.header_ver[2] == 'F'
			|| ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
		}
	} else if (ois_minfo.header_ver[0] == '8') {
		if (ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC_2, &buf);
		}
	} else {
		info("Module FW version does not matched with phone FW version.\n");
		strcpy(ois_pinfo.header_ver, "NULL");
		return;
	}
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)", ret);
		goto p_err;
	}

	if (ois_minfo.header_ver[2] != CAMERA_OIS_DOM_UPDATE_VERSION
		&& ois_minfo.header_ver[2] != CAMERA_OIS_SEC_UPDATE_VERSION) {
		info("Do not update ois Firmware. FW version is low.\n");
		goto p_err;
	}

	if (buf == NULL) {
		err("buf is NULL. OIS FW Update failed.");
		return;
	}

	if (!forced_update) {
		if (ois_uinfo.header_ver[0] == 0xFF && ois_uinfo.header_ver[1] == 0xFF &&
			ois_uinfo.header_ver[2] == 0xFF) {
			err("OIS userdata is not valid.");
			goto p_err;
		}
	}

	/*Update OIS FW when Gyro sensor/Driver IC/ Core version is same*/
	if (!forced_update) {
		if (!fimc_is_ois_version_compare(ois_minfo.header_ver, ois_pinfo.header_ver,
			ois_uinfo.header_ver)) {
			err("Does not update ois fw. OIS module ver = %s, binary ver = %s, userdata ver = %s",
				ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);
			goto p_err;
		}
	} else {
		if (!fimc_is_ois_version_compare_default(ois_minfo.header_ver, ois_pinfo.header_ver)) {
			err("Does not update ois fw. OIS module ver = %s, binary ver = %s",
				ois_minfo.header_ver, ois_pinfo.header_ver);
			goto p_err;
		}
	}

	crc_result = fimc_is_ois_crc_check(core, buf);
	if (crc_result == false) {
		err("OIS CRC32 error.\n");
		goto p_err;
	}

	if (!fw_sdcard && !forced_update) {
		module_ver = fimc_is_ois_fw_revision(ois_minfo.header_ver);
		binary_ver = fimc_is_ois_fw_revision(ois_pinfo.header_ver);
		if (binary_ver <= module_ver) {
			err("OIS module ver = %d, binary ver = %d", module_ver, binary_ver);
			goto p_err;
		}
	}
	info("OIS fw update started. module ver = %s, binary ver = %s, userdata ver = %s\n",
		ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);

	if (core_pdata->use_ois_hsi2c) {
		fimc_is_ois_i2c_config(core->client1, true);
	}

retry:
	if (need_reset) {
		fimc_is_ois_gpio_off(core);
		msleep(30);
		fimc_is_ois_gpio_on(core);
		msleep(150);
	}

	fimc_is_ois_i2c_read(client, 0x01, &RcvData); /* OISSTS Read */

	if (RcvData != 0x01) {/* OISSTS != IDLE */
		err("RCV data return!!");
		goto p_err;
	}

	/* Update a Boot Program */
	/* SET FWUP_CTRL REG */
	fimc_is_ois_i2c_write(client ,0x000C, 0x0B);
	msleep(20);

	position = 0;
	/* Write Boot Data */
	for (block = 4; block < 8; block++) {       /* 0x1000 - 0x1FFF */
		for (i = 0; i < 4; i++) {
			memcpy(SendData, bootCode + position, FW_TRANS_SIZE);
			fimc_is_ois_i2c_write_multi(client, 0x0100, SendData, FW_TRANS_SIZE + 2);
			position += FW_TRANS_SIZE;
			if (i == 0 ) {
				msleep(20);
			} else if ((i == 1) || (i == 2)) {	 /* Wait Erase and Write process */
				 msleep(10);		/* Wait Write process */
			} else {
				msleep(15); /* Wait Write and Verify process */
			}
		}
	}

	/* CHECKSUM (Boot) */
	sum_size = OIS_BOOT_FW_SIZE;
	checkSum = fimc_is_ois_calc_checksum(&bootCode[0], sum_size);
	SendData[0] = (checkSum & 0x00FF);
	SendData[1] = (checkSum & 0xFF00) >> 8;
	SendData[2] = 0x00;
	SendData[3] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);
	msleep(10);			 /* (RUMBA Self Reset) */

	fimc_is_ois_i2c_read_multi(client, 0x06, data, 2); /* Error Status read */
	info("%s: OISSTS Read = 0x%02x%02x\n", __func__, data[1], data[0]);

	if (data[1] == 0x00 && data[0] == 0x01) {					/* Boot F/W Update Error check */
		/* Update a User Program */
		/* SET FWUP_CTRL REG */
		position = 0;
		SendData[0] = 0x09;		/* FWUP_DSIZE=256Byte, FWUP_MODE=PROG, FWUPEN=Start */
		fimc_is_ois_i2c_write(client, 0x0C, SendData[0]);		/* FWUPCTRL REG(0x000C) 1Byte Send */

		/* Write UserProgram Data */
		for (block = 4; block <= 27; block++) {		/* 0x1000 -0x 6FFF (RUMBA-SA)*/
			for (i = 0; i < 4; i++) {
				memcpy(SendData, &progCode[position], (size_t)FW_TRANS_SIZE);
				fimc_is_ois_i2c_write_multi(client, 0x100, SendData, FW_TRANS_SIZE + 2); /* FLS_DATA REG(0x0100) 256Byte Send */
				position += FW_TRANS_SIZE;
				if (i ==0 ) {
					msleep(20);		/* Wait Erase and Write process */
				} else if ((i==1) || (i==2)) {
					msleep(10);		/* Wait Write process */
				} else {
					msleep(15);		/* Wait Write and Verify process */
				}
			}
		}

		/* CHECKSUM (Program) */
		sum_size = OIS_PROG_FW_SIZE;
		checkSum = fimc_is_ois_calc_checksum(&progCode[0], sum_size);
		SendData[0] = (checkSum & 0x00FF);
		SendData[1] = (checkSum & 0xFF00) >> 8;
		SendData[2] = 0;		/* Don't Care */
		SendData[3] = 0x80;		/* Self Reset Request */

		fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);  /* FWUP_CHKSUM REG(0x0008) 4Byte Send */
		msleep(60);		/* (Wait RUMBA Self Reset) */
		fimc_is_ois_i2c_read(client, 0x6, (u8*)&RcvDataShort); /* Error Status read */

		if (RcvDataShort == 0x0000) {
			/* F/W Update Success Process */
			info("%s: OISLOG OIS program update success\n", __func__);
		} else {
			/* Retry Process */
			if (retry_count > 0) {
				err("OISLOG OIS program update fail, retry update. count = %d", retry_count);
				retry_count--;
				need_reset = true;
				goto retry;
			}

			/* F/W Update Error Process */
			err("OISLOG OIS program update fail");
			goto p_err;
		}
	} else {
bool fimc_is_ois_read_userdata(struct fimc_is_core *core)
{
	u8 SendData[2], RcvData[256];
	u8 ois_shift_info = 0;

	struct i2c_client *client = core->client1;
	struct exynos_platform_fimc_is *core_pdata = NULL;

	core_pdata = dev_get_platdata(fimc_is_dev);
	if (!core_pdata) {
		err("core->pdata is null");
		return false;
	}

	if (core_pdata->use_ois_hsi2c) {
	    fimc_is_ois_i2c_config(core->client1, true);
	}

	/* Read OIS Shift CAL */
	fimc_is_ois_i2c_write(client ,0x000F, 0x0E);
	SendData[0] = 0x00;
	SendData[1] = 0x04;
	fimc_is_ois_i2c_write_multi(client, 0x0010, SendData, 4);
	fimc_is_ois_i2c_write(client ,0x000E, 0x04);

	fimc_is_ois_i2c_read(client, 0x0100, &ois_shift_info);
	info("OIS Shift Info : 0x%x\n", ois_shift_info);

	if (ois_shift_info == 0x11) {
		u16 ois_shift_checksum = 0;
		u16 ois_shift_x_diff = 0;
		u16 ois_shift_y_diff = 0;
		s16 ois_shift_x_cal = 0;
		s16 ois_shift_y_cal = 0;
		int i = 0;
		u8 calData[2];

		/* OIS Shift CheckSum */
		calData[0] = 0;
		calData[1] = 0;
		fimc_is_ois_i2c_read_multi(client, 0x0102, calData, 2);
		ois_shift_checksum = (calData[1] << 8)|(calData[0]);
		info("OIS Shift CheckSum = 0x%x\n", ois_shift_checksum);

		/* OIS Shift X Diff */
		calData[0] = 0;
		calData[1] = 0;
		fimc_is_ois_i2c_read_multi(client, 0x0104, calData, 2);
		ois_shift_x_diff = (calData[1] << 8)|(calData[0]);
		info("OIS Shift X Diff = 0x%x\n", ois_shift_x_diff);

		/* OIS Shift Y Diff */
		calData[0] = 0;
		calData[1] = 0;
		fimc_is_ois_i2c_read_multi(client, 0x0106, calData, 2);
		ois_shift_y_diff = (calData[1] << 8)|(calData[0]);
		info("OIS Shift Y Diff = 0x%x\n", ois_shift_y_diff);

		/* OIS Shift CAL DATA */
		for (i = 0; i< 9; i++) {
			calData[0] = 0;
			calData[1] = 0;
			fimc_is_ois_i2c_read_multi(client, 0x0108 + i*2, calData, 2);
			ois_shift_x_cal = (calData[1] << 8)|(calData[0]);

			calData[0] = 0;
			calData[1] = 0;
			fimc_is_ois_i2c_read_multi(client, 0x0120 + i*2, calData, 2);
			ois_shift_y_cal = (calData[1] << 8)|(calData[0]);
			info("OIS CAL[%d]:X[%d], Y[%d]\n", i, ois_shift_x_cal, ois_shift_y_cal);
		}
	}

	/* Read OIS FW */
	fimc_is_ois_i2c_write(client ,0x000F, 0x40);
	SendData[0] = 0x00;
	SendData[1] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x0010, SendData, 4);
	fimc_is_ois_i2c_write(client ,0x000E, 0x04);

	fimc_is_ois_i2c_read(client, 0x000E, &RcvData[0]);
	if (RcvData[0] == 0x14) {
		fimc_is_ois_i2c_read_multi(client, 0x0100, RcvData, FW_TRANS_SIZE);
		if (core_pdata->use_ois_hsi2c) {
			fimc_is_ois_i2c_config(core->client1, false);
		}
		memcpy(ois_uinfo.header_ver, RcvData, 6);
		return true;
	} else {
		if (core_pdata->use_ois_hsi2c) {
			fimc_is_ois_i2c_config(core->client1, false);
		}
		return false;
	}
}
void fimc_is_ois_fw_update(struct fimc_is_core *core)
{
	u8 SendData[256], RcvData;
	u16 RcvDataShort = 0;
	int block, i, position = 0;
	u16 checkSum;
	u8 *buf = NULL;
	int ret = 0, sum_size = 0;
	int module_ver = 0, binary_ver = 0;
	struct i2c_client *client = core->client1;

	/* OIS Status Check */
	ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME, &buf);
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)\n", ret);
		goto p_err;
	}

	fimc_is_ois_fw_version(core);

	/*Update OIS FW when Gyro sensor/Driver IC/ Core version is same*/
	if (!fimc_is_ois_version_compare(ois_minfo.header_ver, ois_pinfo.header_ver)) {
		err("Does not update ois fw. OIS module ver = %s, binary ver = %s\n", ois_minfo.header_ver, ois_pinfo.header_ver );
		goto p_err;
	}

	module_ver = fimc_is_ois_fw_revision(ois_minfo.header_ver);
	binary_ver = fimc_is_ois_fw_revision(ois_pinfo.header_ver);
	if (binary_ver <= module_ver) {
		err("OIS module ver = %d, binary ver = %d\n", module_ver, binary_ver);
		goto p_err;
	}

	fimc_is_ois_i2c_read(client, 0x01, &RcvData); /* OISSTS Read */

	if (RcvData != 0x01) {/* OISSTS != IDLE */
		err("RCV data return!!\n");
		goto p_err;
	}

	/* Update a Boot Program */
	/* SET FWUP_CTRL REG */
	fimc_is_ois_i2c_write(client ,0x000C, 0x0B);

	position = 0;
	/* Write Boot Data */
	for (block = 4; block < 8; block++) {       /* 0x1000 - 0x1FFF */
		for (i = 0; i < 4; i++) {
			memcpy(SendData, bootCode + position, FW_TRANS_SIZE);
			fimc_is_ois_i2c_write_multi(client, 0x0100, SendData, FW_TRANS_SIZE + 2);
			position += FW_TRANS_SIZE;
			if (i == 0 ) {
				msleep(20);
			} else if ((i == 1) || (i == 2)) {	 /* Wait Erase and Write process */
				 msleep(10);		/* Wait Write process */
			} else {
				msleep(15); /* Wait Write and Verify process */
			}
		}
	}

	/* CHECKSUM (Boot) */
	sum_size = OIS_BOOT_FW_SIZE;
	checkSum = fimc_is_ois_calc_checksum(&bootCode[0], sum_size);
	SendData[0] = (checkSum & 0x00FF);
	SendData[1] = (checkSum & 0xFF00) >> 8;
	SendData[2] = 0x00;
	SendData[3] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);
	msleep(10);			 /* (RUMBA Self Reset) */

	fimc_is_ois_i2c_read_multi(client, 0x06, &RcvDataShort); /* Error Status read */
	pr_info("OISSTS Read = 0x%04x\n", RcvDataShort);

	if (RcvDataShort == 0x0001) {					/* Boot F/W Update Error check */
		/* Update a User Program */
		/* SET FWUP_CTRL REG */
		position = 0;
		SendData[0] = 0x09;		/* FWUP_DSIZE=256Byte, FWUP_MODE=PROG, FWUPEN=Start */
		fimc_is_ois_i2c_write(client, 0x0C, SendData[0]);		/* FWUPCTRL REG(0x000C) 1Byte Send */

		/* Write UserProgram Data */
		for (block = 4; block <= 27; block++) {		/* 0x1000 -0x 6FFF (RUMBA-SA)*/
			for (i = 0; i < 4; i++) {
				memcpy(SendData, &progCode[position], (size_t)FW_TRANS_SIZE);
				fimc_is_ois_i2c_write_multi(client, 0x100, SendData, FW_TRANS_SIZE + 2); /* FLS_DATA REG(0x0100) 256Byte Send */
				position += FW_TRANS_SIZE;
				if (i ==0 ) {
					msleep(20);		/* Wait Erase and Write process */
				} else if ((i==1) || (i==2)) {
					msleep(10);		/* Wait Write process */
				} else {
					 msleep(15);		/* Wait Write and Verify process */
				}
			}
		}

		/* CHECKSUM (Program) */
		sum_size = OIS_PROG_FW_SIZE;
		checkSum = fimc_is_ois_calc_checksum(&progCode[0], sum_size);
		SendData[0] = (checkSum & 0x00FF);
		SendData[1] = (checkSum & 0xFF00) >> 8;
		SendData[2] = 0;		/* Don't Care */
		SendData[3] = 0x80;		/* Self Reset Request */

		fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);  /* FWUP_CHKSUM REG(0x0008) 4Byte Send */
		msleep(10);		/* (Wait RUMBA Self Reset) */
		fimc_is_ois_i2c_read(client, 0x6, (u8*)&RcvDataShort); /* Error Status read */

		if (RcvDataShort == 0x0000) {
			/* F/W Update Success Process */
			err("OISLOG OIS program update success\n");
		} else {
			/* F/W Update Error Process */
			err("OISLOG OIS program update fail\n");
		}
	} else {