diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 81258d04fd..fcec47fca2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1910,8 +1910,6 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, SYNC_QUEUE, MSM_SYNC_ENABLE); break; case MSM_CCI_I2C_WRITE: - case MSM_CCI_I2C_WRITE_SEQ: - case MSM_CCI_I2C_WRITE_BURST: for (i = 0; i < NUM_QUEUES; i++) { if (mutex_trylock(&cci_master_info->mutex_q[i])) { rc = cam_cci_i2c_write(sd, c_ctrl, i, @@ -1925,6 +1923,13 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, PRIORITY_QUEUE, MSM_SYNC_DISABLE); mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]); break; + case MSM_CCI_I2C_WRITE_SEQ: + case MSM_CCI_I2C_WRITE_BURST: + mutex_lock(&cci_master_info->mutex_q[PRIORITY_QUEUE]); + rc = cam_cci_i2c_write(sd, c_ctrl, + PRIORITY_QUEUE, MSM_SYNC_DISABLE); + mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]); + break; case MSM_CCI_I2C_WRITE_ASYNC: rc = cam_cci_i2c_write_async(sd, c_ctrl, PRIORITY_QUEUE, MSM_SYNC_DISABLE); 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 99b8a1c074..aec8fc410c 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -239,16 +239,34 @@ static int cam_ois_update_time(struct i2c_settings_array *i2c_set) if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { size = i2c_list->i2c_settings.size; /* qtimer is 8 bytes so validate here*/ - if (size < 8) { + if (size * (uint32_t)(i2c_list->i2c_settings.data_type) != 8) { CAM_ERR(CAM_OIS, "Invalid write time settings"); return -EINVAL; } - for (i = 0; i < size; i++) { - CAM_DBG(CAM_OIS, "time: reg_data[%d]: 0x%x", - i, (qtime_ns & 0xFF)); - i2c_list->i2c_settings.reg_setting[i].reg_data = - (qtime_ns & 0xFF); - qtime_ns >>= 8; + switch (i2c_list->i2c_settings.data_type) { + case CAMERA_SENSOR_I2C_TYPE_BYTE: + for (i = 0; i < size; i++) { + CAM_DBG(CAM_OIS, "time: reg_data[%d]: 0x%x", + i, (qtime_ns & 0xFF)); + i2c_list->i2c_settings.reg_setting[i].reg_data = + (qtime_ns & 0xFF); + qtime_ns >>= 8; + } + + break; + case CAMERA_SENSOR_I2C_TYPE_WORD: + for (i = 0; i < size; i++) { + CAM_DBG(CAM_OIS, "time: reg_data[%d]: 0x%x", + i, (qtime_ns & 0xFFFF)); + i2c_list->i2c_settings.reg_setting[i].reg_data = + (qtime_ns & 0xFFFF); + qtime_ns >>= 16; + } + + break; + default: + CAM_ERR(CAM_OIS, "Unsupported reg data type!"); + return -EINVAL; } } } @@ -356,6 +374,244 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, return rc; } +static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size, + struct i2c_settings_array *reg_settings) +{ + int32_t rc = 0; + uint32_t byte_cnt = 0; + struct common_header *cmm_hdr; + uint16_t op_code; + uint32_t j = 0; + struct list_head *list = NULL; + + while (byte_cnt < size) { + if ((size - byte_cnt) < sizeof(struct common_header)) { + CAM_ERR(CAM_SENSOR, "Not enough buffer"); + rc = -EINVAL; + goto end; + } + cmm_hdr = (struct common_header *)cmd_buf; + op_code = cmm_hdr->fifth_byte; + CAM_DBG(CAM_SENSOR, "Command Type:%d, Op code:%d", + cmm_hdr->cmd_type, op_code); + + switch (cmm_hdr->cmd_type) { + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: { + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_wr + *cam_cmd_i2c_random_wr = + (struct cam_cmd_i2c_random_wr *)cmd_buf; + + if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_random_wr)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided,size %d,byte_cnt %d", + size, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_random_write( + cam_cmd_i2c_random_wr, + reg_settings, + &cmd_length_in_bytes, &j, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in random write %d", rc); + goto end; + } + + byte_cnt += sizeof(struct cam_cmd_i2c_random_wr); + cmd_buf += sizeof(struct cam_cmd_i2c_random_wr); + + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR: { + uint32_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_continuous_wr + *cam_cmd_i2c_continuous_wr = + (struct cam_cmd_i2c_continuous_wr *)cmd_buf; + + if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_continuous_wr)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided,size %d,byte_cnt %d", + size, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_continuous_write( + cam_cmd_i2c_continuous_wr, + reg_settings, + &cmd_length_in_bytes, &j, &list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous write %d", rc); + goto end; + } + + byte_cnt += sizeof(struct cam_cmd_i2c_continuous_wr); + cmd_buf += sizeof(struct cam_cmd_i2c_continuous_wr); + + break; + } + case CAMERA_SENSOR_CMD_TYPE_WAIT: { + if (op_code == CAMERA_SENSOR_WAIT_OP_HW_UCND || + op_code == CAMERA_SENSOR_WAIT_OP_SW_UCND) { + if ((size - byte_cnt) < + sizeof(struct cam_cmd_unconditional_wait)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided,size %d,byte_cnt %d", + size, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_delay( + (uint32_t **)(&cmd_buf), op_code, + reg_settings, j, &byte_cnt, + list); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "delay hdl failed: %d", + rc); + goto end; + } + } + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_rd *i2c_random_rd = + (struct cam_cmd_i2c_random_rd *)cmd_buf; + + if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_random_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided,size %d,byte_cnt %d", + size, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_random_read( + i2c_random_rd, + reg_settings, + &cmd_length_in_bytes, &j, &list, + NULL); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in random read %d", rc); + goto end; + } + + byte_cnt += sizeof(struct cam_cmd_i2c_random_rd); + cmd_buf += sizeof(struct cam_cmd_i2c_random_rd); + + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_continuous_rd + *i2c_continuous_rd = + (struct cam_cmd_i2c_continuous_rd *)cmd_buf; + + if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_continuous_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer provided,size %d,byte_cnt %d", + size, byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_continuous_read( + i2c_continuous_rd, + reg_settings, + &cmd_length_in_bytes, &j, &list, + NULL); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous read %d", rc); + goto end; + } + + byte_cnt += sizeof(struct cam_cmd_i2c_continuous_rd); + cmd_buf += sizeof(struct cam_cmd_i2c_continuous_rd); + + break; + } + default: + CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d", + cmm_hdr->cmd_type); + rc = -EINVAL; + goto end; + } + } + +end: + return rc; +} + +static int cam_ois_fw_info_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, + uint32_t *cmd_buf, size_t len) +{ + int32_t rc = 0; + struct cam_cmd_ois_fw_info *ois_fw_info; + uint8_t *pSettingData = NULL; + uint32_t size; + struct i2c_settings_array *reg_settings = NULL; + uint8_t count = 0; + uint32_t idx; + + if (!o_ctrl || !cmd_buf || len < sizeof(struct cam_cmd_ois_fw_info)) { + CAM_ERR(CAM_OIS, "Invalid Args,o_ctrl %p,cmd_buf %p,len %d", + o_ctrl, cmd_buf, len); + return -EINVAL; + } + + ois_fw_info = (struct cam_cmd_ois_fw_info *)cmd_buf; + CAM_DBG(CAM_SENSOR, "fw_count %d, endianness %d", + ois_fw_info->fw_count, ois_fw_info->endianness); + + if (ois_fw_info->fw_count <= MAX_OIS_FW_COUNT) { + memcpy(&o_ctrl->fw_info, ois_fw_info, sizeof(struct cam_cmd_ois_fw_info)); + pSettingData = (uint8_t *)cmd_buf + sizeof(struct cam_cmd_ois_fw_info); + + for (count = 0; count < ois_fw_info->fw_count*2; count++) { + idx = count / 2; + /* init settings */ + if ((count & 0x1) == 0) { + size = ois_fw_info->fw_param[idx].fw_init_size; + reg_settings = &o_ctrl->i2c_fw_init_data[idx]; + CAM_DBG(CAM_SENSOR, "init size %d", size); + /* finalize settings */ + } else if ((count & 0x1) == 1) { + size = ois_fw_info->fw_param[idx].fw_finalize_size; + reg_settings = &o_ctrl->i2c_fw_finalize_data[idx]; + CAM_DBG(CAM_SENSOR, "finalize size %d", size); + } else { + size = 0; + CAM_DBG(CAM_SENSOR, "Unsupported case!"); + return -EINVAL; + } + + if (size != 0) { + reg_settings->is_settings_valid = 1; + rc = cam_ois_parse_fw_setting(pSettingData, size, reg_settings); + } + + if (rc) { + CAM_ERR(CAM_OIS, "Failed to parse fw setting!"); + return rc; + } + + pSettingData += size; + } + } else { + CAM_ERR(CAM_OIS, "Exceed max fw count!"); + } + + return rc; +} + static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) { uint16_t total_bytes = 0; @@ -480,6 +736,207 @@ release_firmware: return rc; } +static inline uint32_t swap_high_byte_and_low_byte(uint8_t *src, + uint8_t data_type) +{ + uint32_t ret_value = 0x00; + uint8_t cycle = 0; + + for (cycle = 0; cycle < data_type; cycle++) + ret_value = ((ret_value<<8) | ((*(src+cycle))&0xff)); + + return ret_value; +} + +static int write_ois_fw(uint8_t *fw_data, enum cam_endianness_type endianness, + struct cam_cmd_ois_fw_param *fw_param, struct camera_io_master io_master_info, + uint8_t i2c_operation) +{ + int32_t rc = 0; + struct cam_sensor_i2c_reg_setting setting; + uint8_t *ptr = fw_data; + int32_t cnt = 0, wcnt = 0; + void *vaddr = NULL; + uint16_t data_type = fw_param->fw_data_type; + uint16_t len_per_write = fw_param->fw_len_per_write / + fw_param->fw_data_type; + + vaddr = vmalloc((sizeof(struct cam_sensor_i2c_reg_array) * len_per_write)); + if (!vaddr) { + CAM_ERR(CAM_OIS, + "Failed in allocating i2c_array: size: %u", + (sizeof(struct cam_sensor_i2c_reg_array) * len_per_write)); + return -ENOMEM; + } + + setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (vaddr); + setting.addr_type = fw_param->fw_addr_type; + setting.data_type = fw_param->fw_data_type; + setting.size = len_per_write; + setting.delay = fw_param->fw_delayUs; + + for (wcnt = 0; wcnt < (fw_param->fw_size/data_type); wcnt += len_per_write) { + for (cnt = 0; cnt < len_per_write; cnt++, ptr += data_type) { + setting.reg_setting[cnt].reg_addr = + fw_param->fw_reg_addr + wcnt + cnt; + /* Big */ + if (endianness == CAM_ENDIANNESS_BIG) { + setting.reg_setting[cnt].reg_data = + swap_high_byte_and_low_byte(ptr, data_type); + /* Little */ + } else if (endianness == CAM_ENDIANNESS_LITTLE) { + switch (data_type) { + case CAMERA_SENSOR_I2C_TYPE_BYTE: + setting.reg_setting[cnt].reg_data = *((uint8_t *)ptr); + break; + case CAMERA_SENSOR_I2C_TYPE_WORD: + setting.reg_setting[cnt].reg_data = *((uint16_t *)ptr); + break; + default: + CAM_ERR(CAM_OIS, + "Unsupported data type"); + rc = -EINVAL; + goto End; + } + } + + setting.reg_setting[cnt].delay = fw_param->fw_delayUs; + setting.reg_setting[cnt].data_mask = 0; + } + + if (i2c_operation == CAM_SENSOR_I2C_WRITE_RANDOM) { + rc = camera_io_dev_write(&(io_master_info), + &setting); + } else if (i2c_operation == CAM_SENSOR_I2C_WRITE_BURST || + i2c_operation == CAM_SENSOR_I2C_WRITE_SEQ) { + rc = camera_io_dev_write_continuous(&io_master_info, + &setting, i2c_operation); + } + + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed in Applying i2c wrt settings"); + break; + } + } + +End: + vfree(vaddr); + vaddr = NULL; + + return rc; +} + +static int cam_ois_fw_download_v2(struct cam_ois_ctrl_t *o_ctrl) +{ + int32_t rc = 0; + struct cam_cmd_ois_fw_param *fw_param = NULL; + uint32_t fw_size; + uint16_t len_per_write = 0; + uint8_t *ptr = NULL; + const struct firmware *fw = NULL; + struct device *dev = &(o_ctrl->pdev->dev); + uint8_t count = 0; + uint8_t cont_wr_flag = 0; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + for (count = 0; count < o_ctrl->fw_info.fw_count; count++) { + fw_param = &o_ctrl->fw_info.fw_param[count]; + fw_size = fw_param->fw_size; + len_per_write = fw_param->fw_len_per_write / fw_param->fw_data_type; + + CAM_DBG(CAM_OIS, "count: %d, fw_size: %d, data_type: %d, len_per_write: %d", + count, fw_size, fw_param->fw_data_type, len_per_write); + + /* Load FW */ + rc = request_firmware(&fw, fw_param->fw_name, dev); + if (rc) { + CAM_ERR(CAM_OIS, "Failed to locate %s", fw_param->fw_name); + return rc; + } + + if (0 == rc && NULL != fw && + (fw_size <= fw->size - fw_param->fw_start_pos)) { + /* fw init */ + CAM_DBG(CAM_OIS, "fw init"); + if (o_ctrl->i2c_fw_init_data[count].is_settings_valid == 1) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fw_init_data[count]); + if ((rc == -EAGAIN) && + (o_ctrl->io_master_info.master_type == CCI_MASTER)) { + CAM_WARN(CAM_OIS, + "CCI HW is resetting: Reapplying FW init settings"); + usleep_range(1000, 1010); + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fw_init_data[count]); + } + if (rc) { + CAM_ERR(CAM_OIS, + "Cannot apply FW init settings %d", + rc); + goto release_firmware; + } else { + CAM_DBG(CAM_OIS, "OIS FW init settings success"); + } + } + + /* send fw */ + CAM_DBG(CAM_OIS, "send fw, operation %d", fw_param->fw_operation); + + ptr = (uint8_t *)(fw->data + fw_param->fw_start_pos); + if (fw_param->fw_operation == CAMERA_SENSOR_I2C_OP_RNDM_WR) + cont_wr_flag = CAM_SENSOR_I2C_WRITE_RANDOM; + else if (fw_param->fw_operation == CAMERA_SENSOR_I2C_OP_CONT_WR_BRST) + cont_wr_flag = CAM_SENSOR_I2C_WRITE_BURST; + else if (fw_param->fw_operation == CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN) + cont_wr_flag = CAM_SENSOR_I2C_WRITE_SEQ; + + write_ois_fw(ptr, o_ctrl->fw_info.endianness, fw_param, + o_ctrl->io_master_info, cont_wr_flag); + + /* fw finalize */ + CAM_DBG(CAM_OIS, "fw finalize"); + if (o_ctrl->i2c_fw_finalize_data[count].is_settings_valid == 1) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fw_finalize_data[count]); + if ((rc == -EAGAIN) && + (o_ctrl->io_master_info.master_type == CCI_MASTER)) { + CAM_WARN(CAM_OIS, + "CCI HW is resetting: Reapplying FW finalize settings"); + usleep_range(1000, 1010); + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fw_finalize_data[count]); + } + if (rc) { + CAM_ERR(CAM_OIS, + "Cannot apply FW finalize settings %d", + rc); + goto release_firmware; + } else { + CAM_DBG(CAM_OIS, "OIS FW finalize settings success"); + } + } + } + + if (fw != NULL) { + release_firmware(fw); + fw = NULL; + } + } + +release_firmware: + if (fw != NULL) { + release_firmware(fw); + fw = NULL; + } + + return rc; +} + /** * cam_ois_pkt_parse - Parse csl packet * @o_ctrl: ctrl structure @@ -543,13 +1000,13 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: + CAM_DBG(CAM_OIS, "CAM_OIS_PACKET_OPCODE_INIT,num_cmd_buf %d", + csl_packet->num_cmd_buf); + offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); - CAM_DBG(CAM_OIS, "num_cmd_buf %d", - csl_packet->num_cmd_buf); - /* Loop through multiple command buffers */ for (i = 0; i < csl_packet->num_cmd_buf; i++) { total_cmd_buf_in_bytes = cmd_desc[i].length; @@ -580,6 +1037,8 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_buf += cmd_desc[i].offset / sizeof(uint32_t); cmm_hdr = (struct common_header *)cmd_buf; + CAM_DBG(CAM_OIS, + "cmm_hdr->cmd_type: %d", cmm_hdr->cmd_type); switch (cmm_hdr->cmd_type) { case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: rc = cam_ois_slaveInfo_pkt_parser( @@ -604,6 +1063,18 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) return rc; } break; + case CAMERA_SENSOR_OIS_CMD_TYPE_FW_INFO: + CAM_DBG(CAM_OIS, + "Received fwInfo buffer,total_cmd_buf_in_bytes: %d", + total_cmd_buf_in_bytes); + rc = cam_ois_fw_info_pkt_parser( + o_ctrl, cmd_buf, total_cmd_buf_in_bytes); + if (rc) { + CAM_ERR(CAM_OIS, + "Failed: parse fw info settings"); + return rc; + } + break; default: if (o_ctrl->i2c_init_data.is_settings_valid == 0) { CAM_DBG(CAM_OIS, @@ -649,9 +1120,8 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) i2c_reg_settings, &cmd_desc[i], 1, NULL); if (rc < 0) { - CAM_ERR(CAM_OIS, + CAM_DBG(CAM_OIS, "fw init parsing failed: %d", rc); - return rc; } } break; @@ -667,32 +1137,43 @@ 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->i2c_fwinit_data.is_settings_valid == 1) { - rc = cam_ois_apply_settings(o_ctrl, - &o_ctrl->i2c_fwinit_data); - if ((rc == -EAGAIN) && - (o_ctrl->io_master_info.master_type == CCI_MASTER)) { - CAM_WARN(CAM_OIS, - "CCI HW is restting: Reapplying fwinit settings"); - usleep_range(1000, 1010); - rc = cam_ois_apply_settings(o_ctrl, - &o_ctrl->i2c_fwinit_data); - } - if (rc) { - CAM_ERR(CAM_OIS, - "Cannot apply fwinit data %d", - rc); - goto pwr_dwn; - } else { - CAM_DBG(CAM_OIS, "OIS fwinit settings success"); - } - } - + CAM_DBG(CAM_OIS, "ois_fw_flag: %d", o_ctrl->ois_fw_flag); if (o_ctrl->ois_fw_flag) { - rc = cam_ois_fw_download(o_ctrl); - if (rc) { - CAM_ERR(CAM_OIS, "Failed OIS FW Download"); - goto pwr_dwn; + CAM_DBG(CAM_OIS, "fw_count: %d", o_ctrl->fw_info.fw_count); + if (o_ctrl->fw_info.fw_count != 0) { + rc = cam_ois_fw_download_v2(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "Failed OIS FW Download v2"); + goto pwr_dwn; + } + } else { + if (o_ctrl->i2c_fwinit_data.is_settings_valid == 1) { + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fwinit_data); + if ((rc == -EAGAIN) && + (o_ctrl->io_master_info.master_type == + CCI_MASTER)) { + CAM_WARN(CAM_OIS, + "Reapplying fwinit settings"); + usleep_range(1000, 1010); + rc = cam_ois_apply_settings(o_ctrl, + &o_ctrl->i2c_fwinit_data); + } + if (rc) { + CAM_ERR(CAM_OIS, + "Cannot apply fwinit data %d", + rc); + goto pwr_dwn; + } else { + CAM_DBG(CAM_OIS, "OIS fwinit settings success"); + } + + rc = cam_ois_fw_download(o_ctrl); + if (rc) { + CAM_ERR(CAM_OIS, "Failed OIS FW Download"); + goto pwr_dwn; + } + } } } @@ -705,6 +1186,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); } + if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply Init settings: rc = %d", @@ -740,6 +1222,25 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = 0; } + for (i = 0; i < MAX_OIS_FW_COUNT; i++) { + if (o_ctrl->i2c_fw_init_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_init_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_init_data: rc: %d", rc); + rc = 0; + } + } + if (o_ctrl->i2c_fw_finalize_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_finalize_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_finalize_data: rc: %d", rc); + rc = 0; + } + } + } + rc = delete_request(&o_ctrl->i2c_init_data); if (rc < 0) { CAM_WARN(CAM_OIS, @@ -754,6 +1255,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } break; case CAM_OIS_PACKET_OPCODE_OIS_CONTROL: + CAM_DBG(CAM_OIS, "CAM_OIS_PACKET_OPCODE_OIS_CONTROL"); if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { rc = -EINVAL; CAM_WARN(CAM_OIS, @@ -793,6 +1295,8 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) struct cam_buf_io_cfg *io_cfg; struct i2c_settings_array i2c_read_settings; + CAM_DBG(CAM_OIS, "CAM_OIS_PACKET_OPCODE_READ"); + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { rc = -EINVAL; CAM_WARN(CAM_OIS, @@ -869,6 +1373,8 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) break; } case CAM_OIS_PACKET_OPCODE_WRITE_TIME: { + CAM_DBG(CAM_OIS, + "CAM_OIS_PACKET_OPCODE_WRITE_TIME"); if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { rc = -EINVAL; CAM_ERR(CAM_OIS, @@ -925,7 +1431,7 @@ pwr_dwn: void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl) { - int rc = 0; + int rc = 0, i = 0; struct cam_ois_soc_private *soc_private = (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; @@ -952,6 +1458,25 @@ void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl) if (o_ctrl->i2c_fwinit_data.is_settings_valid == 1) delete_request(&o_ctrl->i2c_fwinit_data); + for (i = 0; i < MAX_OIS_FW_COUNT; i++) { + if (o_ctrl->i2c_fw_init_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_init_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_init_data: rc: %d", rc); + rc = 0; + } + } + if (o_ctrl->i2c_fw_finalize_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_finalize_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_finalize_data: rc: %d", rc); + rc = 0; + } + } + } + if (o_ctrl->i2c_mode_data.is_settings_valid == 1) delete_request(&o_ctrl->i2c_mode_data); @@ -980,7 +1505,7 @@ void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl) */ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) { - int rc = 0; + int rc = 0, i = 0; struct cam_ois_query_cap_t ois_cap = {0}; struct cam_control *cmd = (struct cam_control *)arg; struct cam_ois_soc_private *soc_private = NULL; @@ -1091,6 +1616,25 @@ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (o_ctrl->i2c_fwinit_data.is_settings_valid == 1) delete_request(&o_ctrl->i2c_fwinit_data); + for (i = 0; i < MAX_OIS_FW_COUNT; i++) { + if (o_ctrl->i2c_fw_init_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_init_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_init_data: rc: %d", rc); + rc = 0; + } + } + if (o_ctrl->i2c_fw_finalize_data[i].is_settings_valid == 1) { + rc = delete_request(&o_ctrl->i2c_fw_finalize_data[i]); + if (rc < 0) { + CAM_WARN(CAM_OIS, + "Fail deleting i2c_fw_finalize_data: rc: %d", rc); + rc = 0; + } + } + } + break; case CAM_STOP_DEV: if (o_ctrl->cam_ois_state != CAM_OIS_START) { diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 4309482da9..e937bbbdcb 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -334,7 +334,7 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client) static int cam_ois_component_bind(struct device *dev, struct device *master_dev, void *data) { - int32_t rc = 0; + int32_t rc = 0, i = 0; struct cam_ois_ctrl_t *o_ctrl = NULL; struct cam_ois_soc_private *soc_private = NULL; bool i3c_i2c_target; @@ -370,9 +370,15 @@ static int cam_ois_component_bind(struct device *dev, o_ctrl->soc_info.soc_private = soc_private; soc_private->power_info.dev = &pdev->dev; + memset(&o_ctrl->fw_info, 0, sizeof(struct cam_cmd_ois_fw_info)); + INIT_LIST_HEAD(&(o_ctrl->i2c_init_data.list_head)); INIT_LIST_HEAD(&(o_ctrl->i2c_calib_data.list_head)); INIT_LIST_HEAD(&(o_ctrl->i2c_fwinit_data.list_head)); + for (i = 0; i < MAX_OIS_FW_COUNT; i++) { + INIT_LIST_HEAD(&(o_ctrl->i2c_fw_init_data[i].list_head)); + INIT_LIST_HEAD(&(o_ctrl->i2c_fw_finalize_data[i].list_head)); + } INIT_LIST_HEAD(&(o_ctrl->i2c_mode_data.list_head)); INIT_LIST_HEAD(&(o_ctrl->i2c_time_data.list_head)); mutex_init(&(o_ctrl->ois_mutex)); 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 e5736e2519..04157615f5 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -121,6 +121,9 @@ struct cam_ois_ctrl_t { uint8_t ois_fw_flag; uint8_t is_ois_calib; struct cam_ois_opcode opcode; + struct cam_cmd_ois_fw_info fw_info; + struct i2c_settings_array i2c_fw_init_data[MAX_OIS_FW_COUNT]; + struct i2c_settings_array i2c_fw_finalize_data[MAX_OIS_FW_COUNT]; }; /** diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 9e16f32bcc..f8c9572d47 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -304,7 +304,7 @@ int32_t cam_sensor_handle_random_write( return rc; } -static int32_t cam_sensor_handle_continuous_write( +int32_t cam_sensor_handle_continuous_write( struct cam_cmd_i2c_continuous_wr *cam_cmd_i2c_continuous_wr, struct i2c_settings_array *i2c_reg_settings, uint32_t *cmd_length_in_bytes, int32_t *offset, @@ -450,7 +450,7 @@ int32_t cam_sensor_util_write_qtimer_to_io_buffer( return rc; } -static int32_t cam_sensor_handle_random_read( +int32_t cam_sensor_handle_random_read( struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, struct i2c_settings_array *i2c_reg_settings, uint16_t *cmd_length_in_bytes, @@ -498,7 +498,7 @@ static int32_t cam_sensor_handle_random_read( return rc; } -static int32_t cam_sensor_handle_continuous_read( +int32_t cam_sensor_handle_continuous_read( struct cam_cmd_i2c_continuous_rd *cmd_i2c_continuous_rd, struct i2c_settings_array *i2c_reg_settings, uint16_t *cmd_length_in_bytes, int32_t *offset, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 4c314ff693..021d04269d 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -52,6 +52,40 @@ int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns); int32_t cam_sensor_util_write_qtimer_to_io_buffer( uint64_t qtime_ns, struct cam_buf_io_cfg *io_cfg); +int32_t cam_sensor_handle_random_write( + struct cam_cmd_i2c_random_wr *cam_cmd_i2c_random_wr, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list); + +int32_t cam_sensor_handle_continuous_write( + struct cam_cmd_i2c_continuous_wr *cam_cmd_i2c_continuous_wr, + struct i2c_settings_array *i2c_reg_settings, + uint32_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list); + +int32_t cam_sensor_handle_delay( + uint32_t **cmd_buf, + uint16_t generic_op_code, + struct i2c_settings_array *i2c_reg_settings, + uint32_t offset, uint32_t *byte_cnt, + struct list_head *list_ptr); + +int32_t cam_sensor_handle_random_read( + struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, + int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg); + +int32_t cam_sensor_handle_continuous_read( + struct cam_cmd_i2c_continuous_rd *cmd_i2c_continuous_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg); + int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers, diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index f645867218..5e3c0904d4 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -14,6 +14,7 @@ #define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1) #define CAM_FLASH_MAX_LED_TRIGGERS 2 #define MAX_OIS_NAME_SIZE 32 +#define MAX_OIS_FW_COUNT 2 #define CAM_CSIPHY_SECURE_MODE_ENABLED 1 #define CAM_SENSOR_NAME_MAX_SIZE 32 @@ -57,6 +58,7 @@ enum camera_sensor_cmd_type { CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET, CAMERA_SENSOR_CMD_TYPE_RD_DATA, CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE, + CAMERA_SENSOR_OIS_CMD_TYPE_FW_INFO, CAMERA_SENSOR_CMD_TYPE_MAX, }; @@ -87,6 +89,8 @@ enum camera_sensor_i2c_op_code { CAMERA_SENSOR_I2C_OP_CONT_WR_BRST_VERF, CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN, CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN_VERF, + CAMERA_SENSOR_I2C_OP_RNDM_RD, + CAMERA_SENSOR_I2C_OP_CONT_RD, CAMERA_SENSOR_I2C_OP_MAX, }; @@ -120,6 +124,11 @@ enum cam_sensor_packet_opcodes { CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127, }; +enum cam_endianness_type { + CAM_ENDIANNESS_BIG, + CAM_ENDIANNESS_LITTLE, +}; + enum tpg_command_type_t { TPG_CMD_TYPE_INVALID = 0, TPG_CMD_TYPE_GLOBAL_CONFIG, @@ -394,6 +403,68 @@ struct cam_cmd_ois_info { struct cam_ois_opcode opcode; } __attribute__((packed)); + +/** + * struct cam_cmd_ois_fw_param - Contains OIS firmware param + * + * NOTE: if this struct is updated, + * please also update version in struct cam_cmd_ois_fw_info + * + * @fw_name : firmware file name + * @fw_start_pos : data start position in file + * @fw_size : firmware size + * @fw_len_per_write: data length per write in bytes + * @fw_addr_type : addr type + * @fw_data_type : data type + * @fw_operation : type of operation + * @reserved : reserved for 32-bit alignment + * @fw_delayUs : delay in cci write + * @fw_reg_addr : start register addr to write + * @fw_init_size : size of fw download init settings + * @fw_finalize_size: size of fw download finalize settings + */ +struct cam_cmd_ois_fw_param { + char fw_name[MAX_OIS_NAME_SIZE]; + __u32 fw_start_pos; + __u32 fw_size; + __u32 fw_len_per_write; + __u8 fw_addr_type; + __u8 fw_data_type; + __u8 fw_operation; + __u8 reserved; + __u32 fw_delayUs; + __u32 fw_reg_addr; + __u32 fw_init_size; + __u32 fw_finalize_size; +} __attribute__((packed)); + +/** + * struct cam_cmd_ois_fw_info - Contains OIS firmware info + * + * @version : version info + * NOTE: if struct cam_cmd_ois_fw_param is updated, + * version here needs to be updated too. + * @reserved : reserved + * @cmd_type : Explains type of command + * @fw_count : firmware count + * @endianness : firmware data's endianness + * @fw_param : includes firmware parameters + * @num_valid_params: Number of valid params + * @param_mask : Mask to indicate fields in params + * @params : Additional Params + */ +struct cam_cmd_ois_fw_info { + __u32 version; + __u8 reserved; + __u8 cmd_type; + __u8 fw_count; + __u8 endianness; + struct cam_cmd_ois_fw_param fw_param[MAX_OIS_FW_COUNT]; + __u32 num_valid_params; + __u32 param_mask; + __u32 params[4]; +} __attribute__((packed)); + /** * struct cam_cmd_probe - Contains sensor slave info *