Commit e87a52b3 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Daniel Vetter
Browse files

drm/atomic: Add encoder_mask to crtc_state, v3.



This allows iteration over encoders without requiring connection_mutex.

Changes since v1:
- Add a set_best_encoder helper function and update encoder_mask inside
  it.
Changes since v2:
- Relax the WARN_ON(!crtc), with explanation.
- Call set_best_encoder when connector is moved between crtc's.
- Add some paranoia to steal_encoder to prevent accidentally setting
  best_encoder to NULL.

Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/56AA200A.6070501@linux.intel.com
parent 97a8df90
Loading
Loading
Loading
Loading
+50 −3
Original line number Diff line number Diff line
@@ -125,6 +125,47 @@ get_current_crtc_for_encoder(struct drm_device *dev,
	return NULL;
}

static void
set_best_encoder(struct drm_atomic_state *state,
		 struct drm_connector_state *conn_state,
		 struct drm_encoder *encoder)
{
	struct drm_crtc_state *crtc_state;
	struct drm_crtc *crtc;

	if (conn_state->best_encoder) {
		/* Unset the encoder_mask in the old crtc state. */
		crtc = conn_state->connector->state->crtc;

		/* A NULL crtc is an error here because we should have
		 *  duplicated a NULL best_encoder when crtc was NULL.
		 * As an exception restoring duplicated atomic state
		 * during resume is allowed, so don't warn when
		 * best_encoder is equal to encoder we intend to set.
		 */
		WARN_ON(!crtc && encoder != conn_state->best_encoder);
		if (crtc) {
			crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);

			crtc_state->encoder_mask &=
				~(1 << drm_encoder_index(conn_state->best_encoder));
		}
	}

	if (encoder) {
		crtc = conn_state->crtc;
		WARN_ON(!crtc);
		if (crtc) {
			crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);

			crtc_state->encoder_mask |=
				1 << drm_encoder_index(encoder);
		}
	}

	conn_state->best_encoder = encoder;
}

static int
steal_encoder(struct drm_atomic_state *state,
	      struct drm_encoder *encoder,
@@ -164,7 +205,10 @@ steal_encoder(struct drm_atomic_state *state,
		if (IS_ERR(connector_state))
			return PTR_ERR(connector_state);

		connector_state->best_encoder = NULL;
		if (connector_state->best_encoder != encoder)
			continue;

		set_best_encoder(state, connector_state, NULL);
	}

	return 0;
@@ -212,7 +256,7 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
				connector->base.id,
				connector->name);

		connector_state->best_encoder = NULL;
		set_best_encoder(state, connector_state, NULL);

		return 0;
	}
@@ -241,6 +285,8 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
	}

	if (new_encoder == connector_state->best_encoder) {
		set_best_encoder(state, connector_state, new_encoder);

		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n",
				 connector->base.id,
				 connector->name,
@@ -275,7 +321,8 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
	if (WARN_ON(!connector_state->crtc))
		return -EINVAL;

	connector_state->best_encoder = new_encoder;
	set_best_encoder(state, connector_state, new_encoder);

	idx = drm_crtc_index(connector_state->crtc);

	crtc_state = state->crtc_states[idx];
+3 −0
Original line number Diff line number Diff line
@@ -15591,6 +15591,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
		crtc->base.state->active = crtc->active;
		crtc->base.enabled = crtc->active;
		crtc->base.state->connector_mask = 0;
		crtc->base.state->encoder_mask = 0;

		/* Because we only establish the connector -> encoder ->
		 * crtc links if something is active, this means the
@@ -15830,6 +15831,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
				 */
				encoder->base.crtc->state->connector_mask |=
					1 << drm_connector_index(&connector->base);
				encoder->base.crtc->state->encoder_mask |=
					1 << drm_encoder_index(&encoder->base);
			}

		} else {
+2 −0
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ struct drm_plane_helper_funcs;
 * @connectors_changed: connectors to this crtc have been updated
 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
 * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
 * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
 * @last_vblank_count: for helpers and drivers to capture the vblank of the
 * 	update to ensure framebuffer cleanup isn't done too early
 * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
@@ -341,6 +342,7 @@ struct drm_crtc_state {
	u32 plane_mask;

	u32 connector_mask;
	u32 encoder_mask;

	/* last_vblank_count: for vblank waits before cleanup */
	u32 last_vblank_count;