diff --git a/drivers/Makefile b/drivers/Makefile index 10d91f552fac..214817f9aa25 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -163,6 +163,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \ cam_sensor_module/cam_ois/cam_ois_core.o \ cam_sensor_module/cam_ois/cam_ois_soc.o \ cam_sensor_module/cam_ois/cam_ois_dw9781.o \ + cam_sensor_module/cam_ois/cam_ois_dw9784.o \ cam_sensor_module/cam_ois/cam_ois_aw86006.o \ cam_sensor_module/cam_sensor/cam_sensor_dev.o \ cam_sensor_module/cam_sensor/cam_sensor_core.o \ diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 72e3a6e27de0..82d703bc785d 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -15,9 +15,14 @@ #include "cam_common_util.h" #include "cam_packet_util.h" +#define DW9784_IF_SIZE (512) + extern int dw9781c_check_fw_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize); extern void dw9781_post_firmware_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize); extern int aw86006_firmware_update(struct cam_ois_ctrl_t *o_ctrl, const struct firmware *fw); +extern int dw9784_check_fw_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize); +extern void dw9784_post_firmware_download(struct camera_io_master * io_master_info); +extern int dw9784_check_if_download(struct camera_io_master * io_master_info); int32_t cam_ois_construct_default_power_setting( struct cam_sensor_power_ctrl_t *power_info) @@ -433,6 +438,13 @@ static int cam_ois_fw_prog_download(struct cam_ois_ctrl_t *o_ctrl) return 0; } CAM_INFO(CAM_OIS, "Firmware download started."); + }else if (strstr(o_ctrl->ois_name, "dw9784")) { + if (!dw9784_check_fw_download(&(o_ctrl->io_master_info), fw->data, fw->size)) { + CAM_INFO(CAM_OIS, "Skip firmware download."); + release_firmware(fw); + return 0; + } + CAM_INFO(CAM_OIS, "Firmware download started."); } else if (strstr(o_ctrl->ois_name, "aw86006")) { mutex_lock(&o_ctrl->aw_ois_mutex); @@ -474,23 +486,40 @@ static int cam_ois_fw_prog_download(struct cam_ois_ctrl_t *o_ctrl) int regAddrOffset = 0; if(o_ctrl->ois_fw_inc_addr == 1) regAddrOffset = total_idx/o_ctrl->ois_fw_data_type + packet_idx; - - i2c_reg_setting.reg_setting[packet_idx].reg_addr = - o_ctrl->opcode.prog + regAddrOffset; - if (o_ctrl->ois_fw_data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + if (strstr(o_ctrl->ois_name, "dw9784") && total_idx >= total_bytes - DW9784_IF_SIZE) { + i2c_reg_setting.reg_setting[packet_idx].reg_addr = o_ctrl->opcode.prog + regAddrOffset - (total_bytes - DW9784_IF_SIZE)/2; i2c_reg_setting.reg_setting[packet_idx].reg_data = (uint32_t)(*ptr << 8) | *(ptr+1); + i2c_reg_setting.reg_setting[packet_idx].delay = 0; + i2c_reg_setting.reg_setting[packet_idx].data_mask = 0; + CAM_DBG(CAM_OIS, "IF OIS_FW Reg:[0x%04x]: 0x%04x P:0x%x", + i2c_reg_setting.reg_setting[packet_idx].reg_addr, + i2c_reg_setting.reg_setting[packet_idx].reg_data, + (ptr-(uint8_t *)fw->data)); } else { - i2c_reg_setting.reg_setting[packet_idx].reg_data = *ptr; + i2c_reg_setting.reg_setting[packet_idx].reg_addr = + o_ctrl->opcode.prog + regAddrOffset; + if (o_ctrl->ois_fw_data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { + i2c_reg_setting.reg_setting[packet_idx].reg_data = (uint32_t)(*ptr << 8) | *(ptr+1); + } else { + i2c_reg_setting.reg_setting[packet_idx].reg_data = *ptr; + } + i2c_reg_setting.reg_setting[packet_idx].delay = 0; + i2c_reg_setting.reg_setting[packet_idx].data_mask = 0; + CAM_DBG(CAM_OIS, "OIS_FW Reg:[0x%04x]: 0x%04x P:0x%x", + i2c_reg_setting.reg_setting[packet_idx].reg_addr, + i2c_reg_setting.reg_setting[packet_idx].reg_data, + (ptr-(uint8_t *)fw->data)); } - i2c_reg_setting.reg_setting[packet_idx].delay = 0; - i2c_reg_setting.reg_setting[packet_idx].data_mask = 0; - CAM_DBG(CAM_OIS, "OIS_FW Reg:[0x%04x]: 0x%04x P:0x%x", - i2c_reg_setting.reg_setting[packet_idx].reg_addr, - i2c_reg_setting.reg_setting[packet_idx].reg_data, - (ptr-(uint8_t *)fw->data)); } i2c_reg_setting.size = packet_idx; if (o_ctrl->ois_fw_inc_addr == 1) { + if (strstr(o_ctrl->ois_name, "dw9784") && total_idx == total_bytes - DW9784_IF_SIZE){ + rc = dw9784_check_if_download(&(o_ctrl->io_master_info)); + if (rc < 0) { + CAM_ERR(CAM_OIS, "dw9784 check if download fail"); + goto release_firmware; + } + } rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), &i2c_reg_setting, 0); } else { @@ -507,6 +536,8 @@ static int cam_ois_fw_prog_download(struct cam_ois_ctrl_t *o_ctrl) if (strstr(o_ctrl->ois_name, "dw9781")) { dw9781_post_firmware_download(&(o_ctrl->io_master_info), fw->data, fw->size); + } else if (strstr(o_ctrl->ois_name, "dw9784")) { + dw9784_post_firmware_download(&(o_ctrl->io_master_info)); } release_firmware: @@ -536,7 +567,8 @@ static int cam_ois_fw_coeff_download(struct cam_ois_ctrl_t *o_ctrl) return -EINVAL; } - if (strstr(o_ctrl->ois_name, "dw9781") || strstr(o_ctrl->ois_name, "aw86006")) { + if (strstr(o_ctrl->ois_name, "dw9781") || strstr(o_ctrl->ois_name, "aw86006") || + strstr(o_ctrl->ois_name, "dw9784")) { CAM_DBG(CAM_OIS, "not need download coeff fw for %s.", o_ctrl->ois_name); return 0; } diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dw9784.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dw9784.c new file mode 100644 index 000000000000..e79847778356 --- /dev/null +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dw9784.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2021 Motorola Mobility LLC. + * + * 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 +#include "cam_ois_core.h" +#include "cam_ois_soc.h" +#include "cam_sensor_util.h" +#include "cam_debug_util.h" +#include "cam_common_util.h" + +#define DW9784_CHIP_ID_ADDRESS 0x7000 +#define DW9784_CHECKSUM_ADDRESS 0x700C +#define DW9784_CHIP_ID 0x9784 +#define FW_VER_CURR_ADDR 0x7001 + +#define EOK 0 + +#define FW_VERSION_OFFSET 10493 +#define FW_CHECKSUM_OFFSET 10495 + +typedef struct +{ + unsigned int driverIc; + unsigned int size; + const uint16_t *fwContentPtr; + uint16_t version; + uint16_t checksum; +} FirmwareContex; + +static FirmwareContex g_dw9784FirmwareContext; + +static int32_t dw9784_cci_write(struct camera_io_master * io_master_info, uint16_t reg, uint16_t val) +{ + int32_t rc = 0; + struct cam_sensor_i2c_reg_array reg_setting; + struct cam_sensor_i2c_reg_setting wr_setting; + + reg_setting.reg_addr = reg; + reg_setting.reg_data = val; + reg_setting.delay = 0; + reg_setting.data_mask = 0; + wr_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD; + wr_setting.data_type = CAMERA_SENSOR_I2C_TYPE_WORD; + wr_setting.reg_setting = ®_setting; + wr_setting.size = 1; + wr_setting.delay = 0; + rc = camera_io_dev_write(io_master_info, &wr_setting); + return rc; +} + +static int32_t dw9784_cci_read(struct camera_io_master * io_master_info, uint16_t reg, uint16_t *val) +{ + int32_t rc = 0; + uint32_t regVal = 0; + rc = camera_io_dev_read(io_master_info, reg, ®Val, CAMERA_SENSOR_I2C_TYPE_WORD, CAMERA_SENSOR_I2C_TYPE_WORD); + if (!rc) { + *val = (uint16_t)regVal; + } + return rc; +} + +static void dw9784_delay_ms(uint32_t ms) +{ + usleep_range(ms*1000, ms*1000+10); + return; +} + +void dw9784_ois_reset(struct camera_io_master * io_master_info) +{ + CAM_INFO(CAM_OIS, "[dw9784_ois_reset] ois reset"); + dw9784_cci_write(io_master_info, 0xD002, 0x0001); /* DW9784_DBGc reset */ + dw9784_delay_ms(4); + dw9784_cci_write(io_master_info, 0xD001, 0x0001); /* Active mode (DSP ON) */ + dw9784_delay_ms(25); /* ST gyro - over wait 25ms, default Servo On */ + dw9784_cci_write(io_master_info, 0xEBF1, 0x56FA); /* User protection release */ +} + +void dw9784_code_pt_off(struct camera_io_master * io_master_info) +{ + CAM_INFO(CAM_OIS, "[dw9784_code_pt_off] start"); + /* release all protection */ + dw9784_cci_write(io_master_info, 0xFD00, 0x5252); + dw9784_delay_ms(1); + CAM_INFO(CAM_OIS, "[dw9784_code_pt_off] finish"); +} + +void dw9784_pid_erase(struct camera_io_master * io_master_info) +{ + CAM_INFO(CAM_OIS, "[dw9784_pid_erase] start pid flash(IF) erase"); + dw9784_cci_write(io_master_info, 0xde03, 0x0000); // page 0 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0008); // page erase + dw9784_delay_ms(10); // need to delay after erase + CAM_INFO(CAM_OIS, "[dw9784_pid_erase] finish"); +} + +void dw9784_fw_eflash_erase(struct camera_io_master * io_master_info) +{ + CAM_INFO(CAM_OIS, "[dw9784_fw_eflash_erase] start fw flash erase"); + dw9784_cci_write(io_master_info, 0xde03, 0x0000); // 4k Sector_0 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase + dw9784_delay_ms(10); // need to delay after erase + + dw9784_cci_write(io_master_info, 0xde03, 0x0008); // 4k Sector_1 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase + dw9784_delay_ms(10); // need to delay after erase + + dw9784_cci_write(io_master_info, 0xde03, 0x0010); // 4k Sector_2 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase + dw9784_delay_ms(10); // need to delay after erase + + dw9784_cci_write(io_master_info, 0xde03, 0x0018); // 4k Sector_3 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase + dw9784_delay_ms(10); // need to delay after erase + + dw9784_cci_write(io_master_info, 0xde03, 0x0020); // 4k Sector_4 + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase + dw9784_delay_ms(10); // need to delay after erase + CAM_INFO(CAM_OIS, "[dw9784_fw_eflash_erase] finish"); +} + +void dw9784_flash_acess(struct camera_io_master * io_master_info) +{ + CAM_INFO(CAM_OIS, "[dw9784_flash_acess] execution"); + /* release all protection */ + dw9784_cci_write(io_master_info, 0xFAFA, 0x98AC); + dw9784_delay_ms(1); + dw9784_cci_write(io_master_info, 0xF053, 0x70BD); + dw9784_delay_ms(1); +} + +int dw9784_whoami_chk(struct camera_io_master * io_master_info) +{ + uint16_t sec_chip_id; + dw9784_cci_write(io_master_info, 0xD000, 0x0001); /* chip enable */ + dw9784_delay_ms(4); + dw9784_cci_write(io_master_info, 0xD001, 0x0000); /* dsp off mode */ + dw9784_delay_ms(1); + + dw9784_flash_acess(io_master_info); /* All protection */ + + dw9784_cci_read(io_master_info, 0xD060, &sec_chip_id); /* 2nd chip id */ + CAM_INFO(CAM_OIS, "[dw9784_ois_ready_check] sec_chip_id : 0x%04x", sec_chip_id); + if(sec_chip_id != 0x0020) + { + CAM_ERR(CAM_OIS, "[dw9784] second_chip_id check fail : 0x%04X", sec_chip_id); + CAM_ERR(CAM_OIS, "[dw9784] second_enter shutdown mode"); + dw9784_cci_write(io_master_info, 0xD000, 0x0000); /* ic */ + return -1; + } + + dw9784_ois_reset(io_master_info); /* ois reset */ + return 0; +} + +int dw9784_checksum_fw_chk(struct camera_io_master * io_master_info) +{ + /* + Bit [0]: FW checksum error + Bit [1]: Module cal. checksum error + Bit [2]: Set cal. checksum error + */ + uint16_t reg_fw_checksum; // 0x700C + uint16_t reg_checksum_status; // 0x700D + + dw9784_cci_read(io_master_info, 0x700C, ®_fw_checksum); + dw9784_cci_read(io_master_info, 0x700D, ®_checksum_status); + + CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] reg_checksum_status : 0x%04X", reg_checksum_status); + CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] reg_fw_checksum : 0x%04X", reg_fw_checksum); + + if( (reg_checksum_status & 0x0001) == 0) + { + CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] fw checksum pass"); + return 0; + }else + { + CAM_ERR(CAM_OIS, "[dw9784_checksum_fw_chk] fw checksum error reg_fw_checksum : 0x%04X", reg_fw_checksum); + return -1; + } +} + +static int dw9784_erase_mtp_rewritefw(struct camera_io_master * io_master_info) +{ + uint16_t FMC; + CAM_INFO(CAM_OIS, "dw9784 erase for rewritefw starting.."); + dw9784_cci_write(io_master_info, 0xd001, 0x0000); + dw9784_delay_ms(1); + dw9784_flash_acess(io_master_info); + + dw9784_cci_write(io_master_info, 0xDE01, 0x0000); // FMC block FW select + dw9784_delay_ms(1); + dw9784_cci_read(io_master_info, 0xDE01, &FMC); + if (FMC != 0) + { + CAM_INFO(CAM_OIS, "[dw9784_download_fw] FMC register value 1st warning : %04x", FMC); + dw9784_cci_write(io_master_info, 0xDE01, 0x0000); + dw9784_delay_ms(1); + FMC = 0; // initialize FMC value + + dw9784_cci_read(io_master_info, 0xDE01, &FMC); + if (FMC != 0) + { + CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd FMC register value 2nd warning : %04x", FMC); + CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop f/w download"); + return -1; + } + } + + /* code protection off */ + dw9784_code_pt_off(io_master_info); + + /* 512 byte page */ + dw9784_cci_write(io_master_info, 0xde03, 0x0027); + /* page erase */ + dw9784_cci_write(io_master_info, 0xde04, 0x0008); + dw9784_delay_ms(10); + + dw9784_cci_write(io_master_info, 0xd000, 0x0000); /* Shut download mode */ + + return 0; +} + +static int dw9784_prepare_fw_download(struct camera_io_master * io_master_info) +{ + /* step 1: MTP Erase and DSP Disable for firmware 0x8000 write */ + /* step 2: MTP setup */ + /* step 3. FMC register check */ + /* step 4. code protection off */ + /* step 5. erase flash fw data */ + uint16_t FMC; + dw9784_cci_write(io_master_info, 0xd001, 0x0000); + dw9784_flash_acess(io_master_info); + + dw9784_cci_write(io_master_info, 0xDE01, 0x0000); // FMC block FW select + dw9784_delay_ms(1); + dw9784_cci_read(io_master_info, 0xDE01, &FMC); + if (FMC != 0) + { + CAM_INFO(CAM_OIS, "[dw9784_download_fw] FMC register value 1st warning : %04x", FMC); + dw9784_cci_write(io_master_info, 0xDE01, 0x0000); + dw9784_delay_ms(1); + FMC = 0; // initialize FMC value + + dw9784_cci_read(io_master_info, 0xDE01, &FMC); + if (FMC != 0) + { + CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd FMC register value 2nd warning : %04x", FMC); + CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop f/w download"); + return -1; + } + } + + dw9784_code_pt_off(io_master_info); + dw9784_fw_eflash_erase(io_master_info); + CAM_INFO(CAM_OIS, "[dw9784_download_fw] start firmware download"); + return 0; +} + +int dw9784_check_fw_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize) +{ + uint8_t ret; + uint8_t needDownload = 0; + uint16_t fwchecksum = 0; + uint16_t first_chip_id = 0; + uint16_t chip_checksum = 0; + uint16_t fw_version_current = 0; + uint16_t fw_version_latest = 0; + + if (io_master_info == NULL) { + CAM_ERR(CAM_OIS, "FATAL: OIS CCI context error!!!"); + return -1; + } + + if (fwData == NULL || fwSize < FW_VERSION_OFFSET*sizeof(uint16_t)) { + CAM_ERR(CAM_OIS, "FATAL: firmware buffer(%p) is NULL or size(%d) abnormal!!!", fwData, fwSize); + return -1; + } + + g_dw9784FirmwareContext.driverIc = 0x9784; + g_dw9784FirmwareContext.fwContentPtr = (const uint16_t *)fwData; + g_dw9784FirmwareContext.size = fwSize; + g_dw9784FirmwareContext.version = *(g_dw9784FirmwareContext.fwContentPtr+FW_VERSION_OFFSET); + g_dw9784FirmwareContext.version = ((g_dw9784FirmwareContext.version << 8) & 0xff00) | + ((g_dw9784FirmwareContext.version >> 8) & 0xff); + g_dw9784FirmwareContext.checksum = *(g_dw9784FirmwareContext.fwContentPtr+FW_CHECKSUM_OFFSET); + g_dw9784FirmwareContext.checksum = ((g_dw9784FirmwareContext.checksum << 8) & 0xff00) | + ((g_dw9784FirmwareContext.checksum >> 8) & 0xff); + if (dw9784_whoami_chk(io_master_info) != 0) { + CAM_ERR(CAM_OIS, "[dw9784] second chip id check fail"); + return -1; + } + + dw9784_cci_read(io_master_info, DW9784_CHIP_ID_ADDRESS, &first_chip_id); + dw9784_cci_read(io_master_info, 0x7001, &chip_checksum); + CAM_INFO(CAM_OIS, "[dw9784] FW_VER_PHONE_MAKER : 0x%x", chip_checksum); + dw9784_cci_read(io_master_info, 0x7002, &chip_checksum); + CAM_INFO(CAM_OIS, "[dw9784] FW_DATE_PHONE_MAKER : 0x%x", chip_checksum); + + CAM_INFO(CAM_OIS, "[dw9784] first_chip_id : 0x%x", first_chip_id); + if (first_chip_id != DW9784_CHIP_ID) { /* first_chip_id verification failed */ + CAM_INFO(CAM_OIS, "[dw9784] start flash download:: size:%d, version:0x%x", + g_dw9784FirmwareContext.size, g_dw9784FirmwareContext.version); + needDownload = 1; + ret = dw9784_prepare_fw_download(io_master_info); /* Need to forced update OIS firmware again. */ + } else { + fwchecksum = dw9784_checksum_fw_chk(io_master_info); + if(fwchecksum != 0) + { + needDownload = 1; + CAM_INFO(CAM_OIS, "[dw9784] firmware checksum error"); + } + + dw9784_cci_read(io_master_info, FW_VER_CURR_ADDR, &fw_version_current); + fw_version_latest = g_dw9784FirmwareContext.version; /*Firmware version read from file content.*/ + + CAM_INFO(CAM_OIS, "[dw9784] fw_version_current = 0x%x, fw_version_latest = 0x%x", + fw_version_current, fw_version_latest); + + /* download firmware, check if need update, download firmware to flash */ + if (needDownload || ((fw_version_current & 0xFFFF) != (fw_version_latest & 0xFFFF))) { + needDownload = 1; + + CAM_INFO(CAM_OIS, "[dw9784] start flash download:: size:%d, version:0x%x needDownload %d", + g_dw9784FirmwareContext.size, g_dw9784FirmwareContext.version, needDownload); + + ret = dw9784_prepare_fw_download(io_master_info); + CAM_INFO(CAM_OIS, "[dw9784] flash download::vendor_dw9784"); + if (ret != EOK) { + dw9784_erase_mtp_rewritefw(io_master_info); + CAM_ERR(CAM_OIS, "[dw9784] firmware download error, ret = 0x%x", ret); + CAM_ERR(CAM_OIS, "[dw9784] change dw9784 state to shutdown mode"); + needDownload = 1; + } + } else { + CAM_INFO(CAM_OIS, "[dw9784] ois firmware version is updated, skip download"); + } + } + return needDownload; +} +EXPORT_SYMBOL(dw9784_check_fw_download); + +int dw9784_check_if_download(struct camera_io_master * io_master_info) +{ + uint16_t FMC; + + /* step 1. Writes 512Byte FW(PID) data to IF flash. (FMC register check) */ + dw9784_cci_write(io_master_info, 0xDE01, 0x1000); + dw9784_delay_ms(1); + dw9784_cci_read(io_master_info,0xDE01, &FMC); + dw9784_delay_ms(1); + if (FMC != 0x1000) + { + CAM_INFO(CAM_OIS, "[dw9784_download_fw] IF FMC register value 1st warning : %04x", FMC); + dw9784_cci_write(io_master_info, 0xDE01, 0x1000); + dw9784_delay_ms(1); + FMC = 0; // initialize FMC value + + dw9784_cci_read(io_master_info,0xDE01, &FMC); + if (FMC != 0x1000) + { + CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd IF FMC register value 2nd fail : %04x", FMC); + CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop firmware download"); + return -1; + } + } + + /* step 2. erease IF(FW/PID) eFLASH */ + dw9784_pid_erase(io_master_info); + + CAM_INFO(CAM_OIS, "[dw9784_download_fw] start firmware/pid download"); + return 0; +} +EXPORT_SYMBOL(dw9784_check_if_download); + +void dw9784_post_firmware_download(struct camera_io_master * io_master_info) +{ + uint16_t fwchecksum = 0; + + dw9784_ois_reset(io_master_info); + fwchecksum = dw9784_checksum_fw_chk(io_master_info); + if(fwchecksum != 0) + { + CAM_ERR(CAM_OIS, "[dw9784] firmware checksum error"); + dw9784_erase_mtp_rewritefw(io_master_info); + CAM_ERR(CAM_OIS, "[dw9784] change dw9784 state to shutdown mode"); + } + return; +} + +EXPORT_SYMBOL(dw9784_post_firmware_download);