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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
---
  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:

//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




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux