msm: camera: reqmgr: Add EOF trigger notification

Add method in ISP to notify SOF/EOF that is subscribed by camera
modules to CRM, CRM will send apply command to modules as the
subscribe mask.

CRs-fixed: 2096454
Change-Id: I6ad7d77f091386d3be91c670da75e1cd15e41ecd
Signed-off-by: Pavan Kumar Chilamkurthi <pchilamk@codeaurora.org>
Signed-off-by: Junzhe Zou <jnzhezou@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index a6f60f5..6470063 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -219,7 +219,8 @@
 static int __cam_isp_ctx_notify_sof_in_actived_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
-	struct cam_req_mgr_sof_notify  notify;
+	int rc = 0;
+	struct cam_req_mgr_trigger_notify  notify;
 	struct cam_context *ctx = ctx_isp->base;
 	struct cam_ctx_request  *req;
 	uint64_t  request_id  = 0;
@@ -231,15 +232,18 @@
 	 * In this case, we need to skip the current notification. This
 	 * helps the state machine to catch up the delay.
 	 */
-	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
 		ctx_isp->active_req_cnt <= 2) {
-		notify.link_hdl = ctx->link_hdl;
-		notify.dev_hdl = ctx->dev_hdl;
-		notify.frame_id = ctx_isp->frame_id;
+		if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
+			notify.link_hdl = ctx->link_hdl;
+			notify.dev_hdl = ctx->dev_hdl;
+			notify.frame_id = ctx_isp->frame_id;
+			notify.trigger = CAM_TRIGGER_POINT_SOF;
 
-		ctx->ctx_crm_intf->notify_sof(&notify);
-		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
-			ctx_isp->frame_id);
+			ctx->ctx_crm_intf->notify_trigger(&notify);
+			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
+				ctx_isp->frame_id);
+		}
 
 		list_for_each_entry(req, &ctx->active_req_list, list) {
 			if (req->request_id > ctx_isp->reported_req_id) {
@@ -253,11 +257,39 @@
 			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
 	} else {
 		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
+		rc = -EFAULT;
 	}
 
 	return 0;
 }
 
+static int __cam_isp_ctx_notify_eof_in_actived_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	int rc = 0;
+	struct cam_req_mgr_trigger_notify  notify;
+	struct cam_context *ctx = ctx_isp->base;
+
+	if (!(ctx_isp->subscribe_event & CAM_TRIGGER_POINT_EOF))
+		return rc;
+
+	/* notify reqmgr with eof signal */
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
+		notify.link_hdl = ctx->link_hdl;
+		notify.dev_hdl = ctx->dev_hdl;
+		notify.frame_id = ctx_isp->frame_id;
+		notify.trigger = CAM_TRIGGER_POINT_EOF;
+
+		ctx->ctx_crm_intf->notify_trigger(&notify);
+		CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld\n",
+			ctx_isp->frame_id);
+	} else {
+		CAM_ERR(CAM_ISP, "Can not notify EOF to CRM");
+		rc = -EFAULT;
+	}
+
+	return rc;
+}
 
 static int __cam_isp_ctx_sof_in_activated_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
@@ -581,7 +613,7 @@
 			__cam_isp_ctx_sof_in_activated_state,
 			__cam_isp_ctx_reg_upd_in_sof,
 			__cam_isp_ctx_notify_sof_in_actived_state,
-			NULL,
+			__cam_isp_ctx_notify_eof_in_actived_state,
 			NULL,
 		},
 	},
@@ -592,7 +624,7 @@
 			__cam_isp_ctx_sof_in_activated_state,
 			__cam_isp_ctx_reg_upd_in_activated_state,
 			__cam_isp_ctx_epoch_in_applied,
-			NULL,
+			__cam_isp_ctx_notify_eof_in_actived_state,
 			__cam_isp_ctx_buf_done_in_applied,
 		},
 	},
@@ -603,7 +635,7 @@
 			__cam_isp_ctx_sof_in_epoch,
 			NULL,
 			__cam_isp_ctx_notify_sof_in_actived_state,
-			NULL,
+			__cam_isp_ctx_notify_eof_in_actived_state,
 			__cam_isp_ctx_buf_done_in_epoch,
 		},
 	},
@@ -614,7 +646,7 @@
 			__cam_isp_ctx_sof_in_activated_state,
 			NULL,
 			__cam_isp_ctx_notify_sof_in_actived_state,
-			NULL,
+			__cam_isp_ctx_notify_eof_in_actived_state,
 			__cam_isp_ctx_buf_done_in_bubble,
 		},
 	},
@@ -890,7 +922,7 @@
 {
 	int rc = 0;
 	struct cam_context                    *ctx = ctx_isp->base;
-	struct cam_req_mgr_sof_notify          notify;
+	struct cam_req_mgr_trigger_notify      notify;
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 	uint64_t                               request_id  = 0;
 
@@ -911,13 +943,14 @@
 	 * In this case, we need to skip the current notification. This
 	 * helps the state machine to catch up the delay.
 	 */
-	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
 		ctx_isp->active_req_cnt <= 2) {
 		notify.link_hdl = ctx->link_hdl;
 		notify.dev_hdl = ctx->dev_hdl;
 		notify.frame_id = ctx_isp->frame_id;
+		notify.trigger = CAM_TRIGGER_POINT_SOF;
 
-		ctx->ctx_crm_intf->notify_sof(&notify);
+		ctx->ctx_crm_intf->notify_trigger(&notify);
 		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
 			ctx_isp->frame_id);
 
@@ -1037,7 +1070,7 @@
 	uint32_t i;
 	struct cam_ctx_request                *req;
 	struct cam_context                    *ctx = ctx_isp->base;
-	struct cam_req_mgr_sof_notify          notify;
+	struct cam_req_mgr_trigger_notify      notify;
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 	struct cam_isp_ctx_req                *req_isp;
 	uint64_t                               request_id  = 0;
@@ -1072,12 +1105,13 @@
 	}
 
 	/* notify reqmgr with sof signal */
-	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
 		notify.link_hdl = ctx->link_hdl;
 		notify.dev_hdl = ctx->dev_hdl;
 		notify.frame_id = ctx_isp->frame_id;
+		notify.trigger = CAM_TRIGGER_POINT_SOF;
 
-		ctx->ctx_crm_intf->notify_sof(&notify);
+		ctx->ctx_crm_intf->notify_trigger(&notify);
 		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
 			ctx_isp->frame_id);
 
@@ -1106,11 +1140,11 @@
 	struct cam_ctx_request  *req;
 	struct cam_context      *ctx = ctx_isp->base;
 	struct cam_isp_ctx_req  *req_isp;
-	struct cam_req_mgr_sof_notify  notify;
+	struct cam_req_mgr_trigger_notify  notify;
 	uint64_t  request_id  = 0;
 
 	/* notify reqmgr with sof signal*/
-	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
 		if (list_empty(&ctx->pending_req_list)) {
 			CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
 			goto error;
@@ -1138,8 +1172,9 @@
 		notify.link_hdl = ctx->link_hdl;
 		notify.dev_hdl = ctx->dev_hdl;
 		notify.frame_id = ctx_isp->frame_id;
+		notify.trigger = CAM_TRIGGER_POINT_SOF;
 
-		ctx->ctx_crm_intf->notify_sof(&notify);
+		ctx->ctx_crm_intf->notify_trigger(&notify);
 		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
 			ctx_isp->frame_id);
 	} else {
@@ -1608,11 +1643,14 @@
 	struct cam_req_mgr_core_dev_link_setup *link)
 {
 	int rc = 0;
+	struct cam_isp_context *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
 
 	CAM_DBG(CAM_ISP, "Enter.........");
 
 	ctx->link_hdl = link->link_hdl;
 	ctx->ctx_crm_intf = link->crm_cb;
+	ctx_isp->subscribe_event = link->subscribe_event;
 
 	/* change state only if we had the init config */
 	if (!list_empty(&ctx->pending_req_list)) {
@@ -1645,6 +1683,7 @@
 	strlcpy(dev_info->name, CAM_ISP_DEV_NAME, sizeof(dev_info->name));
 	dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE;
 	dev_info->p_delay = 1;
+	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index b0b883c..621d652 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -109,6 +109,9 @@
  * @sof_timestamp_val:     Captured time stamp value at sof hw event
  * @active_req_cnt:        Counter for the active request
  * @reported_req_id:       Last reported request id
+ * @subscribe_event:       The irq event mask that CRM subscribes to, IFE will
+ *                         invoke CRM cb at those event.
+ *
  */
 struct cam_isp_context {
 	struct cam_context              *base;
@@ -125,6 +128,7 @@
 	uint64_t                         sof_timestamp_val;
 	int32_t                          active_req_cnt;
 	int64_t                          reported_req_id;
+	uint32_t                         subscribe_event;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 4893960..3ca2820 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -2444,34 +2444,51 @@
 	return 0;
 }
 
-static int cam_ife_hw_mgr_check_epoch_for_dual_vfe(
+static int cam_ife_hw_mgr_check_irq_for_dual_vfe(
 	struct cam_ife_hw_mgr_ctx   *ife_hw_mgr_ctx,
 	uint32_t                     core_idx0,
-	uint32_t                     core_idx1)
+	uint32_t                     core_idx1,
+	uint32_t                     hw_event_type)
 {
 	int32_t rc = -1;
-	uint32_t *epoch_cnt = ife_hw_mgr_ctx->epoch_cnt;
+	uint32_t *event_cnt = NULL;
 
-	if (epoch_cnt[core_idx0] ==
-			epoch_cnt[core_idx1]) {
+	switch (hw_event_type) {
+	case CAM_ISP_HW_EVENT_SOF:
+		event_cnt = ife_hw_mgr_ctx->sof_cnt;
+		break;
+	case CAM_ISP_HW_EVENT_REG_UPDATE:
+		event_cnt = ife_hw_mgr_ctx->epoch_cnt;
+		break;
+	case CAM_ISP_HW_EVENT_EOF:
+		event_cnt = ife_hw_mgr_ctx->eof_cnt;
+		break;
+	default:
+		return 0;
+	}
 
-		epoch_cnt[core_idx0] = 0;
-		epoch_cnt[core_idx1] = 0;
+	if (event_cnt[core_idx0] ==
+			event_cnt[core_idx1]) {
+
+		event_cnt[core_idx0] = 0;
+		event_cnt[core_idx1] = 0;
 
 		rc = 0;
 		return rc;
 	}
 
-	if ((epoch_cnt[core_idx0] - epoch_cnt[core_idx1] > 1) ||
-		(epoch_cnt[core_idx1] - epoch_cnt[core_idx0] > 1)) {
+	if ((event_cnt[core_idx0] - event_cnt[core_idx1] > 1) ||
+		(event_cnt[core_idx1] - event_cnt[core_idx0] > 1)) {
 
 		CAM_WARN(CAM_ISP,
-			"One of the VFE of dual VFE cound not generate error");
+			"One of the VFE cound not generate hw event %d",
+			hw_event_type);
 		rc = -1;
 		return rc;
 	}
 
-	CAM_DBG(CAM_ISP, "Only one core_index has given EPOCH");
+	CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d",
+			hw_event_type);
 
 	return rc;
 }
@@ -2562,10 +2579,11 @@
 			core_index0 = hw_res_l->hw_intf->hw_idx;
 			core_index1 = hw_res_r->hw_intf->hw_idx;
 
-			rc = cam_ife_hw_mgr_check_epoch_for_dual_vfe(
+			rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(
 					ife_hwr_mgr_ctx,
 					core_index0,
-					core_index1);
+					core_index1,
+					evt_payload->evt_id);
 
 			if (!rc)
 				ife_hwr_irq_epoch_cb(
@@ -2588,37 +2606,6 @@
 	return 0;
 }
 
-static int cam_ife_hw_mgr_check_sof_for_dual_vfe(
-	struct cam_ife_hw_mgr_ctx   *ife_hwr_mgr_ctx,
-	uint32_t                     core_idx0,
-	uint32_t                     core_idx1)
-{
-	uint32_t *sof_cnt = ife_hwr_mgr_ctx->sof_cnt;
-	int32_t rc = -1;
-
-	if (sof_cnt[core_idx0] ==
-			sof_cnt[core_idx1]) {
-
-		sof_cnt[core_idx0] = 0;
-		sof_cnt[core_idx1] = 0;
-
-		rc = 0;
-		return rc;
-	}
-
-	if ((sof_cnt[core_idx0] - sof_cnt[core_idx1] > 1) ||
-		(sof_cnt[core_idx1] - sof_cnt[core_idx0] > 1)) {
-
-		CAM_ERR(CAM_ISP, "One VFE of dual VFE cound not generate SOF");
-		rc = -1;
-		return rc;
-	}
-
-	CAM_INFO(CAM_ISP, "Only one core_index has given SOF");
-
-	return rc;
-}
-
 static int cam_ife_hw_mgr_process_camif_sof(
 	struct cam_ife_hw_mgr_res            *isp_ife_camif_res,
 	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx,
@@ -2709,8 +2696,8 @@
 		core_index0 = hw_res_l->hw_intf->hw_idx;
 		core_index1 = hw_res_r->hw_intf->hw_idx;
 
-		rc = cam_ife_hw_mgr_check_sof_for_dual_vfe(ife_hwr_mgr_ctx,
-			core_index0, core_index1);
+		rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hwr_mgr_ctx,
+			core_index0, core_index1, evt_payload->evt_id);
 
 		if (!rc)
 			ife_hwr_irq_sof_cb(ife_hwr_mgr_ctx->common.cb_priv,
@@ -2803,6 +2790,124 @@
 	return 0;
 }
 
+static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
+	void                              *handler_priv,
+	void                              *payload)
+{
+	int32_t rc = -EINVAL;
+	struct cam_isp_resource_node         *hw_res_l = NULL;
+	struct cam_isp_resource_node         *hw_res_r = NULL;
+	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx;
+	struct cam_vfe_top_irq_evt_payload   *evt_payload;
+	struct cam_ife_hw_mgr_res            *isp_ife_camif_res = NULL;
+	cam_hw_event_cb_func                  ife_hwr_irq_eof_cb;
+	struct cam_isp_hw_eof_event_data      eof_done_event_data;
+	uint32_t  core_idx;
+	uint32_t  eof_status = 0;
+	uint32_t  core_index0;
+	uint32_t  core_index1;
+
+	CAM_DBG(CAM_ISP, "Enter");
+
+	ife_hwr_mgr_ctx = handler_priv;
+	evt_payload = payload;
+	if (!evt_payload) {
+		pr_err("%s: no payload\n", __func__);
+		return IRQ_HANDLED;
+	}
+	core_idx = evt_payload->core_index;
+	ife_hwr_irq_eof_cb =
+		ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF];
+
+	evt_payload->evt_id = CAM_ISP_HW_EVENT_EOF;
+
+	list_for_each_entry(isp_ife_camif_res,
+		&ife_hwr_mgr_ctx->res_list_ife_src, list) {
+
+		if ((isp_ife_camif_res->res_type ==
+			CAM_IFE_HW_MGR_RES_UNINIT) ||
+			(isp_ife_camif_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF))
+			continue;
+
+		hw_res_l = isp_ife_camif_res->hw_res[0];
+		hw_res_r = isp_ife_camif_res->hw_res[1];
+
+		CAM_DBG(CAM_ISP, "is_dual_vfe ? = %d",
+				isp_ife_camif_res->is_dual_vfe);
+		switch (isp_ife_camif_res->is_dual_vfe) {
+		/* Handling Single VFE Scenario */
+		case 0:
+			/* EOF check for Left side VFE */
+			if (!hw_res_l) {
+				pr_err("%s: VFE Device is NULL\n",
+					__func__);
+				break;
+			}
+			CAM_DBG(CAM_ISP, "curr_core_idx = %d, core idx hw = %d",
+					core_idx, hw_res_l->hw_intf->hw_idx);
+
+			if (core_idx == hw_res_l->hw_intf->hw_idx) {
+				eof_status = hw_res_l->bottom_half_handler(
+					hw_res_l, evt_payload);
+				if (!eof_status)
+					ife_hwr_irq_eof_cb(
+						ife_hwr_mgr_ctx->common.cb_priv,
+						CAM_ISP_HW_EVENT_EOF,
+						&eof_done_event_data);
+			}
+
+			break;
+		/* Handling dual VFE Scenario */
+		case 1:
+			if ((!hw_res_l) || (!hw_res_r)) {
+				CAM_ERR(CAM_ISP, "Dual VFE Device is NULL");
+				break;
+			}
+			if (core_idx == hw_res_l->hw_intf->hw_idx) {
+				eof_status = hw_res_l->bottom_half_handler(
+					hw_res_l, evt_payload);
+
+				if (!eof_status)
+					ife_hwr_mgr_ctx->eof_cnt[core_idx]++;
+			}
+
+			/* EOF check for Right side VFE */
+			if (core_idx == hw_res_r->hw_intf->hw_idx) {
+				eof_status = hw_res_r->bottom_half_handler(
+					hw_res_r, evt_payload);
+
+				if (!eof_status)
+					ife_hwr_mgr_ctx->eof_cnt[core_idx]++;
+			}
+
+			core_index0 = hw_res_l->hw_intf->hw_idx;
+			core_index1 = hw_res_r->hw_intf->hw_idx;
+
+			rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(
+					ife_hwr_mgr_ctx,
+					core_index0,
+					core_index1,
+					evt_payload->evt_id);
+
+			if (!rc)
+				ife_hwr_irq_eof_cb(
+					ife_hwr_mgr_ctx->common.cb_priv,
+					CAM_ISP_HW_EVENT_EPOCH,
+					&eof_done_event_data);
+
+			break;
+
+		default:
+			CAM_ERR(CAM_ISP, "error with hw_res");
+		}
+	}
+
+	CAM_DBG(CAM_ISP, "Exit (eof_status = %d)!", eof_status);
+
+	return 0;
+}
+
+
 static int cam_ife_hw_mgr_handle_buf_done_for_hw_res(
 	void                              *handler_priv,
 	void                              *payload)
@@ -3009,6 +3114,8 @@
 	/* EPOCH IRQ */
 	cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(ife_hwr_mgr_ctx,
 		evt_payload_priv);
+	cam_ife_hw_mgr_handle_eof_for_camif_hw_res(ife_hwr_mgr_ctx,
+		evt_payload_priv);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 6dfdb21..750b43e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -106,6 +106,7 @@
  * @cdm_cmd                 cdm base and length request pointer
  * @sof_cnt                 sof count value per core, used for dual VFE
  * @epoch_cnt               epoch count value per core, used for dual VFE
+ * @eof_cnt                 eof count value per core, used for dual VFE
  * @overflow_pending        flat to specify the overflow is pending for the
  *                          context
  * @is_rdi_only_context     flag to specify the context has only rdi resource
@@ -138,6 +139,7 @@
 
 	uint32_t                        sof_cnt[CAM_IFE_HW_NUM_MAX];
 	uint32_t                        epoch_cnt[CAM_IFE_HW_NUM_MAX];
+	uint32_t                        eof_cnt[CAM_IFE_HW_NUM_MAX];
 	atomic_t                        overflow_pending;
 	uint32_t                        is_rdi_only_context;
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
index 275c7b5..da96cac 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
@@ -70,6 +70,7 @@
 	.sof_irq_mask                    = 0x00000001,
 	.epoch0_irq_mask                 = 0x00000004,
 	.reg_update_irq_mask             = 0x00000010,
+	.eof_irq_mask                    = 0x00000002,
 };
 
 struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index e70ecc5..1d15b5b 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
- #include <linux/slab.h>
+#include <linux/slab.h>
 #include <uapi/media/cam_isp.h>
 #include "cam_io_util.h"
 #include "cam_isp_hw_mgr_intf.h"
@@ -207,6 +207,12 @@
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 		break;
+	case CAM_ISP_HW_EVENT_EOF:
+		if (irq_status0 & camif_priv->reg_data->eof_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received EOF\n");
+			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
index 553abf2..485389a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
@@ -54,6 +54,7 @@
 	uint32_t     sof_irq_mask;
 	uint32_t     epoch0_irq_mask;
 	uint32_t     reg_update_irq_mask;
+	uint32_t     eof_irq_mask;
 };
 
 struct cam_vfe_camif_ver2_hw_info {
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index efdda4f..986cc51 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -365,7 +365,7 @@
  *
  */
 static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
-	struct cam_req_mgr_req_queue *in_q)
+	struct cam_req_mgr_req_queue *in_q, uint32_t trigger)
 {
 	int                                  rc = 0, pd, i, idx;
 	struct cam_req_mgr_connected_device *dev = NULL;
@@ -391,6 +391,9 @@
 					link->req.apply_data[pd].req_id);
 				continue;
 			}
+			if (!(dev->dev_info.trigger & trigger))
+				continue;
+
 			apply_req.dev_hdl = dev->dev_hdl;
 			apply_req.request_id =
 				link->req.apply_data[pd].req_id;
@@ -400,6 +403,7 @@
 
 			trace_cam_req_mgr_apply_request(link, &apply_req, dev);
 
+			apply_req.trigger_point = trigger;
 			CAM_DBG(CAM_CRM, "SEND: pd %d req_id %lld",
 				pd, apply_req.request_id);
 			if (dev->ops && dev->ops->apply_req) {
@@ -488,7 +492,8 @@
  * @return   : 0 for success, negative for failure
  *
  */
-static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link)
+static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
+	uint32_t trigger)
 {
 	int                                  rc = 0, idx;
 	struct cam_req_mgr_slot             *slot = NULL;
@@ -499,7 +504,7 @@
 	session = (struct cam_req_mgr_core_session *)link->parent;
 
 	/*
-	 * 1. Check if new read index,
+	 * Check if new read index,
 	 * - if in pending  state, traverse again to complete
 	 *    transaction of this read index.
 	 * - if in applied_state, somthign wrong.
@@ -514,58 +519,70 @@
 		return 0;
 	}
 
-	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx);
-	if (rc >= 0) {
-		rc = __cam_req_mgr_send_req(link, link->req.in_q);
-		if (rc < 0) {
-			/* Apply req failed retry at next sof */
-			slot->status = CRM_SLOT_STATUS_REQ_PENDING;
-		} else {
-			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+	if (trigger != CAM_TRIGGER_POINT_SOF &&
+			trigger != CAM_TRIGGER_POINT_EOF)
+		return rc;
 
+	if (trigger == CAM_TRIGGER_POINT_SOF) {
+		if (!link->trigger_mask) {
+			CAM_ERR(CAM_CRM, "Applying for last EOF fails");
+			return -EINVAL;
+		}
+		rc = __cam_req_mgr_check_link_is_ready(link, slot->idx);
+		if (rc < 0) {
+
+			 /* If traverse result is not success, then some devices
+			  * are not ready with packet for the asked request id,
+			  * hence try again in next sof
+			  */
+			slot->status = CRM_SLOT_STATUS_REQ_PENDING;
 			if (link->state == CAM_CRM_LINK_STATE_ERR) {
-				CAM_WARN(CAM_CRM,
-					"Err recovery done idx %d status %d",
+				/*
+				 * During error recovery all tables should be
+				 * ready, don't expect to enter here.
+				 * @TODO: gracefully handle if recovery fails.
+				 */
+				CAM_ERR(CAM_CRM,
+					"FATAL recovery cant finish idx %d status %d",
 					in_q->rd_idx,
 					in_q->slot[in_q->rd_idx].status);
-				mutex_lock(&link->lock);
-				link->state = CAM_CRM_LINK_STATE_READY;
-				mutex_unlock(&link->lock);
+				rc = -EPERM;
 			}
+			return rc;
+		}
+	}
+	if (trigger == CAM_TRIGGER_POINT_EOF &&
+			(!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) {
+		CAM_ERR(CAM_CRM, "Applying for last SOF fails");
+		return -EINVAL;
+	}
 
-			/*
-			 * 2. Check if any new req is pending in input queue,
-			 *    if not finish the lower pipeline delay device with
-			 *    available req ids.
-			 */
+	rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger);
+	if (rc < 0) {
+		/* Apply req failed retry at next sof */
+		slot->status = CRM_SLOT_STATUS_REQ_PENDING;
+	} else {
+		link->trigger_mask |= trigger;
+
+		if (link->state == CAM_CRM_LINK_STATE_ERR) {
+			CAM_WARN(CAM_CRM, "Err recovery done idx %d",
+				in_q->rd_idx);
+			mutex_lock(&link->lock);
+			link->state = CAM_CRM_LINK_STATE_READY;
+			mutex_unlock(&link->lock);
+		}
+		if (link->trigger_mask == link->subscribe_event) {
+			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+			link->trigger_mask = 0;
+			CAM_DBG(CAM_CRM, "req is applied\n");
 			__cam_req_mgr_check_next_req_slot(in_q);
 
-			/*
-			 * 3. Older req slots can be safely reset as no err ack.
-			 */
 			idx = in_q->rd_idx;
-			__cam_req_mgr_dec_idx(&idx, link->max_delay + 1,
+			__cam_req_mgr_dec_idx(
+				&idx, link->max_delay + 1,
 				in_q->num_slots);
 			__cam_req_mgr_reset_req_slot(link, idx);
 		}
-	} else {
-		/*
-		 * 4.If traverse result is not success, then some devices are
-		 *   not ready with packet for the asked request id,
-		 *   hence try again in next sof
-		 */
-		slot->status = CRM_SLOT_STATUS_REQ_PENDING;
-		if (link->state == CAM_CRM_LINK_STATE_ERR) {
-			/*
-			 * During error recovery all tables should be ready
-			 *   don't expect to enter here.
-			 * @TODO: gracefully handle if recovery fails.
-			 */
-			CAM_ERR(CAM_CRM,
-				"FATAL recovery cant finish idx %d status %d",
-				in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
-			rc = -EPERM;
-		}
 	}
 
 	return rc;
@@ -576,7 +593,7 @@
  *
  * @brief    : Add table to list under link sorted by pd decremeting order
  * @l_tbl    : list of pipeline delay tables.
- * @new_tbl : new tbl which will be appended to above list as per its pd value
+ * @new_tbl  : new tbl which will be appended to above list as per its pd value
  *
  */
 static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl,
@@ -828,6 +845,7 @@
 	link_data.link_enable = 0;
 	link_data.link_hdl = link->link_hdl;
 	link_data.crm_cb = NULL;
+	link_data.subscribe_event = 0;
 
 	/* Using device ops unlink devices */
 	for (i = 0; i < link->num_devs; i++) {
@@ -977,7 +995,7 @@
 	send_req = (struct cam_req_mgr_send_request *)data;
 	in_q = send_req->in_q;
 
-	rc = __cam_req_mgr_send_req(link, in_q);
+	rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF);
 end:
 	return rc;
 }
@@ -1302,7 +1320,7 @@
 }
 
 /**
- * cam_req_mgr_process_sof()
+ * cam_req_mgr_process_trigger()
  *
  * @brief: This runs in workque thread context. Call core funcs to check
  *         which peding requests can be processed.
@@ -1311,10 +1329,10 @@
  *
  * @return: 0 on success.
  */
-static int cam_req_mgr_process_sof(void *priv, void *data)
+static int cam_req_mgr_process_trigger(void *priv, void *data)
 {
 	int                                  rc = 0;
-	struct cam_req_mgr_sof_notify       *sof_data = NULL;
+	struct cam_req_mgr_trigger_notify   *trigger_data = NULL;
 	struct cam_req_mgr_core_link        *link = NULL;
 	struct cam_req_mgr_req_queue        *in_q = NULL;
 	struct crm_task_payload             *task_data = NULL;
@@ -1326,11 +1344,12 @@
 	}
 	link = (struct cam_req_mgr_core_link *)priv;
 	task_data = (struct crm_task_payload *)data;
-	sof_data = (struct cam_req_mgr_sof_notify *)&task_data->u;
+	trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u;
 
-	CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld",
-		sof_data->link_hdl,
-		sof_data->frame_id);
+	CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld, trigger %x\n",
+		trigger_data->link_hdl,
+		trigger_data->frame_id,
+		trigger_data->trigger);
 
 	in_q = link->req.in_q;
 
@@ -1354,7 +1373,7 @@
 		 */
 		__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
 	}
-	rc = __cam_req_mgr_process_req(link);
+	rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
 	mutex_unlock(&link->req.lock);
 
 end:
@@ -1484,7 +1503,7 @@
 }
 
 /**
- * cam_req_mgr_cb_notify_sof()
+ * cam_req_mgr_cb_notify_trigger()
  *
  * @brief   : SOF received from device, sends trigger through workqueue
  * @sof_data: contains information about frame_id, link etc.
@@ -1492,25 +1511,25 @@
  * @return  : 0 on success
  *
  */
-static int cam_req_mgr_cb_notify_sof(
-	struct cam_req_mgr_sof_notify *sof_data)
+static int cam_req_mgr_cb_notify_trigger(
+	struct cam_req_mgr_trigger_notify *trigger_data)
 {
 	int                              rc = 0;
 	struct crm_workq_task           *task = NULL;
 	struct cam_req_mgr_core_link    *link = NULL;
-	struct cam_req_mgr_sof_notify   *notify_sof;
+	struct cam_req_mgr_trigger_notify   *notify_trigger;
 	struct crm_task_payload         *task_data;
 
-	if (!sof_data) {
+	if (!trigger_data) {
 		CAM_ERR(CAM_CRM, "sof_data is NULL");
 		rc = -EINVAL;
 		goto end;
 	}
 
 	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(sof_data->link_hdl);
+		cam_get_device_priv(trigger_data->link_hdl);
 	if (!link) {
-		CAM_DBG(CAM_CRM, "link ptr NULL %x", sof_data->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1519,17 +1538,18 @@
 	task = cam_req_mgr_workq_get_task(link->workq);
 	if (!task) {
 		CAM_ERR(CAM_CRM, "no empty task frame %lld",
-			sof_data->frame_id);
+			trigger_data->frame_id);
 		rc = -EBUSY;
 		goto end;
 	}
 	task_data = (struct crm_task_payload *)task->payload;
 	task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF;
-	notify_sof = (struct cam_req_mgr_sof_notify *)&task_data->u;
-	notify_sof->frame_id = sof_data->frame_id;
-	notify_sof->link_hdl = sof_data->link_hdl;
-	notify_sof->dev_hdl = sof_data->dev_hdl;
-	task->process_cb = &cam_req_mgr_process_sof;
+	notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u;
+	notify_trigger->frame_id = trigger_data->frame_id;
+	notify_trigger->link_hdl = trigger_data->link_hdl;
+	notify_trigger->dev_hdl = trigger_data->dev_hdl;
+	notify_trigger->trigger = trigger_data->trigger;
+	task->process_cb = &cam_req_mgr_process_trigger;
 	rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
 
 end:
@@ -1537,9 +1557,9 @@
 }
 
 static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
-	.notify_sof = cam_req_mgr_cb_notify_sof,
-	.notify_err = cam_req_mgr_cb_notify_err,
-	.add_req    = cam_req_mgr_cb_add_req,
+	.notify_trigger = cam_req_mgr_cb_notify_trigger,
+	.notify_err     = cam_req_mgr_cb_notify_err,
+	.add_req        = cam_req_mgr_cb_add_req,
 };
 
 /**
@@ -1561,6 +1581,7 @@
 	struct cam_req_mgr_connected_device    *dev;
 	struct cam_req_mgr_req_tbl             *pd_tbl;
 	enum cam_pipeline_delay                 max_delay;
+	uint32_t                                subscribe_event = 0;
 
 	if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
 		return -EPERM;
@@ -1594,9 +1615,11 @@
 
 		trace_cam_req_mgr_connect_device(link, &dev->dev_info);
 
-		CAM_DBG(CAM_CRM, "%x: connected: %s, id %d, delay %d",
+		CAM_DBG(CAM_CRM,
+			"%x: connected: %s, id %d, delay %d, trigger %x",
 			link_info->session_hdl, dev->dev_info.name,
-			dev->dev_info.dev_id, dev->dev_info.p_delay);
+			dev->dev_info.dev_id, dev->dev_info.p_delay,
+			dev->dev_info.trigger);
 		if (rc < 0 ||
 			dev->dev_info.p_delay >=
 			CAM_PIPELINE_DELAY_MAX ||
@@ -1609,18 +1632,19 @@
 				link_info->session_hdl,
 				dev->dev_info.name,
 				dev->dev_info.p_delay);
-			if (dev->dev_info.p_delay >
-				max_delay)
-			max_delay =
-				dev->dev_info.p_delay;
+			if (dev->dev_info.p_delay > max_delay)
+				max_delay = dev->dev_info.p_delay;
+
+			subscribe_event |= (uint32_t)dev->dev_info.trigger;
 		}
 	}
 
-
+	link->subscribe_event = subscribe_event;
 	link_data.link_enable = 1;
 	link_data.link_hdl = link->link_hdl;
 	link_data.crm_cb = &cam_req_mgr_ops;
 	link_data.max_delay = max_delay;
+	link_data.subscribe_event = subscribe_event;
 
 	for (i = 0; i < link_info->num_devices; i++) {
 		dev = &link->l_dev[i];
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 3ee0e2f..98a2a4f 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -47,15 +47,15 @@
 
 /**
  * struct crm_task_payload
- * @type       : to identify which type of task is present
- * @u          : union of payload of all types of tasks supported
- * @sched_req  : contains info of  incoming reqest from CSL to CRM
- * @flush_info : contains info of cancelled reqest
- * @dev_req    : contains tracking info of available req id at device
- * @send_req   : contains info of apply settings to be sent to devs in link
- * @apply_req  : contains info of which request is applied at device
- * @notify_sof : contains notification from IFE to CRM about SOF trigger
- * @notify_err : contains error info happened while processing request
+ * @type           : to identify which type of task is present
+ * @u              : union of payload of all types of tasks supported
+ * @sched_req      : contains info of  incoming reqest from CSL to CRM
+ * @flush_info     : contains info of cancelled reqest
+ * @dev_req        : contains tracking info of available req id at device
+ * @send_req       : contains info of apply settings to be sent to devs in link
+ * @apply_req      : contains info of which request is applied at device
+ * @notify_trigger : contains notification from IFE to CRM about trigger
+ * @notify_err     : contains error info happened while processing request
  * -
  */
 struct crm_task_payload {
@@ -65,7 +65,7 @@
 		struct cam_req_mgr_flush_info           flush_info;
 		struct cam_req_mgr_add_request          dev_req;
 		struct cam_req_mgr_send_request         send_req;
-		struct cam_req_mgr_sof_notify           notify_sof;
+		struct cam_req_mgr_trigger_notify       notify_trigger;
 		struct cam_req_mgr_error_notify         notify_err;
 	} u;
 };
@@ -90,8 +90,8 @@
  * State machine for life cycle of request in input queue
  * NO_REQ     : empty slot
  * REQ_ADDED  : new entry in slot
- * INCOMPLETE : waiting for
- * APPLIED    : req is sent to devices
+ * PENDING    : waiting for next trigger to apply
+ * APPLIED    : req is sent to all devices
  * INVALID    : invalid state
  */
 enum crm_slot_status {
@@ -108,7 +108,7 @@
  * AVAILABLE  : link available
  * IDLE       : link initialized but not ready yet
  * READY      : link is ready for use
- * ERR	      : link has encountered error
+ * ERR        : link has encountered error
  * MAX        : invalid state
  */
 enum cam_req_mgr_link_state {
@@ -189,12 +189,12 @@
 /**
  * struct cam_req_mgr_slot
  * - Internal Book keeping
- * @idx      : slot index
- * @skip_idx : if req id in this slot needs to be skipped/not applied
- * @status   : state machine for life cycle of a slot
+ * @idx          : slot index
+ * @skip_idx     : if req id in this slot needs to be skipped/not applied
+ * @status       : state machine for life cycle of a slot
  * - members updated due to external events
- * @recover  : if user enabled recovery for this request.
- * @req_id   : mask tracking which all devices have request ready
+ * @recover      : if user enabled recovery for this request.
+ * @req_id       : mask tracking which all devices have request ready
  */
 struct cam_req_mgr_slot {
 	int32_t               idx;
@@ -275,6 +275,9 @@
  * @state          : link state machine
  * @parent         : pvt data - link's parent is session
  * @lock           : mutex lock to guard link data operations
+ * @subscribe_event: irqs that link subscribes, IFE should send notification
+ * to CRM at those hw events.
+ * @trigger_mask   : mask on which irq the req is already applied
  */
 struct cam_req_mgr_core_link {
 	int32_t                              link_hdl;
@@ -289,6 +292,8 @@
 	enum cam_req_mgr_link_state          state;
 	void                                *parent;
 	struct mutex                         lock;
+	uint32_t                             subscribe_event;
+	uint32_t                             trigger_mask;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index 8faf35a..6195b59 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -18,7 +18,7 @@
 #include "cam_req_mgr_core_defs.h"
 #include "cam_req_mgr_util.h"
 
-struct cam_req_mgr_sof_notify;
+struct cam_req_mgr_trigger_notify;
 struct cam_req_mgr_error_notify;
 struct cam_req_mgr_add_request;
 struct cam_req_mgr_device_info;
@@ -29,13 +29,15 @@
 
 /* Request Manager -- camera device driver interface */
 /**
- * @brief: camera kernel drivers  to cam req mgr communication
+ * @brief: camera kernel drivers to cam req mgr communication
  *
- * @cam_req_mgr_notify_sof: for device which generates sof 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_trigger: for device which generates 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
  */
-typedef int (*cam_req_mgr_notify_sof)(struct cam_req_mgr_sof_notify *);
+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_add_req)(struct cam_req_mgr_add_request *);
 
@@ -57,16 +59,16 @@
 typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *);
 
 /**
- * @brief      : cam_req_mgr_crm_cb - func table
+ * @brief          : cam_req_mgr_crm_cb - func table
  *
- * @notify_sof : payload for sof indication event
- * @notify_err : payload for different error occurred at device
- * @add_req    : payload to inform which device and what request is received
+ * @notify_trigger : payload for trigger indication event
+ * @notify_err     : payload for different error occurred at device
+ * @add_req        : payload to inform which device and what request is received
  */
 struct cam_req_mgr_crm_cb {
-	cam_req_mgr_notify_sof  notify_sof;
-	cam_req_mgr_notify_err  notify_err;
-	cam_req_mgr_add_req     add_req;
+	cam_req_mgr_notify_trigger  notify_trigger;
+	cam_req_mgr_notify_err      notify_err;
+	cam_req_mgr_add_req         add_req;
 };
 
 /**
@@ -103,6 +105,13 @@
 };
 
 /**
+ * @CAM_TRIGGER_POINT_SOF   : Trigger point for SOF
+ * @CAM_TRIGGER_POINT_EOF   : Trigger point for EOF
+ */
+#define CAM_TRIGGER_POINT_SOF     (1 << 0)
+#define CAM_TRIGGER_POINT_EOF     (1 << 1)
+
+/**
  * enum cam_req_status
  * @brief   : enumerator for request status
  *
@@ -177,15 +186,18 @@
 };
 
 /**
- * struct cam_req_mgr_sof_notify
+ * struct cam_req_mgr_trigger_notify
  * @link_hdl : link identifier
  * @dev_hdl  : device handle which has sent this req id
  * @frame_id : frame id for internal tracking
+ * @trigger  : trigger point of this notification, CRM will send apply
+ * only to the devices which subscribe to this point.
  */
-struct cam_req_mgr_sof_notify {
-	int32_t link_hdl;
-	int32_t dev_hdl;
-	int64_t frame_id;
+struct cam_req_mgr_trigger_notify {
+	int32_t  link_hdl;
+	int32_t  dev_hdl;
+	int64_t  frame_id;
+	uint32_t trigger;
 };
 
 /**
@@ -223,6 +235,7 @@
  * @name    : link link or unlink
  * @dev_id  : device id info
  * @p_delay : delay between time settings applied and take effect
+ * @trigger : Trigger point for the client
  *
  */
 struct cam_req_mgr_device_info {
@@ -230,15 +243,17 @@
 	char                        name[256];
 	enum cam_req_mgr_device_id  dev_id;
 	enum cam_pipeline_delay     p_delay;
+	uint32_t                    trigger;
 };
 
 /**
  * struct cam_req_mgr_core_dev_link_setup
- * @link_enable : link link or unlink
- * @link_hdl    : link identifier
- * @dev_hdl     : device handle for reference
- * @max_delay   : max pipeline delay on this link
- * @crm_cb      : callback funcs to communicate with req mgr
+ * @link_enable     : link link or unlink
+ * @link_hdl        : link identifier
+ * @dev_hdl         : device handle for reference
+ * @max_delay       : max pipeline delay on this link
+ * @crm_cb          : callback funcs to communicate with req mgr
+ * @subscribe_event : the mask of trigger points this link subscribes
  *
  */
 struct cam_req_mgr_core_dev_link_setup {
@@ -247,6 +262,7 @@
 	int32_t                    dev_hdl;
 	enum cam_pipeline_delay    max_delay;
 	struct cam_req_mgr_crm_cb *crm_cb;
+	uint32_t                   subscribe_event;
 };
 
 /**
@@ -255,6 +271,7 @@
  * @dev_hdl          : device handle for cross check
  * @request_id       : request id settings to apply
  * @report_if_bubble : report to crm if failure in applying
+ * @trigger_point    : the trigger point of this apply
  *
  */
 struct cam_req_mgr_apply_request {
@@ -262,6 +279,7 @@
 	int32_t    dev_hdl;
 	uint64_t   request_id;
 	int32_t    report_if_bubble;
+	uint32_t   trigger_point;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 18097b0..786a572 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -185,6 +185,7 @@
 	info->dev_id = CAM_REQ_MGR_DEVICE_ACTUATOR;
 	strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name));
 	info->p_delay = 0;
+	info->trigger = CAM_TRIGGER_POINT_SOF;
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index 7af7efc..5c64451 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -617,6 +617,7 @@
 	info->dev_id = CAM_REQ_MGR_DEVICE_FLASH;
 	strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name));
 	info->p_delay = CAM_FLASH_PIPELINE_DELAY;
+	info->trigger = CAM_TRIGGER_POINT_EOF;
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index f6e6a9a..75205f9 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -588,6 +588,7 @@
 	info->dev_id = CAM_REQ_MGR_DEVICE_SENSOR;
 	strlcpy(info->name, CAM_SENSOR_NAME, sizeof(info->name));
 	info->p_delay = 2;
+	info->trigger = CAM_TRIGGER_POINT_SOF;
 
 	return rc;
 }