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 b8cc002edb91..8d1770d307c1 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -332,7 +332,13 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, o_ctrl->io_master_info.cci_client->sid = ois_info->slave_addr >> 1; o_ctrl->ois_fw_flag = ois_info->ois_fw_flag; + o_ctrl->ois_preprog_flag = ois_info->ois_preprog_flag; + o_ctrl->ois_precoeff_flag = ois_info->ois_precoeff_flag; o_ctrl->is_ois_calib = ois_info->is_ois_calib; + o_ctrl->ois_postcalib_flag = ois_info->ois_postcalib_flag; + o_ctrl->ois_fw_txn_data_sz = ois_info->ois_fw_txn_data_sz; + o_ctrl->ois_fw_inc_addr = ois_info->ois_fw_inc_addr; + o_ctrl->ois_fw_addr_type = ois_info->ois_fw_addr_type; memcpy(o_ctrl->ois_name, ois_info->ois_name, OIS_NAME_LEN); o_ctrl->ois_name[OIS_NAME_LEN - 1] = '\0'; o_ctrl->io_master_info.cci_client->retries = 3; @@ -353,16 +359,97 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, return rc; } -static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) +static int cam_ois_fw_prog_download(struct cam_ois_ctrl_t *o_ctrl) { uint16_t total_bytes = 0; uint8_t *ptr = NULL; - int32_t rc = 0, cnt; - uint32_t fw_size; + int32_t rc = 0, total_idx, packet_idx; + uint32_t txn_data_size, txn_regsetting_size; const struct firmware *fw = NULL; const char *fw_name_prog = NULL; - const char *fw_name_coeff = NULL; char name_prog[32] = {0}; + struct device *dev = &(o_ctrl->pdev->dev); + struct cam_sensor_i2c_reg_setting i2c_reg_setting; + void *vaddr = NULL; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name); + + /* cast pointer as const pointer*/ + fw_name_prog = name_prog; + + /* Load FW */ + rc = request_firmware(&fw, fw_name_prog, dev); + if (rc) { + CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog); + return rc; + } + + total_bytes = fw->size; + if(o_ctrl->ois_fw_txn_data_sz == 0) + txn_data_size = total_bytes; + else + txn_data_size = o_ctrl->ois_fw_txn_data_sz; + + i2c_reg_setting.addr_type = o_ctrl->ois_fw_addr_type; + i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_reg_setting.delay = 0; + txn_regsetting_size = sizeof(struct cam_sensor_i2c_reg_array) * txn_data_size; + vaddr = vmalloc(txn_regsetting_size); + if (!vaddr) { + CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); + release_firmware(fw); + return -ENOMEM; + } + + i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (vaddr); + + for (total_idx = 0, ptr = (uint8_t *)fw->data; total_idx < total_bytes;) { + for(packet_idx = 0; + (packet_idx < txn_data_size) && (total_idx + packet_idx < total_bytes); + packet_idx++, ptr++) + { + int regAddrOffset = 0; + if(o_ctrl->ois_fw_inc_addr == 1) + regAddrOffset = total_idx + packet_idx; + + i2c_reg_setting.reg_setting[packet_idx].reg_addr = + o_ctrl->opcode.prog + regAddrOffset; + 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; + } + i2c_reg_setting.size = packet_idx; + rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), + &i2c_reg_setting, 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); + goto release_firmware; + } + total_idx += packet_idx; + } + +release_firmware: + vfree(vaddr); + vaddr = NULL; + txn_regsetting_size = 0; + release_firmware(fw); + + return rc; +} + +static int cam_ois_fw_coeff_download(struct cam_ois_ctrl_t *o_ctrl) +{ + uint16_t total_bytes = 0; + uint8_t *ptr = NULL; + int32_t rc = 0, total_idx, packet_idx; + uint32_t txn_data_size, txn_regsetting_size; + const struct firmware *fw = NULL; + const char *fw_name_coeff = NULL; char name_coeff[32] = {0}; struct device *dev = &(o_ctrl->pdev->dev); struct cam_sensor_i2c_reg_setting i2c_reg_setting; @@ -374,57 +461,8 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) } snprintf(name_coeff, 32, "%s.coeff", o_ctrl->ois_name); - - snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name); - - /* cast pointer as const pointer*/ - fw_name_prog = name_prog; fw_name_coeff = name_coeff; - /* Load FW */ - rc = request_firmware(&fw, fw_name_prog, dev); - if (rc) { - CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog); - return rc; - } - - total_bytes = fw->size; - i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE; - i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; - i2c_reg_setting.size = total_bytes; - i2c_reg_setting.delay = 0; - fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes); - vaddr = vmalloc(fw_size); - if (!vaddr) { - CAM_ERR(CAM_OIS, - "Failed in allocating i2c_array: fw_size: %u", fw_size); - release_firmware(fw); - return -ENOMEM; - } - - i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( - vaddr); - - for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; - cnt++, ptr++) { - i2c_reg_setting.reg_setting[cnt].reg_addr = - o_ctrl->opcode.prog; - i2c_reg_setting.reg_setting[cnt].reg_data = *ptr; - i2c_reg_setting.reg_setting[cnt].delay = 0; - i2c_reg_setting.reg_setting[cnt].data_mask = 0; - } - - rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), - &i2c_reg_setting, 1); - if (rc < 0) { - CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); - goto release_firmware; - } - vfree(vaddr); - vaddr = NULL; - fw_size = 0; - release_firmware(fw); - rc = request_firmware(&fw, fw_name_coeff, dev); if (rc) { CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff); @@ -432,41 +470,55 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) } total_bytes = fw->size; - i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE; + if(o_ctrl->ois_fw_txn_data_sz == 0) + txn_data_size = total_bytes; + else + txn_data_size = o_ctrl->ois_fw_txn_data_sz; + + i2c_reg_setting.addr_type = o_ctrl->ois_fw_addr_type; i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE; - i2c_reg_setting.size = total_bytes; i2c_reg_setting.delay = 0; - fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes); - vaddr = vmalloc(fw_size); + txn_regsetting_size = sizeof(struct cam_sensor_i2c_reg_array) * txn_data_size; + vaddr = vmalloc(txn_regsetting_size); if (!vaddr) { - CAM_ERR(CAM_OIS, - "Failed in allocating i2c_array: fw_size: %u", fw_size); + CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); release_firmware(fw); return -ENOMEM; } - i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) ( - vaddr); + i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (vaddr); - for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes; - cnt++, ptr++) { - i2c_reg_setting.reg_setting[cnt].reg_addr = - o_ctrl->opcode.coeff; - i2c_reg_setting.reg_setting[cnt].reg_data = *ptr; - i2c_reg_setting.reg_setting[cnt].delay = 0; - i2c_reg_setting.reg_setting[cnt].data_mask = 0; + for (total_idx = 0, ptr = (uint8_t *)fw->data; total_idx < total_bytes;) { + for(packet_idx = 0; + (packet_idx < txn_data_size) && (total_idx + packet_idx < total_bytes); + packet_idx++, ptr++) + { + int regAddrOffset = 0; + if(o_ctrl->ois_fw_inc_addr == 1) + regAddrOffset = total_idx + packet_idx; + + i2c_reg_setting.reg_setting[packet_idx].reg_addr = + o_ctrl->opcode.coeff + regAddrOffset; + 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; + } + i2c_reg_setting.size = packet_idx; + rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), + &i2c_reg_setting, 1); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); + goto release_firmware; + } + total_idx += packet_idx; } - rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info), - &i2c_reg_setting, 1); - if (rc < 0) - CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc); - release_firmware: vfree(vaddr); vaddr = NULL; - fw_size = 0; + txn_regsetting_size = 0; release_firmware(fw); + return rc; } @@ -609,6 +661,34 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) "init parsing failed: %d", rc); return rc; } + } else if (((o_ctrl->ois_preprog_flag) != 0) && + o_ctrl->i2c_preprog_data.is_settings_valid == 0) { + CAM_DBG(CAM_OIS, "Received PreProg Settings"); + i2c_reg_settings = &(o_ctrl->i2c_preprog_data); + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser( + &o_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1, NULL); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "preprog parsing failed: %d", rc); + return rc; + } + } else if (((o_ctrl->ois_precoeff_flag) != 0) && + o_ctrl->i2c_precoeff_data.is_settings_valid == 0) { + CAM_DBG(CAM_OIS, "Received PreCoeff Settings"); + i2c_reg_settings = &(o_ctrl->i2c_precoeff_data); + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser( + &o_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1, NULL); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "precoeff parsing failed: %d", rc); + return rc; + } } else if ((o_ctrl->is_ois_calib != 0) && (o_ctrl->i2c_calib_data.is_settings_valid == 0)) { @@ -626,6 +706,20 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) "Calib parsing failed: %d", rc); return rc; } + } else if (((o_ctrl->ois_postcalib_flag) != 0) && + o_ctrl->i2c_postcalib_data.is_settings_valid == 0) { + CAM_DBG(CAM_OIS, "Received PostCalib Settings"); + i2c_reg_settings = &(o_ctrl->i2c_postcalib_data); + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser( + &o_ctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1, NULL); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "postcalib parsing failed: %d", rc); + return rc; + } } break; } @@ -640,14 +734,40 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) o_ctrl->cam_ois_state = CAM_OIS_CONFIG; } + if (o_ctrl->ois_preprog_flag) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_preprog_data); + if (rc) { + CAM_ERR(CAM_OIS, "Cannot apply preprog settings"); + goto pwr_dwn; + } + } + if (o_ctrl->ois_fw_flag) { - rc = cam_ois_fw_download(o_ctrl); + rc = cam_ois_fw_prog_download(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, "Failed OIS FW Download"); goto pwr_dwn; } } + if (o_ctrl->ois_precoeff_flag) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_precoeff_data); + if (rc) { + CAM_ERR(CAM_OIS, "Cannot apply precoeff settings"); + goto pwr_dwn; + } + } + + if (o_ctrl->ois_fw_flag) { + rc = cam_ois_fw_coeff_download(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "Failed OIS COEFF FW Download"); + goto pwr_dwn; + } + } + rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); if ((rc == -EAGAIN) && (o_ctrl->io_master_info.master_type == CCI_MASTER)) { @@ -673,18 +793,46 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } } + if (o_ctrl->ois_postcalib_flag) { + CAM_DBG(CAM_OIS, "starting post calib data"); + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_postcalib_data); + if (rc) { + CAM_ERR(CAM_OIS, "Cannot apply post calib data"); + goto pwr_dwn; + } + } + rc = delete_request(&o_ctrl->i2c_init_data); if (rc < 0) { CAM_WARN(CAM_OIS, "Fail deleting Init data: rc: %d", rc); rc = 0; } + rc = delete_request(&o_ctrl->i2c_preprog_data); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting PreProg data: rc: %d", rc); + rc = 0; + } + rc = delete_request(&o_ctrl->i2c_precoeff_data); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting PreCoeff data: rc: %d", rc); + rc = 0; + } rc = delete_request(&o_ctrl->i2c_calib_data); if (rc < 0) { CAM_WARN(CAM_OIS, "Fail deleting Calibration data: rc: %d", rc); rc = 0; } + rc = delete_request(&o_ctrl->i2c_postcalib_data); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting PostCalib data: rc: %d", rc); + rc = 0; + } break; case CAM_OIS_PACKET_OPCODE_OIS_CONTROL: if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index ddb585bc4f2b..27eb1af573cc 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -95,12 +95,21 @@ struct cam_ois_intf_params { * @i2c_init_data : ois i2c init settings * @i2c_mode_data : ois i2c mode settings * @i2c_time_data : ois i2c time write settings + * @i2c_preprog_data : ois i2c preprog settings + * @i2c_precoeff_data : ois i2c precoeff settings + * @i2c_postcalib_data : ois i2c postcalib settings * @i2c_calib_data : ois i2c calib settings * @ois_device_type : ois device type * @cam_ois_state : ois_device_state * @ois_fw_flag : flag for firmware download + * @ois_preprog_flag : flag for preprog reg settings + * @ois_precoeff_flag : flag for precoeff reg settings * @is_ois_calib : flag for Calibration data + * @ois_postcalib_flag : flag for postcalib reg settings * @opcode : ois opcode + * @ois_fw_inc_addr : flag to increment address when sending fw + * @ois_fw_addr_type : address type of fw + * @ois_fw_txn_data_sz : num data bytes per i2c txn when sending fw * @device_name : Device name * */ @@ -115,14 +124,23 @@ struct cam_ois_ctrl_t { struct cam_subdev v4l2_dev_str; struct cam_ois_intf_params bridge_intf; struct i2c_settings_array i2c_init_data; + struct i2c_settings_array i2c_preprog_data; + struct i2c_settings_array i2c_precoeff_data; struct i2c_settings_array i2c_calib_data; + struct i2c_settings_array i2c_postcalib_data; struct i2c_settings_array i2c_mode_data; struct i2c_settings_array i2c_time_data; enum msm_camera_device_type_t ois_device_type; enum cam_ois_state cam_ois_state; char ois_name[32]; uint8_t ois_fw_flag; + uint8_t ois_preprog_flag; + uint8_t ois_precoeff_flag; uint8_t is_ois_calib; + uint8_t ois_postcalib_flag; + uint8_t ois_fw_txn_data_sz; + uint8_t ois_fw_inc_addr; + uint8_t ois_fw_addr_type; struct cam_ois_opcode opcode; }; diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index f935a7a702b3..9552d118387a 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -137,6 +137,12 @@ struct cam_cmd_ois_info { __u8 cmd_type; __u8 ois_fw_flag; __u8 is_ois_calib; + __u8 ois_preprog_flag; + __u8 ois_precoeff_flag; + __u8 ois_postcalib_flag; + __u8 ois_fw_txn_data_sz; + __u8 ois_fw_inc_addr; + __u8 ois_fw_addr_type; char ois_name[MAX_OIS_NAME_SIZE]; struct cam_ois_opcode opcode; } __attribute__((packed));