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 at 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(-)

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;
-- 
1.9.1

Reply via email to