Selaa lähdekoodia

Merge "msm: camera: isp: Add support for offline IFE" into camera-kernel.lnx.4.0

Camera Software Integration 5 vuotta sitten
vanhempi
sitoutus
6c7de8467b

+ 199 - 7
drivers/cam_isp/cam_isp_context.c

@@ -1028,6 +1028,96 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
 	return rc;
 }
 
+static int __cam_isp_ctx_apply_req_offline(
+	struct cam_context *ctx, uint32_t next_state,
+	struct cam_isp_context *ctx_isp)
+{
+	int rc = 0;
+	struct cam_ctx_request          *req;
+	struct cam_isp_ctx_req          *req_isp;
+	struct cam_hw_config_args        cfg;
+
+	if (list_empty(&ctx->pending_req_list)) {
+		CAM_DBG(CAM_ISP, "No pending requests to apply");
+		rc = -EFAULT;
+		goto end;
+	}
+
+	if (ctx->state != CAM_CTX_ACTIVATED)
+		goto end;
+
+	if (ctx_isp->active_req_cnt >= 2)
+		goto end;
+
+	req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
+		list);
+
+	CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u",
+		req->request_id, ctx_isp->substate_activated, ctx->ctx_id);
+	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
+	cfg.request_id = req->request_id;
+	cfg.hw_update_entries = req_isp->cfg;
+	cfg.num_hw_update_entries = req_isp->num_cfg;
+	cfg.priv  = &req_isp->hw_update_data;
+	cfg.init_packet = 0;
+
+	rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
+	if (rc) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration");
+	} else {
+		atomic_set(&ctx_isp->rxd_epoch, 0);
+		ctx_isp->substate_activated = next_state;
+		ctx_isp->last_applied_req_id = req->request_id;
+		list_del_init(&req->list);
+		list_add_tail(&req->list, &ctx->wait_req_list);
+		CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld",
+			next_state, ctx_isp->last_applied_req_id);
+
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED,
+			req->request_id);
+	}
+end:
+	return rc;
+}
+
+static int __cam_isp_ctx_offline_epoch_in_activated_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	struct cam_context *ctx = ctx_isp->base;
+	struct cam_ctx_request *req, *req_temp;
+	uint64_t request_id = 0;
+
+	atomic_set(&ctx_isp->rxd_epoch, 1);
+
+	CAM_DBG(CAM_ISP, "SOF frame %lld ctx %u", ctx_isp->frame_id,
+		ctx->ctx_id);
+
+	list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
+		if (req->request_id > ctx_isp->reported_req_id) {
+			request_id = req->request_id;
+			ctx_isp->reported_req_id = request_id;
+			break;
+		}
+	}
+
+	__cam_isp_ctx_apply_req_offline(ctx, CAM_ISP_CTX_ACTIVATED_APPLIED,
+		ctx_isp);
+
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
+		request_id);
+
+	return 0;
+}
+
 static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
@@ -1811,6 +1901,9 @@ end:
 
 	} while (req->request_id < ctx_isp->last_applied_req_id);
 
+	if (ctx_isp->offline_context)
+		goto exit;
+
 	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) {
 		notify.link_hdl = ctx->link_hdl;
 		notify.dev_hdl = ctx->dev_hdl;
@@ -1861,6 +1954,7 @@ end:
 
 	CAM_DBG(CAM_ISP, "Exit");
 
+exit:
 	return rc;
 }
 
@@ -2244,6 +2338,63 @@ static struct cam_isp_ctx_irq_ops
 	},
 };
 
+static struct cam_isp_ctx_irq_ops
+	cam_isp_ctx_offline_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
+	/* SOF */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			NULL,
+			NULL,
+			NULL,
+			NULL,
+			NULL,
+		},
+	},
+	/* APPLIED */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			__cam_isp_ctx_sof_in_activated_state,
+			__cam_isp_ctx_reg_upd_in_applied_state,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_applied,
+		},
+	},
+	/* EPOCH */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			NULL,
+			NULL,
+			__cam_isp_ctx_offline_epoch_in_activated_state,
+			NULL,
+			__cam_isp_ctx_buf_done_in_epoch,
+		},
+	},
+	/* BUBBLE */
+	{
+	},
+	/* Bubble Applied */
+	{
+	},
+	/* HW ERROR */
+	{
+		.irq_ops = {
+			NULL,
+			__cam_isp_ctx_sof_in_activated_state,
+			__cam_isp_ctx_reg_upd_in_hw_error,
+			NULL,
+			NULL,
+			NULL,
+		},
+	},
+	/* HALT */
+	{
+	},
+};
+
 static int __cam_isp_ctx_apply_req_in_activated_state(
 	struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
 	enum cam_isp_ctx_activated_substate next_state)
@@ -2796,6 +2947,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 end:
 	ctx_isp->bubble_frame_cnt = 0;
 	atomic_set(&ctx_isp->process_bubble, 0);
+	atomic_set(&ctx_isp->rxd_epoch, 0);
 	return rc;
 }
 
@@ -3685,8 +3837,11 @@ static int __cam_isp_ctx_config_dev_in_top_state(
 				ctx->state);
 		}
 	} else {
-		if (ctx->state != CAM_CTX_FLUSHED && ctx->state >= CAM_CTX_READY
-			&& ctx->ctx_crm_intf->add_req) {
+		if (ctx_isp->offline_context) {
+			__cam_isp_ctx_enqueue_request_in_order(ctx, req);
+		} else if ((ctx->state != CAM_CTX_FLUSHED) &&
+			(ctx->state >= CAM_CTX_READY) &&
+			ctx->ctx_crm_intf->add_req) {
 			add_req.link_hdl = ctx->link_hdl;
 			add_req.dev_hdl  = ctx->dev_hdl;
 			add_req.req_id   = req->request_id;
@@ -3713,6 +3868,13 @@ static int __cam_isp_ctx_config_dev_in_top_state(
 		"Preprocessing Config req_id %lld successful on ctx %u",
 		req->request_id, ctx->ctx_id);
 
+	if (ctx_isp->offline_context && atomic_read(&ctx_isp->rxd_epoch)) {
+		spin_lock_bh(&ctx->lock);
+		__cam_isp_ctx_apply_req_offline(ctx,
+			CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp);
+		spin_unlock_bh(&ctx->lock);
+	}
+
 	return rc;
 
 put_ref:
@@ -3827,11 +3989,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
 			cam_isp_ctx_rdi_only_activated_state_machine;
 		ctx_isp->rdi_only_context = true;
 	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
-		CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+		CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
 		ctx_isp->substate_machine_irq =
 			cam_isp_ctx_fs2_state_machine_irq;
 		ctx_isp->substate_machine =
 			cam_isp_ctx_fs2_state_machine;
+	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
+		CAM_DBG(CAM_ISP, "offline Session has PIX and RD resources");
+		ctx_isp->substate_machine_irq =
+			cam_isp_ctx_offline_state_machine_irq;
 	} else {
 		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
 		ctx_isp->substate_machine_irq =
@@ -3985,11 +4151,16 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
 			cam_isp_ctx_rdi_only_activated_state_machine;
 		ctx_isp->rdi_only_context = true;
 	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
-		CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+		CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
 		ctx_isp->substate_machine_irq =
 			cam_isp_ctx_fs2_state_machine_irq;
 		ctx_isp->substate_machine =
 			cam_isp_ctx_fs2_state_machine;
+	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
+		CAM_DBG(CAM_ISP, "Offline session has PIX and RD resources");
+		ctx_isp->substate_machine_irq =
+			cam_isp_ctx_offline_state_machine_irq;
+		ctx_isp->substate_machine = NULL;
 	} else {
 		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
 		ctx_isp->substate_machine_irq =
@@ -4136,11 +4307,17 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
 			cam_isp_ctx_rdi_only_activated_state_machine;
 		ctx_isp->rdi_only_context = true;
 	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
-		CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+		CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
 		ctx_isp->substate_machine_irq =
 			cam_isp_ctx_fs2_state_machine_irq;
 		ctx_isp->substate_machine =
 			cam_isp_ctx_fs2_state_machine;
+	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
+		CAM_DBG(CAM_ISP, "Offline Session has PIX and RD resources");
+		ctx_isp->substate_machine_irq =
+			cam_isp_ctx_offline_state_machine_irq;
+		ctx_isp->substate_machine = NULL;
+		ctx_isp->offline_context = true;
 	} else {
 		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
 		ctx_isp->substate_machine_irq =
@@ -4207,7 +4384,7 @@ static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx,
 
 	rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);
 
-	if (!rc && (ctx->link_hdl >= 0)) {
+	if (!rc && ((ctx->link_hdl >= 0) || ctx_isp->offline_context)) {
 		ctx->state = CAM_CTX_READY;
 		trace_cam_context_state("ISP", ctx);
 	}
@@ -4368,6 +4545,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
 		start_isp.start_only = false;
 
 	atomic_set(&ctx_isp->process_bubble, 0);
+	atomic_set(&ctx_isp->rxd_epoch, 0);
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
@@ -4390,11 +4568,24 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
 	 */
 	list_del_init(&req->list);
 
-	if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) {
+	if (ctx_isp->offline_context && !req_isp->num_fence_map_out) {
+		list_add_tail(&req->list, &ctx->free_req_list);
+		atomic_set(&ctx_isp->rxd_epoch, 1);
+		CAM_DBG(CAM_REQ,
+			"Move pending req: %lld to free list(cnt: %d) offline ctx %u",
+			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
+	} else if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) {
 		list_add_tail(&req->list, &ctx->wait_req_list);
+		CAM_DBG(CAM_REQ,
+			"Move pending req: %lld to wait list(cnt: %d) ctx %u",
+			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
 	} else {
 		list_add_tail(&req->list, &ctx->active_req_list);
 		ctx_isp->active_req_cnt++;
+		CAM_DBG(CAM_REQ,
+			"Move pending req: %lld to active list(cnt: %d) ctx %u offline %d",
+			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id,
+			ctx_isp->offline_context);
 	}
 
 	/*
@@ -4539,6 +4730,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
 	ctx_isp->last_applied_req_id = 0;
 	ctx_isp->req_info.last_bufdone_req_id = 0;
 	atomic_set(&ctx_isp->process_bubble, 0);
+	atomic_set(&ctx_isp->rxd_epoch, 0);
 	atomic64_set(&ctx_isp->state_monitor_head, -1);
 
 	for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++)

+ 6 - 1
drivers/cam_isp/cam_isp_context.h

@@ -247,13 +247,16 @@ struct cam_isp_context_event_record {
  * @event_record:              Event record array
  * @rdi_only_context:          Get context type information.
  *                             true, if context is rdi only context
+ * @offline_context:           Indicate whether context is for offline IFE
  * @hw_acquired:               Indicate whether HW resources are acquired
  * @init_received:             Indicate whether init config packet is received
  * @split_acquire:             Indicate whether a separate acquire is expected
  * @custom_enabled:            Custom HW enabled for this ctx
  * @use_frame_header_ts:       Use frame header for qtimer ts
  * @init_timestamp:            Timestamp at which this context is initialized
- * @isp_device_type            ISP device type
+ * @isp_device_type:           ISP device type
+ * @rxd_epoch:                 Indicate whether epoch has been received. Used to
+ *                             decide whether to apply request in offline ctx
  *
  */
 struct cam_isp_context {
@@ -286,6 +289,7 @@ struct cam_isp_context {
 	struct cam_isp_context_event_record   event_record[
 		CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES];
 	bool                                  rdi_only_context;
+	bool                                  offline_context;
 	bool                                  hw_acquired;
 	bool                                  init_received;
 	bool                                  split_acquire;
@@ -293,6 +297,7 @@ struct cam_isp_context {
 	bool                                  use_frame_header_ts;
 	unsigned int                          init_timestamp;
 	uint32_t                              isp_device_type;
+	atomic_t                              rxd_epoch;
 };
 
 /**

+ 412 - 288
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -979,90 +979,6 @@ static int cam_ife_mgr_process_base_info(
 	return 0;
 }
 
-static int cam_ife_hw_mgr_acquire_res_bus_rd(
-	struct cam_ife_hw_mgr_ctx       *ife_ctx,
-	struct cam_isp_in_port_generic_info *in_port)
-{
-	int rc = -EINVAL;
-	struct cam_vfe_acquire_args               vfe_acquire;
-	struct cam_isp_hw_mgr_res                *ife_in_rd_res;
-	struct cam_hw_intf                       *hw_intf;
-	struct cam_isp_hw_mgr_res                *ife_src_res;
-	int i;
-
-	CAM_DBG(CAM_ISP, "Enter");
-
-	list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) {
-		if (ife_src_res->res_id != CAM_ISP_HW_VFE_IN_RD)
-			continue;
-
-		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
-			&ife_in_rd_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-			goto err;
-		}
-		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd,
-			&ife_in_rd_res);
-
-		vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
-		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
-		vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
-		vfe_acquire.priv = ife_ctx;
-		vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
-		vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp;
-		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
-			if (!ife_src_res->hw_res[i])
-				continue;
-
-			hw_intf = ife_src_res->hw_res[i]->hw_intf;
-			if (i == CAM_ISP_HW_SPLIT_LEFT) {
-				vfe_acquire.vfe_out.split_id  =
-					CAM_ISP_HW_SPLIT_LEFT;
-				if (ife_src_res->is_dual_isp) {
-					/*TBD */
-					vfe_acquire.vfe_out.is_master     = 1;
-					vfe_acquire.vfe_out.dual_slave_core =
-					ife_ctx->slave_hw_idx;
-				} else {
-					vfe_acquire.vfe_out.is_master   = 0;
-					vfe_acquire.vfe_out.dual_slave_core =
-						0;
-				}
-			} else {
-				vfe_acquire.vfe_out.split_id  =
-					CAM_ISP_HW_SPLIT_RIGHT;
-				vfe_acquire.vfe_out.is_master       = 0;
-				vfe_acquire.vfe_out.dual_slave_core =
-					ife_ctx->master_hw_idx;
-			}
-			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-				&vfe_acquire,
-				sizeof(struct cam_vfe_acquire_args));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Can not acquire out resource 0x%x",
-					vfe_acquire.rsrc_type);
-				goto err;
-			}
-
-			ife_in_rd_res->hw_res[i] =
-				vfe_acquire.vfe_out.rsrc_node;
-			CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
-				ife_in_rd_res->hw_res[i]->res_type,
-				ife_in_rd_res->hw_res[i]->res_id);
-
-		}
-		ife_in_rd_res->is_dual_isp = in_port->usage_type;
-		ife_in_rd_res->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
-	}
-
-	return 0;
-err:
-	CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
-	return rc;
-}
-
 static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
 	struct cam_ife_hw_mgr_ctx       *ife_ctx,
 	struct cam_isp_hw_mgr_res       *ife_src_res,
@@ -1297,125 +1213,6 @@ err:
 	return rc;
 }
 
-static int cam_ife_hw_mgr_acquire_res_ife_rd_src(
-	struct cam_ife_hw_mgr_ctx *ife_ctx,
-	struct cam_isp_in_port_generic_info *in_port)
-{
-	int rc                = -1;
-	struct cam_isp_hw_mgr_res                  *csid_res;
-	struct cam_isp_hw_mgr_res                  *ife_src_res;
-	struct cam_vfe_acquire_args                 vfe_acquire;
-	struct cam_hw_intf                         *hw_intf;
-	struct cam_ife_hw_mgr                      *ife_hw_mgr;
-	int vfe_idx = -1, i = 0;
-
-	ife_hw_mgr = ife_ctx->hw_mgr;
-
-	CAM_DBG(CAM_ISP, "Enter");
-	list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) {
-		if (csid_res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0) {
-			CAM_DBG(CAM_ISP, "not RDI0: %d", csid_res->res_id);
-			continue;
-		}
-
-		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
-			&ife_src_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-			goto err;
-		}
-		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
-			&ife_src_res);
-
-		CAM_DBG(CAM_ISP, "csid_res_id %d", csid_res->res_id);
-		vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
-		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
-		vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
-		vfe_acquire.vfe_in.in_port = in_port;
-		vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RD;
-		vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
-
-		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;
-
-		hw_intf =
-			ife_hw_mgr->ife_devices[csid_res->hw_res[
-			CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx];
-
-		vfe_idx = csid_res->hw_res[
-			CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx;
-
-		/*
-		 * fill in more acquire information as needed
-		 */
-		if (ife_src_res->is_dual_isp)
-			vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
-
-		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-				&vfe_acquire,
-				sizeof(struct cam_vfe_acquire_args));
-		if (rc) {
-			CAM_ERR(CAM_ISP,
-				"Can not acquire IFE HW res %d",
-				csid_res->res_id);
-			goto err;
-		}
-		ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] =
-			vfe_acquire.vfe_in.rsrc_node;
-		CAM_DBG(CAM_ISP,
-			"acquire success IFE:%d  res type :0x%x res id:0x%x",
-			hw_intf->hw_idx,
-			ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_type,
-			ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_id);
-
-		if (!ife_src_res->is_dual_isp)
-			goto acq;
-
-		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
-			if (i == CAM_ISP_HW_SPLIT_LEFT) {
-				CAM_DBG(CAM_ISP, "vfe_idx %d is acquired",
-					vfe_idx);
-				continue;
-			}
-
-			hw_intf = ife_hw_mgr->ife_devices[i];
-
-			/* fill in more acquire information as needed */
-			if (i == CAM_ISP_HW_SPLIT_RIGHT)
-				vfe_acquire.vfe_in.sync_mode =
-					CAM_ISP_HW_SYNC_SLAVE;
-
-			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-					&vfe_acquire,
-					sizeof(struct cam_vfe_acquire_args));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Can not acquire IFE HW res %d",
-					csid_res->res_id);
-				goto err;
-			}
-			ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
-			CAM_DBG(CAM_ISP,
-				"acquire success IFE:%d  res type :0x%x res id:0x%x",
-				hw_intf->hw_idx,
-				ife_src_res->hw_res[i]->res_type,
-				ife_src_res->hw_res[i]->res_id);
-		}
-acq:
-		/*
-		 * It should be one to one mapping between
-		 * csid resource and ife source resource
-		 */
-		csid_res->num_children++;
-	}
-
-err:
-	/* release resource at the entry function */
-	CAM_DBG(CAM_ISP, "Exit rc %d", rc);
-	return rc;
-}
-
 static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx)
 {
 	uint32_t hw_version, rc = 0;
@@ -1547,6 +1344,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
 		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
 		vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
 		vfe_acquire.vfe_in.in_port = in_port;
+		vfe_acquire.vfe_in.is_fe_enabled = ife_ctx->is_fe_enabled;
+		vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline;
 		vfe_acquire.priv = ife_ctx;
 		vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
 
@@ -1800,7 +1599,7 @@ static int cam_ife_mgr_acquire_cid_res(
 
 	/* Acquire Left if not already acquired */
 	/* For dual IFE cases, start acquiring the lower idx first */
-	if (ife_ctx->is_fe_enable || in_port->usage_type)
+	if (ife_ctx->is_fe_enabled || in_port->usage_type)
 		rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr,
 			&csid_acquire, true);
 	else
@@ -2166,7 +1965,7 @@ static int cam_ife_hw_mgr_acquire_res_root(
 		ife_ctx->res_list_ife_in.res_id = in_port->res_type;
 		ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_type;
 	} else if ((ife_ctx->res_list_ife_in.res_id !=
-		in_port->res_type) && (!ife_ctx->is_fe_enable))  {
+		in_port->res_type) && (!ife_ctx->is_fe_enabled))  {
 		CAM_ERR(CAM_ISP, "No Free resource for this context");
 		goto err;
 	} else {
@@ -2211,14 +2010,14 @@ static int cam_ife_mgr_check_and_update_fe_v0(
 		CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
 			in_port->res_type);
 		if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
-			ife_ctx->is_fe_enable = true;
+			ife_ctx->is_fe_enabled = true;
 			break;
 		}
 
 		in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
 			in_port_length);
 	}
-	CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
+	CAM_DBG(CAM_ISP, "is_fe_enabled %d", ife_ctx->is_fe_enabled);
 
 	return 0;
 }
@@ -2256,14 +2055,17 @@ static int cam_ife_mgr_check_and_update_fe_v2(
 		CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
 			in_port->res_type);
 		if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
-			ife_ctx->is_fe_enable = true;
+			ife_ctx->is_fe_enabled = true;
+			if (in_port->offline_mode)
+				ife_ctx->is_offline = true;
 			break;
 		}
 
 		in_port = (struct cam_isp_in_port_info_v2 *)
 			((uint8_t *)in_port + in_port_length);
 	}
-	CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
+	CAM_DBG(CAM_ISP, "is_fe_enabled %d is_offline %d",
+		ife_ctx->is_fe_enabled, ife_ctx->is_offline);
 
 	return 0;
 }
@@ -2316,22 +2118,21 @@ static int cam_ife_hw_mgr_preprocess_port(
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
 
-	if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+	if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD)
 		ife_rd_num++;
-	} else {
-		for (i = 0; i < in_port->num_out_res; i++) {
-			out_port = &in_port->data[i];
-			if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
-				rdi_num++;
-			else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
-				ppp_num++;
-			else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)
-				lcr_num++;
-			else {
-				CAM_DBG(CAM_ISP, "out_res_type %d",
-				out_port->res_type);
-				ipp_num++;
-			}
+
+	for (i = 0; i < in_port->num_out_res; i++) {
+		out_port = &in_port->data[i];
+		if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+			rdi_num++;
+		else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
+			ppp_num++;
+		else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)
+			lcr_num++;
+		else {
+			CAM_DBG(CAM_ISP, "out_res_type %d",
+			out_port->res_type);
+			ipp_num++;
 		}
 	}
 
@@ -2347,6 +2148,290 @@ static int cam_ife_hw_mgr_preprocess_port(
 	return 0;
 }
 
+static int cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(
+	struct cam_ife_hw_mgr_ctx                  *ife_ctx,
+	struct cam_isp_in_port_generic_info        *in_port)
+{
+	int                                         rc = -EINVAL, j;
+	int                                         i = CAM_ISP_HW_SPLIT_LEFT;
+	struct cam_vfe_acquire_args                 vfe_acquire;
+	struct cam_isp_hw_mgr_res                  *ife_bus_rd_res;
+	struct cam_hw_intf                         *hw_intf;
+	struct cam_ife_hw_mgr                      *ife_hw_mgr;
+
+	ife_hw_mgr = ife_ctx->hw_mgr;
+
+	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_bus_rd_res);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+		goto end;
+	}
+
+	vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+	vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+	vfe_acquire.priv = ife_ctx;
+	vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
+
+	vfe_acquire.vfe_bus_rd.cdm_ops = ife_ctx->cdm_ops;
+	vfe_acquire.vfe_bus_rd.is_dual = (uint32_t)ife_ctx->is_dual;
+	vfe_acquire.vfe_bus_rd.is_offline = ife_ctx->is_offline;
+	vfe_acquire.vfe_bus_rd.res_id = CAM_ISP_HW_VFE_IN_RD;
+	vfe_acquire.vfe_bus_rd.unpacker_fmt = in_port->fe_unpacker_fmt;
+
+	for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) {
+		if (!ife_hw_mgr->ife_devices[j])
+			continue;
+
+		hw_intf = ife_hw_mgr->ife_devices[j];
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+			&vfe_acquire, sizeof(struct cam_vfe_acquire_args));
+
+		if (!rc) {
+			ife_bus_rd_res->hw_res[i] =
+				vfe_acquire.vfe_bus_rd.rsrc_node;
+
+			CAM_DBG(CAM_ISP, "Acquired VFE:%d BUS RD for LEFT", j);
+			break;
+		}
+	}
+
+	if (j == CAM_IFE_HW_NUM_MAX || !vfe_acquire.vfe_bus_rd.rsrc_node) {
+		CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for LEFT", i);
+		goto put_res;
+	}
+
+	ife_bus_rd_res->res_type = vfe_acquire.rsrc_type;
+	ife_bus_rd_res->res_id = vfe_acquire.vfe_in.res_id;
+	ife_bus_rd_res->is_dual_isp = (uint32_t)ife_ctx->is_dual;
+	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd, &ife_bus_rd_res);
+
+	if (ife_ctx->is_dual) {
+		for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) {
+			if (!ife_hw_mgr->ife_devices[j])
+				continue;
+
+			if (j == ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx)
+				continue;
+
+			hw_intf = ife_hw_mgr->ife_devices[j];
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&vfe_acquire,
+				sizeof(struct cam_vfe_acquire_args));
+
+			if (!rc) {
+				ife_bus_rd_res->hw_res[++i] =
+					vfe_acquire.vfe_bus_rd.rsrc_node;
+
+				CAM_DBG(CAM_ISP,
+					"Acquired VFE:%d BUS RD for RIGHT", j);
+				break;
+			}
+		}
+
+		if (j == CAM_IFE_HW_NUM_MAX ||
+			!vfe_acquire.vfe_bus_rd.rsrc_node) {
+			CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for RIGHT");
+			goto end;
+		}
+	}
+
+	return 0;
+
+put_res:
+	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_bus_rd_res);
+
+end:
+	return rc;
+}
+
+static int cam_ife_hw_mgr_acquire_offline_res_ife_camif(
+	struct cam_ife_hw_mgr_ctx                  *ife_ctx,
+	struct cam_isp_in_port_generic_info        *in_port,
+	bool                                        acquire_lcr,
+	uint32_t                                   *acquired_hw_id,
+	uint32_t                                   *acquired_hw_path)
+{
+	int                                         rc = -1;
+	int                                         i = CAM_ISP_HW_SPLIT_LEFT;
+	struct cam_isp_hw_mgr_res                  *ife_src_res;
+	struct cam_isp_hw_mgr_res                  *ife_bus_rd_res;
+	struct cam_vfe_acquire_args                 vfe_acquire;
+	struct cam_hw_intf                         *hw_intf;
+	struct cam_ife_hw_mgr                      *ife_hw_mgr;
+
+	ife_hw_mgr = ife_ctx->hw_mgr;
+
+	ife_bus_rd_res = list_first_entry(&ife_ctx->res_list_ife_in_rd,
+		struct cam_isp_hw_mgr_res, list);
+
+	if (!ife_bus_rd_res) {
+		CAM_ERR(CAM_ISP, "BUS RD resource has not been acquired");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_src_res);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "No free resource");
+		goto end;
+	}
+
+	vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
+	vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+	vfe_acquire.priv = ife_ctx;
+	vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
+
+	vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
+	vfe_acquire.vfe_in.in_port = in_port;
+	vfe_acquire.vfe_in.is_fe_enabled = ife_ctx->is_fe_enabled;
+	vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline;
+
+	if (!acquire_lcr)
+		vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_CAMIF;
+	else
+		vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_LCR;
+
+	if (ife_ctx->is_dual)
+		vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
+	else
+		vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
+
+	hw_intf = ife_hw_mgr->ife_devices[
+		ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx];
+
+	rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire,
+		sizeof(struct cam_vfe_acquire_args));
+
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for LEFT");
+		goto put_res;
+	}
+
+	ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
+
+	*acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num(
+		hw_intf->hw_idx);
+
+	acquired_hw_path[i] |= cam_convert_res_id_to_hw_path(
+		ife_src_res->hw_res[i]->res_id);
+
+	CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for LEFT",
+		ife_src_res->hw_res[i]->hw_intf->hw_idx);
+
+	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 = (uint32_t)ife_ctx->is_dual;
+	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src, &ife_src_res);
+
+	if (ife_ctx->is_dual) {
+		vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE;
+
+		hw_intf = ife_hw_mgr->ife_devices[
+			ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx];
+
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire,
+			sizeof(struct cam_vfe_acquire_args));
+
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for RIGHT");
+			goto end;
+		}
+
+		ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
+
+		*acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num(
+			hw_intf->hw_idx);
+
+		acquired_hw_path[i] |= cam_convert_res_id_to_hw_path(
+			ife_src_res->hw_res[i]->res_id);
+
+		CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for RIGHT",
+			ife_src_res->hw_res[i]->hw_intf->hw_idx);
+	}
+
+	ife_bus_rd_res->num_children++;
+
+	return rc;
+
+put_res:
+	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_src_res);
+
+end:
+	return rc;
+}
+
+static int cam_ife_mgr_acquire_hw_for_fe_ctx(
+	struct cam_ife_hw_mgr_ctx           *ife_ctx,
+	struct cam_isp_in_port_generic_info *in_port,
+	uint32_t                            *num_pix_port,
+	uint32_t                            *acquired_hw_id,
+	uint32_t                            *acquired_hw_path)
+{
+	int                                  rc = -1;
+	int                                  ipp_count = 0;
+	int                                  rdi_count = 0;
+	int                                  ppp_count = 0;
+	int                                  ife_rd_count = 0;
+	int                                  lcr_count = 0;
+
+	ife_ctx->is_dual = (bool)in_port->usage_type;
+
+	cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count,
+		&rdi_count, &ppp_count, &ife_rd_count, &lcr_count);
+
+	if ((!ipp_count && !lcr_count) || !ife_rd_count) {
+		CAM_ERR(CAM_ISP,
+			"Invalid %d BUS RD %d PIX %d LCR ports for FE ctx");
+		return -EINVAL;
+	}
+
+	if (rdi_count || ppp_count) {
+		CAM_ERR(CAM_ISP,
+			"%d RDI %d PPP ports invalid for FE ctx",
+			rdi_count, ppp_count);
+		return -EINVAL;
+	}
+
+	rc = cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(ife_ctx, in_port);
+
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed");
+		goto err;
+	}
+
+	if (ipp_count)
+		rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx,
+			in_port, false, acquired_hw_id, acquired_hw_path);
+
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Acquire IFE IPP SRC resource Failed");
+		goto err;
+	}
+
+	if (lcr_count)
+		rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx,
+			in_port, true, acquired_hw_id, acquired_hw_path);
+
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Acquire IFE LCR SRC resource Failed");
+		goto err;
+	}
+
+	rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed");
+		goto err;
+	}
+
+	*num_pix_port += ipp_count + lcr_count;
+
+	return 0;
+
+err:
+	return rc;
+}
+
+
 static int cam_ife_mgr_acquire_hw_for_ctx(
 	struct cam_ife_hw_mgr_ctx           *ife_ctx,
 	struct cam_isp_in_port_generic_info *in_port,
@@ -2373,10 +2458,14 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
 	cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count,
 		&rdi_count, &ppp_count, &ife_rd_count, &lcr_count);
 
-	if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count
-		&& !lcr_count) {
+	if (ife_rd_count) {
+		CAM_ERR(CAM_ISP, "Invalid BUS RD port for non-FE ctx");
+		return -EINVAL;
+	}
+
+	if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) {
 		CAM_ERR(CAM_ISP,
-			"No PIX or RDI or PPP or IFE RD or LCR resource");
+			"No PIX or RDI or PPP or LCR resource");
 		return -EINVAL;
 	}
 
@@ -2421,15 +2510,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
 	}
 
 	/* get ife src resource */
-	if (ife_rd_count) {
-		rc = cam_ife_hw_mgr_acquire_res_ife_rd_src(ife_ctx, in_port);
-		rc = cam_ife_hw_mgr_acquire_res_bus_rd(ife_ctx, in_port);
-
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Acquire IFE RD SRC resource Failed");
-			goto err;
-		}
-	} else if (ipp_count || ppp_count || rdi_count) {
+	if (ipp_count || ppp_count || rdi_count) {
 		rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx,
 			in_port, false,
 			acquired_hw_id, acquired_hw_path);
@@ -2633,10 +2714,12 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2(
 
 	if (port_info->num_valid_vc_dt == 0 ||
 		port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) {
-		CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d",
-			in->num_valid_vc_dt);
-		rc = -EINVAL;
-		goto release_mem;
+		if (in->res_type != CAM_ISP_IFE_IN_RES_RD) {
+			CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d",
+				in->num_valid_vc_dt);
+			rc = -EINVAL;
+			goto release_mem;
+		}
 	}
 
 	for (i = 0; i < port_info->num_valid_vc_dt; i++) {
@@ -2644,26 +2727,27 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2(
 		port_info->dt[i]      =  in->dt[i];
 	}
 
-	port_info->format         =  in->format;
-	port_info->test_pattern   =  in->test_pattern;
-	port_info->usage_type     =  in->usage_type;
-	port_info->left_start     =  in->left_start;
-	port_info->left_stop      =  in->left_stop;
-	port_info->left_width     =  in->left_width;
-	port_info->right_start    =  in->right_start;
-	port_info->right_stop     =  in->right_stop;
-	port_info->right_width    =  in->right_width;
-	port_info->line_start     =  in->line_start;
-	port_info->line_stop      =  in->line_stop;
-	port_info->height         =  in->height;
-	port_info->pixel_clk      =  in->pixel_clk;
-	port_info->batch_size     =  in->batch_size;
-	port_info->dsp_mode       =  in->dsp_mode;
-	port_info->hbi_cnt        =  in->hbi_cnt;
-	port_info->cust_node      =  in->cust_node;
-	port_info->horizontal_bin =  in->horizontal_bin;
-	port_info->qcfa_bin       =  in->qcfa_bin;
-	port_info->num_out_res    =  in->num_out_res;
+	port_info->format          =  in->format;
+	port_info->test_pattern    =  in->test_pattern;
+	port_info->usage_type      =  in->usage_type;
+	port_info->left_start      =  in->left_start;
+	port_info->left_stop       =  in->left_stop;
+	port_info->left_width      =  in->left_width;
+	port_info->right_start     =  in->right_start;
+	port_info->right_stop      =  in->right_stop;
+	port_info->right_width     =  in->right_width;
+	port_info->line_start      =  in->line_start;
+	port_info->line_stop       =  in->line_stop;
+	port_info->height          =  in->height;
+	port_info->pixel_clk       =  in->pixel_clk;
+	port_info->batch_size      =  in->batch_size;
+	port_info->dsp_mode        =  in->dsp_mode;
+	port_info->fe_unpacker_fmt =  in->format;
+	port_info->hbi_cnt         =  in->hbi_cnt;
+	port_info->cust_node       =  in->cust_node;
+	port_info->horizontal_bin  =  in->horizontal_bin;
+	port_info->qcfa_bin        =  in->qcfa_bin;
+	port_info->num_out_res     =  in->num_out_res;
 
 	port_info->data = kcalloc(in->num_out_res,
 		sizeof(struct cam_isp_out_port_generic_info),
@@ -2822,10 +2906,17 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 			goto free_mem;
 		}
 
-		rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
-			&num_pix_port_per_in, &num_rdi_port_per_in,
-			&acquire_args->acquired_hw_id[i],
-			acquire_args->acquired_hw_path[i]);
+		if (ife_ctx->is_fe_enabled)
+			rc = cam_ife_mgr_acquire_hw_for_fe_ctx(
+				ife_ctx, in_port,
+				&num_pix_port_per_in,
+				&acquire_args->acquired_hw_id[i],
+				acquire_args->acquired_hw_path[i]);
+		else
+			rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
+				&num_pix_port_per_in, &num_rdi_port_per_in,
+				&acquire_args->acquired_hw_id[i],
+				acquire_args->acquired_hw_path[i]);
 
 		total_pix_port += num_pix_port_per_in;
 		total_rdi_port += num_rdi_port_per_in;
@@ -2915,6 +3006,7 @@ void cam_ife_mgr_acquire_get_unified_dev_str(struct cam_isp_in_port_info *in,
 	gen_port_info->batch_size      =  in->batch_size;
 	gen_port_info->dsp_mode        =  in->dsp_mode;
 	gen_port_info->hbi_cnt         =  in->hbi_cnt;
+	gen_port_info->fe_unpacker_fmt =  in->format;
 	gen_port_info->cust_node       =  0;
 	gen_port_info->num_out_res     =  in->num_out_res;
 
@@ -3788,11 +3880,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
 
-	/* IFE bus rd resources */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
-		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
-	}
-
 	CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
 
 	/* IFE mux in resources */
@@ -3800,6 +3887,11 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
 		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
 	}
 
+	/* IFE bus rd resources */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+	}
+
 	cam_tasklet_stop(ctx->common.tasklet_info);
 
 	cam_ife_mgr_pause_hw(ctx);
@@ -4090,18 +4182,6 @@ start_only:
 		}
 	}
 
-	CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d",
-		ctx->ctx_index);
-	/* Start the IFE mux in devices */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
-				 hw_mgr_res->res_id);
-			goto err;
-		}
-	}
-
 	if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX)
 		primary_rdi_src_res =
 			cam_convert_rdi_out_res_id_to_src(primary_rdi_out_res);
@@ -4114,15 +4194,25 @@ start_only:
 			hw_mgr_res->hw_res[0]->rdi_only_ctx =
 				ctx->is_rdi_only_context;
 		}
-
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)",
+			CAM_ERR(CAM_ISP, "Can not start IFE Mux (%d)",
 				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
+	CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d", ctx->ctx_index);
+	/* Start IFE Bus RD devices */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+				hw_mgr_res->res_id);
+			goto err;
+		}
+	}
+
 	CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d",
 		ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
@@ -5838,6 +5928,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 		}
 	}
 
+
+	/* add go_cmd for offline context */
+	if (prepare->num_out_map_entries && prepare->num_in_map_entries &&
+		ctx->is_offline) {
+		rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd,
+			ctx->base[i].idx, &kmd_buf);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Add GO_CMD faled i: %d, idx: %d, rc: %d",
+				i, ctx->base[i].idx, rc);
+	}
+
 	/*
 	 * reg update will be done later for the initial configure.
 	 * need to plus one to the op_code and only take the lower
@@ -6075,7 +6177,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 				isp_hw_cmd_args->u.sof_irq_enable);
 			break;
 		case CAM_ISP_HW_MGR_CMD_CTX_TYPE:
-			if (ctx->is_fe_enable)
+			if (ctx->is_fe_enabled && ctx->is_offline)
+				isp_hw_cmd_args->u.ctx_type =
+					CAM_ISP_CTX_OFFLINE;
+			else if (ctx->is_fe_enabled && !ctx->is_offline)
 				isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_FS2;
 			else if (ctx->is_rdi_only_context)
 				isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI;
@@ -6309,6 +6414,17 @@ end:
 	return rc;
 }
 
+static inline void cam_ife_hw_mgr_get_offline_sof_timestamp(
+	uint64_t                             *timestamp,
+	uint64_t                             *boot_time)
+{
+	struct timespec64                     ts;
+
+	ktime_get_boottime_ts64(&ts);
+	*timestamp = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec);
+	*boot_time = *timestamp;
+}
+
 static int cam_ife_mgr_cmd_get_sof_timestamp(
 	struct cam_ife_hw_mgr_ctx            *ife_ctx,
 	uint64_t                             *time_stamp,
@@ -6681,6 +6797,7 @@ static int cam_ife_hw_mgr_handle_hw_rup(
 
 	case CAM_ISP_HW_VFE_IN_PDLIB:
 	case CAM_ISP_HW_VFE_IN_LCR:
+	case CAM_ISP_HW_VFE_IN_RD:
 		break;
 	default:
 		CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d",
@@ -6810,6 +6927,8 @@ static int cam_ife_hw_mgr_handle_hw_sof(
 	struct cam_isp_hw_sof_event_data      sof_done_event_data;
 	int                                   rc = 0;
 
+	memset(&sof_done_event_data, 0, sizeof(sof_done_event_data));
+
 	ife_hw_irq_sof_cb =
 		ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF];
 
@@ -6820,10 +6939,15 @@ static int cam_ife_hw_mgr_handle_hw_sof(
 		rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx,
 			CAM_ISP_HW_EVENT_SOF);
 		if (!rc) {
-			cam_ife_mgr_cmd_get_sof_timestamp(
-				ife_hw_mgr_ctx,
-				&sof_done_event_data.timestamp,
-				&sof_done_event_data.boot_time);
+			if (ife_hw_mgr_ctx->is_offline)
+				cam_ife_hw_mgr_get_offline_sof_timestamp(
+					&sof_done_event_data.timestamp,
+					&sof_done_event_data.boot_time);
+			else
+				cam_ife_mgr_cmd_get_sof_timestamp(
+					ife_hw_mgr_ctx,
+					&sof_done_event_data.timestamp,
+					&sof_done_event_data.boot_time);
 
 			/* if frame header is enabled reset qtimer ts */
 			if (ife_hw_mgr_ctx->use_frame_header_ts)

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

@@ -82,12 +82,13 @@ struct cam_ife_hw_mgr_debug {
  * @last_dump_flush_req_id  Last req id for which reg dump on flush was called
  * @last_dump_err_req_id    Last req id for which reg dump on error was called
  * @init_done               indicate whether init hw is done
- * @is_fe_enable            indicate whether fetch engine\read path is enabled
+ * @is_fe_enabled           Indicate whether fetch engine\read path is enabled
  * @is_dual                 indicate whether context is in dual VFE mode
  * @custom_enabled          update the flag if context is connected to custom HW
  * @use_frame_header_ts     obtain qtimer ts using frame header
  * @ts                      captured timestamp when the ctx is acquired
  * @is_tpg                  indicate whether context is using PHY TPG
+ * @is_offline              Indicate whether context is for offline IFE
  */
 struct cam_ife_hw_mgr_ctx {
 	struct list_head                list;
@@ -133,12 +134,13 @@ struct cam_ife_hw_mgr_ctx {
 	uint64_t                        last_dump_flush_req_id;
 	uint64_t                        last_dump_err_req_id;
 	bool                            init_done;
-	bool                            is_fe_enable;
+	bool                            is_fe_enabled;
 	bool                            is_dual;
 	bool                            custom_enabled;
 	bool                            use_frame_header_ts;
 	struct timespec64               ts;
 	bool                            is_tpg;
+	bool                            is_offline;
 };
 
 /**

+ 98 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -947,7 +947,7 @@ int cam_isp_add_reg_update(
 				return rc;
 
 			CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d",
-				res->res_id, res->hw_intf->hw_idx);
+				res->res_type, res->hw_intf->hw_idx);
 			reg_update_size += get_regup.cmd.used_bytes;
 		}
 	}
@@ -981,3 +981,100 @@ int cam_isp_add_reg_update(
 
 	return rc;
 }
+
+int cam_isp_add_go_cmd(
+	struct cam_hw_prepare_update_args    *prepare,
+	struct list_head                     *res_list_isp_rd,
+	uint32_t                              base_idx,
+	struct cam_kmd_buf_info              *kmd_buf_info)
+{
+	int rc = -EINVAL;
+	struct cam_isp_resource_node         *res;
+	struct cam_isp_hw_mgr_res            *hw_mgr_res;
+	struct cam_hw_update_entry           *hw_entry;
+	struct cam_isp_hw_get_cmd_update      get_regup;
+	uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size;
+
+	hw_entry = prepare->hw_update_entries;
+	if (prepare->num_hw_update_entries + 1 >=
+		prepare->max_hw_update_entries) {
+		CAM_ERR(CAM_ISP, "Insufficient HW entries current: %d max: %d",
+			prepare->num_hw_update_entries,
+			prepare->max_hw_update_entries);
+		return -EINVAL;
+	}
+
+	reg_update_size = 0;
+	list_for_each_entry(hw_mgr_res, res_list_isp_rd, 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];
+			if (res->hw_intf->hw_idx != base_idx)
+				continue;
+
+			if (kmd_buf_info->size > (kmd_buf_info->used_bytes +
+				reg_update_size)) {
+				kmd_buf_remain_size =  kmd_buf_info->size -
+					(kmd_buf_info->used_bytes +
+					reg_update_size);
+			} else {
+				CAM_ERR(CAM_ISP, "no free mem %d %d %d",
+					base_idx, kmd_buf_info->size,
+					kmd_buf_info->used_bytes +
+					reg_update_size);
+				rc = -EINVAL;
+				return rc;
+			}
+
+			get_regup.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
+				kmd_buf_info->used_bytes/4 +
+				reg_update_size/4;
+			get_regup.cmd.size = kmd_buf_remain_size;
+			get_regup.cmd_type = CAM_ISP_HW_CMD_FE_TRIGGER_CMD;
+			get_regup.res = res;
+
+			rc = res->process_cmd(res->res_priv,
+				CAM_ISP_HW_CMD_FE_TRIGGER_CMD, &get_regup,
+				sizeof(struct cam_isp_hw_get_cmd_update));
+			if (rc)
+				return rc;
+
+			CAM_DBG(CAM_ISP, "GO_CMD added for RD res %d hw_id %d",
+				res->res_type, res->hw_intf->hw_idx);
+			reg_update_size += get_regup.cmd.used_bytes;
+		}
+	}
+
+	if (reg_update_size) {
+		/* Update the HW entries */
+		num_ent = prepare->num_hw_update_entries;
+		prepare->hw_update_entries[num_ent].handle =
+					kmd_buf_info->handle;
+		prepare->hw_update_entries[num_ent].len = reg_update_size;
+		prepare->hw_update_entries[num_ent].offset =
+			kmd_buf_info->offset;
+
+		prepare->hw_update_entries[num_ent].flags =
+			CAM_ISP_IOCFG_BL;
+		CAM_DBG(CAM_ISP,
+			"num_ent=%d handle=0x%x, len=%u, offset=%u",
+			num_ent,
+			prepare->hw_update_entries[num_ent].handle,
+			prepare->hw_update_entries[num_ent].len,
+			prepare->hw_update_entries[num_ent].offset);
+		num_ent++;
+
+		kmd_buf_info->used_bytes += reg_update_size;
+		kmd_buf_info->offset     += reg_update_size;
+		prepare->num_hw_update_entries = num_ent;
+		rc = 0;
+	}
+
+	return rc;
+}
+

+ 19 - 0
drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h

@@ -176,4 +176,23 @@ int cam_isp_add_reg_update(
 	uint32_t                              base_idx,
 	struct cam_kmd_buf_info              *kmd_buf_info);
 
+/*
+ * cam_isp_add_go_cmd()
+ *
+ * @brief                  Add go_cmd in the hw entries list for each rd source
+ *
+ * @prepare:               Contain the  packet and HW update variables
+ * @res_list_isp_rd:       Resource list for BUS RD ports
+ * @base_idx:              Base or dev index of the IFE/VFE HW instance
+ * @kmd_buf_info:          Kmd buffer to store the change base command
+ * @return:                0 for success
+ *                         -EINVAL for Fail
+ */
+int cam_isp_add_go_cmd(
+	struct cam_hw_prepare_update_args    *prepare,
+	struct list_head                     *res_list_isp_rd,
+	uint32_t                              base_idx,
+	struct cam_kmd_buf_info              *kmd_buf_info);
+
+
 #endif /*_CAM_ISP_HW_PARSER_H */

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

@@ -239,6 +239,7 @@ enum cam_isp_ctx_type {
 	CAM_ISP_CTX_FS2 = 1,
 	CAM_ISP_CTX_RDI,
 	CAM_ISP_CTX_PIX,
+	CAM_ISP_CTX_OFFLINE,
 	CAM_ISP_CTX_MAX,
 };
 /**

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

@@ -97,6 +97,7 @@ struct cam_isp_in_port_generic_info {
 	uint32_t                        batch_size;
 	uint32_t                        dsp_mode;
 	uint32_t                        hbi_cnt;
+	uint32_t                        fe_unpacker_fmt;
 	uint32_t                        cust_node;
 	uint32_t                        num_out_res;
 	uint32_t                        horizontal_bin;

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

@@ -77,8 +77,8 @@ enum cam_isp_resource_type {
 	CAM_ISP_RESOURCE_CID,
 	CAM_ISP_RESOURCE_PIX_PATH,
 	CAM_ISP_RESOURCE_VFE_IN,
-	CAM_ISP_RESOURCE_VFE_OUT,
 	CAM_ISP_RESOURCE_VFE_BUS_RD,
+	CAM_ISP_RESOURCE_VFE_OUT,
 	CAM_ISP_RESOURCE_TPG,
 	CAM_ISP_RESOURCE_TFE_IN,
 	CAM_ISP_RESOURCE_TFE_OUT,
@@ -114,6 +114,7 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE,
 	CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
 	CAM_ISP_HW_CMD_DUMP_HW,
+	CAM_ISP_HW_CMD_FE_TRIGGER_CMD,
 	CAM_ISP_HW_CMD_MAX,
 };
 

+ 28 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h

@@ -102,6 +102,27 @@ struct cam_vfe_hw_get_hw_cap {
 	uint32_t                max_rdi_num;
 };
 
+/*
+ * struct cam_vfe_hw_vfe_bus_rd_acquire_args:
+ *
+ * @rsrc_node:               Pointer to Resource Node object, filled if acquire
+ *                           is successful
+ * @res_id:                  Unique Identity of port to associate with this
+ *                           resource.
+ * @is_dual:                 Flag to indicate dual VFE usecase
+ * @cdm_ops:                 CDM operations
+ * @unpacket_fmt:            Unpacker format for read engine
+ * @is_offline:              Flag to indicate offline usecase
+ */
+struct cam_vfe_hw_vfe_bus_rd_acquire_args {
+	struct cam_isp_resource_node         *rsrc_node;
+	uint32_t                              res_id;
+	uint32_t                              is_dual;
+	struct cam_cdm_utils_ops             *cdm_ops;
+	uint32_t                              unpacker_fmt;
+	bool                                  is_offline;
+};
+
 /*
  * struct cam_vfe_hw_vfe_out_acquire_args:
  *
@@ -143,6 +164,8 @@ struct cam_vfe_hw_vfe_out_acquire_args {
  * @sync_mode:               In case of Dual VFE, this is Master or Slave.
  *                           (Default is Master in case of Single VFE)
  * @in_port:                 Input port details to acquire
+ * @is_fe_enabled:           Flag to indicate if FE is enabled
+ * @is_offline:              Flag to indicate Offline IFE
  */
 struct cam_vfe_hw_vfe_in_acquire_args {
 	struct cam_isp_resource_node         *rsrc_node;
@@ -152,6 +175,8 @@ struct cam_vfe_hw_vfe_in_acquire_args {
 	void                                 *cdm_ops;
 	enum cam_isp_hw_sync_mode             sync_mode;
 	struct cam_isp_in_port_generic_info  *in_port;
+	bool                                  is_fe_enabled;
+	bool                                  is_offline;
 };
 
 /*
@@ -173,9 +198,9 @@ struct cam_vfe_acquire_args {
 	void                                *priv;
 	cam_hw_mgr_event_cb_func             event_cb;
 	union {
-		struct cam_vfe_hw_vfe_out_acquire_args  vfe_out;
-		struct cam_vfe_hw_vfe_out_acquire_args  vfe_bus_rd;
-		struct cam_vfe_hw_vfe_in_acquire_args   vfe_in;
+		struct cam_vfe_hw_vfe_out_acquire_args     vfe_out;
+		struct cam_vfe_hw_vfe_bus_rd_acquire_args  vfe_bus_rd;
+		struct cam_vfe_hw_vfe_in_acquire_args      vfe_in;
 	};
 };
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h

@@ -407,6 +407,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
 			.max_height    = -1,
 		},
 	},
+	.top_irq_shift = 23,
 };
 
 static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h

@@ -1360,6 +1360,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = {
 			.max_height    = -1,
 		},
 	},
+	.top_irq_shift = 8,
 };
 
 struct cam_vfe_hw_info cam_vfe480_hw_info = {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 391 - 252
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c


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

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_VFE_BUS_R_VER1_H_
@@ -88,6 +88,7 @@ struct cam_vfe_bus_rd_ver1_hw_info {
 	uint32_t num_bus_rd_resc;
 	struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
 		vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+	uint32_t top_irq_shift;
 };
 
 /*

+ 42 - 16
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c

@@ -54,6 +54,8 @@ struct cam_vfe_mux_camif_ver3_data {
 	uint32_t                           qcfa_bin;
 	uint32_t                           dual_hw_idx;
 	uint32_t                           is_dual;
+	bool                               is_fe_enabled;
+	bool                               is_offline;
 };
 
 static int cam_vfe_camif_ver3_get_evt_payload(
@@ -248,19 +250,20 @@ int cam_vfe_camif_ver3_acquire_resource(
 		return rc;
 	}
 
-	camif_data->sync_mode   = acquire_data->vfe_in.sync_mode;
-	camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
-	camif_data->dsp_mode    = acquire_data->vfe_in.in_port->dsp_mode;
-	camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
-	camif_data->last_pixel  = acquire_data->vfe_in.in_port->left_stop;
-	camif_data->first_line  = acquire_data->vfe_in.in_port->line_start;
-	camif_data->last_line   = acquire_data->vfe_in.in_port->line_stop;
+	camif_data->sync_mode      = acquire_data->vfe_in.sync_mode;
+	camif_data->pix_pattern    = acquire_data->vfe_in.in_port->test_pattern;
+	camif_data->dsp_mode       = acquire_data->vfe_in.in_port->dsp_mode;
+	camif_data->first_pixel    = acquire_data->vfe_in.in_port->left_start;
+	camif_data->last_pixel     = acquire_data->vfe_in.in_port->left_stop;
+	camif_data->first_line     = acquire_data->vfe_in.in_port->line_start;
+	camif_data->last_line      = acquire_data->vfe_in.in_port->line_stop;
+	camif_data->is_fe_enabled  = acquire_data->vfe_in.is_fe_enabled;
+	camif_data->is_offline     = acquire_data->vfe_in.is_offline;
+	camif_data->event_cb       = acquire_data->event_cb;
+	camif_data->priv           = acquire_data->priv;
+	camif_data->qcfa_bin       = acquire_data->vfe_in.in_port->qcfa_bin;
 	camif_data->horizontal_bin =
 		acquire_data->vfe_in.in_port->horizontal_bin;
-	camif_data->qcfa_bin    = acquire_data->vfe_in.in_port->qcfa_bin;
-	camif_data->event_cb    = acquire_data->event_cb;
-	camif_data->priv        = acquire_data->priv;
-	camif_data->is_dual     = acquire_data->vfe_in.is_dual;
 
 	if (acquire_data->vfe_in.is_dual)
 		camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx;
@@ -417,12 +420,20 @@ static int cam_vfe_camif_ver3_resource_start(
 	val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) <<
 		CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP;
 
+	if (rsrc_data->is_fe_enabled && !rsrc_data->is_offline)
+		val |= 0x2 << rsrc_data->reg_data->operating_mode_shift;
+	else
+		val |= 0x1 << rsrc_data->reg_data->operating_mode_shift;
+
 	if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) {
 		val |= (((rsrc_data->dual_hw_idx &
 				rsrc_data->reg_data->dual_vfe_sync_mask) + 1) <<
 				rsrc_data->reg_data->dual_ife_sync_sel_shift);
 	}
 
+	CAM_DBG(CAM_ISP, "VFE:%d TOP core_cfg: 0x%X",
+		camif_res->hw_intf->hw_idx, val);
+
 	cam_io_w_mb(val, rsrc_data->mem_base +
 		rsrc_data->common_reg->core_cfg_0);
 
@@ -459,11 +470,14 @@ static int cam_vfe_camif_ver3_resource_start(
 	camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
 	/* Reg Update */
-	cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
-		rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd);
-	CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X",
-		camif_res->hw_intf->hw_idx,
-		rsrc_data->reg_data->reg_update_cmd_data);
+	if (!rsrc_data->is_offline) {
+		cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
+			rsrc_data->mem_base +
+			rsrc_data->camif_reg->reg_update_cmd);
+		CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X",
+			camif_res->hw_intf->hw_idx,
+			rsrc_data->reg_data->reg_update_cmd_data);
+	}
 
 	/* disable sof irq debug flag */
 	rsrc_data->enable_sof_irq_debug = false;
@@ -606,6 +620,18 @@ static int cam_vfe_camif_ver3_reg_dump(
 		CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val);
 	}
 
+	CAM_INFO(CAM_ISP, "IFE:%d BUS RD", camif_res->hw_intf->hw_idx);
+	for (offset = 0xA800; offset <= 0xA89C; offset += 0x4) {
+		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
+		CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val);
+		if (offset == 0xA838)
+			offset = 0xA844;
+		if (offset == 0xA864)
+			offset = 0xA874;
+		if (offset == 0xA878)
+			offset = 0xA87C;
+	}
+
 	CAM_INFO(CAM_ISP, "IFE:%d BUS WR", camif_res->hw_intf->hw_idx);
 	for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) {
 		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä