Преглед на файлове

disp: msm: sde: add support for CTL done irq

From Kalama, the HW scheduler abstracts the low level
PP_DONE/WB_DONE interrupts and generates a common
CTL_DONE interrupt per hw ctl. This saves the software
the irq latency delays to process the frame complete
operations when multiple encoders are involved.

If supported, this change enables and waits for the
CTL_DONE interrupt instead of PP_DONE and WB_DONE.

This change adds support to wait for CTL_DONE irq in
only command mode panels as we don't drive two WB blocks
with single CTL.

Change-Id: I084d6bfb6a9fb0b48f912fe5787401c460ec5b56
Signed-off-by: Jeykumar Sankaran <[email protected]>
Jeykumar Sankaran преди 4 години
родител
ревизия
39e7775bff
променени са 8 файла, в които са добавени 129 реда и са изтрити 27 реда
  1. 6 1
      msm/sde/sde_encoder.c
  2. 17 0
      msm/sde/sde_encoder.h
  3. 6 2
      msm/sde/sde_encoder_phys.h
  4. 68 24
      msm/sde/sde_encoder_phys_cmd.c
  5. 2 0
      msm/sde/sde_hw_catalog.c
  6. 3 0
      msm/sde/sde_hw_catalog.h
  7. 24 0
      msm/sde/sde_hw_interrupts.c
  8. 3 0
      msm/sde/sde_hw_interrupts.h

+ 6 - 1
msm/sde/sde_encoder.c

@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -3504,7 +3505,8 @@ static void sde_encoder_frame_done_callback(
 
 	if (event & (SDE_ENCODER_FRAME_EVENT_DONE
 			| SDE_ENCODER_FRAME_EVENT_ERROR
-			| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode) {
+			| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode
+			&& !sde_encoder_check_ctl_done_support(drm_enc)) {
 
 		if (ready_phys->connector)
 			topology = sde_connector_get_topology_name(
@@ -5099,6 +5101,9 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
 	sde_enc->input_event_enabled = test_bit(SDE_FEATURE_TOUCH_WAKEUP,
 						sde_kms->catalog->features);
 
+	sde_enc->ctl_done_supported = test_bit(SDE_FEATURE_CTL_DONE,
+						sde_kms->catalog->features);
+
 	mutex_lock(&sde_enc->enc_lock);
 	for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
 		/*

+ 17 - 0
msm/sde/sde_encoder.h

@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -182,6 +183,8 @@ enum sde_enc_rc_states {
  *				next update is triggered.
  * @autorefresh_solver_disable	It tracks if solver state is disabled from this
  *				encoder due to autorefresh concurrency.
+ * @ctl_done_supported          boolean flag to indicate the availability of
+ *                              ctl done irq support for the hardware
  */
 struct sde_encoder_virt {
 	struct drm_encoder base;
@@ -248,6 +251,7 @@ struct sde_encoder_virt {
 	struct msm_mode_info mode_info;
 	bool delay_kickoff;
 	bool autorefresh_solver_disable;
+	bool ctl_done_supported;
 };
 
 #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -524,6 +528,19 @@ bool sde_encoder_is_primary_display(struct drm_encoder *enc);
  */
 bool sde_encoder_is_built_in_display(struct drm_encoder *enc);
 
+/**
+ * sde_encoder_check_ctl_done_support - checks if ctl_done irq is available
+ *		for the display
+ * @drm_enc:    Pointer to drm encoder structure
+ * @Return:     true if scheduler update is enabled
+ */
+static inline bool sde_encoder_check_ctl_done_support(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+
+	return sde_enc && sde_enc->ctl_done_supported;
+}
+
 /**
  * sde_encoder_is_dsi_display - checks if underlying display is DSI
  *     display or not.

+ 6 - 2
msm/sde/sde_encoder_phys.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -195,6 +196,8 @@ struct sde_encoder_phys_ops {
  * @INTR_IDX_VSYNC:    Vsync interrupt for video mode panel
  * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel
  * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel
+ * @INTR_IDX_CTL_START:Control start interrupt to indicate the frame start
+ * @INTR_IDX_CTL_DONE: Control done interrupt indicating the control path being idle
  * @INTR_IDX_RDPTR:    Readpointer done interrupt for cmd mode panel
  * @INTR_IDX_WB_DONE:  Writeback done interrupt for WB
  * @INTR_IDX_PP1_OVFL: Pingpong overflow interrupt on PP1 for Concurrent WB
@@ -213,6 +216,7 @@ enum sde_intr_idx {
 	INTR_IDX_PINGPONG,
 	INTR_IDX_UNDERRUN,
 	INTR_IDX_CTL_START,
+	INTR_IDX_CTL_DONE,
 	INTR_IDX_RDPTR,
 	INTR_IDX_AUTOREFRESH_DONE,
 	INTR_IDX_WB_DONE,
@@ -400,7 +404,7 @@ struct sde_encoder_phys_cmd_te_timestamp {
  *	mode specific operations
  * @base:	Baseclass physical encoder structure
  * @stream_sel:	Stream selection for multi-stream interfaces
- * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
+ * @frame_tx_timeout_report_cnt: number of pp_done/ctl_done irq timeout errors
  * @autorefresh: autorefresh feature state
  * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
  * @pending_vblank_wq: Wait queue for blocking until VBLANK received
@@ -411,7 +415,7 @@ struct sde_encoder_phys_cmd_te_timestamp {
 struct sde_encoder_phys_cmd {
 	struct sde_encoder_phys base;
 	int stream_sel;
-	int pp_timeout_report_cnt;
+	int frame_tx_timeout_report_cnt;
 	struct sde_encoder_phys_cmd_autorefresh autorefresh;
 	atomic_t pending_vblank_cnt;
 	wait_queue_head_t pending_vblank_wq;

+ 68 - 24
msm/sde/sde_encoder_phys_cmd.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -170,30 +171,24 @@ static void _sde_encoder_phys_cmd_update_intf_cfg(
 	}
 }
 
-static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
+static void _sde_encoder_phys_signal_frame_done(struct sde_encoder_phys *phys_enc)
 {
-	struct sde_encoder_phys *phys_enc = arg;
 	struct sde_encoder_phys_cmd *cmd_enc;
 	struct sde_hw_ctl *ctl;
 	u32 scheduler_status = INVALID_CTL_STATUS, event = 0;
 
-	if (!phys_enc || !phys_enc->hw_pp)
-		return;
-
 	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
 	ctl = phys_enc->hw_ctl;
 
-	SDE_ATRACE_BEGIN("pp_done_irq");
-
 	/* notify all synchronous clients first, then asynchronous clients */
 	if (phys_enc->parent_ops.handle_frame_done &&
-	    atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
+		atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
 		event = SDE_ENCODER_FRAME_EVENT_DONE |
 			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
 		spin_lock(phys_enc->enc_spinlock);
 		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
 				phys_enc, event);
-		if (cmd_enc->pp_timeout_report_cnt)
+		if (cmd_enc->frame_tx_timeout_report_cnt)
 			phys_enc->recovered = true;
 		spin_unlock(phys_enc->enc_spinlock);
 	}
@@ -201,11 +196,38 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
 	if (ctl && ctl->ops.get_scheduler_status)
 		scheduler_status = ctl->ops.get_scheduler_status(ctl);
 
-	SDE_EVT32_IRQ(DRMID(phys_enc->parent),
-			phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status);
+	SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
+		phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status);
 
 	/* Signal any waiting atomic commit thread */
 	wake_up_all(&phys_enc->pending_kickoff_wq);
+}
+
+static void sde_encoder_phys_cmd_ctl_done_irq(void *arg, int irq_idx)
+{
+	struct sde_encoder_phys *phys_enc = arg;
+
+	if (!phys_enc)
+		return;
+
+	SDE_ATRACE_BEGIN("ctl_done_irq");
+
+	_sde_encoder_phys_signal_frame_done(phys_enc);
+
+	SDE_ATRACE_END("ctl_done_irq");
+}
+
+static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
+{
+	struct sde_encoder_phys *phys_enc = arg;
+
+	if (!phys_enc || !phys_enc->hw_pp)
+		return;
+
+	SDE_ATRACE_BEGIN("pp_done_irq");
+
+	_sde_encoder_phys_signal_frame_done(phys_enc);
+
 	SDE_ATRACE_END("pp_done_irq");
 }
 
@@ -337,6 +359,9 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
 	irq = &phys_enc->irq[INTR_IDX_CTL_START];
 	irq->hw_idx = phys_enc->hw_ctl->idx;
 
+	irq = &phys_enc->irq[INTR_IDX_CTL_DONE];
+	irq->hw_idx = phys_enc->hw_ctl->idx;
+
 	irq = &phys_enc->irq[INTR_IDX_PINGPONG];
 	irq->hw_idx = phys_enc->hw_pp->idx;
 
@@ -457,7 +482,7 @@ static void sde_encoder_phys_cmd_mode_set(
 		sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
 }
 
-static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
+static int _sde_encoder_phys_cmd_handle_framedone_timeout(
 		struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
@@ -479,11 +504,11 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
 	if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0))
 		return 0;
 
-	cmd_enc->pp_timeout_report_cnt++;
+	cmd_enc->frame_tx_timeout_report_cnt++;
 	pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1;
 
 	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
-			cmd_enc->pp_timeout_report_cnt,
+			cmd_enc->frame_tx_timeout_report_cnt,
 			pending_kickoff_cnt,
 			frame_event);
 
@@ -492,7 +517,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
 		goto exit;
 
 	/* to avoid flooding, only log first time, and "dead" time */
-	if (cmd_enc->pp_timeout_report_cnt == 1) {
+	if (cmd_enc->frame_tx_timeout_report_cnt == 1) {
 		SDE_ERROR_CMDENC(cmd_enc,
 				"pp:%d kickoff timed out ctl %d koff_cnt %d\n",
 				phys_enc->hw_pp->idx - PINGPONG_0,
@@ -517,7 +542,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
 	if (recovery_events)
 		sde_connector_event_notify(conn, DRM_EVENT_SDE_HW_RECOVERY,
 				sizeof(uint8_t), SDE_RECOVERY_CAPTURE);
-	else if (cmd_enc->pp_timeout_report_cnt)
+	else if (cmd_enc->frame_tx_timeout_report_cnt)
 		SDE_DBG_DUMP(0x0, "panic");
 
 	/* request a ctl reset before the next kickoff */
@@ -701,6 +726,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 		struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_wait_info wait_info = {0};
+	enum sde_intr_idx intr_idx;
 	int ret;
 
 	if (!phys_enc) {
@@ -722,13 +748,14 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 	if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
 		return 0;
 
-	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
-			&wait_info);
+	intr_idx = sde_encoder_check_ctl_done_support(phys_enc->parent) ?
+				INTR_IDX_CTL_DONE : INTR_IDX_PINGPONG;
+
+	ret = sde_encoder_helper_wait_for_irq(phys_enc, intr_idx, &wait_info);
 	if (ret == -ETIMEDOUT) {
 		if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
 			return 0;
-
-		_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc);
+		_sde_encoder_phys_cmd_handle_framedone_timeout(phys_enc);
 	}
 
 	return ret;
@@ -834,6 +861,7 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
 		bool enable)
 {
 	struct sde_encoder_phys_cmd *cmd_enc;
+	bool ctl_done_supported = false;
 
 	if (!phys_enc)
 		return;
@@ -851,8 +879,12 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
 	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
 			enable, atomic_read(&phys_enc->vblank_refcount));
 
+	ctl_done_supported = sde_encoder_check_ctl_done_support(phys_enc->parent);
+
 	if (enable) {
-		sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG);
+		if (!ctl_done_supported)
+			sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG);
+
 		sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
 
 		if (sde_encoder_phys_cmd_is_master(phys_enc)) {
@@ -860,6 +892,8 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
 					INTR_IDX_WRPTR);
 			sde_encoder_helper_register_irq(phys_enc,
 					INTR_IDX_AUTOREFRESH_DONE);
+			if (ctl_done_supported)
+				sde_encoder_helper_register_irq(phys_enc, INTR_IDX_CTL_DONE);
 		}
 
 	} else {
@@ -868,10 +902,14 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
 					INTR_IDX_WRPTR);
 			sde_encoder_helper_unregister_irq(phys_enc,
 					INTR_IDX_AUTOREFRESH_DONE);
+			if (ctl_done_supported)
+				sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_CTL_DONE);
 		}
 
 		sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
-		sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG);
+
+		if (!ctl_done_supported)
+			sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG);
 	}
 }
 
@@ -1337,13 +1375,13 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
 	if (phys_enc->recovered) {
 		recovery_events = sde_encoder_recovery_events_enabled(
 				phys_enc->parent);
-		if (cmd_enc->pp_timeout_report_cnt && recovery_events)
+		if (cmd_enc->frame_tx_timeout_report_cnt && recovery_events)
 			sde_connector_event_notify(phys_enc->connector,
 					DRM_EVENT_SDE_HW_RECOVERY,
 					sizeof(uint8_t),
 					SDE_RECOVERY_SUCCESS);
 
-		cmd_enc->pp_timeout_report_cnt = 0;
+		cmd_enc->frame_tx_timeout_report_cnt = 0;
 		phys_enc->recovered = false;
 	}
 
@@ -1988,6 +2026,12 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
 	irq->intr_idx = INTR_IDX_CTL_START;
 	irq->cb.func = NULL;
 
+	irq = &phys_enc->irq[INTR_IDX_CTL_DONE];
+	irq->name = "ctl_done";
+	irq->intr_type = SDE_IRQ_TYPE_CTL_DONE;
+	irq->intr_idx = INTR_IDX_CTL_DONE;
+	irq->cb.func = sde_encoder_phys_cmd_ctl_done_irq;
+
 	irq = &phys_enc->irq[INTR_IDX_PINGPONG];
 	irq->name = "pp_done";
 	irq->intr_type = SDE_IRQ_TYPE_PING_PONG_COMP;

+ 2 - 0
msm/sde/sde_hw_catalog.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -5226,6 +5227,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
 		set_bit(SDE_FEATURE_HW_VSYNC_TS, sde_cfg->features);
 		set_bit(SDE_FEATURE_AVR_STEP, sde_cfg->features);
 		set_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features);
+		set_bit(SDE_FEATURE_CTL_DONE, sde_cfg->features);
 		sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache = true;
 		sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH;
 		sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2;

+ 3 - 0
msm/sde/sde_hw_catalog.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -676,6 +677,7 @@ enum {
  * @SDE_FEATURE_TRUSTED_VM     Trusted VM supported
  * @SDE_FEATURE_UBWC_STATS     UBWC statistics supported
  * @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
+ * @SDE_FEATURE_CTL_DONE       Support for CTL DONE irq
  * @SDE_FEATURE_MAX:             MAX features value
  */
 enum sde_mdss_features {
@@ -716,6 +718,7 @@ enum sde_mdss_features {
 	SDE_FEATURE_TRUSTED_VM,
 	SDE_FEATURE_UBWC_STATS,
 	SDE_FEATURE_VBIF_CLK_SPLIT,
+	SDE_FEATURE_CTL_DONE,
 	SDE_FEATURE_MAX
 };
 

+ 24 - 0
msm/sde/sde_hw_interrupts.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -91,6 +92,16 @@
 #define SDE_INTR_CTL_4_START BIT(13)
 #define SDE_INTR_CTL_5_START BIT(23)
 
+/**
+ * Ctl done interrupt status bit definitions
+ */
+#define SDE_INTR_CTL_0_DONE BIT(0)
+#define SDE_INTR_CTL_1_DONE BIT(1)
+#define SDE_INTR_CTL_2_DONE BIT(2)
+#define SDE_INTR_CTL_3_DONE BIT(3)
+#define SDE_INTR_CTL_4_DONE BIT(4)
+#define SDE_INTR_CTL_5_DONE BIT(5)
+
 /**
  * Concurrent WB overflow interrupt status bit definitions
  */
@@ -283,6 +294,19 @@ static struct sde_irq_type sde_irq_intr2_map[] = {
 	{ SDE_IRQ_TYPE_CTL_START, CTL_5,
 		SDE_INTR_CTL_5_START, -1},
 
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_0,
+		SDE_INTR_CTL_0_DONE, -1},
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_1,
+		SDE_INTR_CTL_1_DONE, -1},
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_2,
+		SDE_INTR_CTL_2_DONE, -1},
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_3,
+		SDE_INTR_CTL_3_DONE, -1},
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_4,
+		SDE_INTR_CTL_4_DONE, -1},
+	{ SDE_IRQ_TYPE_CTL_DONE, CTL_5,
+		SDE_INTR_CTL_5_DONE, -1},
+
 	{ SDE_IRQ_TYPE_CWB_OVERFLOW, PINGPONG_CWB_0, SDE_INTR_CWB_OVERFLOW, -1},
 
 	{ SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_4,

+ 3 - 0
msm/sde/sde_hw_interrupts.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
  */
 
@@ -49,6 +50,7 @@
  * @SDE_IRQ_TYPE_PROG_LINE:		Programmable Line interrupt
  * @SDE_IRQ_TYPE_AD4_BL_DONE:		AD4 backlight
  * @SDE_IRQ_TYPE_CTL_START:		Control start
+ * @SDE_IRQ_TYPE_CTL_DONE:		Frame transfer complete
  * @SDE_IRQ_TYPE_INTF_TEAR_RD_PTR:	INTF Tear read pointer
  * @SDE_IRQ_TYPE_INTF_TEAR_WR_PTR:	INTF Tear write pointer
  * @SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF:	INTF Tear auto refresh
@@ -87,6 +89,7 @@ enum sde_intr_type {
 	SDE_IRQ_TYPE_PROG_LINE,
 	SDE_IRQ_TYPE_AD4_BL_DONE,
 	SDE_IRQ_TYPE_CTL_START,
+	SDE_IRQ_TYPE_CTL_DONE,
 	SDE_IRQ_TYPE_INTF_TEAR_RD_PTR,
 	SDE_IRQ_TYPE_INTF_TEAR_WR_PTR,
 	SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF,