aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2016-06-02 10:21:44 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-06-02 10:59:05 -0400
commit2f196b7c4b82eeff3574eb2999e78add33ef4361 (patch)
treee6559bd5fcc1bb317aabfebdb1de7db2bab136e1
parent2e7a5701c9b2ee47089677ed5fbbc397b3bf3dec (diff)
drm/atomic: Add drm_atomic_crtc_state_for_each_plane_state
... 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 ... v2: Provide safe macro to wrap up the unsafe helper better, suggested by Maarten. v3: Fixup subject (Maarten) and spelling fixes (Eric Engestrom). Cc: Eric Anholt <eric@anholt.net> Cc: Rob Clark <robdclark@gmail.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Eric Engestrom <eric.engestrom@imgtec.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1464877304-4213-1-git-send-email-daniel.vetter@ffwll.ch
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c10
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c13
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h2
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c5
-rw-r--r--include/drm/drm_atomic.h36
-rw-r--r--include/drm/drm_atomic_helper.h24
6 files changed, 66 insertions, 24 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..4e8ed739f558 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -374,6 +374,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
374 struct drm_device *dev = crtc->dev; 374 struct drm_device *dev = crtc->dev;
375 struct plane_state pstates[STAGE_MAX + 1]; 375 struct plane_state pstates[STAGE_MAX + 1];
376 const struct mdp5_cfg_hw *hw_cfg; 376 const struct mdp5_cfg_hw *hw_cfg;
377 const struct drm_plane_state *pstate;
377 int cnt = 0, i; 378 int cnt = 0, i;
378 379
379 DBG("%s: check", mdp5_crtc->name); 380 DBG("%s: check", mdp5_crtc->name);
@@ -382,20 +383,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
382 * and that we don't have conflicting mixer stages: 383 * and that we don't have conflicting mixer stages:
383 */ 384 */
384 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); 385 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
385 drm_atomic_crtc_state_for_each_plane(plane, state) { 386 drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
386 struct drm_plane_state *pstate;
387 if (cnt >= (hw_cfg->lm.nb_stages)) { 387 if (cnt >= (hw_cfg->lm.nb_stages)) {
388 dev_err(dev->dev, "too many planes!\n"); 388 dev_err(dev->dev, "too many planes!\n");
389 return -EINVAL; 389 return -EINVAL;
390 } 390 }
391 391
392 pstate = state->state->plane_states[drm_plane_index(plane)];
393 392
394 /* plane might not have changed, in which case take
395 * current state:
396 */
397 if (!pstate)
398 pstate = plane->state;
399 pstates[cnt].plane = plane; 393 pstates[cnt].plane = plane;
400 pstates[cnt].state = to_mdp5_plane_state(pstate); 394 pstates[cnt].state = to_mdp5_plane_state(pstate);
401 395
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 904d0754ad78..ba2e373ec901 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -395,6 +395,7 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
395 struct vc4_dev *vc4 = to_vc4_dev(dev); 395 struct vc4_dev *vc4 = to_vc4_dev(dev);
396 struct drm_plane *plane; 396 struct drm_plane *plane;
397 unsigned long flags; 397 unsigned long flags;
398 const struct drm_plane_state *plane_state;
398 u32 dlist_count = 0; 399 u32 dlist_count = 0;
399 int ret; 400 int ret;
400 401
@@ -404,18 +405,8 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
404 if (hweight32(state->connector_mask) > 1) 405 if (hweight32(state->connector_mask) > 1)
405 return -EINVAL; 406 return -EINVAL;
406 407
407 drm_atomic_crtc_state_for_each_plane(plane, state) { 408 drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, state)
408 struct drm_plane_state *plane_state =
409 state->state->plane_states[drm_plane_index(plane)];
410
411 /* plane might not have changed, in which case take
412 * current state:
413 */
414 if (!plane_state)
415 plane_state = plane->state;
416
417 dlist_count += vc4_plane_dlist_size(plane_state); 409 dlist_count += vc4_plane_dlist_size(plane_state);
418 }
419 410
420 dlist_count++; /* Account for SCALER_CTL0_END. */ 411 dlist_count++; /* Account for SCALER_CTL0_END. */
421 412
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);
469struct drm_plane *vc4_plane_init(struct drm_device *dev, 469struct drm_plane *vc4_plane_init(struct drm_device *dev,
470 enum drm_plane_type type); 470 enum drm_plane_type type);
471u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); 471u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
472u32 vc4_plane_dlist_size(struct drm_plane_state *state); 472u32 vc4_plane_dlist_size(const struct drm_plane_state *state);
473void vc4_plane_async_set_fb(struct drm_plane *plane, 473void vc4_plane_async_set_fb(struct drm_plane *plane,
474 struct drm_framebuffer *fb); 474 struct drm_framebuffer *fb);
475 475
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)
690 return vc4_state->dlist_count; 690 return vc4_state->dlist_count;
691} 691}
692 692
693u32 vc4_plane_dlist_size(struct drm_plane_state *state) 693u32 vc4_plane_dlist_size(const struct drm_plane_state *state)
694{ 694{
695 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 695 const struct vc4_plane_state *vc4_state =
696 container_of(state, typeof(*vc4_state), base);
696 697
697 return vc4_state->dlist_count; 698 return vc4_state->dlist_count;
698} 699}
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,
109 return state->connector_states[index]; 109 return state->connector_states[index];
110} 110}
111 111
112/**
113 * __drm_atomic_get_current_plane_state - get current plane state
114 * @state: global atomic state object
115 * @plane: plane to grab
116 *
117 * This function returns the plane state for the given plane, either from
118 * @state, or if the plane isn't part of the atomic state update, from @plane.
119 * This is useful in atomic check callbacks, when drivers need to peek at, but
120 * not change, state of other planes, since it avoids threading an error code
121 * back up the call chain.
122 *
123 * WARNING:
124 *
125 * Note that this function is in general unsafe since it doesn't check for the
126 * required locking for access state structures. Drivers must ensure that it is
127 * save to access the returned state structure through other means. One commone
128 * example is when planes are fixed to a single CRTC, and the driver knows that
129 * the CRTC locks is held already. In that case holding the CRTC locks gives a
130 * read-lock on all planes connected to that CRTC. But if planes can be
131 * reassigned things get more tricky. In that case it's better to use
132 * drm_atomic_get_plane_state and wire up full error handling.
133 *
134 * Returns:
135 *
136 * Read-only pointer to the current plane state.
137 */
138static inline const struct drm_plane_state *
139__drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
140 struct drm_plane *plane)
141{
142 if (state->plane_states[drm_plane_index(plane)])
143 return state->plane_states[drm_plane_index(plane)];
144
145 return plane->state;
146}
147
112int __must_check 148int __must_check
113drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, 149drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
114 struct drm_display_mode *mode); 150 struct drm_display_mode *mode);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index d473dcc91f54..b03bd83703b4 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -159,7 +159,7 @@ void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
159 * This iterates over the current state, useful (for example) when applying 159 * This iterates over the current state, useful (for example) when applying
160 * atomic state after it has been checked and swapped. To iterate over the 160 * atomic state after it has been checked and swapped. To iterate over the
161 * planes which *will* be attached (for ->atomic_check()) see 161 * planes which *will* be attached (for ->atomic_check()) see
162 * drm_crtc_for_each_pending_plane() 162 * drm_crtc_for_each_pending_plane().
163 */ 163 */
164#define drm_atomic_crtc_for_each_plane(plane, crtc) \ 164#define drm_atomic_crtc_for_each_plane(plane, crtc) \
165 drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask) 165 drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask)
@@ -171,11 +171,31 @@ void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
171 * 171 *
172 * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be 172 * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
173 * attached if the specified state is applied. Useful during (for example) 173 * attached if the specified state is applied. Useful during (for example)
174 * ->atomic_check() operations, to validate the incoming state 174 * ->atomic_check() operations, to validate the incoming state.
175 */ 175 */
176#define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \ 176#define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \
177 drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) 177 drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)
178 178
179/**
180 * drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state
181 * @plane: the loop cursor
182 * @plane_state: loop cursor for the plane's state, must be const
183 * @crtc_state: the incoming crtc-state
184 *
185 * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
186 * attached if the specified state is applied. Useful during (for example)
187 * ->atomic_check() operations, to validate the incoming state.
188 *
189 * Compared to just drm_atomic_crtc_state_for_each_plane() this also fills in a
190 * const plane_state. This is useful when a driver just wants to peek at other
191 * active planes on this crtc, but does not need to change it.
192 */
193#define drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) \
194 drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) \
195 for_each_if ((plane_state = \
196 __drm_atomic_get_current_plane_state((crtc_state)->state, \
197 plane)))
198
179/* 199/*
180 * drm_atomic_plane_disabling - check whether a plane is being disabled 200 * drm_atomic_plane_disabling - check whether a plane is being disabled
181 * @plane: plane object 201 * @plane: plane object