[PATCH] ASoC: nau8822: choose the best master clock prescalar

David Lin ctlin0.linux at gmail.com
Tue May 24 10:23:29 CEST 2022


On 2022/5/24 上午 11:33, Hui Wang wrote:
> We have an imx6sx EVB with the codec nau8822, when playing the audio
> with 48k sample rate, the audio sounds distorted and obviously faster
> than expected.
>
> The codec input MCLK is 24000000Hz on our board, if the target sample
> rate is 48000Hz, with the current algorithm, the computed prescalar
> will result in 62500Hz, with the patched algorithm, the sample rate
> will be 46875Hz which is nearer the target sample rate.
>
> And for other sample rate like 44100, 22050, 11025 or 8000, the
> patched algorithm has no difference with the current algorithm, they
> will generate the same prescalar and the same sample rate.
>
> Signed-off-by: Hui Wang <hui.wang at canonical.com>
> ---
>   sound/soc/codecs/nau8822.c | 9 ++++++---
>   1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
> index 66bbd8f4f1ad..b67fdf64ddab 100644
> --- a/sound/soc/codecs/nau8822.c
> +++ b/sound/soc/codecs/nau8822.c
> @@ -668,21 +668,24 @@ static int nau8822_config_clkdiv(struct snd_soc_dai *dai, int div, int rate)
>   	struct snd_soc_component *component = dai->component;
>   	struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component);
>   	struct nau8822_pll *pll = &nau8822->pll;
> +	int diff = INT_MAX;
>   	int i, sclk, imclk;
>   
>   	switch (nau8822->div_id) {
>   	case NAU8822_CLK_MCLK:
>   		/* Configure the master clock prescaler div to make system
>   		 * clock to approximate the internal master clock (IMCLK);
> -		 * and large or equal to IMCLK.
> +		 * and find the nearest value to IMCLK.
>   		 */
>   		div = 0;
>   		imclk = rate * 256;
>   		for (i = 1; i < ARRAY_SIZE(nau8822_mclk_scaler); i++) {
>   			sclk = (nau8822->sysclk * 10) /	nau8822_mclk_scaler[i];
> -			if (sclk < imclk)
> +			if (abs(sclk - imclk) < diff) {
> +				diff = abs(sclk - imclk);
> +				div =  i;
> +			} else
>   				break;
> -			div = i;
>   		}
>   		dev_dbg(component->dev, "master clock prescaler %x for fs %d\n",
>   			div, rate);
Regarding to your environment with input MCLK is 24 MHz, I think you 
should enable PLL for the internal process of codec.

So you should do the following calls/operations from machine driver.

//PLL
     ret = snd_soc_dai_set_sysclk(codec_dai, NAU8822_CLK_PLL,
                       24000000, SND_SOC_CLOCK_IN);
     if (ret < 0 )
         dev_err(card->dev, "failed to set codec sysclk: %d\n", ret);

     ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
                   24000000, 256 * params_rate(params));
     if (ret < 0 )

         dev_err(card->dev, "failed to set codec pll: %d\n", ret);

David


More information about the Alsa-devel mailing list