msm: camera: sensor: Add OIS FW version check support

Adding infrastructure to check OIS FW version before downloading
OIS FW to avoid downloading the same FW.

CRs-Fixed: 3383153
Change-Id: Ic92b62bfe2277eaba9b417a13201fabeab04383e
Signed-off-by: Yulei Yao <quic_yuleiy@quicinc.com>
Signed-off-by: Karthik Anantha Ram <quic_kartanan@quicinc.com>
This commit is contained in:
Karthik Anantha Ram
2023-03-03 14:39:16 +08:00
committed by Camera Software Integration
parent e494f8909d
commit c3364a0aa2
5 changed files with 124 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -16,6 +16,7 @@
#include "cam_common_util.h"
#include "cam_packet_util.h"
#define CAM_OIS_FW_VERSION_CHECK_MASK 0x1
static inline uint64_t swap_high_byte_and_low_byte(uint8_t *src,
uint8_t size_bytes)
@@ -362,6 +363,9 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
CAM_ERR(CAM_OIS,
"i2c poll apply setting Fail");
return rc;
} else if (rc == I2C_COMPARE_MISMATCH) {
CAM_ERR(CAM_OIS, "i2c poll mismatch");
return rc;
}
}
}
@@ -421,13 +425,13 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
while (byte_cnt < size) {
if ((size - byte_cnt) < sizeof(struct common_header)) {
CAM_ERR(CAM_SENSOR, "Not enough buffer");
CAM_ERR(CAM_OIS, "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",
CAM_DBG(CAM_OIS, "Command Type:%d, Op code:%d",
cmm_hdr->cmd_type, op_code);
switch (cmm_hdr->cmd_type) {
@@ -438,7 +442,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
(struct cam_cmd_i2c_random_wr *)cmd_buf;
if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_random_wr)) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
@@ -450,7 +454,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
reg_settings,
&cmd_length_in_bytes, &j, &list);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Failed in random write %d", rc);
goto end;
}
@@ -467,7 +471,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
(struct cam_cmd_i2c_continuous_wr *)cmd_buf;
if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_continuous_wr)) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
@@ -479,7 +483,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
reg_settings,
&cmd_length_in_bytes, &j, &list);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Failed in continuous write %d", rc);
goto end;
}
@@ -494,7 +498,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
op_code == CAMERA_SENSOR_WAIT_OP_SW_UCND) {
if ((size - byte_cnt) <
sizeof(struct cam_cmd_unconditional_wait)) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
@@ -506,11 +510,35 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
reg_settings, j, &byte_cnt,
list);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"delay hdl failed: %d",
rc);
goto end;
}
} else if (op_code == CAMERA_SENSOR_WAIT_OP_COND) {
if ((size - byte_cnt) <
sizeof(struct cam_cmd_conditional_wait)) {
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
goto end;
}
rc = cam_sensor_handle_poll(
(uint32_t **)(&cmd_buf), reg_settings,
&byte_cnt, &j, &list);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"parsing POLL fail: %d",
rc);
goto end;
}
} else {
CAM_ERR(CAM_OIS,
"Wrong Wait Command: %d",
op_code);
rc = -EINVAL;
goto end;
}
break;
}
@@ -520,7 +548,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
(struct cam_cmd_i2c_random_rd *)cmd_buf;
if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_random_rd)) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
@@ -533,7 +561,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
&cmd_length_in_bytes, &j, &list,
NULL);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Failed in random read %d", rc);
goto end;
}
@@ -550,7 +578,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
(struct cam_cmd_i2c_continuous_rd *)cmd_buf;
if ((size - byte_cnt) < sizeof(struct cam_cmd_i2c_continuous_rd)) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Not enough buffer provided,size %d,byte_cnt %d",
size, byte_cnt);
rc = -EINVAL;
@@ -563,7 +591,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
&cmd_length_in_bytes, &j, &list,
NULL);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
CAM_ERR(CAM_OIS,
"Failed in continuous read %d", rc);
goto end;
}
@@ -574,7 +602,7 @@ static int cam_ois_parse_fw_setting(uint8_t *cmd_buf, uint32_t size,
break;
}
default:
CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d",
CAM_ERR(CAM_OIS, "Invalid Command Type:%d",
cmm_hdr->cmd_type);
rc = -EINVAL;
goto end;
@@ -591,7 +619,8 @@ static int cam_ois_fw_info_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
int32_t rc = 0;
struct cam_cmd_ois_fw_info *ois_fw_info;
uint8_t *pSettingData = NULL;
uint32_t size;
uint32_t size = 0;
uint32_t version_size = 0;
struct i2c_settings_array *reg_settings = NULL;
uint8_t count = 0;
uint32_t idx;
@@ -603,28 +632,45 @@ static int cam_ois_fw_info_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
}
ois_fw_info = (struct cam_cmd_ois_fw_info *)cmd_buf;
CAM_DBG(CAM_SENSOR, "endianness %d, fw_count %d",
CAM_DBG(CAM_OIS, "endianness %d, fw_count %d",
ois_fw_info->endianness, ois_fw_info->fw_count);
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);
if ((ois_fw_info->param_mask & CAM_OIS_FW_VERSION_CHECK_MASK) == 0x1) {
version_size = ois_fw_info->params[0];
CAM_DBG(CAM_OIS, "versionSize: %d", version_size);
}
if ((version_size != 0) && (o_ctrl->i2c_fw_version_data.is_settings_valid == 0)) {
reg_settings = &o_ctrl->i2c_fw_version_data;
reg_settings->is_settings_valid = 1;
rc = cam_ois_parse_fw_setting(pSettingData, version_size, reg_settings);
if (rc) {
CAM_ERR(CAM_OIS, "Failed to parse fw version settings");
return rc;
}
pSettingData += version_size;
}
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);
CAM_DBG(CAM_OIS, "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);
CAM_DBG(CAM_OIS, "finalize size %d", size);
} else {
size = 0;
CAM_DBG(CAM_SENSOR, "Unsupported case");
CAM_DBG(CAM_OIS, "Unsupported case");
return -EINVAL;
}
@@ -867,6 +913,33 @@ static int cam_ois_fw_download_v2(struct cam_ois_ctrl_t *o_ctrl)
return -EINVAL;
}
if (o_ctrl->i2c_fw_version_data.is_settings_valid == 1) {
CAM_DBG(CAM_OIS, "check version to decide FW download");
rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_fw_version_data);
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_version_data);
}
if (delete_request(&o_ctrl->i2c_fw_version_data) < 0)
CAM_WARN(CAM_OIS,
"Fail deleting i2c_fw_version_data: rc: %d", rc);
if (rc == I2C_COMPARE_MATCH) {
CAM_INFO(CAM_OIS,
"OIS FW version matched, skipping FW download");
return rc;
} else if (rc == I2C_COMPARE_MISMATCH) {
CAM_INFO(CAM_OIS, "OIS FW version not matched, load FW");
} else {
CAM_WARN(CAM_OIS, "OIS FW version check failed,rc=%d", rc);
}
}
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;
@@ -884,6 +957,7 @@ static int cam_ois_fw_download_v2(struct cam_ois_ctrl_t *o_ctrl)
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) {
@@ -1364,7 +1438,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed to get qtimer rc:%d");
CAM_ERR(CAM_OIS, "failed to get qtimer rc:%d");
return rc;
}
@@ -1505,6 +1579,15 @@ void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl)
}
}
if (o_ctrl->i2c_fw_version_data.is_settings_valid == 1) {
rc = delete_request(&o_ctrl->i2c_fw_version_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting i2c_fw_version_data: rc: %d", rc);
rc = 0;
}
}
if (o_ctrl->i2c_mode_data.is_settings_valid == 1)
delete_request(&o_ctrl->i2c_mode_data);
@@ -1673,8 +1756,11 @@ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg)
}
o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
break;
case CAM_FLUSH_REQ:
CAM_DBG(CAM_OIS, "Flush recveived");
break;
default:
CAM_ERR(CAM_OIS, "invalid opcode");
CAM_ERR(CAM_OIS, "invalid opcode: %d", cmd->op_code);
goto release_mutex;
}
release_mutex:

View File

@@ -380,6 +380,7 @@ static int cam_ois_component_bind(struct device *dev,
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_fw_version_data.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));

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_OIS_DEV_H_
#define _CAM_OIS_DEV_H_
@@ -124,6 +124,7 @@ struct cam_ois_ctrl_t {
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];
struct i2c_settings_array i2c_fw_version_data;
};
/**

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "cam_sensor_cmn_header.h"
@@ -181,7 +181,12 @@ static int32_t cam_cci_i2c_compare(struct cam_sensor_cci_client *client,
reg_data = reg_data & 0xFFFF;
if (data == (reg_data & ~data_mask))
return I2C_COMPARE_MATCH;
return I2C_COMPARE_MISMATCH;
else {
CAM_WARN(CAM_SENSOR,
"mismatch: reg_data 0x%x: data: 0x%x, data_mask: 0x%x",
reg_data, data, data_mask);
return I2C_COMPARE_MISMATCH;
}
}
int32_t cam_cci_i2c_poll(struct cam_sensor_cci_client *client,

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_SENSOR_UTIL_H_
@@ -71,6 +71,12 @@ int32_t cam_sensor_handle_delay(
uint32_t offset, uint32_t *byte_cnt,
struct list_head *list_ptr);
int32_t cam_sensor_handle_poll(
uint32_t **cmd_buf,
struct i2c_settings_array *i2c_reg_settings,
uint32_t *byte_cnt, int32_t *offset,
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,