[1/3] drm/atomic-helper: Add option to update planes only on active crtc
diff mbox

Message ID 1438171270-11471-1-git-send-email-daniel.vetter@ffwll.ch
State New
Headers show

Commit Message

Daniel Vetter July 29, 2015, 12:01 p.m. UTC
With drivers supporting runtime pm it's generally not a good idea to
touch the hardware when it's off. Add an option to the commit_planes
helper to support this case.

Note that the helpers already add all planes on a crtc when a modeset
happens, hence plane updates will not be lost if drivers set this to
true.

v2: Check for NULL state->crtc before chasing the pointer. Also check
both old and new crtc if there's a switch. Finally just outright
disallow switching crtcs for a plane if the plane is in active use, on
most hardware that doesn't make sense.

v3: Since commit_planes(active_only = true) is for enabling things
only after all the crtc are on we should only look at the new crtc to
decide whether to call the plane hooks - if the current CRTC isn't on
then skip. If the old crtc (when moving a plane) went down then the
plane should have been disabled as part of the pipe shutdown work
already. For which there's currently no helper really unfortunately.
Also move the check for wether a plane gets a new CRTC assigned while
still in active use out of this patch.

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Thierry Reding <treding@nvidia.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c    | 20 ++++++++++++++++++--
 drivers/gpu/drm/exynos/exynos_drm_fb.c |  2 +-
 drivers/gpu/drm/msm/msm_atomic.c       |  2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c     |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c  |  2 +-
 drivers/gpu/drm/sti/sti_drm_drv.c      |  2 +-
 drivers/gpu/drm/tegra/drm.c            |  2 +-
 include/drm/drm_atomic_helper.h        |  3 ++-
 8 files changed, 26 insertions(+), 9 deletions(-)

Comments

Maarten Lankhorst July 30, 2015, 4:28 p.m. UTC | #1
Op 29-07-15 om 14:01 schreef Daniel Vetter:
> With drivers supporting runtime pm it's generally not a good idea to
> touch the hardware when it's off. Add an option to the commit_planes
> helper to support this case.
>
> Note that the helpers already add all planes on a crtc when a modeset
> happens, hence plane updates will not be lost if drivers set this to
> true.
>
> v2: Check for NULL state->crtc before chasing the pointer. Also check
> both old and new crtc if there's a switch. Finally just outright
> disallow switching crtcs for a plane if the plane is in active use, on
> most hardware that doesn't make sense.
>
> v3: Since commit_planes(active_only = true) is for enabling things
> only after all the crtc are on we should only look at the new crtc to
> decide whether to call the plane hooks - if the current CRTC isn't on
> then skip. If the old crtc (when moving a plane) went down then the
> plane should have been disabled as part of the pipe shutdown work
> already. For which there's currently no helper really unfortunately.
> Also move the check for wether a plane gets a new CRTC assigned while
> still in active use out of this patch.
>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Thierry Reding <treding@nvidia.com>
> Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c    | 20 ++++++++++++++++++--
>  drivers/gpu/drm/exynos/exynos_drm_fb.c |  2 +-
>  drivers/gpu/drm/msm/msm_atomic.c       |  2 +-
>  drivers/gpu/drm/omapdrm/omap_drv.c     |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c  |  2 +-
>  drivers/gpu/drm/sti/sti_drm_drv.c      |  2 +-
>  drivers/gpu/drm/tegra/drm.c            |  2 +-
>  include/drm/drm_atomic_helper.h        |  3 ++-
>  8 files changed, 26 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 0b475fae067d..6be0adb5a0e9 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1029,7 +1029,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  
>  	drm_atomic_helper_commit_modeset_disables(dev, state);
>  
> -	drm_atomic_helper_commit_planes(dev, state);
> +	drm_atomic_helper_commit_planes(dev, state, false);
>  
>  	drm_atomic_helper_commit_modeset_enables(dev, state);
>  
> @@ -1144,10 +1144,16 @@ fail:
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
>  
> +bool plane_crtc_active(struct drm_plane_state *state)
> +{
> +	return state->crtc && state->crtc->state->active;
> +}
> +
>  /**
>   * drm_atomic_helper_commit_planes - commit plane state
>   * @dev: DRM device
>   * @old_state: atomic state object with old state structures
> + * @active_only: Only commit on active CRTC if set
>   *
>   * This function commits the new plane state using the plane and atomic helper
>   * functions for planes and crtcs. It assumes that the atomic state has already
> @@ -1162,7 +1168,8 @@ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
>   * drm_atomic_helper_commit_planes_on_crtc() instead.
>   */
>  void drm_atomic_helper_commit_planes(struct drm_device *dev,
> -				     struct drm_atomic_state *old_state)
> +				     struct drm_atomic_state *old_state,
> +				     bool active_only)
>  {
>  	struct drm_crtc *crtc;
>  	struct drm_crtc_state *old_crtc_state;
> @@ -1178,6 +1185,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
>  		if (!funcs || !funcs->atomic_begin)
>  			continue;
>  
> +		if (active_only && !crtc->state->active)
> +			continue;
> +
>  		funcs->atomic_begin(crtc, old_crtc_state);
>  	}
>  
> @@ -1189,6 +1199,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
>  		if (!funcs)
>  			continue;
>  
> +		if (active_only && !plane_crtc_active(plane->state))
> +			continue;
> +
>  		/*
>  		 * Special-case disabling the plane if drivers support it.
>  		 */
>
This would leave a plane active if it was moved from a active crtc to a inactive crtc, you would still need to call the atomic_disable(plane) callback for that one. ;-)

~Maarten

Patch
diff mbox

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 0b475fae067d..6be0adb5a0e9 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1029,7 +1029,7 @@  int drm_atomic_helper_commit(struct drm_device *dev,
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
-	drm_atomic_helper_commit_planes(dev, state);
+	drm_atomic_helper_commit_planes(dev, state, false);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
 
@@ -1144,10 +1144,16 @@  fail:
 }
 EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
 
+bool plane_crtc_active(struct drm_plane_state *state)
+{
+	return state->crtc && state->crtc->state->active;
+}
+
 /**
  * drm_atomic_helper_commit_planes - commit plane state
  * @dev: DRM device
  * @old_state: atomic state object with old state structures
+ * @active_only: Only commit on active CRTC if set
  *
  * This function commits the new plane state using the plane and atomic helper
  * functions for planes and crtcs. It assumes that the atomic state has already
@@ -1162,7 +1168,8 @@  EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
  * drm_atomic_helper_commit_planes_on_crtc() instead.
  */
 void drm_atomic_helper_commit_planes(struct drm_device *dev,
-				     struct drm_atomic_state *old_state)
+				     struct drm_atomic_state *old_state,
+				     bool active_only)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *old_crtc_state;
@@ -1178,6 +1185,9 @@  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 		if (!funcs || !funcs->atomic_begin)
 			continue;
 
+		if (active_only && !crtc->state->active)
+			continue;
+
 		funcs->atomic_begin(crtc, old_crtc_state);
 	}
 
@@ -1189,6 +1199,9 @@  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 		if (!funcs)
 			continue;
 
+		if (active_only && !plane_crtc_active(plane->state))
+			continue;
+
 		/*
 		 * Special-case disabling the plane if drivers support it.
 		 */
@@ -1208,6 +1221,9 @@  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 		if (!funcs || !funcs->atomic_flush)
 			continue;
 
+		if (active_only && !crtc->state->active)
+			continue;
+
 		funcs->atomic_flush(crtc, old_crtc_state);
 	}
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 2b6320e6eae2..7b383acbb5af 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -293,7 +293,7 @@  static int exynos_atomic_commit(struct drm_device *dev,
 	 * have the relevant clocks enabled to perform the update.
 	 */
 
-	drm_atomic_helper_commit_planes(dev, state);
+	drm_atomic_helper_commit_planes(dev, state, false);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 1b22d8bfe142..0709b97251bf 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -125,7 +125,7 @@  static void complete_commit(struct msm_commit *c)
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
-	drm_atomic_helper_commit_planes(dev, state);
+	drm_atomic_helper_commit_planes(dev, state, false);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index e888a831dd3c..0ecce79fc782 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -96,7 +96,7 @@  static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
 	dispc_runtime_get();
 
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state);
+	drm_atomic_helper_commit_planes(dev, old_state, false);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
 	omap_atomic_wait_for_completion(dev, old_state);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 56518eb1269a..ca12e8ca5552 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -456,7 +456,7 @@  static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
 	/* Apply the atomic update. */
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state);
+	drm_atomic_helper_commit_planes(dev, old_state, false);
 
 	drm_atomic_helper_wait_for_vblanks(dev, old_state);
 
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.c b/drivers/gpu/drm/sti/sti_drm_drv.c
index 59d558b400b3..123f1408d508 100644
--- a/drivers/gpu/drm/sti/sti_drm_drv.c
+++ b/drivers/gpu/drm/sti/sti_drm_drv.c
@@ -59,7 +59,7 @@  static void sti_drm_atomic_complete(struct sti_drm_private *private,
 	 */
 
 	drm_atomic_helper_commit_modeset_disables(drm, state);
-	drm_atomic_helper_commit_planes(drm, state);
+	drm_atomic_helper_commit_planes(drm, state, false);
 	drm_atomic_helper_commit_modeset_enables(drm, state);
 
 	drm_atomic_helper_wait_for_vblanks(drm, state);
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index c6276aebfec3..783edc242648 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -56,7 +56,7 @@  static void tegra_atomic_complete(struct tegra_drm *tegra,
 	 */
 
 	drm_atomic_helper_commit_modeset_disables(drm, state);
-	drm_atomic_helper_commit_planes(drm, state);
+	drm_atomic_helper_commit_planes(drm, state, false);
 	drm_atomic_helper_commit_modeset_enables(drm, state);
 
 	drm_atomic_helper_wait_for_vblanks(drm, state);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 11266d147a29..4ffe9dca07c4 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -55,7 +55,8 @@  void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 int drm_atomic_helper_prepare_planes(struct drm_device *dev,
 				     struct drm_atomic_state *state);
 void drm_atomic_helper_commit_planes(struct drm_device *dev,
-				     struct drm_atomic_state *state);
+				     struct drm_atomic_state *state,
+				     bool active_only);
 void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
 				      struct drm_atomic_state *old_state);
 void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state);