Explorar o código

Merge "msm: camera: common: Multiple fixes for crm redesign" into camera-kernel.lnx.5.0

Camera Software Integration %!s(int64=4) %!d(string=hai) anos
pai
achega
69b929466b

+ 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

@@ -8763,6 +8763,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;
@@ -9201,6 +9222,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
  *