[PATCH 03/49] staging: hikey9xx/gpu: solve tearing issue of display

Mauro Carvalho Chehab mchehab+huawei at kernel.org
Wed Aug 19 11:45:31 UTC 2020


From: Liwei Cai <cailiwei at hisilicon.com>

The use of synchronization mechanisms to deal with the display of
buffer, to solve the problem of display tearing.

Signed-off-by: Wanchun Zheng <zhengwanchun at hisilicon.com>
Signed-off-by: Liwei Cai <cailiwei at hisilicon.com>
Signed-off-by: John Stultz <john.stultz at linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei at kernel.org>
---
 drivers/staging/hikey9xx/gpu/dw_drm_dsi.c     |  3 +-
 drivers/staging/hikey9xx/gpu/kirin_drm_dss.c  |  4 +-
 .../hikey9xx/gpu/kirin_drm_overlay_utils.c    | 90 ++++++++-----------
 3 files changed, 41 insertions(+), 56 deletions(-)

diff --git a/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
index 9871b375416b..db408beb33ec 100644
--- a/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
+++ b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
@@ -35,7 +35,6 @@
 
 #define DTS_COMP_DSI_NAME "hisilicon,hi3660-dsi"
 
-#define MAX_TX_ESC_CLK		10
 #define ROUND(x, y)		((x) / (y) + \
 				((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
 #define ROUND1(x, y)	((x) / (y) + ((x) % (y)  ? 1 : 0))
@@ -1237,7 +1236,7 @@ static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
 	host->dev = dev;
 	host->ops = &dsi_host_ops;
 
-	mipi->max_tx_esc_clk = 10;
+	mipi->max_tx_esc_clk = 10 * 1000000UL;
 	mipi->vc = 0;
 	mipi->color_mode = DSI_24BITS_1;
 	mipi->clk_post_adjust = 120;
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
index c47d860f4697..62ac1a0648cc 100644
--- a/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
@@ -167,8 +167,8 @@ static int dss_power_up(struct dss_crtc *acrtc)
 	dss_inner_clk_common_enable(acrtc);
 	dpe_interrupt_mask(acrtc);
 	dpe_interrupt_clear(acrtc);
-	dpe_irq_enable(acrtc);
-	dpe_interrupt_unmask(acrtc);
+	//dpe_irq_enable(acrtc);
+	//dpe_interrupt_unmask(acrtc);
 
 	ctx->power_on = true;
 	return 0;
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
index 095335eba16d..917e1a7d7bdf 100644
--- a/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
@@ -30,6 +30,7 @@
 
 
 #define DSS_CHN_MAX_DEFINE (DSS_COPYBIT_MAX)
+#define TIME_OUT  (16)
 
 static int mid_array[DSS_CHN_MAX_DEFINE] = {0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0};
 
@@ -1064,6 +1065,38 @@ void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask)
 	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, tmp);
 }
 
+void hisi_dss_wait_for_complete(struct dss_hw_ctx *ctx, bool need_clear)
+{
+	void __iomem *dss_base;
+	u32 tmp = 0;
+	u32 isr_s2 = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+
+	do {
+		isr_s2 = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+		if (isr_s2 & BIT_VACTIVE0_END) {
+			DRM_DEBUG("hisi_dss_wait_for_complete exit! temp = %d\n", tmp);
+			if (need_clear)
+				outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, BIT_VACTIVE0_END);
+			break;
+		} else {
+			msleep(1);
+			tmp++;
+		}
+	} while (tmp < TIME_OUT);
+
+	if (tmp == TIME_OUT) {
+		isr_s2 = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+		DRM_INFO("wait vactive0_end timeout: isr_s2 = 0x%x\n", isr_s2);
+	}
+}
+#if 0
 static int hisi_vactive0_start_config(struct dss_hw_ctx *ctx)
 {
 	int ret = 0;
@@ -1094,6 +1127,7 @@ static int hisi_vactive0_start_config(struct dss_hw_ctx *ctx)
 
 	return ret;
 }
+#endif
 
 void hisi_fb_pan_display(struct drm_plane *plane)
 {
@@ -1109,9 +1143,6 @@ void hisi_fb_pan_display(struct drm_plane *plane)
 	struct kirin_drm_private *priv = plane->dev->dev_private;
 	struct kirin_fbdev *fbdev = to_kirin_fbdev(priv->fbdev);
 
-	ktime_t prepare_timestamp;
-	u64 vsync_timediff;
-
 	bool afbcd = false;
 	bool mmu_enable = true;
 	dss_rect_ltrb_t rect;
@@ -1164,26 +1195,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
 	vbp = mode->vtotal - mode->vsync_end;
 	vsw = mode->vsync_end - mode->vsync_start;
 
-	vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) *
-		(mode->vdisplay + vbp + vfp + vsw) *
-		1000000000UL / (adj_mode->clock * 1000);
-
-	prepare_timestamp = ktime_get();
-
-	if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) &&
-		(ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) &&
-		(ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) {
-		DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n",
-			vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp));
-	} else {
-		DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff);
-
-		if (hisi_vactive0_start_config(ctx) != 0) {
-			DRM_ERROR("hisi_vactive0_start_config failed!\n");
-			return;
-		}
-	}
-	ctx->vsync_timestamp_prev = ctx->vsync_timestamp;
+	hisi_dss_wait_for_complete(ctx, true);
 
 	hisi_dss_mctl_mutex_lock(ctx);
 	hisi_dss_aif_ch_config(ctx, chn_idx);
@@ -1198,9 +1210,8 @@ void hisi_fb_pan_display(struct drm_plane *plane)
 	hisi_dss_mctl_sys_config(ctx, chn_idx);
 	hisi_dss_mctl_mutex_unlock(ctx);
 
-	hisi_dss_unflow_handler(ctx, true);
-
 	enable_ldi(acrtc);
+	hisi_dss_wait_for_complete(ctx, false);
 }
 
 void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
@@ -1213,9 +1224,6 @@ void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
 	struct dss_crtc *acrtc = aplane->acrtc;
 	struct dss_hw_ctx *ctx = acrtc->ctx;
 
-	ktime_t prepare_timestamp;
-	u64 vsync_timediff;
-
 	bool afbcd = false;
 	bool mmu_enable = true;
 	dss_rect_ltrb_t rect;
@@ -1249,28 +1257,7 @@ void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
 	vfp = mode->vsync_start - mode->vdisplay;
 	vbp = mode->vtotal - mode->vsync_end;
 	vsw = mode->vsync_end - mode->vsync_start;
-
-	vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) *
-		(mode->vdisplay + vbp + vfp + vsw) *
-		1000000000UL / (adj_mode->clock * 1000);
-
-	prepare_timestamp = ktime_get();
-
-	if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) &&
-		(ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) &&
-		(ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) {
-		DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n",
-			vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp));
-	} else {
-		DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff);
-
-		if (hisi_vactive0_start_config(ctx) != 0) {
-			DRM_ERROR("hisi_vactive0_start_config failed!\n");
-			return;
-		}
-	}
-
-	ctx->vsync_timestamp_prev = ctx->vsync_timestamp;
+	hisi_dss_wait_for_complete(ctx, true);
 
 	hisi_dss_mctl_mutex_lock(ctx);
 	hisi_dss_aif_ch_config(ctx, chn_idx);
@@ -1285,7 +1272,6 @@ void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
 	hisi_dss_mctl_sys_config(ctx, chn_idx);
 	hisi_dss_mctl_mutex_unlock(ctx);
 
-	hisi_dss_unflow_handler(ctx, true);
-
 	enable_ldi(acrtc);
+	hisi_dss_wait_for_complete(ctx, false);
 }
-- 
2.26.2



More information about the dri-devel mailing list