msm: camera: isp: Add support for Multi Context IO Buffer Config

In case of multi context supported targets for MC ports,
before configuring the bus related registers, correct context
needs to be configured to update the correct registers in the
respective context domain.
This commit adds support for context selection register
and update the io buffers for each context sequentially.

CRs-Fixed: 3321317
Change-Id: Icd660c2dfa56fad0d349679701a638943a0e833c
Signed-off-by: Gaurav Jindal <quic_gjindal@quicinc.com>
This commit is contained in:
Gaurav Jindal
2022-10-21 21:43:24 +05:30
committed by Camera Software Integration
vanhempi 56e0bcc8ee
commit 5b90165446
8 muutettua tiedostoa jossa 216 lisäystä ja 33 poistoa

Näytä tiedosto

@@ -4197,6 +4197,7 @@ static int cam_ife_mgr_check_and_update_fe(
major_ver = (acquire_hw_info->common_info_version >> 12) & 0xF;
minor_ver = (acquire_hw_info->common_info_version) & 0xFFF;
ife_ctx->major_version = major_ver;
switch (major_ver) {
case 1:
@@ -12189,6 +12190,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
io_buf_info.iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl;
io_buf_info.sec_iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure;
io_buf_info.base = &ctx->base[i];
io_buf_info.hw_intf = cam_ife_hw_mgr_get_hw_intf(&ctx->base[i]);
io_buf_info.major_version = ctx->major_version;
if (ctx->base[i].hw_type == CAM_ISP_HW_TYPE_VFE) {
io_buf_info.fill_fence = fill_ife_fence;

Näytä tiedosto

@@ -323,6 +323,9 @@ struct cam_isp_comp_record_query {
* @try_recovery_cnt: Retry count for overflow recovery
* @recovery_req_id: The request id on which overflow recovery happens
* @drv_path_idle_en: Path idle enable value for DRV
* @major_version: Major version for acquire
* @vfe_bus_comp_grp: VFE composite group placeholder
* @sfe_bus_comp_grp: SFE composite group placeholder
* @cdm_done_ts: CDM callback done timestamp
*/
struct cam_ife_hw_mgr_ctx {
@@ -385,6 +388,7 @@ struct cam_ife_hw_mgr_ctx {
uint32_t try_recovery_cnt;
uint64_t recovery_req_id;
uint32_t drv_path_idle_en;
uint32_t major_version;
struct cam_isp_context_comp_record *vfe_bus_comp_grp;
struct cam_isp_context_comp_record *sfe_bus_comp_grp;
struct timespec64 cdm_done_ts;

Näytä tiedosto

@@ -1031,6 +1031,81 @@ static int cam_isp_add_io_buffers_util(
return rc;
}
static int cam_isp_add_io_buffers_mc(
uint64_t *mc_io_cfg,
struct cam_isp_io_buf_info *io_info,
uint8_t num_ports,
uint32_t ctxt_id)
{
uint32_t bytes_used;
uint32_t kmd_buf_remain_size;
uint32_t *cmd_buf_addr;
struct cam_isp_hw_mgr_res *hw_mgr_res = NULL;
struct cam_isp_resource_node *res = NULL;
uint8_t max_out = 0;
int rc = 0;
int i;
if (io_info->kmd_buf_info->used_bytes < io_info->kmd_buf_info->size) {
kmd_buf_remain_size = io_info->kmd_buf_info->size -
io_info->kmd_buf_info->used_bytes;
} else {
CAM_ERR(CAM_ISP,
"no free kmd memory for base=%d bytes_used=%u buf_size=%u",
io_info->base->idx, io_info->kmd_buf_info->used_bytes,
io_info->kmd_buf_info->size);
rc = -ENOMEM;
return rc;
}
cmd_buf_addr = io_info->kmd_buf_info->cpu_addr +
io_info->kmd_buf_info->used_bytes/4;
rc = cam_isp_add_cmd_buf_update(
NULL, io_info->hw_intf,
CAM_ISP_HW_CMD_MC_CTXT_SEL,
CAM_ISP_HW_CMD_MC_CTXT_SEL,
(void *)cmd_buf_addr,
kmd_buf_remain_size,
(void *)(&ctxt_id),
&bytes_used);
if (rc) {
CAM_ERR(CAM_ISP, "Adding MC context[%u] failed for base[%d]",
ctxt_id, io_info->base->idx);
return rc;
}
io_info->kmd_buf_info->used_bytes += bytes_used;
io_info->kmd_buf_info->offset += bytes_used;
max_out = io_info->out_max;
for (i = 0; i < num_ports; i++) {
rc = cam_isp_io_buf_get_entries_util(io_info,
(struct cam_buf_io_cfg *)mc_io_cfg[(max_out * ctxt_id) + i], &hw_mgr_res);
if (!hw_mgr_res) {
CAM_ERR(CAM_ISP, "hw_mgr res is NULL");
return -EINVAL;
}
res = hw_mgr_res->hw_res[io_info->base->split_id];
if (!res)
continue;
rc = cam_isp_add_io_buffers_util(io_info,
(struct cam_buf_io_cfg *)mc_io_cfg[(max_out * ctxt_id) + i], res);
if (rc) {
CAM_ERR(CAM_ISP, "ctxt[%d] io_cfg[%d] add buf failed rc %d",
ctxt_id, i, rc);
return rc;
}
}
return rc;
}
int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info)
{
int rc = 0;
@@ -1041,6 +1116,11 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info)
uint32_t bytes_updated = 0;
uint32_t curr_offset = 0;
struct cam_isp_resource_node *res = NULL;
int ctxt_id = 0;
uint8_t num_ports[CAM_ISP_MULTI_CTXT_MAX] = {0};
uint8_t max_out_res = 0;
uint64_t *mc_cfg = NULL;
uint32_t major_version = 0;
io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
&io_info->prepare->packet->payload +
@@ -1057,32 +1137,71 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info)
return -EINVAL;
}
max_out_res = io_info->out_max & 0xFF;
major_version = io_info->major_version;
if (major_version == 3) {
mc_cfg = vzalloc(sizeof(uint64_t) * CAM_ISP_MULTI_CTXT_MAX * (max_out_res));
if (!mc_cfg) {
CAM_ERR(CAM_ISP, "Memory allocation failed for MC cases");
return -ENOMEM;
}
}
for (i = 0; i < io_info->prepare->packet->num_io_configs; i++) {
rc = cam_isp_io_buf_get_entries_util(io_info, &io_cfg[i], &hw_mgr_res);
if (major_version == 3) {
ctxt_id = ffs(io_cfg[i].flag) - 1;
if (ctxt_id < 0) {
CAM_ERR(CAM_ISP,
"Invalid ctxt_id %d req_id %llu resource_type:%d",
ctxt_id, io_info->prepare->packet->header.request_id,
io_cfg[i].resource_type);
rc = -EINVAL;
goto err;
}
if (rc == -ENOMSG) {
rc = 0;
continue;
} else if (rc) {
CAM_ERR(CAM_ISP, "io_cfg[%d] failed rc %d", i, rc);
return rc;
mc_cfg[(max_out_res * ctxt_id) + num_ports[ctxt_id]] = (uint64_t)&io_cfg[i];
num_ports[ctxt_id]++;
} else {
rc = cam_isp_io_buf_get_entries_util(io_info, &io_cfg[i], &hw_mgr_res);
if (rc == -ENOMSG) {
rc = 0;
continue;
} else if (rc) {
CAM_ERR(CAM_ISP, "io_cfg[%d] failed rc %d", i, rc);
return rc;
}
if (!hw_mgr_res) {
CAM_ERR(CAM_ISP, "hw_mgr res is NULL");
return -EINVAL;
}
res = hw_mgr_res->hw_res[io_info->base->split_id];
if (!res)
continue;
rc = cam_isp_add_io_buffers_util(io_info, &io_cfg[i], res);
if (rc) {
CAM_ERR(CAM_ISP, "io_cfg[%d] add buf failed rc %d", i, rc);
return rc;
}
}
}
if (!hw_mgr_res) {
CAM_ERR(CAM_ISP, "hw_mgr_res is NULL i:%d", i);
return -EINVAL;
}
res = hw_mgr_res->hw_res[io_info->base->split_id];
if (!res)
continue;
rc = cam_isp_add_io_buffers_util(io_info, &io_cfg[i], res);
if (rc) {
CAM_ERR(CAM_ISP, "io_cfg[%d] failed rc %d", i, rc);
return rc;
if (major_version == 3) {
for (i = 0; i < CAM_ISP_MULTI_CTXT_MAX; i++) {
if (!num_ports[i])
continue;
rc = cam_isp_add_io_buffers_mc(mc_cfg, io_info, num_ports[i], i);
if (rc) {
CAM_ERR(CAM_ISP, "MC context[%u] failed for base[%d]",
i, io_info->base->idx);
goto err;
}
}
vfree(mc_cfg);
}
bytes_updated = io_info->kmd_buf_info->used_bytes - curr_used_bytes;
@@ -1102,6 +1221,9 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info)
io_info->kmd_buf_info, bytes_updated, false);
}
return rc;
err:
vfree(mc_cfg);
return rc;
}

Näytä tiedosto

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_ISP_HW_PARSER_H_
@@ -129,11 +129,13 @@ struct cam_isp_cmd_buf_count {
* @res_list_ife_in_rd: IFE/SFE in rd resource list
* @base: Base info for IFE/SFE
* @out_map: Outport map
* @hw_intf: HW intf
* @iommu_hdl: Iommu handle to get the IO buf from memory manager
* @sec_iommu_hdl: Secure iommu handle to get the IO buf from
* memory manager
* @out_base: Base value of ISP resource (IFE/SFE)
* @out_max: Max of supported ISP resources(IFE/SFE)
* @major_version: Major version
* @fill_fence: If true, Fence map table will be filled
* @return: 0 for success
* -EINVAL for Fail
@@ -148,10 +150,12 @@ struct cam_isp_io_buf_info {
struct list_head *res_list_in_rd;
struct cam_isp_ctx_base_info *base;
uint8_t *out_map;
struct cam_hw_intf *hw_intf;
int iommu_hdl;
int sec_iommu_hdl;
uint32_t out_base;
uint32_t out_max;
uint32_t major_version;
bool fill_fence;
};

Näytä tiedosto

@@ -231,6 +231,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_RDI_LCR_CFG,
CAM_ISP_HW_CMD_DRV_CONFIG,
CAM_ISP_HW_CMD_CSID_DUMP_CROP_REG,
CAM_ISP_HW_CMD_MC_CTXT_SEL,
CAM_ISP_HW_CMD_MAX,
};

Näytä tiedosto

@@ -534,6 +534,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_IFE_BUS_MINI_DUMP:
case CAM_ISP_HW_CMD_BUF_UPDATE:
case CAM_ISP_HW_USER_DUMP:
case CAM_ISP_HW_CMD_MC_CTXT_SEL:
rc = core_info->vfe_bus->hw_ops.process_cmd(
core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
arg_size);

Näytä tiedosto

@@ -89,6 +89,7 @@ struct cam_vfe_bus_ver3_common_data {
void *buf_done_controller;
void *priv;
struct cam_vfe_bus_ver3_reg_offset_common *common_reg;
struct cam_cdm_utils_ops *cdm_util_ops;
uint32_t io_buf_update[
MAX_REG_VAL_PAIR_SIZE];
@@ -197,7 +198,6 @@ struct cam_vfe_bus_ver3_vfe_out_data {
uint32_t format;
uint32_t max_width;
uint32_t max_height;
struct cam_cdm_utils_ops *cdm_util_ops;
uint32_t secure_mode;
void *priv;
uint32_t *mid;
@@ -1912,7 +1912,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args,
rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
rsrc_node->tasklet_info = acq_args->tasklet;
rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
rsrc_data->common_data->cdm_util_ops = out_acquire_args->cdm_ops;
rsrc_data->format = out_acquire_args->out_port_info->format;
if ((rsrc_data->out_type == CAM_VFE_BUS_VER3_VFE_OUT_FD) &&
@@ -2009,7 +2009,6 @@ static int cam_vfe_bus_ver3_release_vfe_out(void *bus_priv, void *release_args,
vfe_out->tasklet_info = NULL;
vfe_out->cdm_ops = NULL;
rsrc_data->cdm_util_ops = NULL;
secure_caps = cam_vfe_bus_ver3_can_be_secure(rsrc_data->out_type);
mutex_lock(&rsrc_data->common_data->bus_mutex);
@@ -3301,12 +3300,12 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
update_buf->res->res_priv;
if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
if (!vfe_out_data || !vfe_out_data->common_data->cdm_util_ops) {
CAM_ERR(CAM_ISP, "Invalid data");
return -EINVAL;
}
cdm_util_ops = vfe_out_data->cdm_util_ops;
cdm_util_ops = vfe_out_data->common_data->cdm_util_ops;
if ((update_buf->wm_update->num_buf != vfe_out_data->num_wm) &&
(!(update_buf->use_scratch_cfg))) {
CAM_ERR(CAM_ISP,
@@ -3587,12 +3586,12 @@ static int cam_vfe_bus_ver3_update_hfr(void *priv, void *cmd_args,
vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
update_hfr->res->res_priv;
if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
if (!vfe_out_data || !vfe_out_data->common_data->cdm_util_ops) {
CAM_ERR(CAM_ISP, "Invalid data");
return -EINVAL;
}
cdm_util_ops = vfe_out_data->cdm_util_ops;
cdm_util_ops = vfe_out_data->common_data->cdm_util_ops;
reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
hfr_cfg = (struct cam_isp_port_hfr_config *)update_hfr->data;
@@ -3712,7 +3711,7 @@ static int cam_vfe_bus_ver3_update_ubwc_config_v2(void *cmd_args)
vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
update_ubwc->res->res_priv;
if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
if (!vfe_out_data || !vfe_out_data->common_data->cdm_util_ops) {
CAM_ERR(CAM_ISP, "Invalid data");
rc = -EINVAL;
goto end;
@@ -3894,7 +3893,7 @@ static int cam_vfe_bus_ver3_update_wm_config(
wm_config = (struct cam_isp_vfe_wm_config *)
wm_config_update->data;
if (!vfe_out_data || !vfe_out_data->cdm_util_ops || !wm_config) {
if (!vfe_out_data || !vfe_out_data->common_data->cdm_util_ops || !wm_config) {
CAM_ERR(CAM_ISP, "Invalid data");
return -EINVAL;
}
@@ -3990,12 +3989,12 @@ static int cam_vfe_bus_update_bw_limiter(
vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *)
wm_config_update->res->res_priv;
if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
if (!vfe_out_data || !vfe_out_data->common_data->cdm_util_ops) {
CAM_ERR(CAM_ISP, "Invalid data");
return -EINVAL;
}
cdm_util_ops = vfe_out_data->cdm_util_ops;
cdm_util_ops = vfe_out_data->common_data->cdm_util_ops;
reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
if (j >= (MAX_REG_VAL_PAIR_SIZE - (MAX_BUF_UPDATE_REG_NUM * 2))) {
@@ -4088,6 +4087,51 @@ add_reg_pair:
return 0;
}
static int cam_vfe_bus_ver3_mc_ctxt_sel(
void *priv, void *cmd_args, uint32_t arg_size)
{
struct cam_vfe_bus_ver3_priv *bus_priv;
struct cam_isp_hw_get_cmd_update *mc_config;
struct cam_cdm_utils_ops *cdm_util_ops = NULL;
struct cam_vfe_bus_ver3_reg_offset_common *common_reg;
uint32_t reg_val[2], ctxt_id = 0;
uint32_t size = 0;
if (!priv || !cmd_args) {
CAM_ERR(CAM_ISP, "Invalid args priv %x cmd_args %x",
priv, cmd_args);
return -EINVAL;
}
bus_priv = (struct cam_vfe_bus_ver3_priv *)priv;
mc_config = (struct cam_isp_hw_get_cmd_update *)cmd_args;
ctxt_id = *((uint32_t *)mc_config->data);
common_reg = bus_priv->common_data.common_reg;
reg_val[0] = common_reg->ctxt_sel;
reg_val[1] = ctxt_id << common_reg->mc_write_sel_shift;
cdm_util_ops = bus_priv->common_data.cdm_util_ops;
size = cdm_util_ops->cdm_required_size_reg_random(1);
/* cdm util returns dwords, need to convert to bytes */
if ((size * 4) > mc_config->cmd.size) {
CAM_ERR(CAM_ISP,
"Failed! Buf size:%d insufficient, expected size:%d",
mc_config->cmd.size, size);
return -ENOMEM;
}
cdm_util_ops->cdm_write_regrandom(
mc_config->cmd.cmd_buf_addr, 1, reg_val);
/* cdm util returns dwords, need to convert to bytes */
mc_config->cmd.used_bytes = size * 4;
return 0;
}
static int cam_vfe_bus_ver3_start_hw(void *hw_priv,
void *start_hw_args, uint32_t arg_size)
{
@@ -4317,6 +4361,10 @@ static int cam_vfe_bus_ver3_process_cmd(
case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG:
rc = cam_vfe_bus_update_bw_limiter(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_MC_CTXT_SEL:
rc = cam_vfe_bus_ver3_mc_ctxt_sel(priv, cmd_args, arg_size);
break;
default:
CAM_ERR_RATE_LIMIT(CAM_ISP, "VFE:%u Invalid camif process command:%d",
priv->hw_intf->hw_idx, cmd_type);

Näytä tiedosto

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/