[v2,3/8] ASoC: cs42l42: Ensure MCLKint is a multiple of the sample rate

Message ID 20230118160452.2385494-4-sbinding@opensource.cirrus.com
State New
Headers
Series ASoC: cs42l42: Add Soundwire support |

Commit Message

Stefan Binding Jan. 18, 2023, 4:04 p.m. UTC
  From: Richard Fitzgerald <rf@opensource.cirrus.com>

The chosen clocking configuration must give an internal MCLK (MCLKint)
that is an integer multiple of the sample rate.

On I2S each of the supported bit clock frequencies can only be generated
from one sample rate group (either the 44100 or the 48000) so the code
could use only the bitclock to look up a PLL config.

The relationship between sample rate and bitclock frequency is more
complex on Soundwire and so it is possible to set a frame shape to
generate a bitclock from the "wrong" group. For example 2*147 with a
48000 sample rate would give a bitclock of 14112000 which on I2S
could only be derived from a 44100 sample rate.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
  

Comments

Pierre-Louis Bossart Jan. 18, 2023, 4:46 p.m. UTC | #1
On 1/18/23 10:04, Stefan Binding wrote:
> From: Richard Fitzgerald <rf@opensource.cirrus.com>
> 
> The chosen clocking configuration must give an internal MCLK (MCLKint)
> that is an integer multiple of the sample rate.
> 
> On I2S each of the supported bit clock frequencies can only be generated
> from one sample rate group (either the 44100 or the 48000) so the code
> could use only the bitclock to look up a PLL config.
> 
> The relationship between sample rate and bitclock frequency is more
> complex on Soundwire and so it is possible to set a frame shape to
> generate a bitclock from the "wrong" group. For example 2*147 with a
> 48000 sample rate would give a bitclock of 14112000 which on I2S
> could only be derived from a 44100 sample rate.

The explanation is a bit convoluted, clearly the 147-row configuration
was only meant to be used with 44100 kHz. I don't think 48kHz can be
supported without using the source- or sink-controlled async modes.

This is still a valid change so:

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
> Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>



> ---
>  sound/soc/codecs/cs42l42.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
> index 82aa11d6937be..939f8bcc222c0 100644
> --- a/sound/soc/codecs/cs42l42.c
> +++ b/sound/soc/codecs/cs42l42.c
> @@ -653,7 +653,8 @@ static const struct cs42l42_pll_params pll_ratio_table[] = {
>  	{ 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1}
>  };
>  
> -static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk)
> +static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk,
> +			      unsigned int sample_rate)
>  {
>  	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
>  	int i;
> @@ -668,6 +669,10 @@ static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int
>  	}
>  
>  	for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
> +		/* MCLKint must be a multiple of the sample rate */
> +		if (pll_ratio_table[i].mclk_int % sample_rate)
> +			continue;
> +
>  		if (pll_ratio_table[i].sclk == clk) {
>  			cs42l42->pll_config = i;
>  
> @@ -893,6 +898,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
>  	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
>  	unsigned int channels = params_channels(params);
>  	unsigned int width = (params_width(params) / 8) - 1;
> +	unsigned int sample_rate = params_rate(params);
>  	unsigned int slot_width = 0;
>  	unsigned int val = 0;
>  	unsigned int bclk;
> @@ -956,11 +962,11 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
>  		break;
>  	}
>  
> -	ret = cs42l42_pll_config(component, bclk);
> +	ret = cs42l42_pll_config(component, bclk, sample_rate);
>  	if (ret)
>  		return ret;
>  
> -	cs42l42_src_config(component, params_rate(params));
> +	cs42l42_src_config(component, sample_rate);
>  
>  	return 0;
>  }
  

Patch

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 82aa11d6937be..939f8bcc222c0 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -653,7 +653,8 @@  static const struct cs42l42_pll_params pll_ratio_table[] = {
 	{ 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1}
 };
 
-static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk)
+static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk,
+			      unsigned int sample_rate)
 {
 	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
 	int i;
@@ -668,6 +669,10 @@  static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int
 	}
 
 	for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
+		/* MCLKint must be a multiple of the sample rate */
+		if (pll_ratio_table[i].mclk_int % sample_rate)
+			continue;
+
 		if (pll_ratio_table[i].sclk == clk) {
 			cs42l42->pll_config = i;
 
@@ -893,6 +898,7 @@  static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
 	unsigned int channels = params_channels(params);
 	unsigned int width = (params_width(params) / 8) - 1;
+	unsigned int sample_rate = params_rate(params);
 	unsigned int slot_width = 0;
 	unsigned int val = 0;
 	unsigned int bclk;
@@ -956,11 +962,11 @@  static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	ret = cs42l42_pll_config(component, bclk);
+	ret = cs42l42_pll_config(component, bclk, sample_rate);
 	if (ret)
 		return ret;
 
-	cs42l42_src_config(component, params_rate(params));
+	cs42l42_src_config(component, sample_rate);
 
 	return 0;
 }