... and use it in msm&vc4. Again just want to encapsulate
drm_atomic_state internals a bit.

The const threading is a bit awkward in vc4 since C sucks, but I still
think it's worth to enforce this. Eventually I want to make all the
obj->state pointers const too, but that's a lot more work ...

Cc: Eric Anholt <eric at anholt.net>
Cc: Rob Clark <robdclark at gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 10 +++------
 drivers/gpu/drm/vc4/vc4_crtc.c           | 11 +++-------
 drivers/gpu/drm/vc4/vc4_drv.h            |  2 +-
 drivers/gpu/drm/vc4/vc4_plane.c          |  5 +++--
 include/drm/drm_atomic.h                 | 36 ++++++++++++++++++++++++++++++++
 5 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 88fe256c1931..6d4086ee0503 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -383,19 +383,15 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
         */
        hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
        drm_atomic_crtc_state_for_each_plane(plane, state) {
-               struct drm_plane_state *pstate;
+               const struct drm_plane_state *pstate;
                if (cnt >= (hw_cfg->lm.nb_stages)) {
                        dev_err(dev->dev, "too many planes!\n");
                        return -EINVAL;
                }

-               pstate = state->state->plane_states[drm_plane_index(plane)];
+               pstate = __drm_atomic_get_current_plane_state(state->state,
+                                                             plane);

-               /* plane might not have changed, in which case take
-                * current state:
-                */
-               if (!pstate)
-                       pstate = plane->state;
                pstates[cnt].plane = plane;
                pstates[cnt].state = to_mdp5_plane_state(pstate);

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 904d0754ad78..703bda170105 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -405,14 +405,9 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
                return -EINVAL;

        drm_atomic_crtc_state_for_each_plane(plane, state) {
-               struct drm_plane_state *plane_state =
-                       state->state->plane_states[drm_plane_index(plane)];
-
-               /* plane might not have changed, in which case take
-                * current state:
-                */
-               if (!plane_state)
-                       plane_state = plane->state;
+               const struct drm_plane_state *plane_state =
+                       __drm_atomic_get_current_plane_state(state->state,
+                                                            plane);

                dlist_count += vc4_plane_dlist_size(plane_state);
        }
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 37cac59401d7..c799baabc008 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -469,7 +469,7 @@ int vc4_kms_load(struct drm_device *dev);
 struct drm_plane *vc4_plane_init(struct drm_device *dev,
                                 enum drm_plane_type type);
 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
-u32 vc4_plane_dlist_size(struct drm_plane_state *state);
+u32 vc4_plane_dlist_size(const struct drm_plane_state *state);
 void vc4_plane_async_set_fb(struct drm_plane *plane,
                            struct drm_framebuffer *fb);

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 4037b52fde31..5d2c3d9fd17a 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -690,9 +690,10 @@ u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 
__iomem *dlist)
        return vc4_state->dlist_count;
 }

-u32 vc4_plane_dlist_size(struct drm_plane_state *state)
+u32 vc4_plane_dlist_size(const struct drm_plane_state *state)
 {
-       struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+       const struct vc4_plane_state *vc4_state =
+               container_of(state, typeof(*vc4_state), base);

        return vc4_state->dlist_count;
 }
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 92c84e9ab09a..4e97186293be 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -109,6 +109,42 @@ drm_atomic_get_existing_connector_state(struct 
drm_atomic_state *state,
        return state->connector_states[index];
 }

+/**
+ * __drm_atomic_get_current_plane_state - get current plane state
+ * @state: global atomic state object
+ * @plane: plane to grab
+ *
+ * This function returns the plane state for the given plane, either from
+ * @state, or if the plane isn't part of the atomic state update, from @plane.
+ * This is useful in atomic check callbacks, when drivers need to peek at, but
+ * not change, state of other planes, since it avoids threading an error code
+ * back up the call chain.
+ *
+ * WARNING:
+ *
+ * Note that this function is in general unsafe since it doesn't check for the
+ * required locking for access state structures. Drivers must ensure that it is
+ * save to access the returned state structure through other means. One commone
+ * example is when planes are fixed to a single CRTC, and the driver knows that
+ * the CRTC locks is held already. In that case holding the CRTC locks gives a
+ * read-lock on all planes connected to that CRTC. But if planes can be
+ * reassigned things get more tricky. In that case it's better to use
+ * drm_atomic_get_plane_state and wire up full error handling.
+ *
+ * Returns:
+ *
+ * Read-only pointer to the current plane state.
+ */
+static inline const struct drm_plane_state *
+__drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
+                                    struct drm_plane *plane)
+{
+       if (state->plane_states[drm_plane_index(plane)])
+               return state->plane_states[drm_plane_index(plane)];
+
+       return plane->state;
+}
+
 int __must_check
 drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
                             struct drm_display_mode *mode);
-- 
2.8.1

Reply via email to