[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240919-exynosdrm-decon-v1-4-6c5861c1cb04@disroot.org>
Date: Thu, 19 Sep 2024 20:41:03 +0530
From: Kaustabh Chakraborty <kauschluss@...root.org>
To: Inki Dae <inki.dae@...sung.com>, Seung-Woo Kim <sw0312.kim@...sung.com>,
Kyungmin Park <kyungmin.park@...sung.com>, David Airlie <airlied@...il.com>,
Simona Vetter <simona@...ll.ch>, Krzysztof Kozlowski <krzk@...nel.org>,
Alim Akhtar <alim.akhtar@...sung.com>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>,
Rob Herring <robh@...nel.org>, Conor Dooley <conor@...nel.org>
Cc: dri-devel@...ts.freedesktop.org, linux-arm-kernel@...ts.infradead.org,
linux-samsung-soc@...r.kernel.org, linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org, Kaustabh Chakraborty <kauschluss@...root.org>
Subject: [PATCH 4/6] drm/exynos: exynos7_drm_decon: properly clear channels
during bind
The DECON channels are not cleared properly as the windows aren't
shadow protected. When accompanied with an IOMMU, it pagefaults, and
the kernel panics.
Implement shadow protect/unprotect, along with a standalone update,
for channel clearing to properly take effect.
Signed-off-by: Kaustabh Chakraborty <kauschluss@...root.org>
---
drivers/gpu/drm/exynos/exynos7_drm_decon.c | 55 +++++++++++++++++-------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 4e4ced50ff15..7f0985eb216e 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -81,6 +81,28 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
DRM_PLANE_TYPE_CURSOR,
};
+/**
+ * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
+ *
+ * @ctx: display and enhancement controller context
+ * @win: window to protect registers for
+ * @protect: 1 to protect (disable updates)
+ */
+static void decon_shadow_protect_win(struct decon_context *ctx,
+ unsigned int win, bool protect)
+{
+ u32 bits, val;
+
+ bits = SHADOWCON_WINx_PROTECT(win);
+
+ val = readl(ctx->regs + SHADOWCON);
+ if (protect)
+ val |= bits;
+ else
+ val &= ~bits;
+ writel(val, ctx->regs + SHADOWCON);
+}
+
static void decon_wait_for_vblank(struct decon_context *ctx)
{
if (ctx->suspended)
@@ -101,18 +123,27 @@ static void decon_wait_for_vblank(struct decon_context *ctx)
static void decon_clear_channels(struct decon_context *ctx)
{
unsigned int win, ch_enabled = 0;
+ u32 val;
/* Check if any channel is enabled. */
for (win = 0; win < WINDOWS_NR; win++) {
- u32 val = readl(ctx->regs + WINCON(win));
+ val = readl(ctx->regs + WINCON(win));
if (val & WINCONx_ENWIN) {
+ decon_shadow_protect_win(ctx, win, true);
+
val &= ~WINCONx_ENWIN;
writel(val, ctx->regs + WINCON(win));
ch_enabled = 1;
+
+ decon_shadow_protect_win(ctx, win, false);
}
}
+ val = readl(ctx->regs + DECON_UPDATE);
+ val |= DECON_UPDATE_STANDALONE_F;
+ writel(val, ctx->regs + DECON_UPDATE);
+
/* Wait for vsync, as disable channel takes effect at next vsync */
if (ch_enabled)
decon_wait_for_vblank(ctx);
@@ -340,28 +371,6 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
}
-/**
- * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
- *
- * @ctx: display and enhancement controller context
- * @win: window to protect registers for
- * @protect: 1 to protect (disable updates)
- */
-static void decon_shadow_protect_win(struct decon_context *ctx,
- unsigned int win, bool protect)
-{
- u32 bits, val;
-
- bits = SHADOWCON_WINx_PROTECT(win);
-
- val = readl(ctx->regs + SHADOWCON);
- if (protect)
- val |= bits;
- else
- val &= ~bits;
- writel(val, ctx->regs + SHADOWCON);
-}
-
static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
--
2.46.1
Powered by blists - more mailing lists