[RFC,v2,1/2] drm/atomic: Track drm_plane's active state
diff mbox

Message ID 31721575aebfdce64636ab06ffc2a25a30621b61.1447428525.git.jsarha@ti.com
State New
Headers show

Commit Message

Jyri Sarha Nov. 13, 2015, 3:53 p.m. UTC
Track drm_plane's active state with a new boolean in struct
drm_plane_state. The patch replaces drm_atomic_plane_disabling() with
drm_atomic_helper_update_plane_state(). In addition to all the same
things the drm_atomic_plane_disabling() used to do the new function
updates the active-flag and calls atomic_update() or atomic_disable()
from the plane's helper funcs as needed.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 63 ++++++++++++++++++++++++++++---------
 drivers/gpu/drm/drm_plane_helper.c  | 10 +-----
 include/drm/drm_atomic_helper.h     | 39 ++---------------------
 include/drm/drm_crtc.h              |  2 ++
 4 files changed, 53 insertions(+), 61 deletions(-)

Patch
diff mbox

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index aecb5d6..d03e2ac 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1197,15 +1197,7 @@  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 		if (!funcs)
 			continue;
 
-		/*
-		 * Special-case disabling the plane if drivers support it.
-		 */
-		if (drm_atomic_plane_disabling(plane, old_plane_state) &&
-		    funcs->atomic_disable)
-			funcs->atomic_disable(plane, old_plane_state);
-		else if (plane->state->crtc ||
-			 drm_atomic_plane_disabling(plane, old_plane_state))
-			funcs->atomic_update(plane, old_plane_state);
+		drm_atomic_helper_update_plane_state(plane, old_plane_state);
 	}
 
 	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
@@ -1266,12 +1258,7 @@  drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
 
 		WARN_ON(plane->state->crtc && plane->state->crtc != crtc);
 
-		if (drm_atomic_plane_disabling(plane, old_plane_state) &&
-		    plane_funcs->atomic_disable)
-			plane_funcs->atomic_disable(plane, old_plane_state);
-		else if (plane->state->crtc ||
-			 drm_atomic_plane_disabling(plane, old_plane_state))
-			plane_funcs->atomic_update(plane, old_plane_state);
+		drm_atomic_helper_update_plane_state(plane, old_plane_state);
 	}
 
 	if (crtc_funcs && crtc_funcs->atomic_flush)
@@ -1279,6 +1266,52 @@  drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
 
+/*
+ * drm_atomic_helper_update_plane_state - update plane's atomic state
+ * @plane: plane object
+ * @old_state: previous atomic state
+ *
+ * Update plane's atomic state, disables it if that is required, and
+ * updates drm_palnes_state's active-flag. This also WARNs if it
+ * detects an invalid state (both CRTC and FB need to either both be
+ * NULL or both be non-NULL).
+ */
+void drm_atomic_helper_update_plane_state(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	const struct drm_plane_helper_funcs *funcs = plane->helper_private;
+
+	/*
+	 * When disabling a plane, CRTC and FB should always be NULL together.
+	 * Anything else should be considered a bug in the atomic core, so we
+	 * gently warn about it.
+	 */
+	WARN_ON((plane->state->crtc == NULL && plane->state->fb != NULL) ||
+		(plane->state->crtc != NULL && plane->state->fb == NULL));
+
+	if (!funcs)
+		return;
+
+	/*
+	 * The plane needs to be active only if it has an associated CRTC
+	 * and the CRTC is active. Use atomic_disable() if available.
+	 */
+	if (plane->state->active) {
+		if (!plane->state->crtc || !plane->state->crtc->state->active) {
+			plane->state->active = false;
+			if (funcs->atomic_disable) {
+				funcs->atomic_disable(plane, old_state);
+				return;
+			}
+		}
+		funcs->atomic_update(plane, old_state);
+	} else if (plane->state->crtc && plane->state->crtc->state->active) {
+		plane->state->active = true;
+		funcs->atomic_update(plane, old_state);
+	}
+}
+EXPORT_SYMBOL(drm_atomic_helper_update_plane_state);
+
 /**
  * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit
  * @dev: DRM device
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 5e5a07a..93052de 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -440,15 +440,7 @@  int drm_plane_helper_commit(struct drm_plane *plane,
 			crtc_funcs[i]->atomic_begin(crtc[i], crtc[i]->state);
 	}
 
-	/*
-	 * Drivers may optionally implement the ->atomic_disable callback, so
-	 * special-case that here.
-	 */
-	if (drm_atomic_plane_disabling(plane, plane_state) &&
-	    plane_funcs->atomic_disable)
-		plane_funcs->atomic_disable(plane, plane_state);
-	else
-		plane_funcs->atomic_update(plane, plane_state);
+	drm_atomic_helper_update_plane_state(plane, plane_state);
 
 	for (i = 0; i < 2; i++) {
 		if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 11266d14..2fbdf5e 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -59,6 +59,8 @@  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 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);
+void drm_atomic_helper_update_plane_state(struct drm_plane *plane,
+					  struct drm_plane_state *old_state);
 
 void drm_atomic_helper_swap_state(struct drm_device *dev,
 				  struct drm_atomic_state *state);
@@ -148,41 +150,4 @@  void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
 #define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \
 	drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)
 
-/*
- * drm_atomic_plane_disabling - check whether a plane is being disabled
- * @plane: plane object
- * @old_state: previous atomic state
- *
- * Checks the atomic state of a plane to determine whether it's being disabled
- * or not. This also WARNs if it detects an invalid state (both CRTC and FB
- * need to either both be NULL or both be non-NULL).
- *
- * RETURNS:
- * True if the plane is being disabled, false otherwise.
- */
-static inline bool
-drm_atomic_plane_disabling(struct drm_plane *plane,
-			   struct drm_plane_state *old_state)
-{
-	/*
-	 * When disabling a plane, CRTC and FB should always be NULL together.
-	 * Anything else should be considered a bug in the atomic core, so we
-	 * gently warn about it.
-	 */
-	WARN_ON((plane->state->crtc == NULL && plane->state->fb != NULL) ||
-		(plane->state->crtc != NULL && plane->state->fb == NULL));
-
-	/*
-	 * When using the transitional helpers, old_state may be NULL. If so,
-	 * we know nothing about the current state and have to assume that it
-	 * might be enabled.
-	 *
-	 * When using the atomic helpers, old_state won't be NULL. Therefore
-	 * this check assumes that either the driver will have reconstructed
-	 * the correct state in ->reset() or that the driver will have taken
-	 * appropriate measures to disable all planes.
-	 */
-	return (!old_state || old_state->crtc) && !plane->state->crtc;
-}
-
 #endif /* DRM_ATOMIC_HELPER_H_ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index faaeff7..c5ee6b6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -768,6 +768,8 @@  struct drm_connector {
 struct drm_plane_state {
 	struct drm_plane *plane;
 
+	bool active;
+
 	struct drm_crtc *crtc;   /* do not write directly, use drm_atomic_set_crtc_for_plane() */
 	struct drm_framebuffer *fb;  /* do not write directly, use drm_atomic_set_fb_for_plane() */
 	struct fence *fence;