Subject: Re: [PATCH] drm/bridge: dw-hdmi-qp: compute audio CTS from N when not in TMDS table

From: "Luca Ceresoli" <[email-masked]>
Date: Mon, 18 May 2026 12:50:18 +0200

Hello Simon,

On Sat May 9, 2026 at 9:09 AM CEST, Simon Wright wrote:
> dw_hdmi_qp_find_cts() returns 0 for any TMDS character rate not
> present in common_tmds_cts_table[] (which terminates at 148.5 MHz).
> In that case dw_hdmi_qp_set_sample_rate() calls dw_hdmi_qp_set_cts_n()
> with cts == 0, which leaves AUDPKT_ACR_CTS_OVR_EN clear and falls
> back to the controller's internal CTS auto-measurement.
> On at least the RK3576 hdptx integration, strict HDMI sinks mute
> audio in this configuration.  The behaviour reproduces at any rate
> not present in the table -- it is not specific to HDMI 2.x:
> 1920x1080@60 with 10-bit deep colour (185.625 MHz, HDMI 1.4) is
> affected, as is 3840x2160@60 8-bit (594 MHz, HDMI 2.0).  Supplying
> explicit CTS via the standard set_cts_n() override path resolves
> the mute.
> The driver already has the symmetric machinery for the N-table-miss
> case: dw_hdmi_qp_compute_n() falls back to a dynamic search using
> dw_hdmi_qp_audio_math_diff() ((pixel_clk * n) / (128 * freq)) when
> no table entry matches.  The CTS path lacks the equivalent fallback.
> Compute CTS inline in dw_hdmi_qp_set_sample_rate() from N per the
> HDMI spec (CTS = TMDS * N / (128 * Fs)) when find_cts() returns 0.
> The same formula appears in the legacy DesignWare HDMI driver
> (drivers/gpu/drm/bridge/synopsys/dw-hdmi.c, hdmi_set_clk_regenerator())
> under its AHB / GP audio paths.
> Tested on R76S (RK3576) on Armbian-edge mainline 7.0.1 with Cristian
> Ciocaltea's hdptx-clk-fixes v1 series applied:
>    TMDS         Mode             In table?  Audio with fix
>    148.5 MHz    1080p60  8-bit   yes        plays (regression check)
>    185.625 MHz  1080p60 10-bit   no         plays
>    297 MHz      3840p30  8-bit   no         plays
>    594 MHz      3840p60  8-bit   no         plays
> Sinks tested: LG G3 OLED, LG C4 OLED, TCL 75P7K QLED, Kogan
> KALED43XU9210STA (Changhong-OEM 4K LED).  Without the fix, the LG
> G3 mutes audio -- this is the originally reported bug
> (linux-rockchip 070633).  The LG C4 was verified during this cycle
> to mute at 185.625 MHz (1080p60 10-bit) with the unpatched module.
> The Kogan TV plays audio with or without the fix; it is a
> permissive HDMI 2.0 implementation that does not strictly cross-
> check ACR timing.  The TCL 75P7K was tested with the fix loaded
> only.
> Audio plays at every supported sample rate (32 / 44.1 / 48 / 96 /
> 192 kHz) verified on the TCL at the 185.625 MHz out-of-table TMDS
> rate -- the fallback's CTS = (TMDS * N) / (128 * Fs) computation is
> independent of sample rate, as expected.
> The LG C4's CTA-861 SVDs do not advertise 3840x2160@60 over TMDS
> (it is signalled FRL-only on that model), so that one row is N/A
> on the C4.  The same audio-path code is exercised at 297 MHz on
> that sink and behaves identically to the G3.
> Reported-by: Simon Wright <[email-masked]>
> Closes:
> https://lists.infradead.org/pipermail/linux-rockchip/2026-May/070633.html
> Suggested-by: Cristian Ciocaltea <[email-masked]>
> Tested-by: Simon Wright <[email-masked]>
> Signed-off-by: Simon Wright <[email-masked]>
> ---
>   drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> index 0dbb1274360..25ac8d3cfc8 100644
> ---a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> +++b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> @@-461,6 +461,21 @@static void dw_hdmi_qp_set_sample_rate(struct
> dw_hdmi_qp *hdmi, unsigned long lo
>    n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate);
>    cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate);
> + /*
> +  * dw_hdmi_qp_find_cts() returns 0 for any TMDS rate not in
> +  * common_tmds_cts_table[].  Falling through to the controller's
> +  * auto-measure path mutes audio on strict HDMI sinks at out-of-
> +  * table rates (e.g. 185.625 MHz, 297 MHz, 594 MHz).  Compute CTS
> +  * from N per HDMI spec instead, so the standard override path
> +  * supplies it on the wire.
> +  */
> + if (!cts && n) {
> +   u64 computed = (u64)tmds_char_rate * n;
> +
> +   do_div(computed, 128ULL * sample_rate);
> +   cts = (unsigned int)computed;
> + }
> +
>    dw_hdmi_qp_set_cts_n(hdmi, cts, n);
>   }

Thanks for your patch. I cannot comment on the content but I can point for
formal issues with your submission.

Your patch got mangled by your mailer and cannot be applied. Please don't
try to convince your mailer to send patches the right way: save your time
and use "git-format patch + git send-email", or even better use b4.

Also your commit message is very detailed, and think it would be more
readable if split in paragraphs. You can have a look at various commits in
the kernel log for inspiration.

There's plenty of suggestions on how to send patches in [0], ensure you
read them all.

[0] https://docs.kernel.org/process/submitting-patches.html

Thanks!

Luca

--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com