summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2020-12-04 12:43:58 +0100
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2021-01-05 06:19:56 +0100
commit53ced169373aab52d3b5da0fee6a342002d1876d (patch)
tree144a344465d232d62b4d8748fd5baacaa3ff2bde /drivers/gpu/drm/rcar-du/rcar_du_crtc.c
parentdrm: Add default modes for connectors in unknown state (diff)
downloadlinux-53ced169373aab52d3b5da0fee6a342002d1876d.tar.xz
linux-53ced169373aab52d3b5da0fee6a342002d1876d.zip
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
On D3 and E3 platforms, the LVDS encoder includes a PLL that can generate a clock for the corresponding CRTC, used even when the CRTC output to a non-LVDS port. This mechanism is supported by the driver, but the implementation is broken in dual-link LVDS mode. In that case, the LVDS1 drm_encoder is skipped, which causes a crash when trying to access its bridge later on. Fix this by storing bridge pointers internally instead of retrieving them from the encoder. The rcar_du_device encoders field isn't used anymore and can be dropped. Fixes: 8e8fddab0d0a ("drm: rcar-du: Skip LVDS1 output on Gen3 when using dual-link LVDS mode") Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_crtc.c')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c10
1 files changed, 2 insertions, 8 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index b5fb941e0f53..e23b9c7b4afe 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -730,13 +730,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
*/
if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
- struct rcar_du_encoder *encoder =
- rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
+ struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
const struct drm_display_mode *mode =
&crtc->state->adjusted_mode;
- struct drm_bridge *bridge;
- bridge = drm_bridge_chain_get_first_bridge(&encoder->base);
rcar_lvds_clk_enable(bridge, mode->clock * 1000);
}
@@ -764,15 +761,12 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
- struct rcar_du_encoder *encoder =
- rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
- struct drm_bridge *bridge;
+ struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
/*
* Disable the LVDS clock output, see
* rcar_du_crtc_atomic_enable().
*/
- bridge = drm_bridge_chain_get_first_bridge(&encoder->base);
rcar_lvds_clk_disable(bridge);
}