summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2017-01-20 07:52:23 +0100
committerInki Dae <inki.dae@samsung.com>2017-02-07 13:52:51 +0900
commit5aa6c9ace55d2ca2d41118208fe8476907b4b066 (patch)
treeb6b97cfc0b1ce3de8046dff0e77f6e89b8c0d7bf
parent849fb0de898c907d1249edb2182ef0dfcaf4fdb4 (diff)
downloadlinux-5aa6c9ace55d2ca2d41118208fe8476907b4b066.tar.gz
linux-5aa6c9ace55d2ca2d41118208fe8476907b4b066.tar.xz
drm/exynos/decon5433: add support for interlace modes
Some registers should be programmed differently in interlace mode. Additionally IP does not signal stop state properly in interlaced mode, so warning has been removed. Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c45
-rw-r--r--include/video/exynos5433_decon.h1
2 files changed, 33 insertions, 13 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 9f5d37e46a29..b828480e81c5 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -146,6 +146,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
struct drm_display_mode *m = &crtc->base.mode;
+ bool interlaced = false;
u32 val;
if (test_bit(BIT_SUSPENDED, &ctx->flags))
@@ -156,12 +157,16 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
m->crtc_hsync_end = m->crtc_htotal - 92;
m->crtc_vsync_start = m->crtc_vdisplay + 1;
m->crtc_vsync_end = m->crtc_vsync_start + 1;
+ if (m->flags & DRM_MODE_FLAG_INTERLACE)
+ interlaced = true;
}
decon_setup_trigger(ctx);
/* lcd on and use command if */
val = VIDOUT_LCD_ON;
+ if (interlaced)
+ val |= VIDOUT_INTERLACE_EN_F;
if (ctx->out_type & IFTYPE_I80) {
val |= VIDOUT_COMMAND_IF;
} else {
@@ -170,15 +175,21 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
writel(val, ctx->addr + DECON_VIDOUTCON0);
- val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
- VIDTCON2_HOZVAL(m->hdisplay - 1);
+ if (interlaced)
+ val = VIDTCON2_LINEVAL(m->vdisplay / 2 - 1) |
+ VIDTCON2_HOZVAL(m->hdisplay - 1);
+ else
+ val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
+ VIDTCON2_HOZVAL(m->hdisplay - 1);
writel(val, ctx->addr + DECON_VIDTCON2);
if (!(ctx->out_type & IFTYPE_I80)) {
- val = VIDTCON00_VBPD_F(
- m->crtc_vtotal - m->crtc_vsync_end - 1) |
- VIDTCON00_VFPD_F(
- m->crtc_vsync_start - m->crtc_vdisplay - 1);
+ int vbp = m->crtc_vtotal - m->crtc_vsync_end;
+ int vfp = m->crtc_vsync_start - m->crtc_vdisplay;
+
+ if (interlaced)
+ vbp = vbp / 2 - 1;
+ val = VIDTCON00_VBPD_F(vbp - 1) | VIDTCON00_VFPD_F(vfp - 1);
writel(val, ctx->addr + DECON_VIDTCON00);
val = VIDTCON01_VSPW_F(
@@ -293,12 +304,22 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
- val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
- writel(val, ctx->addr + DECON_VIDOSDxA(win));
+ if (crtc->base.mode.flags & DRM_MODE_FLAG_INTERLACE) {
+ val = COORDINATE_X(state->crtc.x) |
+ COORDINATE_Y(state->crtc.y / 2);
+ writel(val, ctx->addr + DECON_VIDOSDxA(win));
+
+ val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
+ COORDINATE_Y((state->crtc.y + state->crtc.h) / 2 - 1);
+ writel(val, ctx->addr + DECON_VIDOSDxB(win));
+ } else {
+ val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
+ writel(val, ctx->addr + DECON_VIDOSDxA(win));
- val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
- COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
- writel(val, ctx->addr + DECON_VIDOSDxB(win));
+ val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
+ COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
+ writel(val, ctx->addr + DECON_VIDOSDxB(win));
+ }
val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
VIDOSD_Wx_ALPHA_B_F(0x0);
@@ -370,8 +391,6 @@ static void decon_swreset(struct decon_context *ctx)
udelay(10);
}
- WARN(tries == 0, "failed to disable DECON\n");
-
writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0);
for (tries = 2000; tries; --tries) {
if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_SWRESET)
diff --git a/include/video/exynos5433_decon.h b/include/video/exynos5433_decon.h
index 0098a522d9f4..b26511a0ddf8 100644
--- a/include/video/exynos5433_decon.h
+++ b/include/video/exynos5433_decon.h
@@ -89,6 +89,7 @@
#define VIDCON0_ENVID_F (1 << 0)
/* VIDOUTCON0 */
+#define VIDOUT_INTERLACE_EN_F (1 << 28)
#define VIDOUT_LCD_ON (1 << 24)
#define VIDOUT_IF_F_MASK (0x3 << 20)
#define VIDOUT_RGB_IF (0x0 << 20)