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: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/56AA200A.6070501@linux.intel.com
This commit is contained in:
parent
97a8df9087
commit
e87a52b389
|
@ -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];
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue