msm: camera: isp: Disable/Enable SFE read masters dynamically

For dynamic switch use-cases, disable SFE RMs if they are not
used. Enable them if there is a switch utilizing that RM.
This is the HW recommendation for dynamic switch use-cases.

CRs-Fixed: 2841729
Change-Id: I93732fddced02c4e375635143de3f122f37ef008
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Karthik Anantha Ram
2021-06-09 18:29:34 -07:00
committed by Gerrit - the friendly Code Review server
parent 311380c961
commit a5fbb956da
4 changed files with 182 additions and 4 deletions

View File

@@ -7217,6 +7217,93 @@ end:
return 0;
}
static int cam_isp_blob_sfe_update_fetch_core_cfg(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
struct cam_hw_prepare_update_args *prepare)
{
int rc;
uint32_t used_bytes = 0, total_used_bytes = 0;
uint32_t remain_size, res_id;
uint32_t *cpu_addr = NULL;
bool enable = true;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_kmd_buf_info *kmd_buf_info;
struct cam_ife_hw_mgr_ctx *ctx = NULL;
ctx = prepare->ctxt_to_hw_map;
if (prepare->num_hw_update_entries + 1 >=
prepare->max_hw_update_entries) {
CAM_ERR(CAM_ISP, "Insufficient HW entries :%d",
prepare->num_hw_update_entries);
return -EINVAL;
}
kmd_buf_info = blob_info->kmd_buf_info;
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
if ((kmd_buf_info->used_bytes
+ total_used_bytes) < kmd_buf_info->size) {
remain_size = kmd_buf_info->size -
(kmd_buf_info->used_bytes +
total_used_bytes);
} else {
CAM_ERR(CAM_ISP,
"No free kmd memory for base idx: %d",
blob_info->base_info->idx);
rc = -ENOMEM;
return rc;
}
cpu_addr = kmd_buf_info->cpu_addr +
(kmd_buf_info->used_bytes / 4) +
(total_used_bytes / 4);
res_id = hw_mgr_res->res_id;
/* check for active fetches */
if ((ctx->ctx_config &
CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
((res_id - CAM_ISP_SFE_IN_RD_0) >=
ctx->sfe_info.scratch_config->curr_num_exp))
enable = false;
else
enable = true;
cpu_addr = kmd_buf_info->cpu_addr +
kmd_buf_info->used_bytes / 4 +
total_used_bytes / 4;
CAM_DBG(CAM_ISP,
"SFE:%u RM: %u res_id: 0x%x enable: %u num_exp: %u",
blob_info->base_info->idx,
(res_id - CAM_ISP_SFE_IN_RD_0), res_id, enable,
ctx->sfe_info.scratch_config->curr_num_exp);
rc = cam_isp_add_cmd_buf_update(
hw_mgr_res, blob_type,
CAM_ISP_HW_CMD_RM_ENABLE_DISABLE,
blob_info->base_info->idx,
(void *)cpu_addr, remain_size,
(void *)&enable, &used_bytes);
if (rc < 0) {
CAM_ERR(CAM_ISP,
"Failed to dynamically %s SFE: %u RM: %u bytes_used: %u rc: %d",
(enable ? "enable" : "disable"),
blob_info->base_info->idx, res_id,
used_bytes, rc);
return rc;
}
total_used_bytes += used_bytes;
}
if (total_used_bytes)
cam_ife_mgr_update_hw_entries_util(
false, total_used_bytes, kmd_buf_info, prepare);
return 0;
}
static int cam_isp_blob_hfr_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
@@ -9042,8 +9129,16 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
}
mup_config = (struct cam_isp_mode_switch_info *)blob_data;
ife_mgr_ctx->sfe_info.scratch_config->curr_num_exp =
mup_config->num_expoures;
if (ife_mgr_ctx->flags.is_sfe_shdr) {
ife_mgr_ctx->sfe_info.scratch_config->curr_num_exp =
mup_config->num_expoures;
rc = cam_isp_blob_sfe_update_fetch_core_cfg(
blob_type, blob_info, prepare);
if (rc)
CAM_ERR(CAM_ISP,
"SFE dynamic enable/disable for fetch failed");
}
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_SFE_EXP_ORDER_CFG: {

View File

@@ -161,6 +161,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG,
CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG,
CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG,
CAM_ISP_HW_CMD_RM_ENABLE_DISABLE,
CAM_ISP_HW_CMD_MAX,
};

View File

@@ -345,6 +345,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
case CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG:
case CAM_ISP_HW_CMD_RM_ENABLE_DISABLE:
rc = core_info->sfe_bus_rd->hw_ops.process_cmd(
core_info->sfe_bus_rd->bus_priv, cmd_type,
cmd_args, arg_size);

View File

@@ -459,9 +459,9 @@ static int cam_sfe_bus_start_rm(struct cam_isp_resource_node *rm_res)
rm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
CAM_DBG(CAM_SFE,
"Start SFE:%d RM:%d offset:0x%X en_cfg:0x%X width:%d height:%d",
"Start SFE:%d RM:%d offset:0x%X width:%d height:%d",
rm_data->common_data->core_index, rm_data->index,
(uint32_t) rm_data->hw_regs->cfg, rm_data->en_cfg,
(uint32_t) rm_data->hw_regs->cfg,
rm_data->width, rm_data->height);
CAM_DBG(CAM_SFE, "RM:%d pk_fmt:%d stride:%d", rm_data->index,
rm_data->unpacker_cfg, rm_data->stride);
@@ -1392,6 +1392,84 @@ skip_cache_cfg:
return 0;
}
static int cam_sfe_bus_rd_update_rm_core_cfg(
void *priv, void *cmd_args, uint32_t arg_size)
{
struct cam_sfe_bus_rd_priv *bus_priv;
struct cam_isp_hw_get_cmd_update *cmd_update;
struct cam_sfe_bus_rd_data *sfe_bus_rd_data = NULL;
struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
struct cam_cdm_utils_ops *cdm_util_ops;
bool enable_disable = false;
uint32_t *reg_val_pair;
uint32_t num_regval_pairs = 0, i, j, size = 0;
bus_priv = (struct cam_sfe_bus_rd_priv *) priv;
cmd_update = (struct cam_isp_hw_get_cmd_update *) cmd_args;
enable_disable = *(bool *)cmd_update->data;
sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
cmd_update->res->res_priv;
if (!sfe_bus_rd_data) {
CAM_ERR(CAM_SFE, "Invalid SFE rd data: %pK",
sfe_bus_rd_data);
return -EINVAL;
}
cdm_util_ops = sfe_bus_rd_data->cdm_util_ops;
if (!cdm_util_ops) {
CAM_ERR(CAM_SFE, "Invalid cdm ops: %pK",
cdm_util_ops);
return -EINVAL;
}
reg_val_pair = &sfe_bus_rd_data->common_data->io_buf_update[0];
for (i = 0, j = 0; i < sfe_bus_rd_data->num_rm; i++) {
if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
CAM_ERR(CAM_SFE,
"reg_val_pair %d exceeds the array limit %lu",
j, MAX_REG_VAL_PAIR_SIZE);
return -ENOMEM;
}
rm_data = sfe_bus_rd_data->rm_res[i]->res_priv;
CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
rm_data->hw_regs->cfg, enable_disable);
CAM_DBG(CAM_SFE, "SFE:%d RM:%d cfg:0x%x",
rm_data->common_data->core_index,
rm_data->index, reg_val_pair[j-1]);
}
num_regval_pairs = j / 2;
if (num_regval_pairs) {
size = cdm_util_ops->cdm_required_size_reg_random(
num_regval_pairs);
/* cdm util returns dwords, need to convert to bytes */
if ((size * 4) > cmd_update->cmd.size) {
CAM_ERR(CAM_SFE,
"Failed! Buf size:%d insufficient, expected size:%d",
cmd_update->cmd.size, size);
return -ENOMEM;
}
cdm_util_ops->cdm_write_regrandom(
cmd_update->cmd.cmd_buf_addr, num_regval_pairs,
reg_val_pair);
/* cdm util returns dwords, need to convert to bytes */
cmd_update->cmd.used_bytes = size * 4;
} else {
cmd_update->cmd.used_bytes = 0;
CAM_DBG(CAM_SFE,
"No reg val pairs. num_rms: %u",
sfe_bus_rd_data->num_rm);
}
return 0;
}
static int cam_sfe_bus_init_hw(void *hw_priv,
void *init_hw_args, uint32_t arg_size)
{
@@ -1495,6 +1573,9 @@ static int cam_sfe_bus_rd_process_cmd(
case CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG:
rc = cam_sfe_bus_rd_cache_config(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_RM_ENABLE_DISABLE:
rc = cam_sfe_bus_rd_update_rm_core_cfg(priv, cmd_args, arg_size);
break;
default:
CAM_ERR_RATE_LIMIT(CAM_SFE,
"Invalid SFE BUS RD command type: %d",