diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 45 | ||||
-rw-r--r-- | include/video/exynos5433_decon.h | 1 |
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) |