[alsa-devel] [PATCH] Patched to allow fine-grained control of PLL and clock dividers

Liam Girdwood liam.r.girdwood at linux.intel.com
Wed Jan 8 13:08:08 CET 2014


Please make sure you CC the maintainers on patch submission otherwise
they may miss the patch. Please also use the correct subject prefix too
e.g.

ASoC: wm8804: allow fine-grained control of PLL and clock dividers

Btw, you should use git format-patch to create your patch otherwise it
cant easily be applied.

Some minor comments below :-

On Sun, 2014-01-05 at 20:45 +0100, Daniel Matuschek wrote:
> Changes:
> 1. allow the driver to accept S32_LE PCM streams
> 2. fine-grained control of the PLL generation
> WM8804 can run with PLL frequencies of 256xfs and 128xfs for most sample
> rates. At 192kHz only 128xfs is supported. The existing driver selects
> 128xfs automatically for some lower samples rates. By using the "pllid" 
> argument of the "set_pll" function is is now possible to control the
> behaviour. This allows using 256xfs PLL frequency on all sample rates up
> to 96kHz. It should allow lower jitter and better signal quality.
> When pllid=0, the behaviour of the driver does not change.
> 
> ---
>  sound/soc/codecs/wm8804.c |   25 +++++++++++++++++--------
>  sound/soc/codecs/wm8804.h |    7 +++++++
>  2 files changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
> index 1704b1e..f3f73b2 100644
> --- a/sound/soc/codecs/wm8804.c
> +++ b/sound/soc/codecs/wm8804.c
> @@ -2,6 +2,7 @@
>   * wm8804.c  --  WM8804 S/PDIF transceiver driver
>   *
>   * Copyright 2010-11 Wolfson Microelectronics plc
> + *  patched by Daniel Matuschek <info at crazyaudio.com> to allow fine-grained
> + *  control of PLL and dividers
>   *
>   * Author: Dimitris Papastamos <dp at opensource.wolfsonmicro.com>
>   *
> @@ -277,6 +278,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream,
>  		blen = 0x1;
>  		break;
>  	case SNDRV_PCM_FORMAT_S24_LE:
> +	case SNDRV_PCM_FORMAT_S32_LE:
>  		blen = 0x2;
>  		break;
>  	default:
> @@ -318,7 +320,7 @@ static struct {
>  
>  #define FIXED_PLL_SIZE ((1ULL << 22) * 10)
>  static int pll_factors(struct pll_div *pll_div, unsigned int target,
> -		       unsigned int source)
> +		       unsigned int source, int mclk_div)
>  {
>  	u64 Kpart;
>  	unsigned long int K, Ndiv, Nmod, tmp;
> @@ -332,9 +334,14 @@ static int pll_factors(struct pll_div *pll_div, unsigned int target,
>  		tmp = target * post_table[i].div;
>  		if (tmp >= 90000000 && tmp <= 100000000) {
>  			pll_div->freqmode = post_table[i].freqmode;
> -			pll_div->mclkdiv = post_table[i].mclkdiv;
> -			target *= post_table[i].div;
> -			break;
> +			if ((mclk_div == WM8804_MCLKDIV_DONTCARE) ||
> +			    ((post_table[i].mclkdiv == 1) &&
> +				(mclk_div == WM8804_MCLKDIV_1)) ||
> +			    ((post_table[i].mclkdiv == 0) &&
> +				(mclk_div == WM8804_MCLKDIV_0))) {
> +				pll_div->mclkdiv = post_table[i].mclkdiv;
> +				target *= post_table[i].div;
> +				break;
> +			}
>  		}
>  	}
>  
> @@ -388,7 +395,7 @@ static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
>  		int ret;
>  		struct pll_div pll_div;
>  
> -		ret = pll_factors(&pll_div, freq_out, freq_in);
> +		ret = pll_factors(&pll_div, freq_out, freq_in, pll_id);
>  		if (ret)
>  			return ret;
>  
> @@ -641,7 +648,8 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = {
>  };
>  
>  #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
> -			SNDRV_PCM_FMTBIT_S24_LE)
> +			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE | \
> +			SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
>  

You don't mention adding support for IEC format in your patch
description.

>  #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
>  		      SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
> @@ -674,7 +682,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
>  	.suspend = wm8804_suspend,
>  	.resume = wm8804_resume,
>  	.set_bias_level = wm8804_set_bias_level,
> -	.idle_bias_off = true,
> +	.idle_bias_off = false,


Why does idle bias change here ?

>  	.controls = wm8804_snd_controls,
>  	.num_controls = ARRAY_SIZE(wm8804_snd_controls),
> @@ -760,6 +768,7 @@ static int wm8804_i2c_probe(struct i2c_client *i2c,
>  
>  	ret = snd_soc_register_codec(&i2c->dev,
>  				     &soc_codec_dev_wm8804, &wm8804_dai, 1);
> +

Any need for this ?

>  	return ret;
>  }
>  
> diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
> index 8ec14f5..0365177 100644
> --- a/sound/soc/codecs/wm8804.h
> +++ b/sound/soc/codecs/wm8804.h
> @@ -58,4 +58,11 @@
>  
>  #define WM8804_CLKOUT_DIV			1
>  
> +#define WM8804_MCLKDIV_DONTCARE			0
> +#define WM8804_MCLKDIV_0			1
> +#define WM8804_MCLKDIV_1			2
> +#define WM8804_PLL_MCLKDIV_DONTCARE		WM8804_MCLKDIV_DONTCARE
> +#define WM8804_PLL_MCLKDIV_0			WM8804_MCLKDIV_0
> +#define WM8804_PLL_MCLKDIV_1			WM8804_MCLKDIV_1
> +
>  #endif  /* _WM8804_H */





More information about the Alsa-devel mailing list