This function provides a way for the driver to redo a modeset on the current mode and retry the link training at a lower link rate/lane count/bpp. This will get called incase the link training fails during the current modeset.
Cc: dri-devel at lists.freedesktop.org Cc: Jani Nikula <jani.nikula at linux.intel.com> Cc: Daniel Vetter <daniel.vetter at intel.com> Cc: Ville Syrjala <ville.syrjala at linux.intel.com> Signed-off-by: Manasi Navare <manasi.d.navare at intel.com> --- drivers/gpu/drm/drm_atomic_helper.c | 58 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 1 + 2 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f936276..0c1614e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2895,6 +2895,64 @@ int drm_atomic_helper_connector_dpms(struct drm_connector *connector, EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); /** + * drm_atomic_helper_connector_modeset - Force a modeset on a connector + * @connector: DRM connector + * + * Provides a way to redo a modeset with the current mode so that it can + * drop the bpp, link rate/lane count and retry the link training. + * + * Returns: + * Returns 0 on success, negative errno numbers on failure. + */ +int +drm_atomic_helper_connector_modeset(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_connector_state *connector_state; + struct drm_crtc_state *crtc_state; + int ret = 0; + + drm_modeset_acquire_init(&ctx, 0); + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto fail; + } + state->acquire_ctx = &ctx; +retry: + ret = 0; + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + goto fail; + } + if (!connector_state->crtc) + goto fail; + + crtc_state = drm_atomic_get_existing_crtc_state(state, + connector_state->crtc); + crtc_state->connectors_changed = true; + ret = drm_atomic_commit(state); +fail: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; + } + + if (state) + drm_atomic_state_put(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_modeset); + +/** * drm_atomic_helper_best_encoder - Helper for &drm_connector_helper_funcs * ->best_encoder callback * @connector: Connector control structure diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 7ff92b0..8de24dc 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -126,6 +126,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, uint32_t flags); int drm_atomic_helper_connector_dpms(struct drm_connector *connector, int mode); +int drm_atomic_helper_connector_modeset(struct drm_connector *connector); struct drm_encoder * drm_atomic_helper_best_encoder(struct drm_connector *connector); -- 1.9.1