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

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 <[email protected]>
Karthik Anantha Ram 4 жил өмнө
parent
commit
a5fbb956da

+ 97 - 2
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -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: {

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

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

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c

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

+ 83 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c

@@ -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",