Hi Andrzej,

Gentle ping, do you think this could go in drm-misc-next for 5.3 ?

Thanks,
Neil

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.skra...@siol.net>
> Cc: Maxime Ripard <maxime.rip...@bootlin.com>
> Cc: Jonas Karlman <jo...@kwiboo.se>
> Cc: Heiko Stuebner <he...@sntech.de>
> Cc: Jerome Brunet <jbru...@baylibre.com>
> Signed-off-by: Neil Armstrong <narmstr...@baylibre.com>
> ---
>  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;
> 

Reply via email to