Explorar o código

msm: camera: req_mgr: Re-design CRM to support multi links in sync mode

This change is to support multi links in sync mode. Supports dynmanic
switching to select master link in rtb and sat use case in sync mode.
Supports sync logic for rtb and sat use case in sync mode. Apply
requests for all links is triggered only on master epoch. Supports
bubble recovery and sync logic for different pd links in sync mode.

CRs-Fixed: 2783209
Change-Id: I81d1d0d37aa0d6e18c19ca87eac51ef3f160abfb
Signed-off-by: Ayush Kumar <[email protected]>
Ayush Kumar %!s(int64=4) %!d(string=hai) anos
pai
achega
0259331da4

+ 28 - 1
drivers/cam_core/cam_context.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -182,6 +182,33 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
 	return rc;
 }
 
+int cam_context_handle_crm_state_change(struct cam_context *ctx,
+	struct cam_req_mgr_request_change_state *state_info)
+{
+	int rc;
+
+	if (!ctx->state_machine) {
+		CAM_ERR(CAM_CORE, "Context is not ready");
+		return -EINVAL;
+	}
+
+	if (!state_info) {
+		CAM_ERR(CAM_CORE, "Invalid change state payload");
+		return -EINVAL;
+	}
+
+	if (ctx->state_machine[ctx->state].crm_ops.change_state) {
+		rc = ctx->state_machine[ctx->state].crm_ops.change_state(ctx,
+			state_info);
+	} else {
+		CAM_ERR(CAM_CORE, "No crm change state req in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
+		rc = -EPROTO;
+	}
+
+	return rc;
+}
+
 int cam_context_handle_crm_notify_frame_skip(
 	struct cam_context *ctx,
 	struct cam_req_mgr_apply_request *apply)

+ 15 - 0
drivers/cam_core/cam_context.h

@@ -129,6 +129,7 @@ struct cam_ctx_ioctl_ops {
  * @flush_req:             Flush request to remove request ids
  * @process_evt:           Handle event notification from CRM.(optional)
  * @dump_req:              Dump information for the issue request
+ * @change_state:          Change sub-state of hw context layer to bubble
  *
  */
 struct cam_ctx_crm_ops {
@@ -148,6 +149,8 @@ struct cam_ctx_crm_ops {
 			struct cam_req_mgr_link_evt_data *evt_data);
 	int (*dump_req)(struct cam_context *ctx,
 			struct cam_req_mgr_dump_info *dump);
+	int (*change_state)(struct cam_context *ctx,
+			struct cam_req_mgr_request_change_state *change_state);
 };
 
 
@@ -327,6 +330,18 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx,
 int cam_context_handle_crm_apply_req(struct cam_context *ctx,
 		struct cam_req_mgr_apply_request *apply);
 
+/**
+ * cam_context_handle_crm_state_change()
+ *
+ * @brief:        Handle state change request
+ *
+ * @ctx:          Object pointer for cam_context
+ * @state_info:   State change request command payload
+ *
+ */
+int cam_context_handle_crm_state_change(struct cam_context *ctx,
+		struct cam_req_mgr_request_change_state *state_info);
+
 /**
  * cam_context_handle_crm_notify_frame_skip()
  *

+ 19 - 0
drivers/cam_core/cam_node.c

@@ -619,6 +619,24 @@ static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush)
 	return cam_context_handle_crm_flush_req(ctx, flush);
 }
 
+static int __cam_node_crm_state_change_req(
+	struct cam_req_mgr_request_change_state *state_info)
+{
+	struct cam_context *ctx = NULL;
+
+	if (!state_info)
+		return -EINVAL;
+
+	ctx = (struct cam_context *) cam_get_device_priv(state_info->dev_hdl);
+	if (!ctx) {
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			state_info->dev_hdl);
+		return -EINVAL;
+	}
+
+	return cam_context_handle_crm_state_change(ctx, state_info);
+}
+
 static int __cam_node_crm_process_evt(
 	struct cam_req_mgr_link_evt_data *evt_data)
 {
@@ -715,6 +733,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf,
 	node->crm_node_intf.dump_req = __cam_node_crm_dump_req;
 	node->crm_node_intf.notify_frame_skip =
 		__cam_node_crm_notify_frame_skip;
+	node->crm_node_intf.change_state = __cam_node_crm_state_change_req;
 
 	mutex_init(&node->list_mutex);
 	INIT_LIST_HEAD(&node->free_ctx_list);

+ 1 - 0
drivers/cam_cust/cam_custom_context.c

@@ -549,6 +549,7 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
 	dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW;
 	dev_info->p_delay = 1;
 	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
+	dev_info->sof_ts_cb = NULL;
 
 	return 0;
 }

+ 186 - 16
drivers/cam_isp/cam_isp_context.c

@@ -749,8 +749,8 @@ static void __cam_isp_ctx_send_sof_timestamp(
 	req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta;
 
 	CAM_DBG(CAM_ISP,
-		"request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u",
-		 request_id, ctx_isp->frame_id,
+		"link hdl 0x%x request id:%lld frame number:%lld SOF time stamp:%lld status:%u",
+		ctx_isp->base->link_hdl, request_id, ctx_isp->frame_id,
 		ctx_isp->sof_timestamp_val, sof_event_status);
 
 	if (cam_req_mgr_notify_message(&req_msg,
@@ -1677,6 +1677,7 @@ static int __cam_isp_ctx_reg_upd_in_applied_state(
 	}
 	req = list_first_entry(&ctx->wait_req_list,
 			struct cam_ctx_request, list);
+
 	list_del_init(&req->list);
 
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
@@ -1685,8 +1686,9 @@ static int __cam_isp_ctx_reg_upd_in_applied_state(
 		ctx_isp->active_req_cnt++;
 		request_id = req->request_id;
 		CAM_DBG(CAM_REQ,
-			"move request %lld to active list(cnt = %d), ctx %u",
-			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
+			"move request %lld to active list(cnt = %d), ctx %u link %x",
+			req->request_id, ctx_isp->active_req_cnt,
+			ctx->ctx_id, ctx->link_hdl);
 		__cam_isp_ctx_update_event_record(ctx_isp,
 			CAM_ISP_CTX_EVENT_RUP, req);
 	} else {
@@ -1828,6 +1830,7 @@ notify_only:
 			notify.trigger = CAM_TRIGGER_POINT_SOF;
 			notify.req_id = ctx_isp->req_info.last_bufdone_req_id;
 			notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
+			notify.sof_boottime = ctx_isp->boot_timestamp;
 			notify.trigger_id = ctx_isp->trigger_id;
 
 			ctx->ctx_crm_intf->notify_trigger(&notify);
@@ -1949,8 +1952,9 @@ static int __cam_isp_ctx_sof_in_activated_state(
 	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
 		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, request_id);
 
-	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u",
-		ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id);
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u link %x",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val,
+		ctx->ctx_id, ctx->link_hdl);
 
 	return rc;
 }
@@ -1995,6 +1999,7 @@ end:
 static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 	void *evt_data)
 {
+	bool rc = false;
 	uint64_t request_id = 0;
 	uint32_t sof_event_status = CAM_REQ_MGR_SOF_EVENT_SUCCESS;
 	struct cam_req_mgr_trigger_notify   notify;
@@ -2036,8 +2041,9 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 	req_isp->reapply = true;
 	req_isp->cdm_reset_before_apply = false;
 
-	CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld",
-		ctx->ctx_id, req_isp->bubble_report, req->request_id);
+	CAM_INFO_RATE_LIMIT(CAM_ISP, "ctx:%d link %x  Report Bubble flag %d req id:%lld",
+		ctx->ctx_id, ctx->link_hdl,
+		req_isp->bubble_report, req->request_id);
 	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
 		ctx->ctx_crm_intf->notify_err) {
 		struct cam_req_mgr_error_notify notify;
@@ -2051,12 +2057,25 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 			notify.trigger = CAM_TRIGGER_POINT_SOF;
 		notify.frame_id = ctx_isp->frame_id;
 		notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
+		notify.sof_boottime_val = ctx_isp->boot_timestamp;
+		notify.need_recovery = true;
 		CAM_WARN_RATE_LIMIT(CAM_ISP,
 			"Notify CRM about Bubble req %lld frame %lld, ctx %u",
 			req->request_id, ctx_isp->frame_id, ctx->ctx_id);
 		trace_cam_log_event("Bubble", "Rcvd epoch in applied state",
 			req->request_id, ctx->ctx_id);
-		ctx->ctx_crm_intf->notify_err(&notify);
+		rc = ctx->ctx_crm_intf->notify_err(&notify);
+
+		CAM_DBG(CAM_CRM, "Need bubble recovery %d", rc);
+
+		if (rc) {
+			req_isp->bubble_detected = false;
+			req_isp->reapply = false;
+			CAM_DBG(CAM_ISP, "Disable bubble for ctx %d link %d",
+				ctx->ctx_id, ctx->link_hdl);
+			return 0;
+		}
+
 		atomic_set(&ctx_isp->process_bubble, 1);
 	} else {
 		req_isp->bubble_report = 0;
@@ -2230,6 +2249,7 @@ static int __cam_isp_ctx_buf_done_in_bubble(
 static int __cam_isp_ctx_epoch_in_bubble_applied(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
+	int rc = 0;
 	uint64_t  request_id = 0;
 	struct cam_req_mgr_trigger_notify   notify;
 	struct cam_ctx_request             *req;
@@ -2287,10 +2307,17 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
 			notify.trigger = CAM_TRIGGER_POINT_SOF;
 		notify.frame_id = ctx_isp->frame_id;
 		notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
+		notify.sof_boottime_val = ctx_isp->boot_timestamp;
+		notify.need_recovery = true;
 		CAM_WARN_RATE_LIMIT(CAM_REQ,
 			"Notify CRM about Bubble req_id %llu frame %lld, ctx %u",
 			req->request_id, ctx_isp->frame_id, ctx->ctx_id);
-		ctx->ctx_crm_intf->notify_err(&notify);
+		rc = ctx->ctx_crm_intf->notify_err(&notify);
+		if (rc) {
+			req_isp->bubble_detected = false;
+			req_isp->reapply = false;
+			return 0;
+		}
 		atomic_set(&ctx_isp->process_bubble, 1);
 	} else {
 		req_isp->bubble_report = 0;
@@ -3167,10 +3194,10 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
 		goto end;
 	}
 
-	CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u",
+	CAM_DBG(CAM_REQ, "Apply request %lld in Substate[%s] ctx %u link %x",
 		req->request_id,
 		__cam_isp_ctx_substate_val_to_type(ctx_isp->substate_activated),
-		ctx->ctx_id);
+		ctx->ctx_id, ctx->link_hdl);
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 
 	if (ctx_isp->active_req_cnt >=  2) {
@@ -3253,6 +3280,81 @@ end:
 	return rc;
 }
 
+static int __cam_isp_ctx_change_substate(
+	struct cam_context *ctx,
+	struct cam_req_mgr_request_change_state *state_info)
+{
+	int                        rc = 0;
+	uint64_t                   request_id = 0;
+	struct cam_ctx_request    *req = NULL;
+	struct cam_ctx_request    *req_temp = NULL;
+	struct cam_ctx_request    *bubble_req = NULL;
+	struct cam_isp_ctx_req    *req_isp = NULL;
+	struct cam_isp_context    *ctx_isp =
+				    (struct cam_isp_context *) ctx->ctx_priv;
+
+	if (!list_empty(&ctx->wait_req_list)) {
+		req = list_first_entry(&ctx->wait_req_list,
+			struct cam_ctx_request,
+			list);
+		if (req->request_id == state_info->req_id) {
+			req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+			req_isp->bubble_detected = true;
+			req_isp->reapply = true;
+			bubble_req = req;
+			list_del_init(&req->list);
+			list_add_tail(&req->list, &ctx->active_req_list);
+			goto end;
+		}
+	} else {
+		CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id);
+	}
+
+	if (!bubble_req) {
+		list_for_each_entry_safe(req, req_temp,
+			&ctx->active_req_list, list) {
+			if (req->request_id == state_info->req_id) {
+				req_isp =
+					(struct cam_isp_ctx_req *)req->req_priv;
+				req_isp->bubble_detected = true;
+				req_isp->reapply = true;
+				bubble_req = req;
+				break;
+			}
+		}
+	}
+
+	if (!bubble_req) {
+		CAM_ERR(CAM_ISP, "Req %lld not in active list ctx : %d",
+			state_info->req_id,
+			ctx->ctx_id);
+		goto done;
+	}
+
+end:
+
+	if (req_isp->bubble_report)
+		atomic_set(&ctx_isp->process_bubble, 1);
+
+	if ((req->request_id > ctx_isp->reported_req_id)
+		&& !req_isp->bubble_report) {
+		request_id = req->request_id;
+		ctx_isp->reported_req_id = request_id;
+	}
+
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_ERROR);
+
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
+
+	CAM_DBG(CAM_ISP, "next Substate[%s] ctx : %d",
+		__cam_isp_ctx_substate_val_to_type(
+		ctx_isp->substate_activated), ctx->ctx_id);
+
+done:
+	return rc;
+}
+
 static int __cam_isp_ctx_apply_req_in_sof(
 	struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
 {
@@ -3313,8 +3415,8 @@ static int __cam_isp_ctx_apply_req_in_bubble(
 		ctx_isp->substate_activated));
 	rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
 		CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED);
-	CAM_DBG(CAM_ISP, "new Substate[%s]",
-		__cam_isp_ctx_substate_val_to_type(
+	CAM_DBG(CAM_ISP, "ctx %d link %x new Substate[%s]",
+		ctx->ctx_id, ctx->link_hdl, __cam_isp_ctx_substate_val_to_type(
 		ctx_isp->substate_activated));
 
 	if (rc)
@@ -3704,6 +3806,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 				flush_req);
 
 		ctx_isp->active_req_cnt = 0;
+
 		spin_unlock_bh(&ctx->lock);
 
 		reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
@@ -3753,13 +3856,16 @@ static struct cam_ctx_ops
 			.apply_req = __cam_isp_ctx_apply_req_in_sof,
 			.notify_frame_skip =
 				__cam_isp_ctx_apply_default_req_settings,
+			.change_state = __cam_isp_ctx_change_substate,
 		},
 		.irq_ops = NULL,
 	},
 	/* APPLIED */
 	{
 		.ioctl_ops = {},
-		.crm_ops = {},
+		.crm_ops = {
+			.change_state = __cam_isp_ctx_change_substate,
+		},
 		.irq_ops = NULL,
 	},
 	/* EPOCH */
@@ -3769,6 +3875,7 @@ static struct cam_ctx_ops
 			.apply_req = __cam_isp_ctx_apply_req_in_epoch,
 			.notify_frame_skip =
 				__cam_isp_ctx_apply_default_req_settings,
+			.change_state = __cam_isp_ctx_change_substate,
 		},
 		.irq_ops = NULL,
 	},
@@ -3779,13 +3886,16 @@ static struct cam_ctx_ops
 			.apply_req = __cam_isp_ctx_apply_req_in_bubble,
 			.notify_frame_skip =
 				__cam_isp_ctx_apply_default_req_settings,
+			.change_state = __cam_isp_ctx_change_substate,
 		},
 		.irq_ops = NULL,
 	},
 	/* Bubble Applied */
 	{
 		.ioctl_ops = {},
-		.crm_ops = {},
+		.crm_ops = {
+			.change_state = __cam_isp_ctx_change_substate,
+		},
 		.irq_ops = NULL,
 	},
 	/* HW ERROR */
@@ -5506,6 +5616,33 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx,
 	return rc;
 }
 
+static int __cam_isp_ctx_get_isp_info(int32_t dev_hdl, void *data)
+{
+	int rc = 0;
+	struct cam_context               *ctx;
+	struct cam_req_mgr_dev_info      *isp_dev = data;
+	struct cam_isp_context           *isp_ctx = NULL;
+
+	ctx = (struct cam_context *)cam_get_device_priv(dev_hdl);
+
+	isp_ctx = (struct cam_isp_context *)ctx->ctx_priv;
+
+	isp_dev->state = isp_ctx->substate_activated;
+	isp_dev->timestamp = isp_ctx->sof_timestamp_val;
+	isp_dev->boot_time = isp_ctx->boot_timestamp;
+	isp_dev->frame_id = isp_ctx->frame_id;
+
+	if ((isp_ctx->substate_activated ==
+		CAM_ISP_CTX_ACTIVATED_APPLIED) ||
+		(isp_ctx->substate_activated ==
+		CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED))
+		isp_dev->is_applied = true;
+	else
+		isp_dev->is_applied = false;
+
+	return rc;
+}
+
 static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
 	struct cam_req_mgr_device_info *dev_info)
 {
@@ -5517,6 +5654,7 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
 	dev_info->p_delay = 1;
 	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
 	dev_info->trigger_on = true;
+	dev_info->sof_ts_cb = &__cam_isp_ctx_get_isp_info;
 
 	return rc;
 }
@@ -5574,6 +5712,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
 	atomic_set(&ctx_isp->process_bubble, 0);
 	atomic_set(&ctx_isp->rxd_epoch, 0);
 	ctx_isp->frame_id = 0;
+	ctx_isp->sof_timestamp_val = 0;
+	ctx_isp->boot_timestamp = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
 	ctx_isp->bubble_frame_cnt = 0;
@@ -5923,6 +6063,33 @@ static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx,
 	return rc;
 }
 
+static int __cam_isp_ctx_change_state_req(struct cam_context *ctx,
+	struct cam_req_mgr_request_change_state *state_info)
+{
+	int rc = 0;
+	struct cam_ctx_ops *ctx_ops = NULL;
+	struct cam_isp_context *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	CAM_DBG(CAM_ISP, "Enter: changes state ctx id %d link 0x%x",
+		ctx->ctx_id, ctx->link_hdl);
+	ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated];
+	if (ctx_ops->crm_ops.change_state) {
+		rc = ctx_ops->crm_ops.change_state(ctx, state_info);
+	} else {
+		CAM_WARN_RATE_LIMIT(CAM_ISP,
+		"No handle function in activated Substate[%s]",
+			__cam_isp_ctx_substate_val_to_type(
+			ctx_isp->substate_activated));
+		rc = -EFAULT;
+	}
+
+	if (rc)
+		CAM_WARN_RATE_LIMIT(CAM_ISP,
+			"changes state failed");
+	return rc;
+}
+
 static int __cam_isp_ctx_apply_req(struct cam_context *ctx,
 	struct cam_req_mgr_apply_request *apply)
 {
@@ -6109,6 +6276,7 @@ static struct cam_ctx_ops
 			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
 			.process_evt = __cam_isp_ctx_process_evt,
 			.dump_req = __cam_isp_ctx_dump_in_top_state,
+			.change_state = __cam_isp_ctx_change_state_req,
 		},
 		.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
 		.pagefault_ops = cam_isp_context_dump_requests,
@@ -6305,6 +6473,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
 
 	ctx->base = ctx_base;
 	ctx->frame_id = 0;
+	ctx->sof_timestamp_val = 0;
+	ctx->boot_timestamp = 0;
 	ctx->custom_enabled = false;
 	ctx->use_frame_header_ts = false;
 	ctx->use_default_apply = false;

+ 6 - 4
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h

@@ -284,15 +284,17 @@ enum cam_isp_ctx_type {
  * @ctx_type:              RDI_ONLY, PIX and RDI, or FS2
  * @packet_op_code:        Packet opcode
  * @last_cdm_done:         Last cdm done request
+ * @cam_isp_hw_sof_event_data  sof event timestamp
  */
 struct cam_isp_hw_cmd_args {
 	uint32_t                          cmd_type;
 	void                             *cmd_data;
 	union {
-		uint32_t                      sof_irq_enable;
-		uint32_t                      ctx_type;
-		uint32_t                      packet_op_code;
-		uint64_t                      last_cdm_done;
+		uint32_t                          sof_irq_enable;
+		uint32_t                          ctx_type;
+		uint32_t                          packet_op_code;
+		uint64_t                          last_cdm_done;
+		struct cam_isp_hw_sof_event_data  sof_done_event_data;
 	} u;
 };
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 282 - 538
drivers/cam_req_mgr/cam_req_mgr_core.c


+ 47 - 8
drivers/cam_req_mgr/cam_req_mgr_core.h

@@ -263,7 +263,8 @@ struct cam_req_mgr_req_tbl {
  * - members updated due to external events
  * @recover            : if user enabled recovery for this request.
  * @req_id             : mask tracking which all devices have request ready
- * @sync_mode          : Sync mode in which req id in this slot has to applied
+ * @sync_mode          : Modified sync mode in which req id in this slot has to applied
+ * @real_sync_mode     : Actual sync mode in which req id in this slot has to applied
  * @additional_timeout : Adjusted watchdog timeout value associated with
  * this request
  */
@@ -274,6 +275,7 @@ struct cam_req_mgr_slot {
 	int32_t               recover;
 	int64_t               req_id;
 	int32_t               sync_mode;
+	int32_t               real_sync_mode;
 	int32_t               additional_timeout;
 };
 
@@ -356,7 +358,7 @@ struct cam_req_mgr_connected_device {
  * @lock                 : mutex lock to guard link data operations
  * @link_state_spin_lock : spin lock to protect link state variable
  * @sync_link            : array of pointer to the sync link for synchronization
- * @num_sync_links       : num of links sync associated with this link
+ * @num_sync_link        : total number of sync links
  * @sync_link_sof_skip   : flag determines if a pkt is not available for a given
  *                         frame in a particular link skip corresponding
  *                         frame in sync link as well.
@@ -366,11 +368,14 @@ struct cam_req_mgr_connected_device {
  * @is_used              : 1 if link is in use else 0
  * @is_master            : Based on pd among links, the link with the highest pd
  *                         is assigned as master
- * @initial_skip         : Flag to determine if slave has started streaming in
- *                         master-slave sync
+ * @initial_skip         : Flag to determine if initial req need to skip for
+ *                         diff pd
+ * @is_sync_req          : flag used for deciding sync and non-sync
  * @in_msync_mode        : Flag to determine if a link is in master-slave mode
  * @initial_sync_req     : The initial req which is required to sync with the
  *                         other link
+ * @modified_init_sync_req : Modified initial req which is required to sync
+ *                          with the other link
  * @retry_cnt            : Counter that tracks number of attempts to apply
  *                         the same req
  * @is_shutdown          : Flag to indicate if link needs to be disconnected
@@ -385,6 +390,10 @@ struct cam_req_mgr_connected_device {
  *                         case of long exposure use case
  * @last_sof_trigger_jiffies : Record the jiffies of last sof trigger jiffies
  * @wq_congestion        : Indicates if WQ congestion is detected or not
+ * @activate_seq         : sequence in which link is activated
+ * @frame_id             : current frame id
+ * @sync_frame_id        : current frame id of sync link
+ * @bubble_skip          : req to skip on bubble
  */
 struct cam_req_mgr_core_link {
 	int32_t                              link_hdl;
@@ -401,19 +410,22 @@ struct cam_req_mgr_core_link {
 	void                                *parent;
 	struct mutex                         lock;
 	spinlock_t                           link_state_spin_lock;
-	struct cam_req_mgr_core_link
-			*sync_link[MAXIMUM_LINKS_PER_SESSION - 1];
-	int32_t                              num_sync_links;
+	struct cam_req_mgr_core_link        *sync_link[
+						MAXIMUM_LINKS_PER_SESSION];
+	int32_t                              num_sync_link;
 	bool                                 sync_link_sof_skip;
 	uint32_t                             open_req_cnt;
 	uint32_t                             last_flush_id;
 	atomic_t                             is_used;
 	bool                                 is_master;
-	bool                                 initial_skip;
+	uint32_t                             initial_skip;
+	bool                                 is_sync_req;
 	bool                                 in_msync_mode;
 	int64_t                              initial_sync_req;
+	int64_t                              modified_init_sync_req;
 	uint32_t                             retry_cnt;
 	bool                                 is_shutdown;
+	uint64_t                             sof_boottime;
 	uint64_t                             sof_timestamp;
 	uint64_t                             prev_sof_timestamp;
 	bool                                 dual_trigger;
@@ -422,6 +434,11 @@ struct cam_req_mgr_core_link {
 	bool                                 skip_init_frame;
 	uint64_t                             last_sof_trigger_jiffies;
 	bool                                 wq_congestion;
+	int32_t                              activate_seq;
+	uint64_t                             frame_id;
+	uint64_t                             sync_frame_id;
+	int32_t                              bubble_skip;
+	bool                                 skip_sync_apply;
 };
 
 /**
@@ -455,11 +472,33 @@ struct cam_req_mgr_core_session {
  * @session_head : list head holding sessions
  * @crm_lock     : mutex lock to protect session creation & destruction
  * @recovery_on_apply_fail : Recovery on apply failure using debugfs.
+ * @bitmap       : bitmap to store index of link
+ * @max_delay    : max pipeline delay in a session
  */
 struct cam_req_mgr_core_device {
 	struct list_head             session_head;
 	struct mutex                 crm_lock;
 	bool                         recovery_on_apply_fail;
+	DECLARE_BITMAP(bitmap, MAXIMUM_LINKS_PER_SESSION);
+	uint32_t                     max_delay;
+};
+
+/**
+ * struct cam_req_mgr_dump_link_data
+ * - Dump data
+ * @m_link          : master link handle
+ * @s_link          : slave link handle
+ * @m_req_id        : master req id
+ * @s_req_id        : slave req id
+ * @dev_info        : current timing data of slave link
+ *
+ */
+struct cam_req_mgr_dump_link_data {
+	struct cam_req_mgr_core_link      *m_link;
+	struct cam_req_mgr_core_link      *s_link;
+	uint64_t                           m_req_id;
+	uint64_t                           s_req_id;
+	struct cam_req_mgr_dev_info        dev_data;
 };
 
 /**

+ 57 - 9
drivers/cam_req_mgr/cam_req_mgr_interface.h

@@ -22,6 +22,7 @@ struct cam_req_mgr_apply_request;
 struct cam_req_mgr_flush_request;
 struct cam_req_mgr_link_evt_data;
 struct cam_req_mgr_dump_info;
+struct cam_req_mgr_request_change_state;
 
 /* Request Manager -- camera device driver interface */
 /**
@@ -33,8 +34,9 @@ struct cam_req_mgr_dump_info;
  *                              userspace
  * @cam_req_mgr_notify_timer  : start the timer
  */
-typedef int (*cam_req_mgr_notify_trigger)(struct cam_req_mgr_trigger_notify *);
-typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *);
+typedef int (*cam_req_mgr_notify_trigger)(
+	struct cam_req_mgr_trigger_notify *);
+typedef bool (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *);
 typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *);
 typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *);
 typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *);
@@ -48,8 +50,9 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *);
  * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for
  *                                 frame skip
  * @cam_req_mgr_flush_req        : Flush or cancel request
- * cam_req_mgr_process_evt       : generic events
+ * @cam_req_mgr_process_evt      : generic events
  * @cam_req_mgr_dump_req         : dump request
+ * @cam_req_mgr_change_state     : CRM asks device to change its state
  */
 typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *);
 typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *);
@@ -59,6 +62,8 @@ typedef int (*cam_req_mgr_notify_frame_skip)(
 typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *);
 typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *);
 typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *);
+typedef int (*cam_req_mgr_change_state)(
+	struct cam_req_mgr_request_change_state *);
 
 /**
  * @brief          : cam_req_mgr_crm_cb - func table
@@ -87,15 +92,17 @@ struct cam_req_mgr_crm_cb {
  * @flush_req        : payload to flush request
  * @process_evt      : payload to generic event
  * @dump_req         : payload to dump request
+ * @change_state     : payload to change state
  */
 struct cam_req_mgr_kmd_ops {
-	cam_req_mgr_get_dev_info      get_dev_info;
-	cam_req_mgr_link_setup        link_setup;
-	cam_req_mgr_apply_req         apply_req;
+	cam_req_mgr_get_dev_info     get_dev_info;
+	cam_req_mgr_link_setup       link_setup;
+	cam_req_mgr_apply_req        apply_req;
 	cam_req_mgr_notify_frame_skip notify_frame_skip;
-	cam_req_mgr_flush_req         flush_req;
-	cam_req_mgr_process_evt       process_evt;
-	cam_req_mgr_dump_req          dump_req;
+	cam_req_mgr_flush_req        flush_req;
+	cam_req_mgr_process_evt      process_evt;
+	cam_req_mgr_dump_req         dump_req;
+	cam_req_mgr_change_state     change_state;
 };
 
 /**
@@ -216,6 +223,7 @@ enum cam_req_mgr_link_evt_type {
  * @trigger  : trigger point of this notification, CRM will send apply
  *             only to the devices which subscribe to this point.
  * @sof_timestamp_val: Captured time stamp value at sof hw event
+ * @sof_boottime : Captured boot time stamp value at sof hw event
  * @req_id   : req id which returned buf_done
  * @trigger_id: ID to differentiate between the trigger devices
  */
@@ -225,6 +233,7 @@ struct cam_req_mgr_trigger_notify {
 	int64_t  frame_id;
 	uint32_t trigger;
 	uint64_t sof_timestamp_val;
+	uint64_t sof_boottime;
 	uint64_t req_id;
 	int32_t  trigger_id;
 };
@@ -249,6 +258,8 @@ struct cam_req_mgr_timer_notify {
  * @frame_id : frame id for internal tracking
  * @trigger  : trigger point of this notification, CRM will send apply
  * @sof_timestamp_val : Captured time stamp value at sof hw event
+ * @sof_boottime_val  : Captured boottime stamp value at sof hw event
+ * @need_recovery     : flag to check if recovery is needed
  * @error    : what error device hit while processing this req
  */
 struct cam_req_mgr_error_notify {
@@ -258,6 +269,8 @@ struct cam_req_mgr_error_notify {
 	int64_t  frame_id;
 	uint32_t trigger;
 	uint64_t sof_timestamp_val;
+	uint64_t sof_boottime_val;
+	bool     need_recovery;
 	enum cam_req_mgr_device_error error;
 };
 
@@ -302,6 +315,7 @@ struct cam_req_mgr_notify_stop {
  * @p_delay : delay between time settings applied and take effect
  * @trigger : Trigger point for the client
  * @trigger_on : This device provides trigger
+ * @sof_ts_cb  : callback to real time drivers
  */
 struct cam_req_mgr_device_info {
 	int32_t                     dev_hdl;
@@ -310,6 +324,7 @@ struct cam_req_mgr_device_info {
 	enum cam_pipeline_delay     p_delay;
 	uint32_t                    trigger;
 	bool                        trigger_on;
+	int32_t                     (*sof_ts_cb)(int32_t dev_hdl, void *data);
 };
 
 /**
@@ -408,4 +423,37 @@ struct cam_req_mgr_dump_info {
 	int32_t     link_hdl;
 	int32_t     dev_hdl;
 };
+
+/**
+ * struct cam_req_mgr_dev_info
+ * @link_hdl    : link identifier
+ * @state       : Current substate for the activated state.
+ * @timestamp   : time stamp for the sof event
+ * @boot_time   : boot time stamp for the sof event
+ * @frame_id    : frame id
+ * @is_applied  : if ISP is in applied state
+ *
+ */
+struct cam_req_mgr_dev_info {
+	int32_t     link_hdl;
+	uint32_t    state;
+	uint64_t    timestamp;
+	uint64_t    boot_time;
+	uint64_t    frame_id;
+	bool        is_applied;
+};
+
+/**
+ * struct cam_req_mgr_request_change_state
+ * @link_hdl    : link identifier
+ * @dev_hdl     : device handle or identifier
+ * @req_id      : request id
+ *
+ */
+struct cam_req_mgr_request_change_state {
+	int32_t    link_hdl;
+	int32_t    dev_hdl;
+	uint64_t   req_id;
+};
+
 #endif

+ 1 - 0
drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c

@@ -410,6 +410,7 @@ int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info)
 	strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name));
 	info->p_delay = 1;
 	info->trigger = CAM_TRIGGER_POINT_SOF;
+	info->sof_ts_cb = NULL;
 
 	return 0;
 }

+ 2 - 0
drivers/cam_sensor_module/cam_flash/cam_flash_core.c

@@ -1784,6 +1784,8 @@ int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info)
 	strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name));
 	info->p_delay = CAM_FLASH_PIPELINE_DELAY;
 	info->trigger = CAM_TRIGGER_POINT_SOF;
+	info->sof_ts_cb = NULL;
+
 	return 0;
 }
 

+ 1 - 0
drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c

@@ -1216,6 +1216,7 @@ int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info)
 	else
 		info->p_delay = 2;
 	info->trigger = CAM_TRIGGER_POINT_SOF;
+	info->sof_ts_cb = NULL;
 
 	return rc;
 }

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio