diff options
Diffstat (limited to 'drivers/gpu/drm/mcde/mcde_display.c')
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_display.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 751454ae3cd1..e59907e68854 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -498,24 +498,20 @@ static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch, } /* Set up channel 0 sync (based on chnl_update_registers()) */ - if (mcde->te_sync) { - /* - * Turn on hardware TE0 synchronization - */ + if (mcde->video_mode || mcde->te_sync) val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; - val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 - << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; - } else { - /* - * Set up sync source to software, out sync formatter - * Code mostly from mcde_hw.c chnl_update_registers() - */ + else val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; + + if (mcde->te_sync) + val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 + << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; + else val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; - } + writel(val, mcde->regs + sync); /* Set up pixels per line and lines per frame */ @@ -934,10 +930,17 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, val = readl(mcde->regs + MCDE_CRC); val |= MCDE_CRC_SYCEN0; writel(val, mcde->regs + MCDE_CRC); - - drm_crtc_vblank_on(crtc); } + drm_crtc_vblank_on(crtc); + + if (mcde->video_mode) + /* + * Keep FIFO permanently enabled in video mode, + * otherwise MCDE will stop feeding data to the panel. + */ + mcde_enable_fifo(mcde, MCDE_FIFO_A); + dev_info(drm->dev, "MCDE display is enabled\n"); } @@ -946,13 +949,22 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = drm->dev_private; + struct drm_pending_vblank_event *event; - if (mcde->te_sync) - drm_crtc_vblank_off(crtc); + drm_crtc_vblank_off(crtc); /* Disable FIFO A flow */ mcde_disable_fifo(mcde, MCDE_FIFO_A, true); + event = crtc->state->event; + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } + dev_info(drm->dev, "MCDE display is disabled\n"); } @@ -1048,8 +1060,9 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, */ if (fb) { mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); - /* Send a single frame using software sync */ - mcde_display_send_one_frame(mcde); + if (!mcde->video_mode) + /* Send a single frame using software sync */ + mcde_display_send_one_frame(mcde); dev_info_once(mcde->dev, "sent first display update\n"); } else { /* @@ -1097,6 +1110,8 @@ static struct drm_simple_display_pipe_funcs mcde_display_funcs = { .enable = mcde_display_enable, .disable = mcde_display_disable, .update = mcde_display_update, + .enable_vblank = mcde_display_enable_vblank, + .disable_vblank = mcde_display_disable_vblank, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; @@ -1123,12 +1138,6 @@ int mcde_display_init(struct drm_device *drm) DRM_FORMAT_YUV422, }; - /* Provide vblank only when we have TE enabled */ - if (mcde->te_sync) { - mcde_display_funcs.enable_vblank = mcde_display_enable_vblank; - mcde_display_funcs.disable_vblank = mcde_display_disable_vblank; - } - ret = drm_simple_display_pipe_init(drm, &mcde->pipe, &mcde_display_funcs, formats, ARRAY_SIZE(formats), |