Commit 2f196b7c authored by Daniel Vetter's avatar Daniel Vetter
Browse files

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: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1464877304-4213-1-git-send-email-daniel.vetter@ffwll.ch
parent 2e7a5701
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -374,6 +374,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
	struct drm_device *dev = crtc->dev;
	struct plane_state pstates[STAGE_MAX + 1];
	const struct mdp5_cfg_hw *hw_cfg;
	const struct drm_plane_state *pstate;
	int cnt = 0, i;

	DBG("%s: check", mdp5_crtc->name);
@@ -382,20 +383,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
	 * and that we don't have conflicting mixer stages:
	 */
	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
	drm_atomic_crtc_state_for_each_plane(plane, state) {
		struct drm_plane_state *pstate;
	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
		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)];

		/* 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);

+2 −11
Original line number Diff line number Diff line
@@ -395,6 +395,7 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
	struct vc4_dev *vc4 = to_vc4_dev(dev);
	struct drm_plane *plane;
	unsigned long flags;
	const struct drm_plane_state *plane_state;
	u32 dlist_count = 0;
	int ret;

@@ -404,18 +405,8 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
	if (hweight32(state->connector_mask) > 1)
		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;

	drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, state)
		dlist_count += vc4_plane_dlist_size(plane_state);
	}

	dlist_count++; /* Account for SCALER_CTL0_END. */

+1 −1
Original line number Diff line number Diff line
@@ -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);

+3 −2
Original line number Diff line number Diff line
@@ -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;
}
+36 −0
Original line number Diff line number Diff line
@@ -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);
Loading