diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-02 10:21:44 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-02 10:59:05 -0400 |
commit | 2f196b7c4b82eeff3574eb2999e78add33ef4361 (patch) | |
tree | e6559bd5fcc1bb317aabfebdb1de7db2bab136e1 | |
parent | 2e7a5701c9b2ee47089677ed5fbbc397b3bf3dec (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.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 5 | ||||
-rw-r--r-- | include/drm/drm_atomic.h | 36 | ||||
-rw-r--r-- | include/drm/drm_atomic_helper.h | 24 |
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); | |||
469 | struct drm_plane *vc4_plane_init(struct drm_device *dev, | 469 | struct drm_plane *vc4_plane_init(struct drm_device *dev, |
470 | enum drm_plane_type type); | 470 | enum drm_plane_type type); |
471 | u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); | 471 | u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); |
472 | u32 vc4_plane_dlist_size(struct drm_plane_state *state); | 472 | u32 vc4_plane_dlist_size(const struct drm_plane_state *state); |
473 | void vc4_plane_async_set_fb(struct drm_plane *plane, | 473 | void 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 | ||
693 | u32 vc4_plane_dlist_size(struct drm_plane_state *state) | 693 | u32 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 | */ | ||
138 | static 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 | |||
112 | int __must_check | 148 | int __must_check |
113 | drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, | 149 | drm_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 |