drm: shmobile: Fix white screen after resume when LCDC is stopped
Subsystems (3)
PATCH v3 1/1 drm: shmobile: Fix white screen after resume when LCDC is stopped
From: bui duc phuc <[email protected]>
The LCDC on R8A7740 may show a completely white screen after resuming from suspend (s2idle or s2ram).
After resume, both Set A and Set B registers are reset to 0. As the Frame End interrupt is not generated while the controller is stopped (DO=0), the hardware register switching mechanism is not triggered. Consequently, Set A remains at 0x00000000 even though a valid Start Address is written to Set B, resulting in a white screen.
This is a timing-dependent race condition. In some configurations, debug options slow down the resume path enough for a Frame End interrupt to occur, which can mask the issue.
Fix this by priming both register sets with the Start Address while the controller is stopped, ensuring a valid base address is available immediately after resume.
---
Changes:
- v3
Update commit message, add Tested-by and Reviewed-by tags
- v2
Fix incorrect use of lcdc_write_mirror() for LDSA2R in the DO=0 path; use lcdc_write() to update both register sets as intended.
.../gpu/drm/renesas/shmobile/shmob_drm_plane.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c +13 -4
@@ -70,6 +70,7 @@ static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,struct shmob_drm_plane_state *sstate =to_shmob_plane_state (state);struct shmob_drm_device *sdev =to_shmob_device (splane->base.dev);struct drm_framebuffer *fb = state->fb; +u32 ldcnt2r;/* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */ lcdc_write (sdev,LDDFR , sstate->format->lddfr |LDDFR_CF1 );
@@ -78,11 +79,19 @@ static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,/* Word and long word swap. */ lcdc_write (sdev,LDDDSR , sstate->format->ldddsr); -lcdc_write_mirror (sdev,LDSA1R , sstate->dma[0 ]); -if (shmob_drm_format_is_yuv (sstate->format)) -lcdc_write_mirror (sdev,LDSA2R , sstate->dma[1 ]); + ldcnt2r =lcdc_read (sdev,LDCNT2R ); + +if (ldcnt2r &LDCNT2R_DO ) { +lcdc_write_mirror (sdev,LDSA1R , sstate->dma[0 ]); +if (shmob_drm_format_is_yuv (sstate->format)) +lcdc_write_mirror (sdev,LDSA2R , sstate->dma[1 ]); -lcdc_write (sdev,LDRCNTR ,lcdc_read (sdev,LDRCNTR ) ^LDRCNTR_MRS ); +lcdc_write (sdev,LDRCNTR ,lcdc_read (sdev,LDRCNTR ) ^LDRCNTR_MRS ); + }else { +lcdc_write (sdev,LDSA1R , sstate->dma[0 ]); +if (shmob_drm_format_is_yuv (sstate->format)) +lcdc_write (sdev,LDSA2R , sstate->dma[1 ]); + } } static void shmob_drm_overlay_plane_setup(struct shmob_drm_plane *splane,
Signature · 1 line
2.43.0
Hi all,
Just a gentle ping on this patch.
It has been reviewed and tested, but I haven't seen it being applied yet. Is there anything I should fix or resend?
Thanks!
Quoted 74 lines · On Thu, Mar 19, 2026 at 3:32 PM <[email protected]> wrote:
From: bui duc phuc <[email protected]>
The LCDC on R8A7740 may show a completely white screen after resuming from suspend (s2idle or s2ram).
After resume, both Set A and Set B registers are reset to 0. As the Frame End interrupt is not generated while the controller is stopped (DO=0), the hardware register switching mechanism is not triggered. Consequently, Set A remains at
0x00000000even though a valid Start Address is written to Set B, resulting in a white screen.This is a timing-dependent race condition. In some configurations, debug options slow down the resume path enough for a Frame End interrupt to occur, which can mask the issue.
Fix this by priming both register sets with the Start Address while the controller is stopped, ensuring a valid base address is available immediately after resume.
Tested-by Geert Uytterhoeven <[email protected]>Reviewed-by Geert Uytterhoeven <[email protected]>Signed-off-by bui duc phuc <[email protected]>---
Changes:
- v3
Update commit message, add Tested-by and Reviewed-by tags
- v2
Fix incorrect use oflcdc_write_mirror()for LDSA2R in the DO=0 path; uselcdc_write()to update both register sets as intended..../gpu/drm/renesas/shmobile/shmob_drm_plane.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c +13
-5@@ -70,6 +70,7 @@ static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,struct shmob_drm_plane_state *sstate =to_shmob_plane_state (state);struct shmob_drm_device *sdev =to_shmob_device (splane->base.dev);struct drm_framebuffer *fb = state->fb; +u32 ldcnt2r;/* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */ lcdc_write (sdev,LDDFR , sstate->format->lddfr |LDDFR_CF1 );@@ -78,11 +79,19 @@ static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,/* Word and long word swap. */ lcdc_write (sdev,LDDDSR , sstate->format->ldddsr); -lcdc_write_mirror (sdev,LDSA1R , sstate->dma[0 ]); -if (shmob_drm_format_is_yuv (sstate->format)) -lcdc_write_mirror (sdev,LDSA2R , sstate->dma[1 ]); + ldcnt2r =lcdc_read (sdev,LDCNT2R ); + +if (ldcnt2r &LDCNT2R_DO ) { +lcdc_write_mirror (sdev,LDSA1R , sstate->dma[0 ]); +if (shmob_drm_format_is_yuv (sstate->format)) +lcdc_write_mirror (sdev,LDSA2R , sstate->dma[1 ]); -lcdc_write (sdev,LDRCNTR ,lcdc_read (sdev,LDRCNTR ) ^LDRCNTR_MRS ); +lcdc_write (sdev,LDRCNTR ,lcdc_read (sdev,LDRCNTR ) ^LDRCNTR_MRS ); + }else { +lcdc_write (sdev,LDSA1R , sstate->dma[0 ]); +if (shmob_drm_format_is_yuv (sstate->format)) +lcdc_write (sdev,LDSA2R , sstate->dma[1 ]); + } } static void shmob_drm_overlay_plane_setup(struct shmob_drm_plane *splane, --2.43.0