[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