Linux-Rockchip Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/bridge: dw-hdmi-qp: Compute ACR CTS for unlisted TMDS rates
@ 2026-09-01 11:25 Christian Hewitt
  2026-09-01 14:28 ` Sebastian Reichel
  0 siblings, 1 reply; 3+ messages in thread
From: Christian Hewitt @ 2026-09-01 11:25 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Cristian Ciocaltea, Daniel Stone, Detlev Casanova,
	Dmitry Baryshkov, Douglas Anderson, Andy Yan, Sugar Zhang,
	Heiko Stuebner, dri-devel, linux-rockchip, linux-kernel

common_tmds_cts_table[] holds only six TMDS character rates (25.175,
25.2, 27, 54, 74.25 and 148.5 MHz), so dw_hdmi_qp_find_cts() returns 0
for everything else. dw_hdmi_qp_set_cts_n() then clears the CTS override
enable and programs a value of 0, leaving the sink with no CTS to
regenerate the audio clock from.

Any deep colour link falls into this gap: a 10 bpc RK3576 HDMI output
runs at 185625000 Hz (148.5 MHz * 1.25), which is absent from both
tables. N is computed dynamically and comes out correct at 6144, but
AUDPKT_ACR_CONTROL1 reads back as 0.

Give CTS the same dynamic fallback that N already has, using the formula
from the Audio chapter of the HDMI specification, and drop the -ENOENT
returned into an unsigned int for the unlisted sample rates.

Fixes: fd0141d1a8a2a ("drm/bridge: synopsys: Add audio support for dw-hdmi-qp")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
---
This was found after testing unrelated patches from DetlevC that rename
the RK audio cards to see the impact in Kodi. RK3588 had audio output,
while RK3576 did not. I'd not used an RK3576 board for a while so tasked
Claude to help triage the problem, and this was the finding. The problem
appears to have been exposed since Kodi reworked plane selection logic
and support for 10bpc planes; earlier Kodi/LibreELEC images were using
8bpc planes thus avoiding the problem.

 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 45 ++++++++++++--------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index 5f4718c3b9db..7cf327de0249 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
+#include <linux/math64.h>
 #include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -307,8 +308,15 @@ static unsigned int dw_hdmi_qp_find_n(struct dw_hdmi_qp *hdmi, unsigned long pix
 	return dw_hdmi_qp_compute_n(hdmi, pixel_clk, sample_rate);
 }
 
+static unsigned int dw_hdmi_qp_compute_cts(unsigned long pixel_clk,
+					   unsigned long sample_rate,
+					   unsigned int n)
+{
+	return div64_u64((u64)pixel_clk * n, 128ULL * sample_rate);
+}
+
 static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
-					unsigned long sample_rate)
+					unsigned long sample_rate, unsigned int n)
 {
 	const struct dw_hdmi_audio_tmds_cts *tmds_cts = NULL;
 	int i;
@@ -320,23 +328,24 @@ static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long p
 		}
 	}
 
-	if (!tmds_cts)
-		return 0;
-
-	switch (sample_rate) {
-	case 32000:
-		return tmds_cts->cts_32k;
-	case 44100:
-	case 88200:
-	case 176400:
-		return tmds_cts->cts_44k1;
-	case 48000:
-	case 96000:
-	case 192000:
-		return tmds_cts->cts_48k;
-	default:
-		return -ENOENT;
+	if (tmds_cts) {
+		switch (sample_rate) {
+		case 32000:
+			return tmds_cts->cts_32k;
+		case 44100:
+		case 88200:
+		case 176400:
+			return tmds_cts->cts_44k1;
+		case 48000:
+		case 96000:
+		case 192000:
+			return tmds_cts->cts_48k;
+		}
 	}
+
+	dev_dbg(hdmi->dev, "Rate %lu missing; compute CTS dynamically\n", pixel_clk);
+
+	return dw_hdmi_qp_compute_cts(pixel_clk, sample_rate, n);
 }
 
 static void dw_hdmi_qp_set_audio_interface(struct dw_hdmi_qp *hdmi,
@@ -471,7 +480,7 @@ static void dw_hdmi_qp_set_sample_rate(struct dw_hdmi_qp *hdmi, unsigned long lo
 	unsigned int n, cts;
 
 	n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate);
-	cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate);
+	cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate, n);
 
 	dw_hdmi_qp_set_cts_n(hdmi, cts, n);
 }
-- 
2.43.0


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/bridge: dw-hdmi-qp: Compute ACR CTS for unlisted TMDS rates
  2026-09-01 11:25 [PATCH] drm/bridge: dw-hdmi-qp: Compute ACR CTS for unlisted TMDS rates Christian Hewitt
@ 2026-09-01 14:28 ` Sebastian Reichel
  2026-09-01 15:50   ` Christian Hewitt
  0 siblings, 1 reply; 3+ messages in thread
From: Sebastian Reichel @ 2026-09-01 14:28 UTC (permalink / raw)
  To: Christian Hewitt
  Cc: Heiko Stuebner, dri-devel, linux-kernel, Laurent Pinchart,
	Andrzej Hajda, David Airlie, Simona Vetter, Detlev Casanova,
	Robert Foss, Jernej Skrabec, Sugar Zhang, linux-rockchip,
	Luca Ceresoli, Jonas Karlman, Maarten Lankhorst, Maxime Ripard,
	Daniel Stone, Dmitry Baryshkov, Neil Armstrong, Douglas Anderson,
	Thomas Zimmermann, Andy Yan


[-- Attachment #1.1: Type: text/plain, Size: 4387 bytes --]

Hi,

On Tue, Sep 01, 2026 at 11:25:41AM +0000, Christian Hewitt wrote:
> common_tmds_cts_table[] holds only six TMDS character rates (25.175,
> 25.2, 27, 54, 74.25 and 148.5 MHz), so dw_hdmi_qp_find_cts() returns 0
> for everything else. dw_hdmi_qp_set_cts_n() then clears the CTS override
> enable and programs a value of 0, leaving the sink with no CTS to
> regenerate the audio clock from.
> 
> Any deep colour link falls into this gap: a 10 bpc RK3576 HDMI output
> runs at 185625000 Hz (148.5 MHz * 1.25), which is absent from both
> tables. N is computed dynamically and comes out correct at 6144, but
> AUDPKT_ACR_CONTROL1 reads back as 0.
> 
> Give CTS the same dynamic fallback that N already has, using the formula
> from the Audio chapter of the HDMI specification, and drop the -ENOENT
> returned into an unsigned int for the unlisted sample rates.
> 
> Fixes: fd0141d1a8a2a ("drm/bridge: synopsys: Add audio support for dw-hdmi-qp")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
> ---
> This was found after testing unrelated patches from DetlevC that rename
> the RK audio cards to see the impact in Kodi. RK3588 had audio output,
> while RK3576 did not. I'd not used an RK3576 board for a while so tasked
> Claude to help triage the problem, and this was the finding. The problem
> appears to have been exposed since Kodi reworked plane selection logic
> and support for 10bpc planes; earlier Kodi/LibreELEC images were using
> 8bpc planes thus avoiding the problem.

You are looking for this series:

https://lore.kernel.org/linux-rockchip/86fcf349-0a7a-4618-9001-612371b0f71b@symple.nz/

Greetings,

-- Sebastian

>  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 45 ++++++++++++--------
>  1 file changed, 27 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> index 5f4718c3b9db..7cf327de0249 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> @@ -12,6 +12,7 @@
>  #include <linux/export.h>
>  #include <linux/i2c.h>
>  #include <linux/irq.h>
> +#include <linux/math64.h>
>  #include <linux/minmax.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> @@ -307,8 +308,15 @@ static unsigned int dw_hdmi_qp_find_n(struct dw_hdmi_qp *hdmi, unsigned long pix
>  	return dw_hdmi_qp_compute_n(hdmi, pixel_clk, sample_rate);
>  }
>  
> +static unsigned int dw_hdmi_qp_compute_cts(unsigned long pixel_clk,
> +					   unsigned long sample_rate,
> +					   unsigned int n)
> +{
> +	return div64_u64((u64)pixel_clk * n, 128ULL * sample_rate);
> +}
> +
>  static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
> -					unsigned long sample_rate)
> +					unsigned long sample_rate, unsigned int n)
>  {
>  	const struct dw_hdmi_audio_tmds_cts *tmds_cts = NULL;
>  	int i;
> @@ -320,23 +328,24 @@ static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long p
>  		}
>  	}
>  
> -	if (!tmds_cts)
> -		return 0;
> -
> -	switch (sample_rate) {
> -	case 32000:
> -		return tmds_cts->cts_32k;
> -	case 44100:
> -	case 88200:
> -	case 176400:
> -		return tmds_cts->cts_44k1;
> -	case 48000:
> -	case 96000:
> -	case 192000:
> -		return tmds_cts->cts_48k;
> -	default:
> -		return -ENOENT;
> +	if (tmds_cts) {
> +		switch (sample_rate) {
> +		case 32000:
> +			return tmds_cts->cts_32k;
> +		case 44100:
> +		case 88200:
> +		case 176400:
> +			return tmds_cts->cts_44k1;
> +		case 48000:
> +		case 96000:
> +		case 192000:
> +			return tmds_cts->cts_48k;
> +		}
>  	}
> +
> +	dev_dbg(hdmi->dev, "Rate %lu missing; compute CTS dynamically\n", pixel_clk);
> +
> +	return dw_hdmi_qp_compute_cts(pixel_clk, sample_rate, n);
>  }
>  
>  static void dw_hdmi_qp_set_audio_interface(struct dw_hdmi_qp *hdmi,
> @@ -471,7 +480,7 @@ static void dw_hdmi_qp_set_sample_rate(struct dw_hdmi_qp *hdmi, unsigned long lo
>  	unsigned int n, cts;
>  
>  	n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate);
> -	cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate);
> +	cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate, n);
>  
>  	dw_hdmi_qp_set_cts_n(hdmi, cts, n);
>  }
> -- 
> 2.43.0
> 

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 170 bytes --]

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/bridge: dw-hdmi-qp: Compute ACR CTS for unlisted TMDS rates
  2026-09-01 14:28 ` Sebastian Reichel
@ 2026-09-01 15:50   ` Christian Hewitt
  0 siblings, 0 replies; 3+ messages in thread
From: Christian Hewitt @ 2026-09-01 15:50 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Heiko Stuebner, dri-devel, linux-kernel, Laurent Pinchart,
	Andrzej Hajda, David Airlie, Simona Vetter, Detlev Casanova,
	Robert Foss, Jernej Skrabec, Sugar Zhang, linux-rockchip,
	Luca Ceresoli, Jonas Karlman, Maarten Lankhorst, Maxime Ripard,
	Daniel Stone, Dmitry Baryshkov, Neil Armstrong, Douglas Anderson,
	Thomas Zimmermann, Andy Yan

> On 1 Sep 2026, at 6:28 pm, Sebastian Reichel <sebastian.reichel@collabora.com> wrote:
> 
> Hi,
> 
> On Tue, Sep 01, 2026 at 11:25:41AM +0000, Christian Hewitt wrote:
>> common_tmds_cts_table[] holds only six TMDS character rates (25.175,
>> 25.2, 27, 54, 74.25 and 148.5 MHz), so dw_hdmi_qp_find_cts() returns 0
>> for everything else. dw_hdmi_qp_set_cts_n() then clears the CTS override
>> enable and programs a value of 0, leaving the sink with no CTS to
>> regenerate the audio clock from.
>> 
>> Any deep colour link falls into this gap: a 10 bpc RK3576 HDMI output
>> runs at 185625000 Hz (148.5 MHz * 1.25), which is absent from both
>> tables. N is computed dynamically and comes out correct at 6144, but
>> AUDPKT_ACR_CONTROL1 reads back as 0.
>> 
>> Give CTS the same dynamic fallback that N already has, using the formula
>> from the Audio chapter of the HDMI specification, and drop the -ENOENT
>> returned into an unsigned int for the unlisted sample rates.
>> 
>> Fixes: fd0141d1a8a2a ("drm/bridge: synopsys: Add audio support for dw-hdmi-qp")
>> Assisted-by: Claude:claude-opus-5
>> Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
>> ---
>> This was found after testing unrelated patches from DetlevC that rename
>> the RK audio cards to see the impact in Kodi. RK3588 had audio output,
>> while RK3576 did not. I'd not used an RK3576 board for a while so tasked
>> Claude to help triage the problem, and this was the finding. The problem
>> appears to have been exposed since Kodi reworked plane selection logic
>> and support for 10bpc planes; earlier Kodi/LibreELEC images were using
>> 8bpc planes thus avoiding the problem.
> 
> You are looking for this series:
> 
> https://lore.kernel.org/linux-rockchip/86fcf349-0a7a-4618-9001-612371b0f71b@symple.nz/

Ahh, I missed that. I have now tested that patch (and will reply
to it with a TB) so please ignore this patch. Thanks!

Christian


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-01 15:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 11:25 [PATCH] drm/bridge: dw-hdmi-qp: Compute ACR CTS for unlisted TMDS rates Christian Hewitt
2026-09-01 14:28 ` Sebastian Reichel
2026-09-01 15:50   ` Christian Hewitt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox