From patchwork Tue Sep 1 18:50:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Ciocaltea X-Patchwork-Id: 3071 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 5B0981C002D for ; Tue, 1 Sep 2026 20:55:22 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=collabora.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-25419-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-25419-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 29BAB60F341 for ; Tue, 1 Sep 2026 18:54:17 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7B3954A2050; Tue, 1 Sep 2026 18:51:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="g64yWRPa" X-Original-To: linux-sunxi@lists.linux.dev Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 783CC4A3F01 for ; Tue, 1 Sep 2026 18:51:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788288667; cv=none; b=hVZM7yZNYaPkXSkqv583M39HFEopOfQZFfcXPsKDjZy1m0xSfnAa33hTOXaaPc3lveDlo7TuevO/3S4enatyiknRLrOjDAi22cq/xzmmd9zp0qChNO5HMT8EpdQyAIqdWh5M8YCPvTnKC+/WlRGJQhxWny5AlxEntLsYGC40PfY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788288667; c=relaxed/simple; bh=F/ORXJLv87LmKmtOIy0lgbR5TcfqZIJa8uHK88OlK5U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DIM42lk0IfKEv4a/+i3PtTezoSbdJoN/U/M6T/HbHiBReSbq0dmLAVtXocdB3VwrePcXiUaWUKuHPZ/Y9mqgY60yeTuC2IMYSJVVQa3Fce1aa4fFZBkt4RWgzOyZQnqg0fRX1ds7tPtYPiAdbV9tpH+41upwcRast8pdXX/LrLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=g64yWRPa; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1788288662; bh=F/ORXJLv87LmKmtOIy0lgbR5TcfqZIJa8uHK88OlK5U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=g64yWRPaXMzyx3SbK6m/CRSH9lr5Tok67BePPFP/CO6ZaY86LEbfRj74I25nHNWs+ rootH8yt9o+I/bnfpZtUsIAWZsQrG/1QPTGdiz7X9xnBdpFv0zzlfz5n5WzV6IGM0I DUEWuBaKk/b2V5EBHs+noOas0MHr2txR/uiHR0Tnpp5tup73bLny4MVjNCzzWsE6Ri koBAzREPdy6kpK6weKtJIG4gCGUpgsfTS7t9TjqlzYAYR8Rtj5IS5dQNuLQsyFndFr xWsxSF2X9g1Kmp5ofjBcMOo/QV0iDbDFs5tZ0J59kuDyd7nUlJVRVGjM2UK17qrWyB 0oeDegdwbdVmA== Received: from localhost (unknown [100.64.0.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange secp256r1 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: cristicc) by bali.collaboradmins.com (Postfix) with ESMTPSA id 7AA1717E39B4; Tue, 01 Sep 2026 20:51:02 +0200 (CEST) From: Cristian Ciocaltea Date: Tue, 01 Sep 2026 21:50:53 +0300 Subject: [PATCH v11 29/74] drm/bridge: dw-hdmi-qp: Add HDMI 2.0 scrambling support Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260901-dw-hdmi-qp-scramb-v11-29-bc12954a0688@collabora.com> References: <20260901-dw-hdmi-qp-scramb-v11-0-bc12954a0688@collabora.com> In-Reply-To: <20260901-dw-hdmi-qp-scramb-v11-0-bc12954a0688@collabora.com> To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Dave Stevenson , Dmitry Baryshkov , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Luca Ceresoli , Chen-Yu Tsai , Samuel Holland , =?utf-8?q?Ma=C3=ADra_Canal?= , Raspberry Pi Kernel Maintenance , Raphael Gallais-Pou , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Algea Cao , Daniel Stone , Liu Ying , Phong LE , Helge Deller Cc: kernel@collabora.com, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-rockchip@lists.infradead.org, linux-fbdev@vger.kernel.org, Maud Spierings , Diederik de Haas X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-2.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.232.135.74:from]; SUSPICIOUS_RECIPS(1.50)[]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FROM_HAS_DN(0.00)[]; PRECEDENCE_BULK(0.00)[]; TAGGED_RCPT(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCPT_COUNT_TWELVE(0.00)[36]; FORGED_SENDER_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; FREEMAIL_CC(0.00)[collabora.com,vger.kernel.org,lists.freedesktop.org,lists.infradead.org,lists.linux.dev,hotmail.com,cknow-tech.com]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo,sntech.de:email,cknow-tech.com:email,collabora.com:email,collabora.com:dkim]; RCVD_COUNT_FIVE(0.00)[5]; R_DKIM_ALLOW(0.00)[collabora.com:s=mail]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; DKIM_TRACE(0.00)[collabora.com:+]; DMARC_POLICY_ALLOW(0.00)[collabora.com,none]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.64.0.241:received,100.90.174.1:received,148.251.105.195:received]; TO_DN_SOME(0.00)[]; FROM_NEQ_ENVFROM(0.00)[cristian.ciocaltea@collabora.com,linux-sunxi@lists.linux.dev]; FREEMAIL_TO(0.00)[linux.intel.com,kernel.org,suse.de,gmail.com,ffwll.ch,raspberrypi.com,intel.com,linaro.org,ideasonboard.com,kwiboo.se,bootlin.com,sholland.org,igalia.com,rock-chips.com,sntech.de,collabora.com,nxp.com,baylibre.com,gmx.de]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-25419-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; RCVD_TLS_LAST(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.232.135.74:from] X-Rspamd-Queue-Id: 5B0981C002D X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Add support for SCDC scrambling and the high TMDS clock ratio required by HDMI 2.0 modes with TMDS character rates above 340 MHz, such as 4K@60Hz. Hook the bridge into the DRM HDMI connector scrambling helpers so the sink-side SCDC state and the controller scrambler are updated together as part of the atomic enable and disable paths. This allows the driver to advertise HDMI 2.0 support when HPD is available. Keep no-HPD configurations limited to HDMI 1.4, since SCDC access requires a connected HDMI sink. Modes above the HDMI 2.0 600 MHz TMDS character-rate limit are now implicitly rejected by the DRM HDMI connector/bridge infrastructure, making the dw_hdmi_qp_bridge_tmds_char_rate_valid() callback redundant. Drop it. Tested-by: Maud Spierings Tested-by: Diederik de Haas # NanoPC-T6 LTS, Rock 5B Acked-by: Heiko Stuebner Signed-off-by: Cristian Ciocaltea --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 60 ++++++++++++++++++---------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 246c4161e627..ee74266b7aa9 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. * Copyright (c) 2024 Collabora Ltd. + * Copyright (c) 2025 Amazon.com, Inc. or its affiliates. * * Author: Algea Cao * Author: Cristian Ciocaltea @@ -751,6 +752,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_connector_state *conn_state; struct drm_connector *connector; unsigned int op_mode; + int ret; connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); if (WARN_ON(!connector)) @@ -761,14 +763,20 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, return; if (connector->display_info.is_hdmi) { - dev_dbg(hdmi->dev, "%s mode=HDMI %s rate=%llu bpc=%u\n", __func__, - drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format), - conn_state->hdmi.tmds_char_rate, conn_state->hdmi.output_bpc); op_mode = 0; hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate; + + ret = drm_connector_hdmi_enable_scrambling(connector, conn_state); + if (ret) + dev_warn(hdmi->dev, "Failed to enable scrambling: %d\n", ret); + + dev_dbg(hdmi->dev, "%s mode=HDMI %s rate=%llu bpc=%u scramb=%d\n", __func__, + drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format), + conn_state->hdmi.tmds_char_rate, conn_state->hdmi.output_bpc, + connector->hdmi.scrambler_enabled); } else { - dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__); op_mode = OPMODE_DVI; + dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__); } hdmi->phy.ops->init(hdmi, hdmi->phy.data); @@ -783,9 +791,13 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_atomic_commit *state) { struct dw_hdmi_qp *hdmi = bridge->driver_private; + struct drm_connector *connector; hdmi->tmds_char_rate = 0; + connector = drm_atomic_get_old_connector_for_encoder(state, bridge->encoder); + drm_connector_hdmi_disable_scrambling(connector); + hdmi->phy.ops->disable(hdmi, hdmi->phy.data); } @@ -820,24 +832,24 @@ dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge, return drm_edid; } -static enum drm_mode_status -dw_hdmi_qp_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge, - const struct drm_display_mode *mode, - unsigned long long rate) +static int dw_hdmi_qp_bridge_scrambler_enable(struct drm_bridge *bridge) { struct dw_hdmi_qp *hdmi = bridge->driver_private; - /* - * TODO: when hdmi->no_hpd is 1 we must not support modes that - * require scrambling, including every mode with a clock above - * HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ. - */ - if (rate > HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ) { - dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate); - return MODE_CLOCK_HIGH; - } + dw_hdmi_qp_write(hdmi, 1, SCRAMB_CONFIG0); + dev_dbg(hdmi->dev, "scrambler enabled\n"); - return MODE_OK; + return 0; +} + +static int dw_hdmi_qp_bridge_scrambler_disable(struct drm_bridge *bridge) +{ + struct dw_hdmi_qp *hdmi = bridge->driver_private; + + dw_hdmi_qp_write(hdmi, 0, SCRAMB_CONFIG0); + dev_dbg(hdmi->dev, "scrambler disabled\n"); + + return 0; } static int dw_hdmi_qp_bridge_clear_avi_infoframe(struct drm_bridge *bridge) @@ -1213,7 +1225,8 @@ static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = { .hpd_enable = dw_hdmi_qp_bridge_hpd_enable, .hpd_disable = dw_hdmi_qp_bridge_hpd_disable, .edid_read = dw_hdmi_qp_bridge_edid_read, - .hdmi_tmds_char_rate_valid = dw_hdmi_qp_bridge_tmds_char_rate_valid, + .hdmi_scrambler_enable = dw_hdmi_qp_bridge_scrambler_enable, + .hdmi_scrambler_disable = dw_hdmi_qp_bridge_scrambler_disable, .hdmi_clear_avi_infoframe = dw_hdmi_qp_bridge_clear_avi_infoframe, .hdmi_write_avi_infoframe = dw_hdmi_qp_bridge_write_avi_infoframe, .hdmi_clear_hdmi_infoframe = dw_hdmi_qp_bridge_clear_hdmi_infoframe, @@ -1341,13 +1354,18 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, DRM_BRIDGE_OP_HDMI_AUDIO | DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME | DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME; - if (!hdmi->no_hpd) - hdmi->bridge.ops |= DRM_BRIDGE_OP_HPD; hdmi->bridge.of_node = pdev->dev.of_node; hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; hdmi->bridge.vendor = "Synopsys"; hdmi->bridge.product = "DW HDMI QP TX"; + if (hdmi->no_hpd) { + hdmi->bridge.supported_hdmi_ver = HDMI_VERSION_1_4; + } else { + hdmi->bridge.supported_hdmi_ver = HDMI_VERSION_2_0; + hdmi->bridge.ops |= DRM_BRIDGE_OP_HPD; + } + if (plat_data->supported_formats) hdmi->bridge.supported_formats = plat_data->supported_formats;