Explorar o código

msm: camera: isp: Report frame timing events in correct sequence

Due to interrupt delays, when VFE top processes the interrupt registers
it might see EPOCH and EOF of frame n along with SOF of frame n+1. The
current logic is based on IRQ controller priority and hence will report
SOF of frame n+1 before EPOCH of frame n. This can result in ISP context
reporting SOF timestamp of frame n+1 for both frame n and frame n+1.

In order to report the events in the order that they occurred, we
maintain a state machine in VFE top to keep track of the last seen
event. This helps detect any missing IRQs and also warn when such
interrupt delays are observed.

The state machine logic is only able to handle delays less than 1 frame.
For example, EPOCH of frame n+1 occurs before VFE top has read EPOCH of
frame n, there is no way to tell that this is the case from the
interrupt registers.

CRs-Fixed: 3067696
Change-Id: I061732c20ff23ca9394ae9844d50729476ad07b5
Signed-off-by: Anand Ravi <[email protected]>
Anand Ravi %!s(int64=3) %!d(string=hai) anos
pai
achega
a3632ffe16

+ 4 - 25
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -164,27 +164,6 @@ static inline int __cam_ife_mgr_get_hw_soc_info(
 	return rc;
 }
 
-static const char *__cam_ife_hw_mgr_evt_type_to_string(
-	enum cam_isp_hw_event_type evt_type)
-{
-	switch (evt_type) {
-	case CAM_ISP_HW_EVENT_ERROR:
-		return "ERROR";
-	case CAM_ISP_HW_EVENT_SOF:
-		return "SOF";
-	case CAM_ISP_HW_EVENT_REG_UPDATE:
-		return "REG_UPDATE";
-	case CAM_ISP_HW_EVENT_EPOCH:
-		return "EPOCH";
-	case CAM_ISP_HW_EVENT_EOF:
-		return "EOF";
-	case CAM_ISP_HW_EVENT_DONE:
-		return "BUF_DONE";
-	default:
-		return "INVALID_EVT";
-	}
-}
-
 static int cam_ife_mgr_regspace_data_cb(uint32_t reg_base_type,
 	void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr,
 	uint32_t *reg_base_idx)
@@ -12366,7 +12345,7 @@ static int cam_ife_hw_mgr_handle_ife_event(
 
 	CAM_DBG(CAM_ISP, "Handle IFE[%u] %s event in ctx: %u",
 		event_info->hw_idx,
-		__cam_ife_hw_mgr_evt_type_to_string(evt_id),
+		cam_isp_hw_evt_type_to_string(evt_id),
 		ctx->ctx_index);
 
 	switch (evt_id) {
@@ -12412,7 +12391,7 @@ static int cam_ife_hw_mgr_handle_csid_event(
 
 	CAM_DBG(CAM_ISP, "Handle CSID[%u] %s event in ctx: %u",
 		event_info->hw_idx,
-		__cam_ife_hw_mgr_evt_type_to_string(evt_id),
+		cam_isp_hw_evt_type_to_string(evt_id),
 		ctx->ctx_index);
 
 	switch (evt_id) {
@@ -12450,7 +12429,7 @@ static int cam_ife_hw_mgr_handle_sfe_event(
 
 	CAM_DBG(CAM_ISP, "Handle SFE[%u] %s event in ctx: %u",
 		event_info->hw_idx,
-		__cam_ife_hw_mgr_evt_type_to_string(evt_id),
+		cam_isp_hw_evt_type_to_string(evt_id),
 		ctx->ctx_index);
 
 	switch (evt_id) {
@@ -12509,7 +12488,7 @@ static int cam_ife_hw_mgr_event_handler(
 
 	if (rc)
 		CAM_ERR(CAM_ISP, "Failed to handle %s [%u] event from hw %u in ctx %u rc %d",
-			__cam_ife_hw_mgr_evt_type_to_string(evt_id),
+			cam_isp_hw_evt_type_to_string(evt_id),
 			evt_id, event_info->hw_type, ctx->ctx_index, rc);
 
 	return rc;

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

@@ -67,6 +67,30 @@ enum cam_isp_hw_event_type {
 	CAM_ISP_HW_EVENT_MAX
 };
 
+/**
+ * cam_isp_hw_evt_type_to_string() - convert cam_isp_hw_event_type to string for printing logs
+ */
+static inline const char *cam_isp_hw_evt_type_to_string(
+	enum cam_isp_hw_event_type evt_type)
+{
+	switch (evt_type) {
+	case CAM_ISP_HW_EVENT_ERROR:
+		return "ERROR";
+	case CAM_ISP_HW_EVENT_SOF:
+		return "SOF";
+	case CAM_ISP_HW_EVENT_REG_UPDATE:
+		return "REG_UPDATE";
+	case CAM_ISP_HW_EVENT_EPOCH:
+		return "EPOCH";
+	case CAM_ISP_HW_EVENT_EOF:
+		return "EOF";
+	case CAM_ISP_HW_EVENT_DONE:
+		return "BUF_DONE";
+	default:
+		return "INVALID_EVT";
+	}
+}
+
 /**
  *  enum cam_isp_hw_secondary-event_type - Collection of the ISP hardware secondary events
  */

+ 211 - 107
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c

@@ -35,6 +35,13 @@ struct cam_vfe_top_ver4_priv {
 	uint32_t                            sof_cnt;
 };
 
+enum cam_vfe_top_ver4_fsm_state {
+	VFE_TOP_VER4_FSM_SOF = 0,
+	VFE_TOP_VER4_FSM_EPOCH,
+	VFE_TOP_VER4_FSM_EOF,
+	VFE_TOP_VER4_FSM_MAX,
+};
+
 struct cam_vfe_mux_ver4_data {
 	void __iomem                                *mem_base;
 	struct cam_hw_soc_info                      *soc_info;
@@ -47,8 +54,7 @@ struct cam_vfe_mux_ver4_data {
 	cam_hw_mgr_event_cb_func             event_cb;
 	void                                *priv;
 	int                                  irq_err_handle;
-	int                                  irq_handle;
-	int                                  sof_irq_handle;
+	int                                  frame_irq_handle;
 	void                                *vfe_irq_controller;
 	struct cam_vfe_top_irq_evt_payload   evt_payload[CAM_VFE_CAMIF_EVT_MAX];
 	struct list_head                     free_payload_list;
@@ -77,10 +83,12 @@ struct cam_vfe_mux_ver4_data {
 	bool                               is_pixel_path;
 	bool                               sfe_binned_epoch_cfg;
 
-	struct timespec64                     sof_ts;
-	struct timespec64                     epoch_ts;
-	struct timespec64                     eof_ts;
-	struct timespec64                     error_ts;
+	struct timespec64                  sof_ts;
+	struct timespec64                  epoch_ts;
+	struct timespec64                  eof_ts;
+	struct timespec64                  error_ts;
+	enum cam_vfe_top_ver4_fsm_state    fsm_state;
+	uint32_t                           n_frame_irqs;
 };
 
 static int cam_vfe_top_ver4_get_path_port_map(struct cam_vfe_top_ver4_priv *top_priv,
@@ -1091,6 +1099,182 @@ static int cam_vfe_handle_irq_top_half(uint32_t evt_id,
 	return rc;
 }
 
+static void cam_vfe_irq_status_to_event(struct cam_vfe_mux_ver4_data *vfe_priv,
+	uint32_t irq_status, bool *sof, bool *epoch, bool *eof)
+{
+	*sof = (irq_status & vfe_priv->reg_data->sof_irq_mask);
+	*epoch = (irq_status & vfe_priv->reg_data->epoch0_irq_mask);
+	*eof = (irq_status & vfe_priv->reg_data->eof_irq_mask);
+}
+
+static enum cam_vfe_top_ver4_fsm_state cam_vfe_top_ver4_fsm_next_state(
+	struct cam_isp_resource_node *res,
+	enum cam_vfe_top_ver4_fsm_state state)
+{
+	switch (state) {
+	case VFE_TOP_VER4_FSM_SOF:
+		return (res->rdi_only_ctx) ? VFE_TOP_VER4_FSM_EOF : VFE_TOP_VER4_FSM_EPOCH;
+	case VFE_TOP_VER4_FSM_EPOCH:
+		return VFE_TOP_VER4_FSM_EOF;
+	case VFE_TOP_VER4_FSM_EOF:
+		return VFE_TOP_VER4_FSM_SOF;
+	default:
+		/* set to SOF to recover from incorrect state */
+		return VFE_TOP_VER4_FSM_SOF;
+	}
+}
+
+static const char *cam_vfe_top_ver4_fsm_state_to_string(
+	enum cam_vfe_top_ver4_fsm_state state)
+{
+	switch (state) {
+	case VFE_TOP_VER4_FSM_SOF:   return "SOF";
+	case VFE_TOP_VER4_FSM_EPOCH: return "EPOCH";
+	case VFE_TOP_VER4_FSM_EOF:   return "EOF";
+	default:                     return "INVALID";
+	}
+}
+
+typedef int (*cam_vfe_handle_frame_irq_t)(struct cam_vfe_mux_ver4_data *vfe_priv,
+	struct cam_vfe_top_irq_evt_payload *payload,
+	struct cam_isp_hw_event_info *evt_info);
+
+
+static int cam_vfe_handle_sof(struct cam_vfe_mux_ver4_data *vfe_priv,
+	struct cam_vfe_top_irq_evt_payload *payload,
+	struct cam_isp_hw_event_info *evt_info)
+{
+	if ((vfe_priv->enable_sof_irq_debug) &&
+		(vfe_priv->irq_debug_cnt <=
+		CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) {
+		CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE:%d Received SOF",
+			vfe_priv->hw_intf->hw_idx);
+
+		vfe_priv->irq_debug_cnt++;
+		if (vfe_priv->irq_debug_cnt ==
+			CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) {
+			vfe_priv->enable_sof_irq_debug = false;
+			vfe_priv->irq_debug_cnt = 0;
+		}
+	} else {
+		CAM_DBG(CAM_ISP, "VFE:%d Received SOF",
+			vfe_priv->hw_intf->hw_idx);
+		vfe_priv->sof_ts.tv_sec = payload->ts.mono_time.tv_sec;
+		vfe_priv->sof_ts.tv_nsec = payload->ts.mono_time.tv_nsec;
+	}
+	vfe_priv->top_priv->sof_cnt++;
+
+	cam_cpas_notify_event("IFE SOF", vfe_priv->hw_intf->hw_idx);
+
+	return 0;
+}
+
+static int cam_vfe_handle_epoch(struct cam_vfe_mux_ver4_data *vfe_priv,
+	struct cam_vfe_top_irq_evt_payload *payload,
+	struct cam_isp_hw_event_info *evt_info)
+{
+	CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", vfe_priv->hw_intf->hw_idx);
+	evt_info->reg_val = payload->reg_val;
+	vfe_priv->epoch_ts.tv_sec = payload->ts.mono_time.tv_sec;
+	vfe_priv->epoch_ts.tv_nsec = payload->ts.mono_time.tv_nsec;
+
+	cam_cpas_notify_event("IFE EPOCH", vfe_priv->hw_intf->hw_idx);
+	return 0;
+}
+
+static int cam_vfe_handle_eof(struct cam_vfe_mux_ver4_data *vfe_priv,
+	struct cam_vfe_top_irq_evt_payload *payload,
+	struct cam_isp_hw_event_info *evt_info)
+{
+	CAM_DBG(CAM_ISP, "VFE:%d Received EOF", vfe_priv->hw_intf->hw_idx);
+	vfe_priv->epoch_ts.tv_sec = payload->ts.mono_time.tv_sec;
+	vfe_priv->epoch_ts.tv_nsec = payload->ts.mono_time.tv_nsec;
+
+	cam_cpas_notify_event("IFE EOF", vfe_priv->hw_intf->hw_idx);
+	return 0;
+}
+
+static int __cam_vfe_handle_frame_timing_irqs(struct cam_isp_resource_node *vfe_res, bool event,
+	enum cam_isp_hw_event_type event_type, cam_vfe_handle_frame_irq_t handle_irq_fn,
+	struct cam_vfe_top_irq_evt_payload *payload, struct cam_isp_hw_event_info *evt_info)
+{
+	struct cam_vfe_mux_ver4_data *vfe_priv = vfe_res->res_priv;
+
+	if (!event) {
+		CAM_WARN(CAM_ISP, "VFE:%u missed %s", vfe_priv->hw_intf->hw_idx,
+			cam_isp_hw_evt_type_to_string(event_type));
+	} else {
+		handle_irq_fn(vfe_priv, payload, evt_info);
+		if (vfe_priv->event_cb)
+			vfe_priv->event_cb(vfe_priv->priv, event_type, evt_info);
+	}
+	vfe_priv->fsm_state = cam_vfe_top_ver4_fsm_next_state(vfe_res, vfe_priv->fsm_state);
+
+	return 0;
+}
+
+static int cam_vfe_handle_frame_timing_irqs(struct cam_isp_resource_node *vfe_res,
+	uint32_t irq_status, struct cam_vfe_top_irq_evt_payload *payload,
+	struct cam_isp_hw_event_info *evt_info)
+{
+	struct cam_vfe_mux_ver4_data *vfe_priv = vfe_res->res_priv;
+	bool sof, epoch, eof;
+	int i, j;
+
+	cam_vfe_irq_status_to_event(vfe_priv, irq_status, &sof, &epoch, &eof);
+	CAM_DBG(CAM_ISP, "VFE:%u SOF:%s EPOCH:%s EOF:%s", vfe_priv->hw_intf->hw_idx,
+		CAM_BOOL_TO_YESNO(sof), CAM_BOOL_TO_YESNO(epoch), CAM_BOOL_TO_YESNO(eof));
+
+	i = (sof ? 1 : 0) + (epoch ? 1 : 0) + (eof ? 1 : 0);
+	j = i;
+
+	if (i == vfe_priv->n_frame_irqs)
+		CAM_WARN_RATE_LIMIT(CAM_ISP, "VFE:%u top-half delay", vfe_priv->hw_intf->hw_idx);
+
+	while (i > 0) {
+		bool event;
+		enum cam_isp_hw_event_type event_type;
+		cam_vfe_handle_frame_irq_t handle_irq_fn;
+
+		CAM_DBG_PR2(CAM_ISP, "VFE:%u enter state:%s (%d/%d)", vfe_priv->hw_intf->hw_idx,
+			cam_vfe_top_ver4_fsm_state_to_string(vfe_priv->fsm_state), i, j);
+
+		switch (vfe_priv->fsm_state) {
+		case VFE_TOP_VER4_FSM_SOF:
+			event = sof;
+			event_type = CAM_ISP_HW_EVENT_SOF;
+			handle_irq_fn = cam_vfe_handle_sof;
+			break;
+		case VFE_TOP_VER4_FSM_EPOCH:
+			event = epoch;
+			event_type = CAM_ISP_HW_EVENT_EPOCH;
+			handle_irq_fn = cam_vfe_handle_epoch;
+			break;
+		case VFE_TOP_VER4_FSM_EOF:
+			event = eof;
+			event_type = CAM_ISP_HW_EVENT_EOF;
+			handle_irq_fn = cam_vfe_handle_eof;
+			break;
+		default:
+			CAM_ERR(CAM_ISP, "VFE:%u frame state machine in invalid state",
+				vfe_priv->hw_intf->hw_idx);
+			return -EINVAL;
+		}
+
+		/* consume event */
+		if (event)
+			i--;
+
+		__cam_vfe_handle_frame_timing_irqs(vfe_res, event, event_type, handle_irq_fn,
+			payload, evt_info);
+
+		CAM_DBG_PR2(CAM_ISP, "VFE:%u exit state:%s (%d/%d)", vfe_priv->hw_intf->hw_idx,
+			cam_vfe_top_ver4_fsm_state_to_string(vfe_priv->fsm_state), i, j);
+	}
+
+	return CAM_VFE_IRQ_STATUS_SUCCESS;
+}
+
 
 static int cam_vfe_handle_irq_bottom_half(void *handler_priv,
 	void *evt_payload_priv)
@@ -1101,7 +1285,7 @@ static int cam_vfe_handle_irq_bottom_half(void *handler_priv,
 	struct cam_vfe_top_irq_evt_payload *payload;
 	struct cam_isp_hw_event_info evt_info;
 	struct cam_isp_hw_error_event_info err_evt_info;
-	uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0};
+	uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}, frame_timing_mask;
 	struct timespec64 ts;
 	int i = 0;
 
@@ -1133,71 +1317,14 @@ static int cam_vfe_handle_irq_bottom_half(void *handler_priv,
 	evt_info.res_type = vfe_res->res_type;
 	evt_info.reg_val = 0;
 
-	if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
-		& vfe_priv->reg_data->sof_irq_mask) {
-		if ((vfe_priv->enable_sof_irq_debug) &&
-			(vfe_priv->irq_debug_cnt <=
-			CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) {
-			CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE:%d Received SOF",
-				evt_info.hw_idx);
-
-			vfe_priv->irq_debug_cnt++;
-			if (vfe_priv->irq_debug_cnt ==
-				CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) {
-				vfe_priv->enable_sof_irq_debug =
-					false;
-				vfe_priv->irq_debug_cnt = 0;
-			}
-		} else {
-			CAM_DBG(CAM_ISP, "VFE:%d Received SOF",
-				evt_info.hw_idx);
-			vfe_priv->sof_ts.tv_sec =
-				payload->ts.mono_time.tv_sec;
-			vfe_priv->sof_ts.tv_nsec =
-				payload->ts.mono_time.tv_nsec;
-		}
-		vfe_priv->top_priv->sof_cnt++;
-
-		cam_cpas_notify_event("IFE SOF", evt_info.hw_idx);
-
-		if (vfe_priv->event_cb)
-			vfe_priv->event_cb(vfe_priv->priv,
-				CAM_ISP_HW_EVENT_SOF, (void *)&evt_info);
-		ret = CAM_VFE_IRQ_STATUS_SUCCESS;
-	}
-
-	if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
-		& vfe_priv->reg_data->epoch0_irq_mask) {
-		CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx);
-		evt_info.reg_val = payload->reg_val;
-		vfe_priv->epoch_ts.tv_sec =
-			payload->ts.mono_time.tv_sec;
-		vfe_priv->epoch_ts.tv_nsec =
-			payload->ts.mono_time.tv_nsec;
+	frame_timing_mask = vfe_priv->reg_data->sof_irq_mask |
+				vfe_priv->reg_data->epoch0_irq_mask |
+				vfe_priv->reg_data->eof_irq_mask;
 
-		cam_cpas_notify_event("IFE EPOCH", evt_info.hw_idx);
-
-		if (vfe_priv->event_cb)
-			vfe_priv->event_cb(vfe_priv->priv,
-				CAM_ISP_HW_EVENT_EPOCH, (void *)&evt_info);
-		ret = CAM_VFE_IRQ_STATUS_SUCCESS;
-	}
-
-	if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
-		& vfe_priv->reg_data->eof_irq_mask) {
-		CAM_DBG(CAM_ISP, "VFE:%d Received EOF", evt_info.hw_idx);
-		vfe_priv->eof_ts.tv_sec =
-			payload->ts.mono_time.tv_sec;
-		vfe_priv->eof_ts.tv_nsec =
-			payload->ts.mono_time.tv_nsec;
-
-		cam_cpas_notify_event("IFE EOF", evt_info.hw_idx);
-
-		if (vfe_priv->event_cb)
-			vfe_priv->event_cb(vfe_priv->priv,
-				CAM_ISP_HW_EVENT_EOF, (void *)&evt_info);
-
-		ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+	if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & frame_timing_mask) {
+		ret = cam_vfe_handle_frame_timing_irqs(vfe_res,
+			irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & frame_timing_mask,
+			payload, &evt_info);
 	}
 
 	if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]
@@ -1374,33 +1501,13 @@ skip_core_cfg:
 		(!rsrc_data->is_pixel_path && !vfe_res->rdi_only_ctx))
 		goto subscribe_err;
 
-	irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] =
+	irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = rsrc_data->reg_data->sof_irq_mask |
 		rsrc_data->reg_data->epoch0_irq_mask | rsrc_data->reg_data->eof_irq_mask;
 
-	if (!rsrc_data->irq_handle) {
-		rsrc_data->irq_handle = cam_irq_controller_subscribe_irq(
-			rsrc_data->vfe_irq_controller,
-			CAM_IRQ_PRIORITY_3,
-			irq_mask,
-			vfe_res,
-			vfe_res->top_half_handler,
-			vfe_res->bottom_half_handler,
-			vfe_res->tasklet_info,
-			&tasklet_bh_api,
-			CAM_IRQ_EVT_GROUP_0);
-
-		if (rsrc_data->irq_handle < 1) {
-			CAM_ERR(CAM_ISP, "IRQ handle subscribe failure");
-			rc = -ENOMEM;
-			rsrc_data->irq_handle = 0;
-		}
-	}
-
-	irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] =
-		rsrc_data->reg_data->sof_irq_mask;
+	rsrc_data->n_frame_irqs = hweight32(irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1]);
 
-	if (!rsrc_data->sof_irq_handle) {
-		rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq(
+	if (!rsrc_data->frame_irq_handle) {
+		rsrc_data->frame_irq_handle = cam_irq_controller_subscribe_irq(
 			rsrc_data->vfe_irq_controller,
 			CAM_IRQ_PRIORITY_1,
 			irq_mask,
@@ -1411,10 +1518,10 @@ skip_core_cfg:
 			&tasklet_bh_api,
 			CAM_IRQ_EVT_GROUP_0);
 
-		if (rsrc_data->sof_irq_handle < 1) {
-			CAM_ERR(CAM_ISP, "SOF IRQ handle subscribe failure");
+		if (rsrc_data->frame_irq_handle < 1) {
+			CAM_ERR(CAM_ISP, "Frame IRQs handle subscribe failure");
 			rc = -ENOMEM;
-			rsrc_data->sof_irq_handle = 0;
+			rsrc_data->frame_irq_handle = 0;
 		}
 	}
 
@@ -1440,6 +1547,8 @@ subscribe_err:
 		}
 	}
 
+	rsrc_data->fsm_state = VFE_TOP_VER4_FSM_SOF;
+
 	CAM_DBG(CAM_ISP, "VFE:%d Res: %s Start Done",
 		vfe_res->hw_intf->hw_idx,
 		vfe_res->res_name);
@@ -1491,18 +1600,13 @@ skip_core_decfg:
 			vfe_priv->common_reg->diag_config);
 	}
 
-	if (vfe_priv->irq_handle) {
-		cam_irq_controller_unsubscribe_irq(
-			vfe_priv->vfe_irq_controller, vfe_priv->irq_handle);
-		vfe_priv->irq_handle = 0;
-	}
-
-	if (vfe_priv->sof_irq_handle) {
+	if (vfe_priv->frame_irq_handle) {
 		cam_irq_controller_unsubscribe_irq(
 			vfe_priv->vfe_irq_controller,
-			vfe_priv->sof_irq_handle);
-		vfe_priv->sof_irq_handle = 0;
+			vfe_priv->frame_irq_handle);
+		vfe_priv->frame_irq_handle = 0;
 	}
+	vfe_priv->n_frame_irqs = 0;
 
 	if (vfe_priv->irq_err_handle) {
 		cam_irq_controller_unsubscribe_irq(