Explorar o código

msm: camera: common: Multiple fixes for crm redesign

This change help to resolve below issues :-
1. Update frame duration calculation
   Add frame duration calculation with the use of fps. In some cases
   where horizonal blanking is more, frame duration calculation based
   on sof epoch calculation is not accurate.
2. Corner case in bubble handling
   Add support to handle master link bubble even if ISP linked with
   slave link receive few buf done irq for bubble request before master
   sends slave link to bubble state.

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

+ 27 - 0
drivers/cam_core/cam_context.c

@@ -182,6 +182,33 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
 	return rc;
 }
 
+int cam_context_handle_crm_signal_buf_done(struct cam_context *ctx,
+	struct cam_req_mgr_signal_info *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.signal_buf_done) {
+		rc = ctx->state_machine[ctx->state].crm_ops.signal_buf_done(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_state_change(struct cam_context *ctx,
 	struct cam_req_mgr_request_change_state *state_info)
 {

+ 15 - 0
drivers/cam_core/cam_context.h

@@ -130,6 +130,7 @@ struct cam_ctx_ioctl_ops {
  * @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
+ * @signal_buf_done        Notify device to signal buf done
  *
  */
 struct cam_ctx_crm_ops {
@@ -151,6 +152,8 @@ struct cam_ctx_crm_ops {
 			struct cam_req_mgr_dump_info *dump);
 	int (*change_state)(struct cam_context *ctx,
 			struct cam_req_mgr_request_change_state *change_state);
+	int (*signal_buf_done)(struct cam_context *ctx,
+			struct cam_req_mgr_signal_info *signal_info);
 };
 
 
@@ -342,6 +345,18 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
 int cam_context_handle_crm_state_change(struct cam_context *ctx,
 		struct cam_req_mgr_request_change_state *state_info);
 
+/**
+ * cam_context_handle_crm_signal_buf_done()
+ *
+ * @brief:         Handle signal buf done command
+ *
+ * @ctx:           Object pointer for cam_context
+ * @signal_info    Signal buf done request command payload
+ *
+ */
+int cam_context_handle_crm_signal_buf_done(struct cam_context *ctx,
+	struct cam_req_mgr_signal_info *signal_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_req_mgr_signal_buf_done(
+	struct cam_req_mgr_signal_info *signal_buf_done_info)
+{
+	struct cam_context *ctx = NULL;
+
+	if (!signal_buf_done_info)
+		return -EINVAL;
+
+	ctx = (struct cam_context *) cam_get_device_priv(signal_buf_done_info->dev_hdl);
+	if (!ctx) {
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			signal_buf_done_info->dev_hdl);
+		return -EINVAL;
+	}
+
+	return cam_context_handle_crm_signal_buf_done(ctx, signal_buf_done_info);
+}
+
 static int __cam_node_crm_state_change_req(
 	struct cam_req_mgr_request_change_state *state_info)
 {
@@ -734,6 +752,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf,
 	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;
+	node->crm_node_intf.signal_buf_done = __cam_req_mgr_signal_buf_done;
 
 	mutex_init(&node->list_mutex);
 	INIT_LIST_HEAD(&node->free_ctx_list);

+ 242 - 41
drivers/cam_isp/cam_isp_context.c

@@ -98,6 +98,87 @@ static void __cam_isp_ctx_update_event_record(
 	ctx_isp->event_record[event][iterator].timestamp  = cur_time;
 }
 
+static int cam_isp_ctx_sync_signal_on_buf_done_ready(
+	struct cam_context *ctx,
+	struct cam_ctx_request *req,
+	uint32_t status, uint32_t event_cause)
+{
+	struct cam_isp_ctx_req  *req_isp;
+	int k = 0, rc = 0;
+
+	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+
+	if (!req_isp->buf_done_mask)
+		return rc;
+
+	for (k = 0; k < req_isp->num_fence_map_out; k++) {
+		if (req_isp->buf_done_mask & (1 << k)) {
+			rc = cam_sync_signal(req_isp->fence_map_out[k].sync_id,
+				status, event_cause);
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"ctx[%d] : Sync signal for Req %llu, sync_id %d status=%d failed with rc = %d",
+					ctx->ctx_id, req->request_id,
+					req_isp->fence_map_out[k].sync_id,
+					status, rc);
+				return rc;
+			} else {
+				CAM_DBG(CAM_ISP,
+					"ctx[%d] : Sync signal success for Req %llu, sync_id %d status=%d",
+					ctx->ctx_id, req->request_id,
+					req_isp->fence_map_out[k].sync_id, status);
+				req_isp->fence_map_out[k].sync_id = -1;
+			}
+		}
+	}
+	req_isp->buf_done_mask = 0;
+
+	return rc;
+}
+
+static int cam_isp_ctx_handle_sync_signal(
+	struct cam_context *ctx,
+	struct cam_ctx_request *req, int32_t sync_index,
+	uint32_t status, uint32_t event_cause)
+{
+	struct cam_isp_ctx_req  *req_isp;
+	int32_t buf_done_ready = 0;
+	int rc = 0;
+
+	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+	buf_done_ready = atomic_read(&req_isp->buf_done_ready);
+
+	if (buf_done_ready != INIT_BUF_DONE) {
+		rc = cam_isp_ctx_sync_signal_on_buf_done_ready(
+			ctx, req, status, event_cause);
+		if (rc) {
+			CAM_DBG(CAM_ISP,
+				"Sync failed with rc = %d", rc);
+			return rc;
+		}
+		rc = cam_sync_signal(req_isp->fence_map_out[sync_index].sync_id,
+			status,
+			event_cause);
+		if (rc) {
+			CAM_DBG(CAM_ISP,
+				"ctx[%d] :Sync failed Req %llu, sync_id %d status %d with rc = %d",
+				ctx->ctx_id, req->request_id,
+				req_isp->fence_map_out[sync_index].sync_id,
+				status, rc);
+			return rc;
+		}
+		CAM_DBG(CAM_ISP,
+			"ctx[%d] : Sync signal success for Req %llu, sync_id %d status %d",
+			ctx->ctx_id, req->request_id,
+			req_isp->fence_map_out[sync_index].sync_id,
+			status);
+		req_isp->fence_map_out[sync_index].sync_id = -1;
+	} else {
+		req_isp->buf_done_mask |= 1 << sync_index;
+	}
+	return rc;
+}
+
 static int __cam_isp_ctx_dump_event_record(
 	struct cam_isp_context *ctx_isp,
 	uintptr_t               cpu_addr,
@@ -836,6 +917,7 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list(
 		atomic_set(&ctx_isp->process_bubble, 0);
 		req_isp->cdm_reset_before_apply = false;
 		ctx_isp->bubble_frame_cnt = 0;
+		atomic_set(&req_isp->buf_done_ready, 0);
 
 		if (buf_done_req_id <= ctx->last_flush_req) {
 			for (i = 0; i < req_isp->num_fence_map_out; i++)
@@ -866,6 +948,11 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list(
 					CAM_REQ_MGR_SOF_EVENT_SUCCESS);
 			}
 		}
+
+		rc = cam_isp_ctx_sync_signal_on_buf_done_ready(
+			ctx, req, CAM_SYNC_STATE_SIGNALED_SUCCESS,
+			CAM_SYNC_COMMON_EVENT_SUCCESS);
+
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->free_req_list);
 		req_isp->reapply = false;
@@ -961,19 +1048,29 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
 		}
 
 		if (!req_isp->bubble_detected) {
-			CAM_DBG(CAM_ISP,
-				"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
-				req->request_id,
-				req_isp->fence_map_out[j].resource_handle,
-				req_isp->fence_map_out[j].sync_id,
-				ctx->ctx_id);
-
-			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
-				CAM_SYNC_STATE_SIGNALED_SUCCESS,
-				CAM_SYNC_COMMON_EVENT_SUCCESS);
-			if (rc)
-				CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
-					 rc);
+			if (req_isp->is_sync_mode) {
+				CAM_DBG(CAM_ISP,
+					"Hold sync signal: req %lld res 0x%x fd 0x%x, ctx %u",
+					req->request_id,
+					req_isp->fence_map_out[j].resource_handle,
+					req_isp->fence_map_out[j].sync_id,
+					ctx->ctx_id);
+				rc = cam_isp_ctx_handle_sync_signal(ctx, req, j,
+					CAM_SYNC_STATE_SIGNALED_SUCCESS,
+					CAM_SYNC_COMMON_EVENT_SUCCESS);
+			} else {
+				CAM_DBG(CAM_ISP,
+					"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
+					req->request_id,
+					req_isp->fence_map_out[j].resource_handle,
+					req_isp->fence_map_out[j].sync_id,
+					ctx->ctx_id);
+				rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+					CAM_SYNC_STATE_SIGNALED_SUCCESS,
+					CAM_SYNC_COMMON_EVENT_SUCCESS);
+				if (rc)
+					CAM_DBG(CAM_ISP, "Sync failed with rc = %d", rc);
+			}
 		} else if (!req_isp->bubble_report) {
 			CAM_DBG(CAM_ISP,
 				"Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u",
@@ -1075,18 +1172,21 @@ static int __cam_isp_handle_deferred_buf_done(
 				"ctx[%d] : Req %llu, status=%d res=0x%x should never happen",
 				ctx->ctx_id, req->request_id, status,
 				req_isp->fence_map_out[j].resource_handle);
-
-			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
-				status, event_cause);
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"ctx[%d] : Sync signal for Req %llu, sync_id %d status=%d failed with rc = %d",
-					ctx->ctx_id, req->request_id,
-					req_isp->fence_map_out[j].sync_id,
-					status, rc);
+			if (req_isp->is_sync_mode) {
+				rc = cam_isp_ctx_handle_sync_signal(
+					ctx, req, j, status, event_cause);
 			} else {
-				req_isp->num_acked++;
-				req_isp->fence_map_out[j].sync_id = -1;
+				rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+					status, event_cause);
+				if (rc) {
+					CAM_ERR(CAM_ISP,
+						"ctx[%d] : Sync signal for Req %llu, sync_id %d status=%d failed with rc = %d",
+						ctx->ctx_id, req->request_id,
+						req_isp->fence_map_out[j].sync_id,
+						status, rc);
+				} else {
+					req_isp->num_acked++;
+				}
 			}
 		} else {
 			req_isp->num_acked++;
@@ -1190,16 +1290,27 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
 				req_isp->fence_map_out[j].sync_id);
 			continue;
 		} else if (!req_isp->bubble_detected) {
-			CAM_DBG(CAM_ISP,
-				"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
-				req->request_id,
-				req_isp->fence_map_out[j].resource_handle,
-				req_isp->fence_map_out[j].sync_id,
-				ctx->ctx_id);
-
-			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
-				CAM_SYNC_STATE_SIGNALED_SUCCESS,
-				CAM_SYNC_COMMON_EVENT_SUCCESS);
+			if (req_isp->is_sync_mode) {
+				CAM_DBG(CAM_ISP,
+					"Hold sync signal: req %lld res 0x%x fd 0x%x, ctx %u",
+					req->request_id,
+					req_isp->fence_map_out[j].resource_handle,
+					req_isp->fence_map_out[j].sync_id,
+					ctx->ctx_id);
+				rc = cam_isp_ctx_handle_sync_signal(ctx, req, j,
+					CAM_SYNC_STATE_SIGNALED_SUCCESS,
+					CAM_SYNC_COMMON_EVENT_SUCCESS);
+			} else {
+				CAM_DBG(CAM_ISP,
+					"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
+					req->request_id,
+					req_isp->fence_map_out[j].resource_handle,
+					req_isp->fence_map_out[j].sync_id,
+					ctx->ctx_id);
+				rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+					CAM_SYNC_STATE_SIGNALED_SUCCESS,
+					CAM_SYNC_COMMON_EVENT_SUCCESS);
+			}
 			if (rc) {
 				CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
 					 rc);
@@ -1258,7 +1369,6 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
 			req_isp->fence_map_out[j].sync_id, ctx->ctx_id);
 		if (!rc) {
 			req_isp->num_acked++;
-			req_isp->fence_map_out[j].sync_id = -1;
 		}
 
 		if ((ctx_isp->use_frame_header_ts) &&
@@ -1666,10 +1776,11 @@ static int __cam_isp_ctx_reg_upd_in_applied_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
 	int rc = 0;
-	struct cam_ctx_request  *req;
-	struct cam_context      *ctx = ctx_isp->base;
-	struct cam_isp_ctx_req  *req_isp;
-	uint64_t                 request_id = 0;
+	struct cam_ctx_request         *req;
+	struct cam_context             *ctx = ctx_isp->base;
+	struct cam_isp_ctx_req         *req_isp;
+	uint64_t                        request_id = 0;
+	struct cam_req_mgr_notify_rup   notify_rup_info;
 
 	if (list_empty(&ctx->wait_req_list)) {
 		CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
@@ -1684,10 +1795,20 @@ static int __cam_isp_ctx_reg_upd_in_applied_state(
 	if (req_isp->num_fence_map_out != 0) {
 		list_add_tail(&req->list, &ctx->active_req_list);
 		ctx_isp->active_req_cnt++;
-		request_id = req->request_id;
+
+		if (req_isp->is_sync_mode) {
+			request_id = req->request_id;
+			notify_rup_info.link_hdl = ctx->link_hdl;
+			notify_rup_info.req_id = request_id;
+			ctx->ctx_crm_intf->notify_rup(&notify_rup_info);
+			atomic_set(&req_isp->buf_done_ready, notify_rup_info.state);
+		}
+
 		CAM_DBG(CAM_REQ,
-			"move request %lld to active list(cnt = %d), ctx %u link %x",
+			"move request %lld to active list(cnt = %d), state %d sync mode %d ctx %u link %x",
 			req->request_id, ctx_isp->active_req_cnt,
+			notify_rup_info.state,
+			req_isp->is_sync_mode,
 			ctx->ctx_id, ctx->link_hdl);
 		__cam_isp_ctx_update_event_record(ctx_isp,
 			CAM_ISP_CTX_EVENT_RUP, req);
@@ -1823,6 +1944,7 @@ notify_only:
 	 */
 	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
 		ctx_isp->active_req_cnt <= 2) {
+
 		if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
 			notify.link_hdl = ctx->link_hdl;
 			notify.dev_hdl = ctx->dev_hdl;
@@ -1833,6 +1955,15 @@ notify_only:
 			notify.sof_boottime = ctx_isp->boot_timestamp;
 			notify.trigger_id = ctx_isp->trigger_id;
 
+			if (!list_empty(&ctx->active_req_list)) {
+				req = list_first_entry(&ctx->active_req_list,
+					struct cam_ctx_request, list);
+				req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+				notify.fps = req_isp->hw_update_data.fps;
+			} else {
+				notify.fps = 0;
+			}
+
 			ctx->ctx_crm_intf->notify_trigger(&notify);
 			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld ctx %u",
 				ctx_isp->frame_id, ctx->ctx_id);
@@ -2071,6 +2202,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 		if (rc) {
 			req_isp->bubble_detected = false;
 			req_isp->reapply = false;
+			ctx_isp->substate_activated =
+				CAM_ISP_CTX_ACTIVATED_APPLIED;
 			CAM_DBG(CAM_ISP, "Disable bubble for ctx %d link %d",
 				ctx->ctx_id, ctx->link_hdl);
 			return 0;
@@ -3229,6 +3362,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
 		goto end;
 	}
 	req_isp->bubble_report = apply->report_if_bubble;
+	req_isp->is_sync_mode = apply->is_sync_mode;
 
 	cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
 	cfg.request_id = req->request_id;
@@ -3280,6 +3414,40 @@ end:
 	return rc;
 }
 
+static int __cam_isp_ctx_signal_buf_done(
+	struct cam_context *ctx,
+	struct cam_req_mgr_signal_info *signal_buf_done)
+{
+	struct cam_ctx_request    *req = NULL;
+	struct cam_isp_ctx_req    *req_isp = NULL;
+
+	if (!list_empty(&ctx->wait_req_list)) {
+		req = list_first_entry(&ctx->wait_req_list,
+			struct cam_ctx_request,
+			list);
+		if (req->request_id == signal_buf_done->req_id) {
+			req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+			atomic_set(&req_isp->buf_done_ready, signal_buf_done->state);
+			goto end;
+		}
+	}
+
+	if (!list_empty(&ctx->active_req_list)) {
+		req = list_first_entry(&ctx->active_req_list,
+			struct cam_ctx_request,
+			list);
+		if (req->request_id == signal_buf_done->req_id) {
+			req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+			atomic_set(&req_isp->buf_done_ready, signal_buf_done->state);
+			goto end;
+		}
+	}
+
+	CAM_WARN(CAM_ISP, "Request %lld not found", signal_buf_done->req_id);
+end:
+	return 0;
+}
+
 static int __cam_isp_ctx_change_substate(
 	struct cam_context *ctx,
 	struct cam_req_mgr_request_change_state *state_info)
@@ -3865,6 +4033,7 @@ static struct cam_ctx_ops
 		.ioctl_ops = {},
 		.crm_ops = {
 			.change_state = __cam_isp_ctx_change_substate,
+			.signal_buf_done = __cam_isp_ctx_signal_buf_done,
 		},
 		.irq_ops = NULL,
 	},
@@ -3876,6 +4045,7 @@ static struct cam_ctx_ops
 			.notify_frame_skip =
 				__cam_isp_ctx_apply_default_req_settings,
 			.change_state = __cam_isp_ctx_change_substate,
+			.signal_buf_done = __cam_isp_ctx_signal_buf_done,
 		},
 		.irq_ops = NULL,
 	},
@@ -3895,6 +4065,7 @@ static struct cam_ctx_ops
 		.ioctl_ops = {},
 		.crm_ops = {
 			.change_state = __cam_isp_ctx_change_substate,
+			.signal_buf_done = __cam_isp_ctx_signal_buf_done,
 		},
 		.irq_ops = NULL,
 	},
@@ -4789,6 +4960,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
 	cfg.pf_data = &(req->pf_data);
 	cfg.num_out_map_entries = 0;
 	cfg.num_in_map_entries = 0;
+	req_isp->hw_update_data.fps = -1;
 
 	CAM_DBG(CAM_ISP, "try to prepare config packet......");
 
@@ -4808,6 +4980,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
 	req_isp->bubble_detected = false;
 	req_isp->cdm_reset_before_apply = false;
 	req_isp->hw_update_data.packet = packet;
+	atomic_set(&req_isp->buf_done_ready, INIT_BUF_DONE);
 
 	for (i = 0; i < req_isp->num_fence_map_out; i++) {
 		rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id);
@@ -6063,6 +6236,33 @@ static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx,
 	return rc;
 }
 
+static int __cam_isp_ctx_signal_buf_done_req(struct cam_context *ctx,
+	struct cam_req_mgr_signal_info *signal_buf_done)
+{
+	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: signal buf done 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.signal_buf_done) {
+		rc = ctx_ops->crm_ops.signal_buf_done(ctx, signal_buf_done);
+	} 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,
+			"signal buf done failed");
+	return rc;
+}
+
 static int __cam_isp_ctx_change_state_req(struct cam_context *ctx,
 	struct cam_req_mgr_request_change_state *state_info)
 {
@@ -6277,6 +6477,7 @@ static struct cam_ctx_ops
 			.process_evt = __cam_isp_ctx_process_evt,
 			.dump_req = __cam_isp_ctx_dump_in_top_state,
 			.change_state = __cam_isp_ctx_change_state_req,
+			.signal_buf_done = __cam_isp_ctx_signal_buf_done_req,
 		},
 		.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
 		.pagefault_ops = cam_isp_context_dump_requests,

+ 8 - 1
drivers/cam_isp/cam_isp_context.h

@@ -157,7 +157,9 @@ struct cam_isp_ctx_irq_ops {
  * @reapply:                   True if reapplying after bubble
  * @cdm_reset_before_apply:    For bubble re-apply when buf done not coming set
  *                             to True
- *
+ * @buf_done_ready             Flag to check if ready to signal buf done when in sync mode
+ * @buf_done_mask              Mask used to check number of buf done which is yet to be signaled
+ * @is_sync_mode               If request need to be apply in sync with other link
  */
 struct cam_isp_ctx_req {
 	struct cam_ctx_request               *base;
@@ -177,6 +179,9 @@ struct cam_isp_ctx_req {
 	bool                                  bubble_detected;
 	bool                                  reapply;
 	bool                                  cdm_reset_before_apply;
+	atomic_t                              buf_done_ready;
+	int32_t                               buf_done_mask;
+	bool                                  is_sync_mode;
 };
 
 /**
@@ -273,6 +278,7 @@ struct cam_isp_context_event_record {
  * @workq:                     Worker thread for offline ife
  * @trigger_id:                ID provided by CRM for each ctx on the link
  * @last_bufdone_err_apply_req_id:  last bufdone error apply request id
+ * @fps:                       Current FPS for the activated state.
  *
  */
 struct cam_isp_context {
@@ -321,6 +327,7 @@ struct cam_isp_context {
 	struct cam_req_mgr_core_workq        *workq;
 	int32_t                               trigger_id;
 	int64_t                               last_bufdone_err_apply_req_id;
+	uint32_t                              fps;
 };
 
 /**

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

@@ -8767,6 +8767,27 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 				"BW limit update failed for IFE rc: %d", rc);
 	}
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: {
+		struct cam_fps_config *fps_config;
+		struct cam_isp_prepare_hw_update_data   *prepare_hw_data;
+
+		if (blob_size < sizeof(struct cam_fps_config)) {
+			CAM_ERR(CAM_ISP, "Invalid fps blob size %u expected %u",
+				blob_size, sizeof(struct cam_fps_config));
+			return -EINVAL;
+		}
+
+		fps_config = (struct cam_fps_config *)blob_data;
+
+		prepare_hw_data = (struct cam_isp_prepare_hw_update_data *)
+				prepare->priv;
+		if (fps_config->fps) {
+			prepare_hw_data->fps = fps_config->fps;
+			CAM_DBG(CAM_ISP, "FPS value %u", fps_config->fps);
+		} else
+			CAM_WARN(CAM_ISP, "FPS value 0");
+	}
+		break;
 	default:
 		CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
 		break;
@@ -9205,6 +9226,7 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 	case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES:
+	case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG:
 		break;
 	default:
 		CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type);

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

@@ -155,6 +155,7 @@ struct cam_isp_bw_config_internal {
  * @num_reg_dump_buf:      Count of descriptors in reg_dump_buf_desc
  * @packet                 CSL packet from user mode driver
  * @mup_en                 Flag if dynamic sensor switch is enabled
+ * @fps:                   Fps vaue associated with this packet/request
  *
  */
 struct cam_isp_prepare_hw_update_data {
@@ -172,6 +173,7 @@ struct cam_isp_prepare_hw_update_data {
 	uint32_t                              num_reg_dump_buf;
 	struct cam_packet                     *packet;
 	bool                                  mup_en;
+	int32_t                               fps;
 };
 
 

+ 156 - 45
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -18,7 +18,10 @@
 #include "cam_req_mgr_debug.h"
 #include "cam_common_util.h"
 
-#define THRESHOLD_FACTOR 3
+#define THRESHOLD_FACTOR_3 3
+#define THRESHOLD_FACTOR_2 2
+#define MILLI_SECOND_CONVERSION_FACTOR 1000000
+#define CAM_REQ_MGR_DEFAULT_FPS 30
 
 static struct cam_req_mgr_core_device *g_crm_core_dev;
 static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];
@@ -69,6 +72,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->sync_frame_id = 0;
 	link->is_sync_req = true;
 	link->skip_sync_apply = false;
+	link->fps = CAM_REQ_MGR_DEFAULT_FPS;
+	link->num_isp_dev = 0;
+	link->retry_threshold = 0;
 	atomic_set(&link->eof_event_cnt, 0);
 
 	for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) {
@@ -611,6 +617,7 @@ static void __cam_req_mgr_flush_req_slot(
 	atomic_set(&link->eof_event_cnt, 0);
 	in_q->wr_idx = 0;
 	in_q->rd_idx = 0;
+	link->sync_frame_id = 0;
 	link->trigger_cnt[0][0] = 0;
 	link->trigger_cnt[0][1] = 0;
 	link->trigger_cnt[1][0] = 0;
@@ -898,6 +905,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
 	struct cam_req_mgr_link_evt_data     evt_data;
 	struct cam_req_mgr_tbl_slot          *slot = NULL;
 	struct cam_req_mgr_apply             *apply_data = NULL;
+	struct cam_req_mgr_slot              *in_q_slot = NULL;
 
 	apply_req.link_hdl = link->link_hdl;
 	apply_req.report_if_bubble = 0;
@@ -1083,6 +1091,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
 				continue;
 
 			apply_req.trigger_point = trigger;
+			in_q_slot = &link->req.in_q->slot[idx];
+			apply_req.is_sync_mode =
+				(in_q_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) ? true : false;
+
 			CAM_DBG(CAM_REQ,
 				"SEND: link_hdl %x dev %s pd %d req_id %lld",
 				link->link_hdl, dev->dev_info.name,
@@ -1522,7 +1534,8 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 	}
 
 	if (link->num_sync_link &&
-		(link->initial_sync_req == slot->req_id)) {
+		((link->initial_sync_req == slot->req_id) ||
+		((link->initial_sync_req < slot->req_id) && link->sync_frame_id == 0))) {
 		link->sync_frame_id = trigger_data->frame_id;
 		CAM_DBG(CAM_CRM, "link %x sync frame %lld",
 			link->link_hdl, link->sync_frame_id);
@@ -2795,12 +2808,6 @@ int cam_req_mgr_process_error(void *priv, void *data)
 			__cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
 			in_q->rd_idx = idx;
 			in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
-			if (link->sync_link[0]) {
-				in_q->slot[idx].sync_mode = 0;
-				__cam_req_mgr_inc_idx(&idx, 1,
-					link->req.l_tbl->num_slots);
-				in_q->slot[idx].sync_mode = 0;
-			}
 
 			/* The next req may also be applied */
 			idx = in_q->rd_idx;
@@ -3081,6 +3088,44 @@ end:
 	return rc;
 }
 
+static int cam_req_mgr_cb_notify_rup(
+	struct cam_req_mgr_notify_rup *rup_info)
+{
+	int                                  i, j, rc = 0;
+	struct cam_req_mgr_core_link        *link = NULL;
+	struct cam_req_mgr_connected_device *dev = NULL;
+	struct cam_req_mgr_signal_info       set_signal_flag;
+
+	link = (struct cam_req_mgr_core_link *)
+		cam_get_device_priv(rup_info->link_hdl);
+	if (!link) {
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", rup_info->link_hdl);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (link->is_master) {
+		for (i = 0; i < link->num_sync_link; i++) {
+			for (j = 0; j < link->sync_link[i]->num_devs; j++) {
+				dev = &link->sync_link[i]->l_dev[j];
+				if (dev->ops->signal_buf_done) {
+					set_signal_flag.link_hdl = link->sync_link[i]->link_hdl;
+					set_signal_flag.dev_hdl = dev->dev_hdl;
+					set_signal_flag.req_id = rup_info->req_id;
+					set_signal_flag.state = SIGNAL_SYNC_BUF_DONE;
+					dev->ops->signal_buf_done(&set_signal_flag);
+				}
+			}
+		}
+		rup_info->state = SIGNAL_SYNC_BUF_DONE;
+	} else {
+		rup_info->state = INIT_BUF_DONE;
+	}
+
+end:
+	return rc;
+}
+
 /**
  * cam_req_mgr_cb_notify_err()
  *
@@ -3096,7 +3141,7 @@ static bool cam_req_mgr_cb_notify_err(
 {
 	bool                             rc = false;
 	int                              i, j;
-	uint32_t                         idx;
+	int32_t                          idx;
 	struct crm_workq_task           *task = NULL;
 	struct cam_req_mgr_core_link    *link = NULL;
 	struct cam_req_mgr_error_notify *notify_err;
@@ -3164,6 +3209,7 @@ static bool cam_req_mgr_cb_notify_err(
 		tmp_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
 		!link->is_master) {
 		crm_timer_reset(link->watchdog);
+		link->frame_id = err_info->frame_id;
 		CAM_DBG(CAM_CRM, "Not processing bubble as it is slave link %x",
 			link->link_hdl);
 		return true;
@@ -3220,6 +3266,7 @@ static bool cam_req_mgr_cb_notify_err(
 						link->sync_link[i]->link_hdl;
 					notify_err->dev_hdl = dev->dev_hdl;
 					notify_err->error = err_info->error;
+					notify_err->trigger = err_info->trigger;
 					task->process_cb =
 						&cam_req_mgr_process_error;
 					cam_req_mgr_workq_enqueue_task(
@@ -3555,6 +3602,12 @@ static int cam_req_mgr_cb_notify_trigger(
 	if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF)
 		crm_timer_reset(link->watchdog);
 
+	if (link->sof_timestamp == trigger_data->sof_timestamp_val) {
+		CAM_DBG(CAM_CRM,
+			"Irq delay, skipping apply");
+		return 0;
+	}
+
 	link->prev_sof_timestamp = link->sof_timestamp;
 	link->sof_timestamp = trigger_data->sof_timestamp_val;
 	link->frame_id = trigger_data->frame_id;
@@ -3582,7 +3635,6 @@ static int cam_req_mgr_cb_notify_trigger(
 			link->link_hdl, slot->req_id, sync_id, slot->status);
 	}
 
-
 	CAM_DBG(CAM_CRM,
 		"link %x req %lld slot mode %d tmp slot mode %d init sync %lld",
 		link->link_hdl, slot->req_id,
@@ -3617,13 +3669,14 @@ static int cam_req_mgr_cb_notify_trigger(
 
 			frame_duration =
 				(curr_boot_timestamp - link->sof_boottime) * 2;
+
 			CAM_DBG(CAM_CRM,
 				"[Master %x] epoch time %lld sof boottime %lld frame id %lld frame duration %d ms  open cnt %d req id %lld",
 				link->link_hdl,
 				curr_boot_timestamp,
 				link->sof_boottime,
 				trigger_data->frame_id,
-				frame_duration/1000000,
+				frame_duration / MILLI_SECOND_CONVERSION_FACTOR,
 				link->open_req_cnt,
 				slot->req_id);
 
@@ -3721,21 +3774,74 @@ static int cam_req_mgr_cb_notify_trigger(
 					dev_data.timestamp - link->sof_timestamp :
 					link->sof_timestamp - dev_data.timestamp;
 
-				threshold = frame_duration / THRESHOLD_FACTOR;
 
 				/* Checking if master and sync links are in
 				 * same frame duration considering master frame
 				 * duration in calculating threshold value
 				 */
+
+				if (trigger_data->fps == 0) {
+					frame_duration =
+						link->fps * MILLI_SECOND_CONVERSION_FACTOR;
+					if (link->retry_threshold) {
+						/* Increase threshold value by dividing frame
+						 * duration with 2, so that sync logic get chance
+						 * to reduce sof time difference in next 3 requests.
+						 */
+						link->retry_threshold -= 1;
+						threshold = frame_duration / THRESHOLD_FACTOR_2;
+					} else {
+						/* Normal threshold calculation by dividing frame
+						 * duration with 3
+						 */
+						threshold = frame_duration / THRESHOLD_FACTOR_3;
+					}
+				} else if (trigger_data->fps == -1) {
+					//Frame duration based on epoch-sof calculation
+					if (link->retry_threshold) {
+						/*  Increase threshold value by dividing frame
+						 * duration with 2
+						 */
+						link->retry_threshold -= 1;
+						threshold = frame_duration / THRESHOLD_FACTOR_2;
+					} else {
+						/* Normal threshold calculation by dividing frame
+						 * duration with 3
+						 */
+						threshold = frame_duration / THRESHOLD_FACTOR_3;
+					}
+				} else {
+					link->fps = trigger_data->fps;
+					frame_duration =
+						trigger_data->fps * MILLI_SECOND_CONVERSION_FACTOR;
+					if (link->retry_threshold) {
+						/* Increase threshold value by dividing frame
+						 * duration with 2
+						 */
+						link->retry_threshold -= 1;
+						threshold = frame_duration / THRESHOLD_FACTOR_2;
+					} else {
+						/* Normal threshold calculation by dividing frame
+						 * duration with 3
+						 */
+						threshold = frame_duration / THRESHOLD_FACTOR_3;
+					}
+				}
+
 				if (curr_sync_time > threshold) {
 					struct cam_req_mgr_dump_link_data
 						dump_info;
-					CAM_DBG(CAM_CRM,
-						"Master %x and slave %x are not in same time frame time diff %lld threshold %lld",
+
+					link->retry_threshold = 3;
+					CAM_INFO_RATE_LIMIT(CAM_CRM,
+						"Master %x and slave %x sof diff is more than threshold: time diff %lld threshold %lld fps %d bootime %lld",
 						link->link_hdl,
 						link->sync_link[i]->link_hdl,
-						curr_sync_time/1000000,
-						threshold/1000000);
+						curr_sync_time / MILLI_SECOND_CONVERSION_FACTOR,
+						threshold / MILLI_SECOND_CONVERSION_FACTOR,
+						trigger_data->fps,
+						(curr_boot_timestamp /
+						MILLI_SECOND_CONVERSION_FACTOR));
 
 					dump_info.m_link = link;
 					dump_info.s_link = link->sync_link[i];
@@ -3780,7 +3886,7 @@ static int cam_req_mgr_cb_notify_trigger(
 					struct cam_req_mgr_dump_link_data
 						dump_info;
 
-					CAM_DBG(CAM_CRM,
+					CAM_INFO_RATE_LIMIT(CAM_CRM,
 						"Req diff %lld Master link %x req %lld slave link %x req %lld",
 						req_diff,
 						link->link_hdl,
@@ -4003,7 +4109,7 @@ slave:
 		tmp_slot->real_sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC)) {
 
 		CAM_DBG(CAM_CRM,
-			"In sync mode req %lld tmp mode % real mode %d sync mode %d link %x ",
+			"In sync mode req %lld tmp mode %d real mode %d sync mode %d link %x ",
 			slot->req_id, tmp_slot->sync_mode,
 			tmp_slot->real_sync_mode,
 			slot->sync_mode, link->link_hdl);
@@ -4062,6 +4168,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
 	.add_req        = cam_req_mgr_cb_add_req,
 	.notify_timer   = cam_req_mgr_cb_notify_timer,
 	.notify_stop    = cam_req_mgr_cb_notify_stop,
+	.notify_rup     = cam_req_mgr_cb_notify_rup,
 };
 
 /**
@@ -4770,43 +4877,47 @@ static void __cam_req_mgr_set_master_link(
 	int32_t num_of_links)
 {
 	int i = 0, j = 0, k = 0;
-	int idx = -1;
-
-	idx = find_first_bit(g_crm_core_dev->bitmap,
-		MAXIMUM_LINKS_PER_SESSION);
+	int master_link_idx = 0;
+	int max_isp = -1, min_isp = MAX_LINKS_PER_SESSION + 1;
+	int min_isp_link_idx = 0, max_isp_link_idx = 0;
+	struct cam_req_mgr_connected_device *dev = NULL;
 
 	for (i = 0; i < num_of_links; i++) {
+		for (j = 0; j < link[i]->num_devs; j++) {
+			dev = &link[i]->l_dev[j];
+			if (strcmp("cam-isp", dev->dev_info.name) == 0)
+				link[i]->num_isp_dev++;
+		}
 
-		CAM_DBG(CAM_CRM, "idx %d, link%d 0x%x active seq %d",
-				idx, i, link[i]->link_hdl,
-				link[i]->activate_seq);
-
-		if (link[i]->activate_seq == idx) {
-
-			link[i]->is_master = true;
-			CAM_DBG(CAM_CRM, "Master link 0x%x num of links %d ",
-				link[i]->link_hdl, num_of_links);
+		if (max_isp < link[i]->num_isp_dev) {
+			max_isp = link[i]->num_isp_dev;
+			max_isp_link_idx = i;
+		}
+		if (min_isp > link[i]->num_isp_dev) {
+			min_isp = link[i]->num_isp_dev;
+			min_isp_link_idx = i;
+		}
 
-			for (j = 0, k = 0; j < num_of_links; j++) {
-				if (link[i]->link_hdl !=
-					link[j]->link_hdl) {
+		if (link[master_link_idx]->activate_seq > link[i]->activate_seq)
+			master_link_idx = i;
+	}
 
-					link[i]->sync_link[k] = link[j];
-					link[i]->num_sync_link++;
+	if (max_isp != min_isp)
+		master_link_idx = min_isp_link_idx;
 
-					link[j]->sync_link[0] = link[i];
-					link[j]->num_sync_link = 1;
-					link[j]->is_master = false;
+	link[master_link_idx]->is_master = true;
+	CAM_DBG(CAM_CRM, "Master link %x ", link[master_link_idx]->link_hdl);
 
-					k++;
-				}
-			}
+	for (i = 0; i < num_of_links; i++) {
+		if (i != master_link_idx) {
+			link[i]->is_master = false;
+			link[i]->sync_link[0] = link[master_link_idx];
+			link[i]->num_sync_link = 1;
+			link[master_link_idx]->sync_link[k++] = link[i];
+			link[master_link_idx]->num_sync_link++;
 		}
-
 		link[i]->initial_skip =
 			g_crm_core_dev->max_delay - link[i]->max_delay;
-		CAM_DBG(CAM_CRM, "link %x initial skip %d",
-			link[i]->link_hdl, link[i]->initial_skip);
 	}
 }
 

+ 6 - 0
drivers/cam_req_mgr/cam_req_mgr_core.h

@@ -394,6 +394,9 @@ struct cam_req_mgr_connected_device {
  * @frame_id             : current frame id
  * @sync_frame_id        : current frame id of sync link
  * @bubble_skip          : req to skip on bubble
+ * @num_isp_dev          : number of isp dev in a link
+ * @retry_threshold      : number of times to retry apply on increased threshold
+ * @fps                  : current frame rate
  */
 struct cam_req_mgr_core_link {
 	int32_t                              link_hdl;
@@ -439,6 +442,9 @@ struct cam_req_mgr_core_link {
 	uint64_t                             sync_frame_id;
 	int32_t                              bubble_skip;
 	bool                                 skip_sync_apply;
+	uint32_t                             num_isp_dev;
+	uint32_t                             retry_threshold;
+	uint32_t                             fps;
 };
 
 /**

+ 52 - 4
drivers/cam_req_mgr/cam_req_mgr_interface.h

@@ -12,6 +12,7 @@
 #include "cam_req_mgr_util.h"
 
 struct cam_req_mgr_trigger_notify;
+struct cam_req_mgr_notify_rup;
 struct cam_req_mgr_error_notify;
 struct cam_req_mgr_add_request;
 struct cam_req_mgr_timer_notify;
@@ -23,19 +24,21 @@ 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;
+struct cam_req_mgr_signal_info;
 
 /* Request Manager -- camera device driver interface */
 /**
  * @brief: camera kernel drivers to cam req mgr communication
  *
  * @cam_req_mgr_notify_trigger: for device which generates trigger to inform CRM
+ * @cam_req_mgr_notify_rup    : for device which generates reg update trigger to inform CRM
  * @cam_req_mgr_notify_err    : device use this to inform about different errors
  * @cam_req_mgr_add_req       : to info CRM about new rqeuest received from
  *                              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_trigger)(struct cam_req_mgr_trigger_notify *);
+typedef int (*cam_req_mgr_notify_rup)(struct cam_req_mgr_notify_rup *);
 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 *);
@@ -62,8 +65,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 *);
+typedef int (*cam_req_mgr_change_state)(struct cam_req_mgr_request_change_state *);
+typedef int (*cam_req_mgr_signal_buf_done)(struct cam_req_mgr_signal_info *);
 
 /**
  * @brief          : cam_req_mgr_crm_cb - func table
@@ -73,6 +76,7 @@ typedef int (*cam_req_mgr_change_state)(
  * @add_req        : payload to inform which device and what request is received
  * @notify_timer   : payload for timer start event
  * @notify_stop    : payload to inform stop event
+ * @notify_rup     : payload to inform reg update ack
  */
 struct cam_req_mgr_crm_cb {
 	cam_req_mgr_notify_trigger  notify_trigger;
@@ -80,6 +84,7 @@ struct cam_req_mgr_crm_cb {
 	cam_req_mgr_add_req         add_req;
 	cam_req_mgr_notify_timer    notify_timer;
 	cam_req_mgr_notify_stop     notify_stop;
+	cam_req_mgr_notify_rup      notify_rup;
 };
 
 /**
@@ -103,6 +108,7 @@ struct cam_req_mgr_kmd_ops {
 	cam_req_mgr_process_evt      process_evt;
 	cam_req_mgr_dump_req         dump_req;
 	cam_req_mgr_change_state     change_state;
+	cam_req_mgr_signal_buf_done  signal_buf_done;
 };
 
 /**
@@ -215,6 +221,17 @@ enum cam_req_mgr_link_evt_type {
 	CAM_REQ_MGR_LINK_EVT_MAX,
 };
 
+/**
+ * enum cam_req_mgr_buf_done_state
+ * @INIT_BUF_DONE             : Initial buf done state of a request
+ * @SIGNAL_SYNC_BUF_DONE      : Ready to signal buf done of a request if in sync mode
+ * @SIGNAL_NON_SYNC_BUF_DONE  : Ready to signal buf done of a request if in non sync mode
+ */
+enum cam_req_mgr_buf_done_state {
+	INIT_BUF_DONE,
+	SIGNAL_SYNC_BUF_DONE,
+};
+
 /**
  * struct cam_req_mgr_trigger_notify
  * @link_hdl : link identifier
@@ -226,6 +243,7 @@ enum cam_req_mgr_link_evt_type {
  * @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
+ * @fps      : Current fps value
  */
 struct cam_req_mgr_trigger_notify {
 	int32_t  link_hdl;
@@ -236,6 +254,19 @@ struct cam_req_mgr_trigger_notify {
 	uint64_t sof_boottime;
 	uint64_t req_id;
 	int32_t  trigger_id;
+	uint32_t fps;
+};
+
+/**
+ * struct cam_req_mgr_notify_rup
+ * @link_hdl  : link identifier
+ * @req_id    : req id which returned reg update ack
+ * @state     : buf done ready state of the request
+ */
+struct cam_req_mgr_notify_rup {
+	int32_t  link_hdl;
+	uint64_t req_id;
+	int32_t  state;
 };
 
 /**
@@ -353,6 +384,7 @@ struct cam_req_mgr_core_dev_link_setup {
  * @report_if_bubble : report to crm if failure in applying
  * @trigger_point    : the trigger point of this apply
  * @re_apply         : to skip re_apply for buf_done request
+ * @is_sync_mode     : if request need to be apply in sync with other link
  *
  */
 struct cam_req_mgr_apply_request {
@@ -362,6 +394,7 @@ struct cam_req_mgr_apply_request {
 	int32_t    report_if_bubble;
 	uint32_t   trigger_point;
 	bool       re_apply;
+	bool       is_sync_mode;
 };
 
 /**
@@ -456,4 +489,19 @@ struct cam_req_mgr_request_change_state {
 	uint64_t   req_id;
 };
 
+/**
+ * struct cam_req_mgr_signal_info
+ * @link_hdl    : link identifier
+ * @dev_hdl     : device handle or identifier
+ * req_id       : request id to be set for buf done ready
+ * state        : Buf done ready state of a request
+ *
+ */
+struct cam_req_mgr_signal_info {
+	int32_t    link_hdl;
+	int32_t    dev_hdl;
+	uint64_t   req_id;
+	int32_t    state;
+};
+
 #endif

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

@@ -122,6 +122,7 @@
 #define CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG           14
 #define CAM_ISP_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH       15
 #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_SFE_CLOCK_CONFIG          21
 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CORE_CONFIG           22
 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_OUT_CONFIG            23
@@ -822,6 +823,18 @@ struct cam_isp_acquire_hw_info {
 	__u64             data;
 };
 
+/**
+ * struct cam_fps_config - FPS info per request
+ *
+ * @fps                 : Fps value
+ * @reserved:           : Reserved field for alignment
+ *
+ */
+struct cam_fps_config {
+	__u32             fps;
+	__u32             reserved_params[3];
+} __attribute__((packed));
+
 /**
  * struct cam_isp_vfe_wm_config  -  VFE write master config per port
  *