[PATCH v2 4/6] drm/atomic: Handle encoder stealing from set_config better.
Daniel Vetter
daniel at ffwll.ch
Fri Mar 4 16:20:08 UTC 2016
On Wed, Feb 24, 2016 at 09:37:31AM +0100, Maarten Lankhorst wrote:
> Instead of failing with -EINVAL when conflicting encoders are found,
> the legacy set_config will disable other connectors when encoders
> conflict.
>
> With the cleanup to update_output_state this is a lot easier to
> implement. set_config only adds connectors to the state that are
> modified, and because of the previous commit that calls
> add_affected_connectors only on set->crtc it means any connector not
> part of the modeset can be stolen from. We disable the connector in
> that case, and possibly the crtc if no connectors are left.
>
> Atomic modeset itself still doesn't allow encoder stealing, the
> results would be too unpredictable.
Shouldn't this be reworked to say something like "With this we can rework
the atomic core to not allow stealing"?
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> ---
> drivers/gpu/drm/drm_atomic_helper.c | 69 +++++++++++++++++++++++++++++++++++++
> include/drm/drm_crtc.h | 2 ++
> 2 files changed, 71 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index e89a5da27463..3543c7fcd072 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -86,6 +86,68 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
> }
> }
>
> +static int disable_conflicting_connectors(struct drm_atomic_state *state)
> +{
> + struct drm_connector_state *conn_state;
> + struct drm_connector *connector;
> + struct drm_encoder *encoder;
> + unsigned encoder_mask = 0;
> + int i, ret;
> +
> + for_each_connector_in_state(state, connector, conn_state, i) {
> + const struct drm_connector_helper_funcs *funcs = connector->helper_private;
> + struct drm_encoder *new_encoder;
> +
> + if (!conn_state->crtc)
> + continue;
> +
> + if (funcs->atomic_best_encoder)
> + new_encoder = funcs->atomic_best_encoder(connector, conn_state);
> + else
> + new_encoder = funcs->best_encoder(connector);
> +
> + if (new_encoder)
> + encoder_mask |= 1 << drm_encoder_index(new_encoder);
> + }
> +
> + drm_for_each_connector(connector, state->dev) {
> + struct drm_crtc_state *crtc_state;
> +
> + if (drm_atomic_get_existing_connector_state(state, connector))
> + continue;
> +
> + encoder = connector->state->best_encoder;
> + if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder))))
> + continue;
> +
> + conn_state = drm_atomic_get_connector_state(state, connector);
> + if (IS_ERR(conn_state))
> + return PTR_ERR(conn_state);
> +
> + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n",
> + encoder->base.id, encoder->name,
> + conn_state->crtc->base.id, conn_state->crtc->name,
> + connector->base.id, connector->name);
> +
> + crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc);
> +
> + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
> + if (ret)
> + return ret;
> +
> + if (!crtc_state->connector_mask) {
> + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
> + NULL);
> + if (ret < 0)
> + return ret;
> +
> + crtc_state->active = false;
> + }
> + }
> +
> + return 0;
> +}
> +
> static bool
> check_pending_encoder_assignment(struct drm_atomic_state *state,
> struct drm_encoder *new_encoder)
> @@ -449,6 +511,12 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
> }
> }
>
> + if (state->legacy_set_config) {
> + ret = disable_conflicting_connectors(state);
> + if (ret)
> + return ret;
> + }
> +
> for_each_connector_in_state(state, connector, connector_state, i) {
> /*
> * This only sets crtc->mode_changed for routing changes,
> @@ -1797,6 +1865,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
> if (!state)
> return -ENOMEM;
>
> + state->legacy_set_config = true;
> state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
> retry:
> ret = __drm_atomic_helper_set_config(set, state);
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 7fad193dc645..9a946df27f07 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1677,6 +1677,7 @@ struct drm_bridge {
> * @dev: parent DRM device
> * @allow_modeset: allow full modeset
> * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
> + * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL.
> * @planes: pointer to array of plane pointers
> * @plane_states: pointer to array of plane states pointers
> * @crtcs: pointer to array of CRTC pointers
> @@ -1690,6 +1691,7 @@ struct drm_atomic_state {
> struct drm_device *dev;
> bool allow_modeset : 1;
> bool legacy_cursor_update : 1;
> + bool legacy_set_config : 1;
> struct drm_plane **planes;
> struct drm_plane_state **plane_states;
> struct drm_crtc **crtcs;
> --
> 2.1.0
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list