drm_atomic_helper_connector_hdmi_hotplug() does not currently synchronize SCDC status on hotplug events, leaving the scrambler state potentially inconsistent after (re)connect.
Hook drm_connector_hdmi_sync_scdc() into both the connect and disconnect paths, replacing the existing TODOs around missing scrambler handling. SCDC synchronization may require a CRTC reset, which in turn needs a modeset acquire context for correct locking. Therefore, extend drm_atomic_helper_connector_hdmi_hotplug() and drm_atomic_helper_connector_hdmi_update() to take a drm_modeset_acquire_ctx argument. Additionally, change their return type from void to int, allowing propagation of errors, such as -EDEADLK from lock contention. Update existing callers to pass NULL for the acquire context, preserving current behavior. Signed-off-by: Cristian Ciocaltea <[email protected]> --- drivers/gpu/drm/display/drm_bridge_connector.c | 3 ++- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 28 +++++++++++++++++-------- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- include/drm/display/drm_hdmi_state_helper.h | 6 ++++-- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 796069dbf1a1..46104506fe32 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -221,7 +221,8 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) status = detect->funcs->detect(detect, connector); if (hdmi) - drm_atomic_helper_connector_hdmi_hotplug(connector, status); + drm_atomic_helper_connector_hdmi_hotplug(connector, status, + NULL); drm_bridge_connector_hpd_notify(connector, status); } else { diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index db76699093e8..69ccfbf123fe 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -1198,18 +1198,20 @@ drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *con } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe); -static void +static int drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + struct drm_modeset_acquire_ctx *ctx) { const struct drm_edid *drm_edid; + int ret = 0; if (status == connector_status_disconnected) { - // TODO: also handle scramber, HDMI sink disconnected. + ret = drm_connector_hdmi_sync_scdc(connector, false, ctx); drm_connector_hdmi_audio_plugged_notify(connector, false); drm_edid_connector_update(connector, NULL); drm_connector_cec_phys_addr_invalidate(connector); - return; + return ret; } if (connector->hdmi.funcs->read_edid) @@ -1222,24 +1224,32 @@ drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector, drm_edid_free(drm_edid); if (status == connector_status_connected) { - // TODO: also handle scramber, HDMI sink is now connected. + ret = drm_connector_hdmi_sync_scdc(connector, true, ctx); drm_connector_hdmi_audio_plugged_notify(connector, true); drm_connector_cec_phys_addr_set(connector); } + + return ret; } /** * drm_atomic_helper_connector_hdmi_hotplug - Handle the hotplug event for the HDMI connector * @connector: A pointer to the HDMI connector * @status: Connection status + * @ctx: Lock acquisition context to be used for resetting CRTC * * This function should be called as a part of the .detect() / .detect_ctx() * callbacks for all status changes. + * + * Returns: + * Zero on success, error code on failure. + * If @ctx is set, it might also return -EDEADLK. */ -void drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector, - enum drm_connector_status status) +int drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector, + enum drm_connector_status status, + struct drm_modeset_acquire_ctx *ctx) { - drm_atomic_helper_connector_hdmi_update(connector, status); + return drm_atomic_helper_connector_hdmi_update(connector, status, ctx); } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_hotplug); @@ -1254,6 +1264,6 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_hotplug); */ void drm_atomic_helper_connector_hdmi_force(struct drm_connector *connector) { - drm_atomic_helper_connector_hdmi_update(connector, connector->status); + drm_atomic_helper_connector_hdmi_update(connector, connector->status, NULL); } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_force); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 74dce4be0c00..e165f604939b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -375,7 +375,7 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, * the lock for now. */ - drm_atomic_helper_connector_hdmi_hotplug(connector, status); + drm_atomic_helper_connector_hdmi_hotplug(connector, status, NULL); if (status != connector_status_connected) return; diff --git a/include/drm/display/drm_hdmi_state_helper.h b/include/drm/display/drm_hdmi_state_helper.h index 13375bd0f4ae..0619cd7c435e 100644 --- a/include/drm/display/drm_hdmi_state_helper.h +++ b/include/drm/display/drm_hdmi_state_helper.h @@ -7,6 +7,7 @@ struct drm_atomic_commit; struct drm_connector; struct drm_connector_state; struct drm_display_mode; +struct drm_modeset_acquire_ctx; struct hdmi_audio_infoframe; enum drm_connector_status; @@ -22,8 +23,9 @@ int drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector int drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector); int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector, struct drm_atomic_commit *state); -void drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector, - enum drm_connector_status status); +int drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector, + enum drm_connector_status status, + struct drm_modeset_acquire_ctx *ctx); void drm_atomic_helper_connector_hdmi_force(struct drm_connector *connector); enum drm_mode_status -- 2.54.0
