aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2017-08-24 09:33:57 -0400
committerInki Dae <inki.dae@samsung.com>2017-08-24 22:58:08 -0400
commit461e60ea1119e974af60b4d43e39df954477e0c5 (patch)
tree8376206bad3e50c6ecca73844d09810b8dcce569
parentc3653fede57f301a134b56c4bf62ac92780d5059 (diff)
drm/exynos/decon5433: use mode info stored in CRTC to detect i80 mode
Since panel's mode of work is propagated properly from panel to DECON, there is no need to use redundant private device tree property. The only issue with such approach is that check for required interrupts should be postponed until panel communicate its requirements, ie to mode validation phase - mode_valid callback. Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 0f5accea51a0..da183e05f267 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -34,9 +34,8 @@
34#define WINDOWS_NR 3 34#define WINDOWS_NR 3
35#define MIN_FB_WIDTH_FOR_16WORD_BURST 128 35#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
36 36
37#define IFTYPE_I80 (1 << 0) 37#define I80_HW_TRG (1 << 0)
38#define I80_HW_TRG (1 << 1) 38#define IFTYPE_HDMI (1 << 1)
39#define IFTYPE_HDMI (1 << 2)
40 39
41static const char * const decon_clks_name[] = { 40static const char * const decon_clks_name[] = {
42 "pclk", 41 "pclk",
@@ -93,7 +92,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
93 u32 val; 92 u32 val;
94 93
95 val = VIDINTCON0_INTEN; 94 val = VIDINTCON0_INTEN;
96 if (ctx->out_type & IFTYPE_I80) 95 if (crtc->i80_mode)
97 val |= VIDINTCON0_FRAMEDONE; 96 val |= VIDINTCON0_FRAMEDONE;
98 else 97 else
99 val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP; 98 val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP;
@@ -142,7 +141,7 @@ static u32 decon_get_frame_count(struct decon_context *ctx, bool end)
142 141
143 switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) { 142 switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) {
144 case VIDCON1_VSTATUS_VS: 143 case VIDCON1_VSTATUS_VS:
145 if (!(ctx->out_type & IFTYPE_I80)) 144 if (!(ctx->crtc->i80_mode))
146 --frm; 145 --frm;
147 break; 146 break;
148 case VIDCON1_VSTATUS_BP: 147 case VIDCON1_VSTATUS_BP:
@@ -169,7 +168,7 @@ static u32 decon_get_vblank_counter(struct exynos_drm_crtc *crtc)
169 168
170static void decon_setup_trigger(struct decon_context *ctx) 169static void decon_setup_trigger(struct decon_context *ctx)
171{ 170{
172 if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))) 171 if (!ctx->crtc->i80_mode && !(ctx->out_type & I80_HW_TRG))
173 return; 172 return;
174 173
175 if (!(ctx->out_type & I80_HW_TRG)) { 174 if (!(ctx->out_type & I80_HW_TRG)) {
@@ -209,7 +208,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
209 val = VIDOUT_LCD_ON; 208 val = VIDOUT_LCD_ON;
210 if (interlaced) 209 if (interlaced)
211 val |= VIDOUT_INTERLACE_EN_F; 210 val |= VIDOUT_INTERLACE_EN_F;
212 if (ctx->out_type & IFTYPE_I80) { 211 if (crtc->i80_mode) {
213 val |= VIDOUT_COMMAND_IF; 212 val |= VIDOUT_COMMAND_IF;
214 } else { 213 } else {
215 val |= VIDOUT_RGB_IF; 214 val |= VIDOUT_RGB_IF;
@@ -225,7 +224,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
225 VIDTCON2_HOZVAL(m->hdisplay - 1); 224 VIDTCON2_HOZVAL(m->hdisplay - 1);
226 writel(val, ctx->addr + DECON_VIDTCON2); 225 writel(val, ctx->addr + DECON_VIDTCON2);
227 226
228 if (!(ctx->out_type & IFTYPE_I80)) { 227 if (!crtc->i80_mode) {
229 int vbp = m->crtc_vtotal - m->crtc_vsync_end; 228 int vbp = m->crtc_vtotal - m->crtc_vsync_end;
230 int vfp = m->crtc_vsync_start - m->crtc_vdisplay; 229 int vfp = m->crtc_vsync_start - m->crtc_vdisplay;
231 230
@@ -513,6 +512,22 @@ err:
513 clk_disable_unprepare(ctx->clks[i]); 512 clk_disable_unprepare(ctx->clks[i]);
514} 513}
515 514
515static enum drm_mode_status decon_mode_valid(struct exynos_drm_crtc *crtc,
516 const struct drm_display_mode *mode)
517{
518 struct decon_context *ctx = crtc->ctx;
519
520 ctx->irq = crtc->i80_mode ? ctx->irq_lcd_sys : ctx->irq_vsync;
521
522 if (ctx->irq)
523 return MODE_OK;
524
525 dev_info(ctx->dev, "Sink requires %s mode, but appropriate interrupt is not provided.\n",
526 crtc->i80_mode ? "command" : "video");
527
528 return MODE_BAD;
529}
530
516static const struct exynos_drm_crtc_ops decon_crtc_ops = { 531static const struct exynos_drm_crtc_ops decon_crtc_ops = {
517 .enable = decon_enable, 532 .enable = decon_enable,
518 .disable = decon_disable, 533 .disable = decon_disable,
@@ -522,6 +537,7 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
522 .atomic_begin = decon_atomic_begin, 537 .atomic_begin = decon_atomic_begin,
523 .update_plane = decon_update_plane, 538 .update_plane = decon_update_plane,
524 .disable_plane = decon_disable_plane, 539 .disable_plane = decon_disable_plane,
540 .mode_valid = decon_mode_valid,
525 .atomic_flush = decon_atomic_flush, 541 .atomic_flush = decon_atomic_flush,
526}; 542};
527 543
@@ -715,11 +731,8 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
715 ctx->out_type = (unsigned long)of_device_get_match_data(dev); 731 ctx->out_type = (unsigned long)of_device_get_match_data(dev);
716 spin_lock_init(&ctx->vblank_lock); 732 spin_lock_init(&ctx->vblank_lock);
717 733
718 if (ctx->out_type & IFTYPE_HDMI) { 734 if (ctx->out_type & IFTYPE_HDMI)
719 ctx->first_win = 1; 735 ctx->first_win = 1;
720 } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) {
721 ctx->out_type |= IFTYPE_I80;
722 }
723 736
724 for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { 737 for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
725 struct clk *clk; 738 struct clk *clk;
@@ -753,9 +766,6 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
753 return ret; 766 return ret;
754 ctx->irq_lcd_sys = ret; 767 ctx->irq_lcd_sys = ret;
755 768
756 ctx->irq = (ctx->out_type & IFTYPE_I80) ? ctx->irq_lcd_sys
757 : ctx->irq_vsync;
758
759 ret = decon_conf_irq(ctx, "te", decon_te_irq_handler, 769 ret = decon_conf_irq(ctx, "te", decon_te_irq_handler,
760 IRQF_TRIGGER_RISING); 770 IRQF_TRIGGER_RISING);
761 if (ret < 0) 771 if (ret < 0)