aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2017-01-20 01:52:23 -0500
committerInki Dae <inki.dae@samsung.com>2017-02-06 23:52:51 -0500
commit5aa6c9ace55d2ca2d41118208fe8476907b4b066 (patch)
treeb6b97cfc0b1ce3de8046dff0e77f6e89b8c0d7bf
parent849fb0de898c907d1249edb2182ef0dfcaf4fdb4 (diff)
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)
146{ 146{
147 struct decon_context *ctx = crtc->ctx; 147 struct decon_context *ctx = crtc->ctx;
148 struct drm_display_mode *m = &crtc->base.mode; 148 struct drm_display_mode *m = &crtc->base.mode;
149 bool interlaced = false;
149 u32 val; 150 u32 val;
150 151
151 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 152 if (test_bit(BIT_SUSPENDED, &ctx->flags))
@@ -156,12 +157,16 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
156 m->crtc_hsync_end = m->crtc_htotal - 92; 157 m->crtc_hsync_end = m->crtc_htotal - 92;
157 m->crtc_vsync_start = m->crtc_vdisplay + 1; 158 m->crtc_vsync_start = m->crtc_vdisplay + 1;
158 m->crtc_vsync_end = m->crtc_vsync_start + 1; 159 m->crtc_vsync_end = m->crtc_vsync_start + 1;
160 if (m->flags & DRM_MODE_FLAG_INTERLACE)
161 interlaced = true;
159 } 162 }
160 163
161 decon_setup_trigger(ctx); 164 decon_setup_trigger(ctx);
162 165
163 /* lcd on and use command if */ 166 /* lcd on and use command if */
164 val = VIDOUT_LCD_ON; 167 val = VIDOUT_LCD_ON;
168 if (interlaced)
169 val |= VIDOUT_INTERLACE_EN_F;
165 if (ctx->out_type & IFTYPE_I80) { 170 if (ctx->out_type & IFTYPE_I80) {
166 val |= VIDOUT_COMMAND_IF; 171 val |= VIDOUT_COMMAND_IF;
167 } else { 172 } else {
@@ -170,15 +175,21 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
170 175
171 writel(val, ctx->addr + DECON_VIDOUTCON0); 176 writel(val, ctx->addr + DECON_VIDOUTCON0);
172 177
173 val = VIDTCON2_LINEVAL(m->vdisplay - 1) | 178 if (interlaced)
174 VIDTCON2_HOZVAL(m->hdisplay - 1); 179 val = VIDTCON2_LINEVAL(m->vdisplay / 2 - 1) |
180 VIDTCON2_HOZVAL(m->hdisplay - 1);
181 else
182 val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
183 VIDTCON2_HOZVAL(m->hdisplay - 1);
175 writel(val, ctx->addr + DECON_VIDTCON2); 184 writel(val, ctx->addr + DECON_VIDTCON2);
176 185
177 if (!(ctx->out_type & IFTYPE_I80)) { 186 if (!(ctx->out_type & IFTYPE_I80)) {
178 val = VIDTCON00_VBPD_F( 187 int vbp = m->crtc_vtotal - m->crtc_vsync_end;
179 m->crtc_vtotal - m->crtc_vsync_end - 1) | 188 int vfp = m->crtc_vsync_start - m->crtc_vdisplay;
180 VIDTCON00_VFPD_F( 189
181 m->crtc_vsync_start - m->crtc_vdisplay - 1); 190 if (interlaced)
191 vbp = vbp / 2 - 1;
192 val = VIDTCON00_VBPD_F(vbp - 1) | VIDTCON00_VFPD_F(vfp - 1);
182 writel(val, ctx->addr + DECON_VIDTCON00); 193 writel(val, ctx->addr + DECON_VIDTCON00);
183 194
184 val = VIDTCON01_VSPW_F( 195 val = VIDTCON01_VSPW_F(
@@ -293,12 +304,22 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
293 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 304 if (test_bit(BIT_SUSPENDED, &ctx->flags))
294 return; 305 return;
295 306
296 val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y); 307 if (crtc->base.mode.flags & DRM_MODE_FLAG_INTERLACE) {
297 writel(val, ctx->addr + DECON_VIDOSDxA(win)); 308 val = COORDINATE_X(state->crtc.x) |
309 COORDINATE_Y(state->crtc.y / 2);
310 writel(val, ctx->addr + DECON_VIDOSDxA(win));
311
312 val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
313 COORDINATE_Y((state->crtc.y + state->crtc.h) / 2 - 1);
314 writel(val, ctx->addr + DECON_VIDOSDxB(win));
315 } else {
316 val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
317 writel(val, ctx->addr + DECON_VIDOSDxA(win));
298 318
299 val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) | 319 val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
300 COORDINATE_Y(state->crtc.y + state->crtc.h - 1); 320 COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
301 writel(val, ctx->addr + DECON_VIDOSDxB(win)); 321 writel(val, ctx->addr + DECON_VIDOSDxB(win));
322 }
302 323
303 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | 324 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
304 VIDOSD_Wx_ALPHA_B_F(0x0); 325 VIDOSD_Wx_ALPHA_B_F(0x0);
@@ -370,8 +391,6 @@ static void decon_swreset(struct decon_context *ctx)
370 udelay(10); 391 udelay(10);
371 } 392 }
372 393
373 WARN(tries == 0, "failed to disable DECON\n");
374
375 writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0); 394 writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0);
376 for (tries = 2000; tries; --tries) { 395 for (tries = 2000; tries; --tries) {
377 if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_SWRESET) 396 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 @@
89#define VIDCON0_ENVID_F (1 << 0) 89#define VIDCON0_ENVID_F (1 << 0)
90 90
91/* VIDOUTCON0 */ 91/* VIDOUTCON0 */
92#define VIDOUT_INTERLACE_EN_F (1 << 28)
92#define VIDOUT_LCD_ON (1 << 24) 93#define VIDOUT_LCD_ON (1 << 24)
93#define VIDOUT_IF_F_MASK (0x3 << 20) 94#define VIDOUT_IF_F_MASK (0x3 << 20)
94#define VIDOUT_RGB_IF (0x0 << 20) 95#define VIDOUT_RGB_IF (0x0 << 20)