commit c9b1150a68d9362a0827609fc0dc1664c0d8bfe1
"drm/atomic-helper: Re-order bridge chain pre-enable and post-disable"
caused regressions in all bridges that e.g. send DSI commands in
their .prepare() and .unprepare() callbacks when used with R-Car DU.
This is needed on R-Car DU, where the CRTC provides clock to LVDS
and DSI, and has to be started before a bridge may call .prepare,
which may trigger e.g. a DSI transfer.
This specifically fixes the case where ILI9881C is connected to R-Car
DU DSI. The ILI9881C panel driver does DSI command transfer in its
struct drm_panel_funcs .prepare function, which is currently called
before R-Car DU rcar_du_crtc_atomic_enable() rcar_mipi_dsi_pclk_enable()
and the DSI command transfer times out.
Fixes: c9b1150a68d9 ("drm/atomic-helper: Re-order bridge chain pre-enable and
post-disable")
Link:
https://lore.kernel.org/all/20251107230517.471894-1-marek.vasut%2Brenesas%40mailbox.org/
Tested-by: Geert Uytterhoeven <[email protected]>
Co-developed-by: Marek Vasut <[email protected]>
Signed-off-by: Marek Vasut <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
---
This is a modified version of Marek's patch using the approach
from MCDE. I'm pretty sure this driver also needs the original
semantic ording during disablement, and it surely doesn't hurt
to restore it too.
---
drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
index 216219accfd9..704f5e067357 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
@@ -540,11 +540,30 @@ static void rcar_du_atomic_commit_tail(struct
drm_atomic_state *old_state)
rcdu->dpad1_source = rcrtc->index;
}
- /* Apply the atomic update. */
- drm_atomic_helper_commit_modeset_disables(dev, old_state);
+ /*
+ * Apply the atomic update.
+ *
+ * We need special ordering to make sure the CRTC disabled last
+ * and enabled first. We do this with modified versions of the
+ * common modeset_disables/enables functions.
+ */
+
+ /* Variant of drm_atomic_helper_commit_modeset_disables() */
+ drm_encoder_bridge_disable(dev, old_state);
+ drm_encoder_bridge_post_disable(dev, old_state);
+ drm_crtc_disable(dev, old_state);
+ drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
+ drm_atomic_helper_calc_timestamping_constants(old_state);
+ drm_crtc_set_mode(dev, old_state);
+
drm_atomic_helper_commit_planes(dev, old_state,
DRM_PLANE_COMMIT_ACTIVE_ONLY);
- drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+ /* Variant of drm_atomic_helper_commit_modeset_enables() */
+ drm_crtc_enable(dev, old_state);
+ drm_encoder_bridge_pre_enable(dev, old_state);
+ drm_encoder_bridge_enable(dev, old_state);
+ drm_atomic_helper_commit_writebacks(dev, old_state);
drm_atomic_helper_commit_hw_done(old_state);
drm_atomic_helper_wait_for_flip_done(dev, old_state);
--
2.51.1