summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)