Pārlūkot izejas kodu

Merge "msm: camera: isp: Add support for RDI LCR" into camera-kernel.lnx.5.0

Camera Software Integration 3 gadi atpakaļ
vecāks
revīzija
4af9ddf8b1
21 mainītis faili ar 696 papildinājumiem un 57 dzēšanām
  1. 237 0
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
  2. 2 0
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
  3. 2 0
      drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h
  4. 12 0
      drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
  5. 16 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid780.h
  6. 58 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_common.c
  7. 15 3
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_common.h
  8. 2 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c
  9. 123 10
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c
  10. 6 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.h
  11. 6 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
  12. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
  13. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h
  14. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
  15. 39 21
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c
  16. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
  17. 19 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe780.h
  18. 37 16
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c
  19. 80 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c
  20. 9 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.h
  21. 27 0
      include/uapi/camera/media/cam_isp.h

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

@@ -1847,6 +1847,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
 		vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
 		vfe_acquire.buf_done_controller = ife_ctx->buf_done_controller;
 		hw_intf = ife_src_res->hw_res[0]->hw_intf;
+		vfe_acquire.vfe_out.use_wm_pack = ife_src_res->use_wm_pack;
 		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
 			&vfe_acquire,
 			sizeof(struct cam_vfe_acquire_args));
@@ -1867,6 +1868,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
 
 	ife_out_res->hw_res[0] = vfe_acquire.vfe_out.rsrc_node;
 	ife_out_res->is_dual_isp = 0;
+	ife_out_res->use_wm_pack = ife_src_res->use_wm_pack;
 	ife_out_res->res_id = vfe_out_res_id;
 	ife_out_res->res_type = CAM_ISP_RESOURCE_VFE_OUT;
 	ife_src_res->num_children++;
@@ -2038,6 +2040,7 @@ static int cam_ife_hw_mgr_acquire_res_sfe_out_rdi(
 		sfe_acquire.sfe_out.is_dual = 0;
 		sfe_acquire.buf_done_controller = ife_ctx->buf_done_controller;
 		sfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
+		sfe_acquire.sfe_out.use_wm_pack = sfe_src_res->use_wm_pack;
 		hw_intf = sfe_src_res->hw_res[0]->hw_intf;
 		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
 			&sfe_acquire,
@@ -2060,6 +2063,7 @@ static int cam_ife_hw_mgr_acquire_res_sfe_out_rdi(
 
 	sfe_out_res->hw_res[0] = sfe_acquire.sfe_out.rsrc_node;
 	sfe_out_res->is_dual_isp = 0;
+	sfe_out_res->use_wm_pack = sfe_src_res->use_wm_pack;
 	sfe_out_res->res_id = sfe_out_res_id;
 	sfe_out_res->res_type = CAM_ISP_RESOURCE_SFE_OUT;
 	sfe_src_res->num_children++;
@@ -2468,6 +2472,7 @@ static int cam_ife_hw_mgr_acquire_res_sfe_src(
 		sfe_src_res->res_type = sfe_acquire.rsrc_type;
 		sfe_src_res->res_id = sfe_acquire.sfe_in.res_id;
 		sfe_src_res->is_dual_isp = csid_res->is_dual_isp;
+		sfe_src_res->use_wm_pack = csid_res->use_wm_pack;
 		for (i = sfe_src_res->is_dual_isp; i >= 0; i--) {
 			rc = cam_ife_hw_mgr_acquire_sfe_hw(
 				((is_rdi) && (!sfe_src_res->is_dual_isp) &&
@@ -3025,6 +3030,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
 		ife_src_res->res_type = vfe_acquire.rsrc_type;
 		ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
 		ife_src_res->is_dual_isp = csid_res->is_dual_isp;
+		ife_src_res->use_wm_pack = csid_res->use_wm_pack;
 
 		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
 			if (!csid_res->hw_res[i])
@@ -3426,6 +3432,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 		csid_acquire.tasklet = ife_ctx->common.tasklet_info;
 		csid_acquire.cb_priv = ife_ctx;
 		csid_acquire.cdm_ops = ife_ctx->cdm_ops;
+		if (ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE)
+			csid_acquire.sfe_en = true;
+
 		if (cam_ife_hw_mgr_is_shdr_fs_rdi_res(
 			out_port->res_type,
 			ife_ctx->flags.is_sfe_shdr, ife_ctx->flags.is_sfe_fs)) {
@@ -3499,6 +3508,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 		csid_res->is_dual_isp = 0;
 		csid_res->hw_res[0] = csid_acquire.node_res;
 		csid_res->hw_res[1] = NULL;
+		csid_res->use_wm_pack = csid_acquire.use_wm_pack;
 		if ((ife_ctx->flags.is_rdi_only_context) ||
 			(ife_ctx->flags.is_sfe_fs) ||
 			(ife_ctx->flags.is_sfe_shdr)) {
@@ -8541,6 +8551,213 @@ static int cam_isp_blob_bw_limit_update(
 	return rc;
 }
 
+static int cam_isp_hw_mgr_add_cmd_buf_util(
+	struct cam_isp_hw_mgr_res         *hw_mgr_res,
+	struct cam_hw_prepare_update_args *prepare,
+	struct cam_isp_generic_blob_info  *blob_info,
+	void                              *data,
+	uint32_t                           hw_cmd_type,
+	uint32_t                           blob_type)
+{
+	uint32_t                       total_used_bytes = 0;
+	uint32_t                       kmd_buf_remain_size;
+	struct cam_kmd_buf_info       *kmd_buf_info;
+	uint32_t                      *cmd_buf_addr;
+	int                            rc = 0;
+
+	kmd_buf_info = blob_info->kmd_buf_info;
+	if (kmd_buf_info->used_bytes < kmd_buf_info->size) {
+		kmd_buf_remain_size = kmd_buf_info->size - kmd_buf_info->used_bytes;
+	} else {
+		CAM_ERR(CAM_ISP, "No free kmd memory for base idx: %d used_bytes %u buf_size %u",
+			blob_info->base_info->idx, kmd_buf_info->used_bytes, kmd_buf_info->size);
+		return -ENOMEM;
+	}
+
+	cmd_buf_addr = kmd_buf_info->cpu_addr + (kmd_buf_info->used_bytes / 4);
+	rc = cam_isp_add_cmd_buf_update(hw_mgr_res, blob_type,
+		hw_cmd_type, blob_info->base_info->idx, (void *)cmd_buf_addr,
+		kmd_buf_remain_size, data, &total_used_bytes);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Add cmd buffer failed idx: %d",
+			blob_info->base_info->idx);
+		return -EINVAL;
+	}
+
+	if (total_used_bytes)
+		cam_ife_mgr_update_hw_entries_util(
+			CAM_ISP_IQ_BL, total_used_bytes, kmd_buf_info, prepare);
+	return rc;
+}
+
+static int cam_isp_update_ife_pdaf_cfg(
+	struct cam_ife_hw_mgr_ctx         *ctx,
+	struct cam_hw_prepare_update_args *prepare,
+	struct cam_isp_generic_blob_info  *blob_info,
+	struct cam_isp_lcr_rdi_cfg_args   *isp_lcr_cfg,
+	uint32_t                           blob_type)
+{
+	struct cam_isp_hw_mgr_res     *hw_mgr_res;
+	uint32_t                       i;
+	uint32_t                       ife_res_id;
+	struct cam_isp_resource_node  *res;
+	int                            rc = -EINVAL;
+
+	ife_res_id = cam_convert_rdi_out_res_id_to_src(isp_lcr_cfg->rdi_lcr_cfg->res_id);
+	if (ife_res_id == CAM_ISP_HW_VFE_IN_MAX) {
+		CAM_ERR(CAM_ISP, "Invalid res_id %u", isp_lcr_cfg->rdi_lcr_cfg->res_id);
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_ISP, "Ctx %d res: %u lcr %u id %u ctx_type %u", ctx->ctx_index, ife_res_id,
+		isp_lcr_cfg->rdi_lcr_cfg->res_id, blob_info->base_info->idx, ctx->ctx_type);
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT)
+			continue;
+
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			res = hw_mgr_res->hw_res[i];
+			/*
+			 * for SFE cases, only CAMIF resource is
+			 * acquired. We need any res to go to vfe drivers
+			 * to update the buffer. For non-sfe case, we match
+			 * with the incoming res_id
+			 */
+			if ((ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE &&
+				res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) ||
+				res->res_id == ife_res_id) {
+
+				rc = cam_isp_hw_mgr_add_cmd_buf_util(hw_mgr_res, prepare,
+					blob_info, (void *)isp_lcr_cfg,
+					CAM_ISP_HW_CMD_RDI_LCR_CFG, blob_type);
+				if (rc)
+					CAM_ERR(CAM_ISP,
+						"Ctx %d res: %u lcr %u id %u ctx_type %u rc %u",
+						ctx->ctx_index, ife_res_id,
+						isp_lcr_cfg->rdi_lcr_cfg->res_id,
+						blob_info->base_info->idx, ctx->ctx_type, rc);
+				goto end;
+			}
+		}
+	}
+end:
+	return rc;
+}
+
+static int  cam_isp_config_rdi_lcr_csid_init_params(
+	struct cam_ife_hw_mgr_ctx         *ctx,
+	struct cam_hw_prepare_update_args *prepare,
+	struct cam_isp_generic_blob_info  *blob_info,
+	struct cam_isp_lcr_rdi_config     *rdi_lcr_cfg,
+	uint32_t                           blob_type)
+{
+	struct cam_isp_hw_mgr_res         *hw_mgr_res;
+	struct cam_isp_resource_node      *res;
+	int                                rc = -EINVAL;
+	uint32_t                           csid_res_id = 0;
+	uint32_t                           acquired_res_id_mask = 0;
+
+	csid_res_id = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+			rdi_lcr_cfg->res_id);
+	CAM_DBG(CAM_ISP,
+		"Ctx: %d csid_res_id: %u rdi_lcr: %u sfe_shdr %u ctx_ctype %u", ctx->ctx_index,
+		csid_res_id, rdi_lcr_cfg->res_id, ctx->flags.is_sfe_shdr, ctx->ctx_type);
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+		if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT)
+			continue;
+
+		if (!hw_mgr_res->hw_res[0])
+			continue;
+
+		if (hw_mgr_res->res_id < CAM_IFE_PIX_PATH_RES_RDI_0 ||
+			hw_mgr_res->res_id > CAM_IFE_PIX_PATH_RES_RDI_2)
+			continue;
+
+		if (!ctx->flags.is_sfe_shdr && hw_mgr_res->res_id != csid_res_id)
+			continue;
+
+		res = hw_mgr_res->hw_res[0];
+		rc = res->hw_intf->hw_ops.process_cmd(res->hw_intf->hw_priv,
+			CAM_ISP_HW_CMD_RDI_LCR_CFG, res, sizeof(*res));
+		acquired_res_id_mask |= BIT(res->res_id);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"Ctx: %d csid_res_id: %u rdi_lcr: %u sfe_shdr %u ctx_ctype %u",
+				ctx->ctx_index, csid_res_id, rdi_lcr_cfg->res_id,
+				ctx->flags.is_sfe_shdr, ctx->ctx_type);
+			break;
+		}
+	}
+
+	if (!(acquired_res_id_mask & BIT(csid_res_id))) {
+		CAM_ERR(CAM_ISP,
+			"Ctx: %d Unacquired csid_res_id: %u rdi_lcr: %u sfe_shdr %u ctx_ctype %u",
+			ctx->ctx_index, csid_res_id, rdi_lcr_cfg->res_id,
+			ctx->flags.is_sfe_shdr, ctx->ctx_type);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static int cam_isp_blob_ife_rdi_lcr_config(
+	struct cam_ife_hw_mgr_ctx         *ctx,
+	struct cam_hw_prepare_update_args *prepare,
+	struct cam_isp_generic_blob_info  *blob_info,
+	struct cam_isp_lcr_rdi_config     *rdi_lcr_cfg,
+	uint32_t                           blob_type)
+{
+	struct cam_isp_prepare_hw_update_data  *prepare_hw_data;
+	struct cam_isp_lcr_rdi_cfg_args         isp_cfg_args = {0};
+	int                                     rc = -EINVAL;
+
+	prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)prepare->priv;
+	CAM_DBG(CAM_ISP,
+		"Blob opcode %u res %u ctx_type %u shdr %u rdi_lcr %u",
+		prepare_hw_data->packet_opcode_type, rdi_lcr_cfg->res_id, ctx->ctx_type,
+		ctx->flags.is_sfe_shdr, ctx->flags.rdi_lcr_en);
+
+	if (prepare_hw_data->packet_opcode_type == CAM_ISP_PACKET_INIT_DEV) {
+		rc = cam_isp_config_rdi_lcr_csid_init_params(ctx,
+			prepare, blob_info, rdi_lcr_cfg, blob_type);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"CSID param failed Ctx: %d rdi_lcr: %u ctx_type: %u",
+				ctx->ctx_index, rdi_lcr_cfg->res_id, ctx->ctx_type);
+			return rc;
+		}
+
+		isp_cfg_args.is_init = true;
+		ctx->flags.rdi_lcr_en = true;
+	} else if (!ctx->flags.rdi_lcr_en || !ctx->flags.is_sfe_shdr) {
+		/*
+		 * we don't expect blob for non-shdr cases other than Init Packet,
+		 * as the RDI input would remain same for the session.
+		 */
+		CAM_ERR(CAM_ISP,
+			"Unexpected Blob opcode %u res %u ctx_type %u shdr %u rdi_lcr %u",
+			prepare_hw_data->packet_opcode_type, rdi_lcr_cfg->res_id, ctx->ctx_type,
+			ctx->flags.is_sfe_shdr, ctx->flags.rdi_lcr_en);
+		return rc;
+	}
+
+	isp_cfg_args.rdi_lcr_cfg = rdi_lcr_cfg;
+	rc = cam_isp_update_ife_pdaf_cfg(ctx, prepare, blob_info,
+		&isp_cfg_args, blob_type);
+	if (rc) {
+		CAM_ERR(CAM_ISP,
+			"IFE param failed %u res %u ctx_type %u shdr %u rdi_lcr %u",
+			prepare_hw_data->packet_opcode_type, rdi_lcr_cfg->res_id, ctx->ctx_type,
+			ctx->flags.is_sfe_shdr, ctx->flags.rdi_lcr_en);
+		return rc;
+	}
+
+	return rc;
+}
+
 static inline int cam_isp_validate_bw_limiter_blob(
 	uint32_t blob_size,
 	struct cam_isp_out_rsrc_bw_limiter_config *bw_limit_config)
@@ -9218,6 +9435,25 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 			CAM_ERR(CAM_ISP,
 				"Init config failed for req: %llu rc: %d",
 				 prepare->packet->header.request_id, rc);
+	}
+		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_RDI_LCR_CONFIG: {
+		struct cam_isp_lcr_rdi_config *lcr_rdi_config;
+
+		if (blob_size < sizeof(struct cam_isp_lcr_rdi_config)) {
+			CAM_ERR(CAM_ISP, "Invalid lcr blob size %u expected %u",
+				blob_size, sizeof(struct cam_isp_lcr_rdi_config));
+			return -EINVAL;
+		}
+
+		lcr_rdi_config = (struct cam_isp_lcr_rdi_config *)blob_data;
+		rc = cam_isp_blob_ife_rdi_lcr_config(ife_mgr_ctx, prepare,
+			blob_info, lcr_rdi_config, blob_type);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"RDI LCR config failed for res %u",
+				 lcr_rdi_config->res_id);
+
 	}
 		break;
 	default:
@@ -9683,6 +9919,7 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 	case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES:
 	case CAM_ISP_GENERIC_BLOB_TYPE_INIT_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG:
+	case CAM_ISP_GENERIC_BLOB_TYPE_RDI_LCR_CONFIG:
 		break;
 	default:
 		CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type);

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

@@ -153,6 +153,7 @@ struct cam_ife_hw_mgr_sfe_info {
  * @dump_on_flush:       Set if reg dump triggered on flush
  * @dump_on_error:       Set if reg dump triggered on error
  * @custom_aeb_mode:     Set if custom AEB stream
+ * @rdi_lcr_en:          To indicate if RDI LCR is enabled
  * @sys_cache_usage:     Per context sys cache usage
  *                       The corresponding index will be set
  *                       for the cache type
@@ -175,6 +176,7 @@ struct cam_ife_hw_mgr_ctx_flags {
 	bool   dump_on_flush;
 	bool   dump_on_error;
 	bool   is_aeb_mode;
+	bool   rdi_lcr_en;
 	bool   sys_cache_usage[CAM_LLCC_MAX];
 };
 

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h

@@ -69,6 +69,7 @@ struct cam_isp_hw_mgr {
  *                       acquired
  * @is_secure            informs whether the resource is in secure mode or not
  * @num_children:        number of the child resource node.
+ * @use_wm_pack:         Flag to indicate if WM is to be used for packing
  *
  */
 struct cam_isp_hw_mgr_res {
@@ -79,6 +80,7 @@ struct cam_isp_hw_mgr_res {
 	struct cam_isp_resource_node    *hw_res[CAM_ISP_HW_SPLIT_MAX];
 	uint32_t                         is_secure;
 	uint32_t                         num_children;
+	bool                             use_wm_pack;
 };
 
 

+ 12 - 0
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h

@@ -370,6 +370,18 @@ struct cam_isp_start_args {
 	bool                      start_only;
 };
 
+/**
+ * struct cam_isp_lcr_rdi_cfg_args - isp hardware start arguments
+ *
+ * @rdi_lcr_cfg:            RDI LCR cfg received from User space.
+ * @is_init:                Flag to indicate if init packet.
+ *
+ */
+struct cam_isp_lcr_rdi_cfg_args {
+	struct cam_isp_lcr_rdi_config *rdi_lcr_cfg;
+	bool                           is_init;
+};
+
 /**
  * cam_isp_hw_mgr_init()
  *

+ 16 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid780.h

@@ -625,6 +625,10 @@ static struct cam_ife_csid_ver2_path_reg_info
 		/* configurations */
 		.resume_frame_boundary            = 1,
 		.overflow_ctrl_en                 = 1,
+		.capabilities                     = CAM_IFE_CSID_CAP_INPUT_LCR |
+							CAM_IFE_CSID_CAP_MIPI10_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI12_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI14_UNPACK,
 		.overflow_ctrl_mode_val           = 0x8,
 		.offline_mode_supported           = 1,
 		.mipi_pack_supported              = 1,
@@ -719,6 +723,10 @@ static struct cam_ife_csid_ver2_path_reg_info
 		/* configurations */
 		.resume_frame_boundary            = 1,
 		.overflow_ctrl_en                 = 1,
+		.capabilities                     = CAM_IFE_CSID_CAP_INPUT_LCR |
+							CAM_IFE_CSID_CAP_MIPI10_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI12_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI14_UNPACK,
 		.overflow_ctrl_mode_val           = 0x8,
 		.mipi_pack_supported              = 1,
 		.offline_mode_supported           = 1,
@@ -813,6 +821,10 @@ static struct cam_ife_csid_ver2_path_reg_info
 		/* configurations */
 		.resume_frame_boundary            = 1,
 		.overflow_ctrl_en                 = 1,
+		.capabilities                     = CAM_IFE_CSID_CAP_INPUT_LCR |
+							CAM_IFE_CSID_CAP_MIPI10_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI12_UNPACK |
+							CAM_IFE_CSID_CAP_MIPI14_UNPACK,
 		.overflow_ctrl_mode_val           = 0x8,
 		.mipi_pack_supported              = 1,
 		.offline_mode_supported           = 1,
@@ -907,6 +919,7 @@ static struct cam_ife_csid_ver2_path_reg_info
 		/* configurations */
 		.resume_frame_boundary            = 1,
 		.overflow_ctrl_en                 = 1,
+		.capabilities                     = 0,
 		.overflow_ctrl_mode_val           = 0x8,
 		.offline_mode_supported           = 1,
 		.mipi_pack_supported              = 1,
@@ -1001,6 +1014,7 @@ static struct cam_ife_csid_ver2_path_reg_info
 		/* configurations */
 		.resume_frame_boundary           = 1,
 		.overflow_ctrl_en                = 1,
+		.capabilities                    = 0,
 		.overflow_ctrl_mode_val          = 0x8,
 		.offline_mode_supported          = 1,
 		.mipi_pack_supported             = 1,
@@ -1142,6 +1156,7 @@ static struct cam_ife_csid_ver2_common_reg_info
 	.timestamp_stb_sel_shift_val             = 8,
 	.vfr_en_shift_val                        = 0,
 	.mup_shift_val                           = 28,
+	.shdr_slave_ppp_shift                    = 20,
 	.shdr_slave_rdi2_shift                   = 22,
 	.shdr_slave_rdi1_shift                   = 21,
 	.shdr_master_rdi0_shift                  = 5,
@@ -1203,6 +1218,7 @@ static struct cam_ife_csid_ver2_top_reg_info
 	.dual_sync_sel_shift_val        = 8,
 	.dual_en_shift_val              = 0,
 	.master_slave_sel_shift_val     = 1,
+	.rdi_lcr_shift_val              = 16,
 	.master_sel_val                 = 0,
 	.slave_sel_val                  = 1,
 	.io_path_cfg_rst_val            = 1,

+ 58 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_common.c

@@ -96,7 +96,8 @@ int cam_ife_csid_is_pix_res_format_supported(
 
 int cam_ife_csid_get_format_rdi(
 	uint32_t in_format, uint32_t out_format,
-	struct cam_ife_csid_path_format *path_format, bool rpp)
+	struct cam_ife_csid_path_format *path_format, bool rpp,
+	bool mipi_unpacked)
 {
 	int rc = 0;
 
@@ -109,10 +110,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x0;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x0;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x0;
+			}
 			break;
 		case CAM_FORMAT_PLAIN8:
 			path_format->decode_fmt = 0x0;
 			path_format->plain_fmt = 0x0;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -129,9 +137,16 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x1;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x1;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x0;
+			}
 			break;
 		case CAM_FORMAT_PLAIN8:
 			path_format->decode_fmt = 0x1;
+			path_format->packing_fmt = 0;
 			path_format->plain_fmt = 0x0;
 			break;
 		default:
@@ -149,10 +164,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x2;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x2;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x1;
+			}
 			break;
 		case CAM_FORMAT_PLAIN16_10:
 			path_format->decode_fmt = 0x2;
 			path_format->plain_fmt = 0x1;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -168,10 +190,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x3;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x3;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x1;
+			}
 			break;
 		case CAM_FORMAT_PLAIN16_12:
 			path_format->decode_fmt = 0x3;
 			path_format->plain_fmt = 0x1;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -187,10 +216,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x4;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x4;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x1;
+			}
 			break;
 		case CAM_FORMAT_PLAIN16_14:
 			path_format->decode_fmt = 0x4;
 			path_format->plain_fmt = 0x1;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -206,10 +242,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x5;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x5;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x1;
+			}
 			break;
 		case CAM_FORMAT_PLAIN16_16:
 			path_format->decode_fmt = 0x5;
 			path_format->plain_fmt = 0x1;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -225,10 +268,17 @@ int cam_ife_csid_get_format_rdi(
 				path_format->decode_fmt = 0x6;
 				path_format->packing_fmt = 0x1;
 			}
+
+			if (mipi_unpacked) {
+				path_format->decode_fmt = 0x6;
+				path_format->packing_fmt = 0x0;
+				path_format->plain_fmt = 0x2;
+			}
 			break;
 		case CAM_FORMAT_PLAIN32_20:
 			path_format->decode_fmt = 0x6;
 			path_format->plain_fmt = 0x2;
+			path_format->packing_fmt = 0;
 			break;
 		default:
 			rc = -EINVAL;
@@ -239,30 +289,37 @@ int cam_ife_csid_get_format_rdi(
 	case CAM_FORMAT_DPCM_10_6_10:
 		path_format->decode_fmt  = 0x7;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_10_8_10:
 		path_format->decode_fmt  = 0x8;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_12_6_12:
 		path_format->decode_fmt  = 0x9;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_12_8_12:
 		path_format->decode_fmt  = 0xA;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_14_8_14:
 		path_format->decode_fmt  = 0xB;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_14_10_14:
 		path_format->decode_fmt  = 0xC;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_DPCM_12_10_12:
 		path_format->decode_fmt  = 0xD;
 		path_format->plain_fmt = 0x1;
+		path_format->packing_fmt = 0;
 		break;
 	case CAM_FORMAT_YUV422:
 		path_format->decode_fmt  = 0x1;

+ 15 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_common.h

@@ -33,6 +33,13 @@
 
 #define CAM_IFE_CSID_LOG_BUF_LEN                          512
 
+#define CAM_IFE_CSID_CAP_INPUT_LCR                        0x1
+#define CAM_IFE_CSID_CAP_MIPI8_UNPACK                     0x2
+#define CAM_IFE_CSID_CAP_MIPI10_UNPACK                    0x4
+#define CAM_IFE_CSID_CAP_MIPI12_UNPACK                    0x8
+#define CAM_IFE_CSID_CAP_MIPI14_UNPACK                    0x10
+#define CAM_IFE_CSID_CAP_MIPI16_UNPACK                    0x20
+#define CAM_IFE_CSID_CAP_MIPI20_UNPACK                    0x40
 /*
  * Debug values enable the corresponding interrupts and debug logs provide
  * necessary information
@@ -283,6 +290,8 @@ struct cam_ife_csid_debug_info {
  * @tpg_configured:         flag to indicate if internal_tpg is configured
  * @reset_awaited:          flag to indicate if reset is awaited
  * @offline_mode:           flag to indicate if csid in offline mode
+ * @rdi_lcr_en:             flag to indicate if RDI to lcr is enabled
+ * @sfe_en:                 flag to indicate if SFE is enabled
  */
 struct cam_ife_csid_hw_flags {
 	bool                  device_enabled;
@@ -295,10 +304,12 @@ struct cam_ife_csid_hw_flags {
 	bool                  tpg_configured;
 	bool                  reset_awaited;
 	bool                  offline_mode;
+	bool                  rdi_lcr_en;
+	bool                  sfe_en;
 };
 
 /*
- * struct cam_ife_csid_hw_flags: place holder for flags
+ * struct am_ife_csid_cid_data: place holder for cid data
  *
  * @vc_dt:        vc_dt structure
  * @cid_cnt:      count of cid acquired
@@ -311,7 +322,7 @@ struct cam_ife_csid_cid_data {
 };
 
 /*
- * struct cam_ife_csid_hw_flags: place holder for flags
+ * struct cam_ife_csid_rx_cfg: place holder for rx cfg
  *
  * @phy_sel:                  Selected phy
  * @lane_type:                type of lane selected
@@ -344,7 +355,8 @@ int cam_ife_csid_is_pix_res_format_supported(
 
 int cam_ife_csid_get_format_rdi(
 	uint32_t in_format, uint32_t out_format,
-	struct cam_ife_csid_path_format *path_format, bool rpp);
+	struct cam_ife_csid_path_format *path_format, bool rpp,
+	bool mipi_unpacked);
 
 int cam_ife_csid_get_format_ipp_ppp(
 	uint32_t in_format,

+ 2 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c

@@ -2172,7 +2172,7 @@ static int cam_ife_csid_ver1_init_config_rdi_path(
 	mem_base = soc_info->reg_map[0].mem_base;
 	is_rpp = path_cfg->crop_enable || path_cfg->drop_enable;
 	rc = cam_ife_csid_get_format_rdi(path_cfg->in_format,
-		path_cfg->out_format, &path_format, is_rpp);
+		path_cfg->out_format, &path_format, is_rpp, false);
 	if (rc)
 		return rc;
 
@@ -2330,7 +2330,7 @@ static int cam_ife_csid_ver1_init_config_udi_path(
 	mem_base = soc_info->reg_map[0].mem_base;
 	is_rpp = path_cfg->crop_enable || path_cfg->drop_enable;
 	rc = cam_ife_csid_get_format_rdi(path_cfg->in_format,
-		path_cfg->out_format, &path_format, is_rpp);
+		path_cfg->out_format, &path_format, is_rpp, false);
 	if (rc)
 		return rc;
 

+ 123 - 10
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -2108,6 +2108,45 @@ err:
 	return rc;
 }
 
+static bool cam_ife_csid_hw_ver2_need_unpack_mipi(
+	struct cam_ife_csid_ver2_hw                  *csid_hw,
+	struct cam_csid_hw_reserve_resource_args     *reserve,
+	const struct cam_ife_csid_ver2_path_reg_info *path_reg,
+	uint32_t                                      format)
+{
+	bool  need_unpack = false;
+
+	switch(format) {
+	case CAM_FORMAT_MIPI_RAW_8:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI8_UNPACK);
+		break;
+	case CAM_FORMAT_MIPI_RAW_10:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI10_UNPACK);
+		break;
+	case CAM_FORMAT_MIPI_RAW_12:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI12_UNPACK);
+		break;
+	case CAM_FORMAT_MIPI_RAW_14:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI14_UNPACK);
+		break;
+	case CAM_FORMAT_MIPI_RAW_16:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI16_UNPACK);
+		break;
+	case CAM_FORMAT_MIPI_RAW_20:
+		need_unpack = (bool)(path_reg->capabilities & CAM_IFE_CSID_CAP_MIPI20_UNPACK);
+		break;
+	default:
+		need_unpack = false;
+		break;
+	}
+
+	CAM_DBG(CAM_ISP, "CSID[%u], RDI_%u format %u need_unpack %u sfe_shdr %u",
+		csid_hw->hw_intf->hw_idx, reserve->res_id, format, need_unpack,
+		reserve->sfe_inline_shdr);
+
+	return need_unpack;
+}
+
 static int cam_ife_csid_hw_ver2_config_path_data(
 	struct cam_ife_csid_ver2_hw *csid_hw,
 	struct cam_ife_csid_ver2_path_cfg *path_cfg,
@@ -2120,6 +2159,7 @@ static int cam_ife_csid_hw_ver2_config_path_data(
 		(struct cam_ife_csid_ver2_reg_info *)csid_hw->core_info->csid_reg;
 	struct cam_ife_csid_cid_data *cid_data = &csid_hw->cid_data[cid];
 	struct cam_isp_resource_node *res = &csid_hw->path_res[reserve->res_id];
+	const struct cam_ife_csid_ver2_path_reg_info  *path_reg = NULL;
 
 	for(i = 0; i < reserve->in_port->num_valid_vc_dt; i++)
 		path_cfg->in_format[i] = reserve->in_port->format[i];
@@ -2138,6 +2178,7 @@ static int cam_ife_csid_hw_ver2_config_path_data(
 	path_cfg->num_bytes_out = reserve->in_port->num_bytes_out;
 	path_cfg->sec_evt_config.en_secondary_evt = reserve->sec_evt_config.en_secondary_evt;
 	path_cfg->sec_evt_config.evt_type = reserve->sec_evt_config.evt_type;
+	path_reg = csid_reg->path_reg[res->res_id];
 
 	if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
 		path_cfg->start_pixel = reserve->in_port->left_start;
@@ -2191,11 +2232,18 @@ static int cam_ife_csid_hw_ver2_config_path_data(
 	case CAM_IFE_PIX_PATH_RES_RDI_3:
 	case CAM_IFE_PIX_PATH_RES_RDI_4:
 		is_rpp = path_cfg->crop_enable || path_cfg->drop_enable;
+		/*
+		 * if csid gives unpacked out, packing needs to be done at
+		 * WM side if needed, based on the format the decision is
+		 * taken at WM side
+		 */
+		reserve->use_wm_pack = cam_ife_csid_hw_ver2_need_unpack_mipi(csid_hw,
+			reserve, path_reg, path_cfg->out_format);
 		rc = cam_ife_csid_get_format_rdi(
 			path_cfg->in_format[CAM_IFE_CSID_MULTI_VC_DT_GRP_0],
 			path_cfg->out_format,
 			&path_cfg->path_format[CAM_IFE_CSID_MULTI_VC_DT_GRP_0],
-			is_rpp);
+			is_rpp, reserve->use_wm_pack);
 		if (rc)
 			goto end;
 
@@ -2206,7 +2254,7 @@ static int cam_ife_csid_hw_ver2_config_path_data(
 				path_cfg->in_format[CAM_IFE_CSID_MULTI_VC_DT_GRP_1],
 				path_cfg->out_format,
 				&path_cfg->path_format[CAM_IFE_CSID_MULTI_VC_DT_GRP_1],
-				is_rpp);
+				is_rpp, reserve->use_wm_pack);
 			if (rc)
 				goto end;
 		}
@@ -2516,9 +2564,9 @@ int cam_ife_csid_ver2_reserve(void *hw_priv,
 	csid_hw->token  = reserve->cb_priv;
 	reserve->buf_done_controller = csid_hw->buf_done_irq_controller;
 	res->cdm_ops = reserve->cdm_ops;
-	path_cfg->sfe_inline_shdr = reserve->sfe_inline_shdr;
+	csid_hw->flags.sfe_en = reserve->sfe_en;
+	path_cfg->sfe_shdr = reserve->sfe_inline_shdr;
 	csid_hw->flags.offline_mode = reserve->is_offline;
-
 	reserve->need_top_cfg = csid_reg->need_top_cfg;
 
 	CAM_DBG(CAM_ISP, "CSID[%u] Resource[id: %d name:%s] state %d cid %d",
@@ -2614,7 +2662,7 @@ end:
 	return rc;
 }
 
-static int cam_ife_csid_ver2_shdr_cfg(
+static int cam_ife_csid_ver2_res_master_slave_cfg(
 	struct cam_ife_csid_ver2_hw *csid_hw,
 	uint32_t res_id)
 {
@@ -2641,6 +2689,9 @@ static int cam_ife_csid_ver2_shdr_cfg(
 	case CAM_IFE_PIX_PATH_RES_RDI_2:
 		val |= BIT(csid_reg->cmn_reg->shdr_slave_rdi2_shift);
 		break;
+	case CAM_IFE_PIX_PATH_RES_PPP:
+		val |= BIT(csid_reg->cmn_reg->shdr_slave_ppp_shift);
+		break;
 	default:
 		break;
 	}
@@ -2803,8 +2854,10 @@ static int cam_ife_csid_ver2_init_config_rdi_path(
 			path_reg->err_recovery_cfg0_addr);
 	}
 
-	if (path_cfg->sfe_inline_shdr)
-		cam_ife_csid_ver2_shdr_cfg(csid_hw, res->res_id);
+	if (path_cfg->sfe_shdr ||
+		(csid_hw->flags.rdi_lcr_en &&
+		 res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0))
+		cam_ife_csid_ver2_res_master_slave_cfg(csid_hw, res->res_id);
 
 	if (csid_hw->debug_info.debug_val &
 		CAM_IFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
@@ -2990,6 +3043,9 @@ static int cam_ife_csid_ver2_init_config_pxl_path(
 			mem_base + path_reg->format_measure_cfg0_addr);
 	}
 
+	if (csid_hw->flags.rdi_lcr_en && res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
+		cam_ife_csid_ver2_res_master_slave_cfg(csid_hw, res->res_id);
+
 	res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
 	return rc;
 }
@@ -3088,7 +3144,7 @@ static int cam_ife_csid_ver2_program_rdi_path(
 	}
 
 	if ((csid_hw->flags.offline_mode ||
-		path_cfg->sfe_inline_shdr) &&
+		path_cfg->sfe_shdr) &&
 		(res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0)) {
 		val |= path_reg->camif_irq_mask;
 		path_cfg->handle_camif_irq = true;
@@ -3693,7 +3749,6 @@ err:
 	return rc;
 }
 
-
 static int cam_ife_csid_ver2_program_top(
 	struct cam_ife_csid_ver2_hw *csid_hw)
 {
@@ -3735,6 +3790,8 @@ static int cam_ife_csid_ver2_program_top(
 	val |= csid_hw->top_cfg.out_ife_en <<
 			top_reg->out_ife_en_shift_val;
 
+	val |= csid_hw->top_cfg.rdi_lcr;
+
 	cam_io_w_mb(val,
 		soc_info->reg_map[CAM_IFE_CSID_TOP_MEM_BASE_ID].mem_base +
 		top_reg->io_path_cfg0_addr[csid_hw->hw_intf->hw_idx]);
@@ -4058,6 +4115,7 @@ static int cam_ife_csid_ver2_disable_core(
 	spin_lock_bh(&csid_hw->lock_state);
 	csid_hw->flags.device_enabled = false;
 	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
+	csid_hw->flags.rdi_lcr_en = false;
 	spin_unlock_bh(&csid_hw->lock_state);
 	rc = cam_ife_csid_disable_soc_resources(soc_info);
 	if (rc)
@@ -4065,7 +4123,6 @@ static int cam_ife_csid_ver2_disable_core(
 			csid_hw->hw_intf->hw_idx);
 
 	csid_hw->counters.error_irq_count = 0;
-
 	return rc;
 }
 
@@ -4280,6 +4337,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 		csid_stop->num_res);
 
 	csid_hw->flags.device_enabled = false;
+	csid_hw->flags.rdi_lcr_en = false;
 
 	reset.reset_type = (csid_hw->flags.fatal_err_detected) ? CAM_IFE_CSID_RESET_GLOBAL :
 		CAM_IFE_CSID_RESET_PATH;
@@ -4906,6 +4964,58 @@ end:
 	return 0;
 }
 
+static int cam_ife_csid_ver2_rdi_lcr_cfg(
+	struct cam_ife_csid_ver2_hw  *csid_hw, void *cmd_args)
+{
+	const struct cam_ife_csid_ver2_path_reg_info *path_reg;
+	struct cam_ife_csid_ver2_reg_info            *csid_reg;
+	struct cam_ife_csid_ver2_path_cfg            *path_cfg = NULL;
+	struct cam_isp_resource_node                 *res = cmd_args;
+
+	if (!csid_hw || !cmd_args) {
+		CAM_ERR(CAM_ISP, "Invalid params");
+		return -EINVAL;
+	}
+
+	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
+			csid_hw->core_info->csid_reg;
+
+	path_reg = csid_reg->path_reg[res->res_id];
+	path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
+	if (!path_cfg || !path_reg || !path_reg->capabilities ||
+		!(path_reg->capabilities & CAM_IFE_CSID_CAP_INPUT_LCR)) {
+		CAM_ERR(CAM_ISP, "Invalid res %s", res->res_name);
+		return -EINVAL;
+	}
+
+	if (!path_cfg->sfe_shdr && (res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0)) {
+		CAM_ERR(CAM_ISP, "Invalid res: %s, capabilities 0x%x sfe_shdr: %u",
+			res->res_name, path_reg->capabilities, path_cfg->sfe_shdr);
+		return -EINVAL;
+	}
+
+	/*
+	 * LCR should not be on for a resource if CSID is giving packed data
+	 * this case would come for formats which are not supported
+	 * */
+	if (path_cfg->path_format[CAM_IFE_CSID_MULTI_VC_DT_GRP_0].packing_fmt) {
+		CAM_ERR(CAM_ISP, "LCR enabled for %s, csid out packed not supported",
+			res->res_name);
+		return -EINVAL;
+	}
+
+	if (csid_hw->flags.sfe_en)
+		csid_hw->top_cfg.rdi_lcr |= BIT(res->res_id) <<
+			csid_reg->top_reg->rdi_lcr_shift_val;
+
+	csid_hw->flags.rdi_lcr_en = true;
+
+	CAM_DBG(CAM_ISP, "CSID[%u] %s top_cfg %u",
+		csid_hw->hw_intf->hw_idx, res->res_name, csid_hw->top_cfg.rdi_lcr);
+
+	return 0;
+}
+
 static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -4983,6 +5093,9 @@ static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
 	case CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES:
 		rc = cam_ife_csid_ver2_set_discard_frame_cfg(csid_hw, cmd_args);
 		break;
+	case CAM_ISP_HW_CMD_RDI_LCR_CFG:
+		rc = cam_ife_csid_ver2_rdi_lcr_cfg(csid_hw, cmd_args);
+		break;
 	default:
 		CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
 			csid_hw->hw_intf->hw_idx, cmd_type);

+ 6 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.h

@@ -108,6 +108,7 @@ struct cam_ife_csid_ver2_top_cfg {
 	bool          dual_en;
 	bool          offline_sfe_en;
 	bool          out_ife_en;
+	bool          rdi_lcr;
 };
 
 struct cam_ife_csid_ver2_evt_payload {
@@ -166,7 +167,7 @@ struct cam_ife_csid_ver2_camif_data {
  *                          If we know the number of paths to avoid configuring discard
  *                          for before processing discard config we can skip it for
  *                          the corresponding paths
- * @sfe_inline_shdr:        flag to indicate if sfe is inline shdr
+ * @sfe_shdr:               flag to indicate if sfe is inline shdr
  *
  */
 struct cam_ife_csid_ver2_path_cfg {
@@ -204,7 +205,7 @@ struct cam_ife_csid_ver2_path_cfg {
 	bool                                 handle_camif_irq;
 	bool                                 discard_init_frames;
 	bool                                 skip_discard_frame_cfg;
-	bool                                 sfe_inline_shdr;
+	bool                                 sfe_shdr;
 };
 
 struct cam_ife_csid_ver2_top_reg_info {
@@ -216,6 +217,7 @@ struct cam_ife_csid_ver2_top_reg_info {
 	uint32_t dual_sync_sel_shift_val;
 	uint32_t dual_en_shift_val;
 	uint32_t master_slave_sel_shift_val;
+	uint32_t rdi_lcr_shift_val;
 	uint32_t master_sel_val;
 	uint32_t slave_sel_val;
 	uint32_t io_path_cfg_rst_val;
@@ -349,6 +351,7 @@ struct cam_ife_csid_ver2_path_reg_info {
 	uint32_t epoch1_cfg_val;
 	uint32_t epoch0_shift_val;
 	uint32_t epoch1_shift_val;
+	uint32_t capabilities;
 };
 
 struct cam_ife_csid_ver2_common_reg_info {
@@ -422,6 +425,7 @@ struct cam_ife_csid_ver2_common_reg_info {
 	uint32_t multi_vcdt_ts_combo_en_shift_val;
 	uint32_t multi_vcdt_en_shift_val;
 	uint32_t mup_shift_val;
+	uint32_t shdr_slave_ppp_shift;
 	uint32_t shdr_slave_rdi2_shift;
 	uint32_t shdr_slave_rdi1_shift;
 	uint32_t shdr_master_rdi0_shift;

+ 6 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h

@@ -192,10 +192,12 @@ struct cam_csid_secondary_evt_config {
  * @buf_done_controller: IRQ controller for buf done for version 680 hw
  * @cdm_ops:             CDM Ops
  * @event_cb:            Callback function to hw mgr in case of hw events
- * @cb_priv:             Private pointer to return to callback
  * @phy_sel:             Phy selection number if tpg is enabled from userspace
+ * @cb_priv:             Private pointer to return to callback
  * @can_use_lite:        Flag to indicate if current call qualifies for
  *                       acquire lite
+ * @sfe_en:              Flag to indicate if SFE is enabled
+ * @use_wm_pack:         [OUT]Flag to indicate if WM packing is to be used for packing
  *
  */
 struct cam_csid_hw_reserve_resource_args {
@@ -218,8 +220,10 @@ struct cam_csid_hw_reserve_resource_args {
 	void                                     *cdm_ops;
 	cam_hw_mgr_event_cb_func                  event_cb;
 	uint32_t                                  phy_sel;
-	bool                                      can_use_lite;
 	void                                     *cb_priv;
+	bool                                      can_use_lite;
+	bool                                      sfe_en;
+	bool                                      use_wm_pack;
 };
 
 /**

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

@@ -203,6 +203,7 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE,
 	CAM_ISP_HW_CSID_MINI_DUMP,
 	CAM_ISP_HW_BUS_MINI_DUMP,
+	CAM_ISP_HW_CMD_RDI_LCR_CFG,
 	CAM_ISP_HW_CMD_MAX,
 };
 

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h

@@ -307,6 +307,7 @@ struct cam_sfe_hw_sfe_in_acquire_args {
  * @split_id:                In case of Dual SFE, this is Left or Right.
  * @is_master:               In case of Dual SFE, this is Master or Slave.
  * @cdm_ops:                 CDM operations
+ * @use_wm_pack:             Flag to indicalte packing at WM side
  */
 struct cam_sfe_hw_sfe_out_acquire_args {
 	struct cam_isp_resource_node         *rsrc_node;
@@ -316,6 +317,7 @@ struct cam_sfe_hw_sfe_out_acquire_args {
 	enum cam_isp_hw_split_id              split_id;
 	uint32_t                              is_master;
 	struct cam_cdm_utils_ops             *cdm_ops;
+	bool                                  use_wm_pack;
 };
 
 /*

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h

@@ -142,6 +142,7 @@ struct cam_vfe_hw_vfe_bus_rd_acquire_args {
  * @dual_slave_core:         If Master and Slave exists, HW Index of Slave
  * @cdm_ops:                 CDM operations
  * @disable_ubwc_comp:       Disable UBWC compression
+ * @use_wm_pack:             Use WM Packing
  */
 struct cam_vfe_hw_vfe_out_acquire_args {
 	struct cam_isp_resource_node         *rsrc_node;
@@ -153,6 +154,7 @@ struct cam_vfe_hw_vfe_out_acquire_args {
 	uint32_t                              dual_slave_core;
 	struct cam_cdm_utils_ops             *cdm_ops;
 	bool                                  disable_ubwc_comp;
+	bool                                  use_wm_pack;
 };
 
 /*

+ 39 - 21
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c

@@ -113,8 +113,6 @@ struct cam_sfe_bus_wr_wm_resource_data {
 	struct cam_sfe_bus_reg_offset_bus_client  *hw_regs;
 	struct cam_sfe_wr_scratch_buf_info scratch_buf_info;
 
-	bool                 init_cfg_done;
-	bool                 hfr_cfg_done;
 
 	uint32_t             offset;
 	uint32_t             width;
@@ -137,9 +135,12 @@ struct cam_sfe_bus_wr_wm_resource_data {
 	uint32_t             acquired_width;
 	uint32_t             acquired_height;
 
-	bool                 enable_caching;
 	uint32_t             cache_cfg;
 	int32_t              current_scid;
+	bool                 enable_caching;
+	bool                 init_cfg_done;
+	bool                 hfr_cfg_done;
+	bool                 use_wm_pack;
 };
 
 struct cam_sfe_bus_wr_comp_grp_data {
@@ -501,7 +502,8 @@ static inline void cam_sfe_bus_config_rdi_wm_frame_based_mode(
 static int cam_sfe_bus_config_rdi_wm(
 	struct cam_sfe_bus_wr_wm_resource_data  *rsrc_data)
 {
-	rsrc_data->pack_fmt = 0x0;
+
+	rsrc_data->pack_fmt = PACKER_FMT_PLAIN_128;
 	switch (rsrc_data->format) {
 	case CAM_FORMAT_MIPI_RAW_10:
 		if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE) {
@@ -514,6 +516,12 @@ static int cam_sfe_bus_config_rdi_wm(
 			CAM_WARN(CAM_SFE, "No index mode support for SFE WM: %u",
 				rsrc_data->index);
 		}
+
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_MIPI10;
+			if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_6:
 		if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE) {
@@ -550,6 +558,12 @@ static int cam_sfe_bus_config_rdi_wm(
 			CAM_WARN(CAM_SFE, "No index mode support for SFE WM: %u",
 				rsrc_data->index);
 		}
+
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_MIPI12;
+			if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_14:
 		if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE) {
@@ -562,6 +576,11 @@ static int cam_sfe_bus_config_rdi_wm(
 			CAM_WARN(CAM_SFE, "No index mode support for SFE WM: %u",
 				rsrc_data->index);
 		}
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_MIPI14;
+			if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_16:
 		if (rsrc_data->wm_mode == CAM_SFE_WM_LINE_BASED_MODE) {
@@ -659,15 +678,14 @@ static int cam_sfe_bus_config_rdi_wm(
 }
 
 static int cam_sfe_bus_acquire_wm(
-	struct cam_sfe_bus_wr_priv            *bus_priv,
-	struct cam_isp_out_port_generic_info  *out_port_info,
-	void                                  *tasklet,
-	enum cam_sfe_bus_sfe_out_type          sfe_out_res_id,
-	enum cam_sfe_bus_plane_type            plane,
-	struct cam_isp_resource_node          *wm_res,
-	uint32_t                              *comp_done_mask,
-	uint32_t                               is_dual,
-	enum cam_sfe_bus_wr_comp_grp_type     *comp_grp_id)
+	struct cam_sfe_bus_wr_priv             *bus_priv,
+	struct cam_sfe_hw_sfe_out_acquire_args *out_acq_args,
+	void                                   *tasklet,
+	enum cam_sfe_bus_sfe_out_type           sfe_out_res_id,
+	enum cam_sfe_bus_plane_type             plane,
+	struct cam_isp_resource_node           *wm_res,
+	uint32_t                               *comp_done_mask,
+	enum cam_sfe_bus_wr_comp_grp_type      *comp_grp_id)
 {
 	int32_t wm_idx = 0, rc;
 	struct cam_sfe_bus_wr_wm_resource_data  *rsrc_data = NULL;
@@ -681,15 +699,16 @@ static int cam_sfe_bus_acquire_wm(
 
 	rsrc_data = wm_res->res_priv;
 	wm_idx = rsrc_data->index;
-	rsrc_data->format = out_port_info->format;
+	rsrc_data->format = out_acq_args->out_port_info->format;
+	rsrc_data->use_wm_pack = out_acq_args->use_wm_pack;
 	rsrc_data->pack_fmt = cam_sfe_bus_get_packer_fmt(bus_priv,
 		rsrc_data->format, wm_idx);
 
-	rsrc_data->width = out_port_info->width;
-	rsrc_data->height = out_port_info->height;
-	rsrc_data->acquired_width = out_port_info->width;
-	rsrc_data->acquired_height = out_port_info->height;
-	rsrc_data->is_dual = is_dual;
+	rsrc_data->width = out_acq_args->out_port_info->width;
+	rsrc_data->height = out_acq_args->out_port_info->height;
+	rsrc_data->acquired_width = out_acq_args->out_port_info->width;
+	rsrc_data->acquired_height = out_acq_args->out_port_info->height;
+	rsrc_data->is_dual = out_acq_args->is_dual;
 	rsrc_data->enable_caching =  false;
 	rsrc_data->offset = 0;
 
@@ -1350,13 +1369,12 @@ static int cam_sfe_bus_acquire_sfe_out(void *priv, void *acquire_args,
 	/* Acquire WM and retrieve COMP GRP ID */
 	for (i = 0; i < rsrc_data->num_wm; i++) {
 		rc = cam_sfe_bus_acquire_wm(bus_priv,
-			out_acquire_args->out_port_info,
+			out_acquire_args,
 			acq_args->tasklet,
 			sfe_out_res_id,
 			i,
 			&rsrc_data->wm_res[i],
 			&client_done_mask,
-			out_acquire_args->is_dual,
 			&comp_grp_id);
 		if (rc) {
 			CAM_ERR(CAM_SFE,

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

@@ -517,6 +517,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_GET_PATH_PORT_MAP:
 	case CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE:
 	case CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE:
+	case CAM_ISP_HW_CMD_RDI_LCR_CFG:
 		rc = core_info->vfe_top->hw_ops.process_cmd(
 			core_info->vfe_top->top_priv, cmd_type, cmd_args,
 			arg_size);

+ 19 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe780.h

@@ -472,6 +472,21 @@ static struct cam_vfe_top_ver4_pdaf_violation_desc vfe780_pdaf_violation_desc[]
 	},
 };
 
+static struct cam_vfe_top_ver4_pdaf_lcr_res_info vfe780_pdaf_lcr_res_mask[] = {
+	{
+		.res_id = CAM_ISP_HW_VFE_IN_RDI0,
+		.val = 0,
+	},
+	{
+		.res_id = CAM_ISP_HW_VFE_IN_RDI1,
+		.val = 1,
+	},
+	{
+		.res_id = CAM_ISP_HW_VFE_IN_RDI2,
+		.val= 2,
+	},
+};
+
 static struct cam_irq_register_set vfe780_top_irq_reg_set[2] = {
 	{
 		.mask_reg_offset   = 0x00000034,
@@ -530,6 +545,8 @@ static struct cam_vfe_top_ver4_reg_offset_common vfe780_top_common_reg = {
 	.bus_overflow_status      = 0x00000C68,
 	.top_debug_cfg            = 0x000000FC,
 	.num_top_debug_reg        = CAM_VFE_780_NUM_DBG_REG,
+	.pdaf_input_cfg_0         = 0x00000130,
+	.pdaf_input_cfg_1         = 0x00000134,
 	.top_debug = {
 		0x000000A0,
 		0x000000A4,
@@ -818,6 +835,8 @@ static struct cam_vfe_top_ver4_hw_info vfe780_top_hw_info = {
 	.num_pdaf_violation_errors       = ARRAY_SIZE(vfe780_pdaf_violation_desc),
 	.pdaf_violation_desc             = vfe780_pdaf_violation_desc,
 	.debug_reg_info                  = &vfe780_dbg_reg_info,
+	.pdaf_lcr_res_mask               = vfe780_pdaf_lcr_res_mask,
+	.num_pdaf_lcr_res                = ARRAY_SIZE(vfe780_pdaf_lcr_res_mask),
 };
 
 static struct cam_irq_register_set vfe780_bus_irq_reg[2] = {

+ 37 - 16
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c

@@ -151,6 +151,7 @@ struct cam_vfe_bus_ver3_wm_resource_data {
 	uint32_t             acquired_width;
 	uint32_t             acquired_height;
 	uint32_t             default_line_based;
+	bool                 use_wm_pack;
 };
 
 struct cam_vfe_bus_ver3_comp_grp_data {
@@ -847,7 +848,7 @@ static int cam_vfe_bus_ver3_handle_rup_bottom_half(void *handler_priv,
 static int cam_vfe_bus_ver3_config_rdi_wm(
 	struct cam_vfe_bus_ver3_wm_resource_data  *rsrc_data)
 {
-	/* Force RDI to use PLAIN128 */
+
 	rsrc_data->pack_fmt = PACKER_FMT_VER3_PLAIN_128;
 	switch (rsrc_data->format) {
 	case CAM_FORMAT_MIPI_RAW_10:
@@ -861,6 +862,12 @@ static int cam_vfe_bus_ver3_config_rdi_wm(
 			rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
 			rsrc_data->en_cfg = (0x1 << 16) | 0x1;
 		}
+
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_VER3_MIPI10;
+			if (rsrc_data->default_line_based)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_6:
 		if (rsrc_data->default_line_based) {
@@ -898,6 +905,12 @@ static int cam_vfe_bus_ver3_config_rdi_wm(
 			rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
 			rsrc_data->en_cfg = (0x1 << 16) | 0x1;
 		}
+
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_VER3_MIPI12;
+			if (rsrc_data->default_line_based)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_14:
 		if (rsrc_data->default_line_based) {
@@ -910,6 +923,12 @@ static int cam_vfe_bus_ver3_config_rdi_wm(
 			rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
 			rsrc_data->en_cfg = (0x1 << 16) | 0x1;
 		}
+
+		if (rsrc_data->use_wm_pack) {
+			rsrc_data->pack_fmt = PACKER_FMT_VER3_MIPI14;
+			if (rsrc_data->default_line_based)
+				rsrc_data->width = ALIGNUP((rsrc_data->acquired_width), 16);
+		}
 		break;
 	case CAM_FORMAT_MIPI_RAW_16:
 		if (rsrc_data->default_line_based) {
@@ -934,6 +953,9 @@ static int cam_vfe_bus_ver3_config_rdi_wm(
 			rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
 			rsrc_data->en_cfg = (0x1 << 16) | 0x1;
 		}
+
+		if (rsrc_data->use_wm_pack)
+			rsrc_data->pack_fmt = PACKER_FMT_VER3_MIPI20;
 		break;
 	case CAM_FORMAT_PLAIN128:
 		if (rsrc_data->default_line_based) {
@@ -998,13 +1020,12 @@ static int cam_vfe_bus_ver3_config_rdi_wm(
 }
 
 static int cam_vfe_bus_ver3_acquire_wm(
-	struct cam_vfe_bus_ver3_priv          *ver3_bus_priv,
-	struct cam_isp_out_port_generic_info  *out_port_info,
-	void                                  *tasklet,
-	enum cam_vfe_bus_ver3_vfe_out_type     vfe_out_res_id,
-	enum cam_vfe_bus_plane_type            plane,
-	struct cam_isp_resource_node          *wm_res,
-	uint32_t                               is_dual,
+	struct cam_vfe_bus_ver3_priv           *ver3_bus_priv,
+	struct cam_vfe_hw_vfe_out_acquire_args *out_acq_args,
+	void                                   *tasklet,
+	enum cam_vfe_bus_ver3_vfe_out_type      vfe_out_res_id,
+	enum cam_vfe_bus_plane_type             plane,
+	struct cam_isp_resource_node           *wm_res,
 	enum cam_vfe_bus_ver3_comp_grp_type   *comp_grp_id)
 {
 	int32_t wm_idx = 0, rc;
@@ -1021,15 +1042,16 @@ static int cam_vfe_bus_ver3_acquire_wm(
 
 	rsrc_data = wm_res->res_priv;
 	wm_idx = rsrc_data->index;
-	rsrc_data->format = out_port_info->format;
+	rsrc_data->format = out_acq_args->out_port_info->format;
+	rsrc_data->use_wm_pack = out_acq_args->use_wm_pack;
 	rsrc_data->pack_fmt = cam_vfe_bus_ver3_get_packer_fmt(rsrc_data->format,
 		wm_idx);
 
-	rsrc_data->width = out_port_info->width;
-	rsrc_data->height = out_port_info->height;
-	rsrc_data->acquired_width = out_port_info->width;
-	rsrc_data->acquired_height = out_port_info->height;
-	rsrc_data->is_dual = is_dual;
+	rsrc_data->width = out_acq_args->out_port_info->width;
+	rsrc_data->height = out_acq_args->out_port_info->height;
+	rsrc_data->acquired_width = out_acq_args->out_port_info->width;
+	rsrc_data->acquired_height = out_acq_args->out_port_info->height;
+	rsrc_data->is_dual = out_acq_args->is_dual;
 	/* Set WM offset value to default */
 	rsrc_data->offset  = 0;
 	CAM_DBG(CAM_ISP, "WM:%d width %d height %d", rsrc_data->index,
@@ -2029,12 +2051,11 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args,
 	/* Acquire WM and retrieve COMP GRP ID */
 	for (i = 0; i < rsrc_data->num_wm; i++) {
 		rc = cam_vfe_bus_ver3_acquire_wm(ver3_bus_priv,
-			out_acquire_args->out_port_info,
+			out_acquire_args,
 			acq_args->tasklet,
 			vfe_out_res_id,
 			i,
 			&rsrc_data->wm_res[i],
-			out_acquire_args->is_dual,
 			&comp_acq_args.comp_grp_id);
 		if (rc) {
 			CAM_ERR(CAM_ISP,

+ 80 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c

@@ -99,6 +99,82 @@ static int cam_vfe_top_ver4_get_path_port_map(struct cam_vfe_top_ver4_priv *top_
 	return 0;
 }
 
+static int cam_vfe_top_ver4_pdaf_lcr_config(struct cam_vfe_top_ver4_priv *top_priv,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_vfe_top_ver4_hw_info  *hw_info;
+	struct cam_isp_hw_get_cmd_update *cdm_args = NULL;
+	struct cam_cdm_utils_ops         *cdm_util_ops = NULL;
+	uint32_t                          i;
+	uint32_t                          reg_val_idx = 0;
+	uint32_t                          num_reg_vals;
+	uint32_t                          reg_val_pair[4];
+	struct cam_isp_lcr_rdi_cfg_args  *cfg_args;
+	size_t                            size;
+
+	if (!cmd_args || !top_priv) {
+		CAM_ERR(CAM_ISP, "Error, Invalid args");
+		return -EINVAL;
+	}
+
+	cdm_args = (struct cam_isp_hw_get_cmd_update *)cmd_args;
+	if (!cdm_args->res) {
+		CAM_ERR(CAM_ISP, "Error, Invalid res");
+		return -EINVAL;
+	}
+
+	hw_info = top_priv->common_data.hw_info;
+	if (!hw_info->num_pdaf_lcr_res || !hw_info->pdaf_lcr_res_mask) {
+		CAM_DBG(CAM_ISP, "PDAF LCR is not supported");
+		return 0;
+	}
+
+	cfg_args = (struct cam_isp_lcr_rdi_cfg_args *)cdm_args->data;
+	cdm_util_ops =
+		(struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
+	if (!cdm_util_ops) {
+		CAM_ERR(CAM_ISP, "Invalid CDM ops");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < hw_info->num_pdaf_lcr_res; i++)
+		if (cdm_args->res->res_id ==
+			hw_info->pdaf_lcr_res_mask[i].res_id)
+			break;
+
+	if (i == hw_info->num_pdaf_lcr_res) {
+		CAM_ERR(CAM_ISP, "Res :%d is not supported for mux",
+			cfg_args->rdi_lcr_cfg->res_id);
+		return -EINVAL;
+	}
+
+	if (cfg_args->is_init)
+		num_reg_vals = 2;
+	else
+		num_reg_vals = 1;
+
+	size = cdm_util_ops->cdm_required_size_reg_random(num_reg_vals);
+	/* since cdm returns dwords, we need to convert it into bytes */
+	if ((size * 4) > cdm_args->cmd.size) {
+		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
+			cdm_args->cmd.size, (size*4));
+		return -EINVAL;
+	}
+
+	if (cfg_args->is_init) {
+		reg_val_pair[reg_val_idx++] = hw_info->common_reg->pdaf_input_cfg_1;
+		reg_val_pair[reg_val_idx++] = 0;
+	}
+
+	reg_val_pair[reg_val_idx++] = hw_info->common_reg->pdaf_input_cfg_0;
+	reg_val_pair[reg_val_idx++] = hw_info->pdaf_lcr_res_mask[i].val;
+	cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr,
+		num_reg_vals, reg_val_pair);
+	cdm_args->cmd.used_bytes = size * 4;
+
+	return 0;
+}
+
 static int cam_vfe_top_ver4_mux_get_base(struct cam_vfe_top_ver4_priv *top_priv,
 	void *cmd_args, uint32_t arg_size)
 {
@@ -887,6 +963,10 @@ int cam_vfe_top_ver4_process_cmd(void *device_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE:
 		rc = cam_vfe_init_config_update(cmd_args, arg_size);
 		break;
+	case CAM_ISP_HW_CMD_RDI_LCR_CFG:
+		rc = cam_vfe_top_ver4_pdaf_lcr_config(top_priv, cmd_args,
+			arg_size);
+		break;
 	default:
 		rc = -EINVAL;
 		CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type);

+ 9 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.h

@@ -57,6 +57,8 @@ struct cam_vfe_top_ver4_reg_offset_common {
 	uint32_t epoch1_pattern_cfg;
 	uint32_t epoch_height_cfg;
 	uint32_t top_debug_cfg;
+	uint32_t pdaf_input_cfg_0;
+	uint32_t pdaf_input_cfg_1;
 	uint32_t num_top_debug_reg;
 	uint32_t top_debug[CAM_VFE_TOP_DBG_REG_MAX];
 };
@@ -93,6 +95,11 @@ struct cam_vfe_top_ver4_pdaf_violation_desc {
 	char     *desc;
 };
 
+struct cam_vfe_top_ver4_pdaf_lcr_res_info {
+	uint32_t  res_id;
+	uint32_t  val;
+};
+
 struct cam_vfe_ver4_path_hw_info {
 	struct cam_vfe_top_ver4_reg_offset_common  *common_reg;
 	struct cam_vfe_ver4_path_reg_data          *reg_data;
@@ -121,6 +128,8 @@ struct cam_vfe_top_ver4_hw_info {
 	struct cam_vfe_top_ver4_top_err_irq_desc    *top_err_desc;
 	uint32_t                                     num_pdaf_violation_errors;
 	struct cam_vfe_top_ver4_pdaf_violation_desc *pdaf_violation_desc;
+	struct cam_vfe_top_ver4_pdaf_lcr_res_info   *pdaf_lcr_res_mask;
+	uint32_t                                     num_pdaf_lcr_res;
 };
 
 struct cam_vfe_ver4_path_reg_data {

+ 27 - 0
include/uapi/camera/media/cam_isp.h

@@ -124,6 +124,7 @@
 #define CAM_ISP_GENERIC_BLOB_TYPE_BW_LIMITER_CFG            16
 #define CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG                17
 #define CAM_ISP_GENERIC_BLOB_TYPE_INIT_CONFIG               18
+#define CAM_ISP_GENERIC_BLOB_TYPE_RDI_LCR_CONFIG            19
 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CLOCK_CONFIG          21
 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CORE_CONFIG           22
 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_OUT_CONFIG            23
@@ -1002,6 +1003,32 @@ struct cam_isp_init_config {
 	__u32             additional_params[19];
 };
 
+/**
+ * struct cam_isp_lcr_rdi_config - RDI res id to be muxed to LCR
+ *
+ *    Configure RDI Res id for LCR
+ *
+ * @res_id                   : Out port Res id, it is same as the out port
+ *                             configured during acquire. It would vary
+ *                             as per SFE or IFE. Based on this res id,
+ *                             Mux register in IFE will be programmed.
+ *                             Examples:
+ *                             IFE:
+ *                             CAM_ISP_IFE_OUT_RES_RDI_0
+ *                             SFE:
+ *                             CAM_ISP_SFE_OUT_RES_RDI_0
+ *                             This blob is expected as a part of init packet for
+ *                             all LCR cases. For SHDR-LCR cases, this can be used
+ *                             per request. For non-shdr cases, this blob is not
+ *                             expected as the input to LCR will remain same throughout
+ *                             the session
+ * @reserved                 : Reserved field
+ */
+struct cam_isp_lcr_rdi_config {
+	__u32                                   res_id;
+	__u32                                   reserved[5];
+};
+
 #define CAM_ISP_ACQUIRE_COMMON_VER0         0x1000
 
 #define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0    0x0