Thread (11 messages) 11 messages, 4 authors, 2026-01-14

Re: [PATCH v2 3/4] drm/bridge: dw-hdmi-qp: Add high TMDS clock ratio and scrambling support

From: Cristian Ciocaltea <hidden>
Date: 2026-01-13 15:10:09
Also in: dri-devel, linux-rockchip, lkml

Hi Maxime,

On 1/13/26 5:00 PM, Maxime Ripard wrote:
On Tue, Jan 13, 2026 at 12:26:20AM +0200, Cristian Ciocaltea wrote:
quoted
@@ -902,13 +981,74 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
 
 	hdmi->tmds_char_rate = 0;
 
+	dw_hdmi_qp_disable_scramb(hdmi);
+
+	hdmi->curr_conn = NULL;
 	hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
 }
 
-static enum drm_connector_status
-dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
+static int dw_hdmi_qp_reset_link(struct dw_hdmi_qp *hdmi,
+				 struct drm_connector *conn,
+				 struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_crtc *crtc;
+	u8 config;
+	int ret;
+
+	if (!conn->state)
+		return 0;
+
+	crtc = conn->state->crtc;
+	if (!crtc)
+		return 0;
+
+retry:
+	ret = drm_modeset_lock(&crtc->mutex, ctx);
+	if (ret)
+		goto check_err;
+
+	if (!crtc->state->active)
+		return 0;
+
+	if (conn->state->commit &&
+	    !try_wait_for_completion(&conn->state->commit->hw_done))
+		return 0;
+
+	ret = drm_scdc_readb(hdmi->bridge.ddc, SCDC_TMDS_CONFIG, &config);
+	if (ret < 0) {
+		dev_err(hdmi->dev, "Failed to read TMDS config: %d\n", ret);
+		return 0;
+	}
+
+	if (!!(config & SCDC_SCRAMBLING_ENABLE) == hdmi->scramb_enabled)
+		return 0;
+
+	dev_dbg(hdmi->dev, "%s resetting crtc\n", __func__);
+
+	drm_atomic_helper_connector_hdmi_hotplug(conn, connector_status_connected);
+
+	/*
+	 * Conform to HDMI 2.0 spec by ensuring scrambled data is not sent
+	 * before configuring the sink scrambling, as well as suspending any
+	 * TMDS transmission while changing the TMDS clock rate in the sink.
+	 */
+	ret = drm_atomic_helper_reset_crtc(crtc, ctx);
+
+check_err:
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(ctx);
+		goto retry;
+	}
+
+	return ret;
+}
+
+static int dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge,
+				    struct drm_connector *connector,
+				    struct drm_modeset_acquire_ctx *ctx)
 {
 	struct dw_hdmi_qp *hdmi = bridge->driver_private;
+	enum drm_connector_status status;
 	const struct drm_edid *drm_edid;
 
 	if (hdmi->no_hpd) {
@@ -919,7 +1059,15 @@ dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connec
 			return connector_status_disconnected;
 	}
 
-	return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+	status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+	dev_dbg(hdmi->dev, "%s status=%d scramb=%d\n", __func__,
+		status, hdmi->scramb_enabled);
+
+	if (status == connector_status_connected && hdmi->scramb_enabled)
+		dw_hdmi_qp_reset_link(hdmi, connector, ctx);
+
+	return status;
 }
We have drm_bridge_helper_reset_crtc() now, any reason you didn't use it?
Ups, I missed it somehow..

Thanks,
Cristian
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help