[PATCH] drm/bridge: dw-hdmi: Use automatic CTS generation mode when using non-AHB audio

Andrzej Hajda a.hajda at samsung.com
Mon Jul 1 10:36:13 UTC 2019


On 12.06.2019 10:51, Neil Armstrong wrote:
> When using an I2S source using a different clock source (usually the I2S
> audio HW uses dedicated PLLs, different from the HDMI PHY PLL), fixed
> CTS values will cause some frequent audio drop-out and glitches as
> reported on Amlogic, Allwinner and Rockchip SoCs setups.
>
> Setting the CTS in automatic mode will let the HDMI controller generate
> automatically the CTS value to match the input audio clock.
>
> The DesignWare DW-HDMI User Guide explains:
>   For Automatic CTS generation
>   Write "0" on the bit field "CTS_manual", Register 0x3205: AUD_CTS3
>
> The DesignWare DW-HDMI Databook explains :
>   If "CTS_manual" bit equals 0b this registers contains "audCTS[19:0]"
>   generated by the Cycle time counter according to specified timing.
>
> Cc: Jernej Skrabec <jernej.skrabec at siol.net>
> Cc: Maxime Ripard <maxime.ripard at bootlin.com>
> Cc: Jonas Karlman <jonas at kwiboo.se>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: Jerome Brunet <jbrunet at baylibre.com>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>


Queued to drm-misc-next.


Regards

Andrzej


> ---
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 44 +++++++++++++++--------
>  1 file changed, 29 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index c68b6ed1bb35..6458c3a31d23 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -437,8 +437,14 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
>  	/* nshift factor = 0 */
>  	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
>  
> -	hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
> -		    HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
> +	/* Use automatic CTS generation mode when CTS is not set */
> +	if (cts)
> +		hdmi_writeb(hdmi, ((cts >> 16) &
> +				   HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
> +				  HDMI_AUD_CTS3_CTS_MANUAL,
> +			    HDMI_AUD_CTS3);
> +	else
> +		hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3);
>  	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
>  	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
>  
> @@ -508,24 +514,32 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>  {
>  	unsigned long ftdms = pixel_clk;
>  	unsigned int n, cts;
> +	u8 config3;
>  	u64 tmp;
>  
>  	n = hdmi_compute_n(sample_rate, pixel_clk);
>  
> -	/*
> -	 * Compute the CTS value from the N value.  Note that CTS and N
> -	 * can be up to 20 bits in total, so we need 64-bit math.  Also
> -	 * note that our TDMS clock is not fully accurate; it is accurate
> -	 * to kHz.  This can introduce an unnecessary remainder in the
> -	 * calculation below, so we don't try to warn about that.
> -	 */
> -	tmp = (u64)ftdms * n;
> -	do_div(tmp, 128 * sample_rate);
> -	cts = tmp;
> +	config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
>  
> -	dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
> -		__func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
> -		n, cts);
> +	/* Only compute CTS when using internal AHB audio */
> +	if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
> +		/*
> +		 * Compute the CTS value from the N value.  Note that CTS and N
> +		 * can be up to 20 bits in total, so we need 64-bit math.  Also
> +		 * note that our TDMS clock is not fully accurate; it is
> +		 * accurate to kHz.  This can introduce an unnecessary remainder
> +		 * in the calculation below, so we don't try to warn about that.
> +		 */
> +		tmp = (u64)ftdms * n;
> +		do_div(tmp, 128 * sample_rate);
> +		cts = tmp;
> +
> +		dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
> +			__func__, sample_rate,
> +			ftdms / 1000000, (ftdms / 1000) % 1000,
> +			n, cts);
> +	} else
> +		cts = 0;
>  
>  	spin_lock_irq(&hdmi->audio_lock);
>  	hdmi->audio_n = n;




More information about the dri-devel mailing list