[PATCH v2 3/6] drm: lcdif: rework runtime PM handling in the atomic commit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



drm_atomic_helper_commit_tail_rpm makes it hard for drivers to follow
the documented encoder/bridge enable flow, as it commits all CRTC enables
before the planes are fully set up, so drivers that can't enable the
display link without valid plane setup either need to do the plane setup
in the CRTC enable or violate the flow by enabling the display link after
the planes have been set up. Neither of those options seem like a good
idea.

For devices that only do coarse-grained runtime PM for the whole display
controller and not per CRTC, like the i.MX LCDIF, we can handle hardware
wakeup and suspend in the atomic_commit_tail. Add a commit tail which
follows the more conventional atomic commit flow of first diabling any
unused CRTCs, setting up all the active plane state, then enable all
active display pipes and also handles the device runtime PM at the
appropriate times.

Signed-off-by: Lucas Stach <l.stach@xxxxxxxxxxxxxx>
---
v2: new patch
---
 drivers/gpu/drm/mxsfb/lcdif_drv.c | 22 +++++++++++++++++++++-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 12 ++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 18de2f17e249..205f6855fb1b 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -36,8 +36,28 @@ static const struct drm_mode_config_funcs lcdif_mode_config_funcs = {
 	.atomic_commit		= drm_atomic_helper_commit,
 };
 
+void lcdif_commit_tail(struct drm_atomic_state *old_state)
+{
+	struct drm_device *drm = old_state->dev;
+
+	pm_runtime_get_sync(drm->dev);
+
+	drm_atomic_helper_commit_modeset_disables(drm, old_state);
+	drm_atomic_helper_commit_planes(drm, old_state,
+					DRM_PLANE_COMMIT_ACTIVE_ONLY);
+	drm_atomic_helper_commit_modeset_enables(drm, old_state);
+
+	drm_atomic_helper_fake_vblank(old_state);
+	drm_atomic_helper_commit_hw_done(old_state);
+	drm_atomic_helper_wait_for_vblanks(drm, old_state);
+
+	pm_runtime_put(drm->dev);
+
+	drm_atomic_helper_cleanup_planes(drm, old_state);
+}
+
 static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = {
-	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+	.atomic_commit_tail = lcdif_commit_tail,
 };
 
 static const struct drm_encoder_funcs lcdif_encoder_funcs = {
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index e277592e5fa5..ccee5e28f236 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -540,7 +540,11 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
 
-	pm_runtime_get_sync(drm->dev);
+	/*
+	 * Update the RPM usage count, actual resume already happened in
+	 * lcdif_commit_tail wrapping all the atomic update.
+	 */
+	pm_runtime_get_noresume(drm->dev);
 
 	lcdif_crtc_mode_set_nofb(new_cstate, new_pstate);
 
@@ -576,7 +580,11 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc *crtc,
 	}
 	spin_unlock_irq(&drm->event_lock);
 
-	pm_runtime_put_sync(drm->dev);
+	/*
+	 * Update the RPM usage count, actual suspend happens in
+	 * lcdif_commit_tail wrapping all the atomic update.
+	 */
+	pm_runtime_put(drm->dev);
 }
 
 static void lcdif_crtc_atomic_destroy_state(struct drm_crtc *crtc,
-- 
2.39.2




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux