[alsa-devel] [PATCH] ASoC: wm8985: rework and fix the clock calculation

Charles Keepax ckeepax at opensource.wolfsonmicro.com
Thu May 12 17:10:22 CEST 2016


On Thu, May 12, 2016 at 03:06:12PM +0200, Petr Kulhavy wrote:
> 
> 
> On 12.05.2016 14:15, Charles Keepax wrote:
> >On Thu, May 12, 2016 at 08:48:54AM +0200, Petr Kulhavy wrote:
> >@@ -693,15 +682,18 @@ static int wm8985_hw_params(struct snd_pcm_substream *substream,
> >  	struct snd_soc_codec *codec;
> >  	struct wm8985_priv *wm8985;
> >  	u16 blen, srate_idx;
> >-	unsigned int tmp;
> >  	int srate_best;
> >+	unsigned int bclk;	/* bit clock matching the current params */
> >+	unsigned int sysclk;	/* the actual sysclk after post division */
> >  	codec = dai->codec;
> >  	wm8985 = snd_soc_codec_get_drvdata(codec);
> >-	wm8985->bclk = snd_soc_params_to_bclk(params);
> >-	if ((int)wm8985->bclk < 0)
> >-		return wm8985->bclk;
> >+	/* always use 256 * fs in order to get best filter quality */
> >+	sysclk = 256 * params_rate(params);
> >Seems quite bold to assume we always want to use 256*fs, I am not
> >super familiar with the part itself but are there good reasons to
> >do that? What if someone wanted to use say a direct MCLK and a
> >lower multiple?
> >
> >The intent presumably here is that set_sysclk is where we set the
> >target SYSCLK and set_pll should set the PLL output then here we
> >probably should work out the correct MCLKDIV to get those.
> As I understand the datasheet the codec is basically designed for 256*fs
> clock:
> DAC and ADC expect it, so do the cutoffs for the digital filters, ALC attack
> and delay times.
> Also all the timing diagrams are specified at 256fs clock.

Ok that seems pretty conclusive that we should always have this
at 256fs.

> >>  static int pll_factors(struct pll_div *pll_div, unsigned int target,
> >>  		       unsigned int source)
> >>  {
> >>@@ -872,17 +867,23 @@ static int wm8985_set_sysclk(struct snd_soc_dai *dai,
> >>  				    WM8985_CLKSEL_MASK, 0);
> >>  		snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
> >>  				    WM8985_PLLEN_MASK, 0);
> >>+		wm8985->pllout = freq;
> >>  		break;
> >>  	case WM8985_CLKSRC_PLL:
> >>  		snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
> >>  				    WM8985_CLKSEL_MASK, WM8985_CLKSEL);
> >>+		/*
> >>+		 * in order to run the PLL within the recommended 90MHz
> >>+		 * operating range the wm8985_set_pll() configures the PLL
> >>+		 * to output double the required frequency
> >>+		 */
> >>+		wm8985->pllout = 2 * freq;
> >Were does this *2 come from? Is this the PLLPRESCALE?
> It comes from the following line in wm8985_set_pll() :
>                  ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);
> 
> This formula is taken over from the datasheet (the section Master Clock and
> PLL, calculation of the f2) and is correct.
> It attempts to get the PLL to run at approx. 90MHz where it performs the
> best.
> But since there is only f/4 fixed post-divider after the PLL (see the Figure
> 40 in the wm8758 or Figure 38 in the wm8985 datasheet) the F_pllout is
> effectively freq*2.

Ok that also makes sense.

I will have another quick look over the patch.

Thanks,
Charles


More information about the Alsa-devel mailing list