Эх сурвалжийг харах

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 <[email protected]>
Gaurav Jindal 2 жил өмнө
parent
commit
5b90165446

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -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;

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h

@@ -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;

+ 141 - 19
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -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 i:%d", i);
-			return -EINVAL;
-		}
+			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);
+			res = hw_mgr_res->hw_res[io_info->base->split_id];
+			if (!res)
+				continue;
 
-		if (rc) {
-			CAM_ERR(CAM_ISP, "io_cfg[%d] failed rc %d", i, rc);
-			return rc;
+			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 (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;
 }
 

+ 5 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h

@@ -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;
 };
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -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,
 };
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c

@@ -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);

+ 59 - 11
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c

@@ -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);

+ 1 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h

@@ -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.
  */