diff options
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_crtc.c')
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 008e172ed43b..d6d29be6b4f4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -298,13 +298,26 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) escr = params.escr; } - if (rcdu->info->gen < 4) { + /* + * The ESCR register only exists in DU channels that can output to an + * LVDS or DPAT, and the OTAR register in DU channels that can output + * to a DPAD. + */ + if ((rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs | + rcdu->info->routes[RCAR_DU_OUTPUT_DPAD1].possible_crtcs | + rcdu->info->routes[RCAR_DU_OUTPUT_LVDS0].possible_crtcs | + rcdu->info->routes[RCAR_DU_OUTPUT_LVDS1].possible_crtcs) & + BIT(rcrtc->index)) { dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr); rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr); - rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0); } + if ((rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs | + rcdu->info->routes[RCAR_DU_OUTPUT_DPAD1].possible_crtcs) & + BIT(rcrtc->index)) + rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0); + /* Signal polarities */ dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0) | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0) @@ -749,16 +762,17 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, /* * On D3/E3 the dot clock is provided by the LVDS encoder attached to - * the DU channel. We need to enable its clock output explicitly if - * the LVDS output is disabled. + * the DU channel. We need to enable its clock output explicitly before + * starting the CRTC, as the bridge hasn't been enabled by the atomic + * helpers yet. */ - if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && - rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { + if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) { + bool dot_clk_only = rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0); struct drm_bridge *bridge = rcdu->lvds[rcrtc->index]; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - rcar_lvds_pclk_enable(bridge, mode->clock * 1000); + rcar_lvds_pclk_enable(bridge, mode->clock * 1000, dot_clk_only); } /* @@ -795,15 +809,16 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, rcar_du_crtc_stop(rcrtc); rcar_du_crtc_put(rcrtc); - if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && - rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { + if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) { + bool dot_clk_only = rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0); struct drm_bridge *bridge = rcdu->lvds[rcrtc->index]; /* * Disable the LVDS clock output, see - * rcar_du_crtc_atomic_enable(). + * rcar_du_crtc_atomic_enable(). When the LVDS output is used, + * this also disables the LVDS encoder. */ - rcar_lvds_pclk_disable(bridge); + rcar_lvds_pclk_disable(bridge, dot_clk_only); } if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) && @@ -815,7 +830,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, * Disable the DSI clock output, see * rcar_du_crtc_atomic_enable(). */ - rcar_mipi_dsi_pclk_disable(bridge); } |