From 6f752c183f1e3c0699d33dd4ced2b29bc3ac3fd4 Mon Sep 17 00:00:00 2001 From: Liu Ying <victor.liu@nxp.com> Date: Mon, 16 Aug 2021 17:07:32 +0800 Subject: [PATCH] LF-4322 drm/imx: dcnano: Avoid double modeset When running the below system suspend/resume test case on i.MX8ulp EVK platform with the RM68200 MIPI DSI panel enabled, DCNANO display controller power usage count and pixel clock enable count would be unbalanced when the DRM connector's DPMS property is changed from off to on after system resumes, if the DPMS property is off before system suspends. The root cause is that the crtc_helper_funcs->mode_set_nofb() is called twice during the procedure without crtc disablement, one at system resume stage and one for DPMS on operation. That means the pm_runtime_get_sync() would be called twice at that function and pixel clock would be enabled twice as well. This patch introduces a flag to indicate if the modeset is done or not to avoid the doulbe modeset so that the reference counts are balanced. while true; do modetest -M imx-dcnano -w 34:DPMS:3; done & while true; do /unit_tests/SRTC/rtcwakeup.out -s 2 -m mem; done Fixes: ce68244e46e7 ("MLK-25531-2 drm/imx: Add dcnano drm support") Cc: Sandor Yu <Sandor.yu@nxp.com> Reviewed-by: Sandor Yu <Sandor.yu@nxp.com> Signed-off-by: Liu Ying <victor.liu@nxp.com> Acked-by: Jason Liu <jason.hui.liu@nxp.com> --- drivers/gpu/drm/imx/dcnano/dcnano-crtc.c | 7 +++++++ drivers/gpu/drm/imx/dcnano/dcnano-drv.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/imx/dcnano/dcnano-crtc.c b/drivers/gpu/drm/imx/dcnano/dcnano-crtc.c index 7524c3f78dbc4d..7de24e5aa5fd34 100644 --- a/drivers/gpu/drm/imx/dcnano/dcnano-crtc.c +++ b/drivers/gpu/drm/imx/dcnano/dcnano-crtc.c @@ -202,6 +202,9 @@ static void dcnano_crtc_mode_set_nofb(struct drm_crtc *crtc) struct dcnano_dev *dcnano = crtc_to_dcnano_dev(crtc); struct drm_display_mode *adj = &crtc->state->adjusted_mode; + if (dcnano->modeset_done) + return; + dcnano_crtc_dbg(crtc, "mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(adj)); dcnano_crtc_set_pixel_clock(crtc); @@ -211,6 +214,8 @@ static void dcnano_crtc_mode_set_nofb(struct drm_crtc *crtc) if (dcnano->port == DCNANO_DPI_PORT) dcnano_crtc_mode_set_nofb_dpi(crtc); + + dcnano->modeset_done = true; } static void dcnano_crtc_queue_state_event(struct drm_crtc *crtc) @@ -330,6 +335,8 @@ static void dcnano_crtc_atomic_disable(struct drm_crtc *crtc, crtc->state->event = NULL; } spin_unlock_irq(&crtc->dev->event_lock); + + dcnano->modeset_done = false; } static bool diff --git a/drivers/gpu/drm/imx/dcnano/dcnano-drv.h b/drivers/gpu/drm/imx/dcnano/dcnano-drv.h index 357a496c5f8520..bbcdd2f5d2041d 100644 --- a/drivers/gpu/drm/imx/dcnano/dcnano-drv.h +++ b/drivers/gpu/drm/imx/dcnano/dcnano-drv.h @@ -42,6 +42,8 @@ struct dcnano_dev { struct drm_pending_vblank_event *event; enum dcnano_port port; + + bool modeset_done; }; static inline struct dcnano_dev *to_dcnano_dev(struct drm_device *drm) -- GitLab