Unverified Commit fdbd2561 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown
Browse files

ASoC: cs42l42: Set correct SRC MCLK



According to the datasheet the SRC MCLK must be as near as possible to
(125 * sample rate). This means it should be ~6MHz for rates up to 48k
and ~12MHz for rates above that. As per datasheet table 4-21.

Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20211015133619.4698-14-rf@opensource.cirrus.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 4ae1d8f9
Loading
Loading
Loading
Loading
+41 −17
Original line number Diff line number Diff line
@@ -678,22 +678,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
					CS42L42_FSYNC_PULSE_WIDTH_MASK,
					CS42L42_FRAC1_VAL(fsync - 1) <<
					CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
			/* Set the sample rates (96k or lower) */
			snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
					CS42L42_FS_EN_MASK,
					(CS42L42_FS_EN_IASRC_96K |
					CS42L42_FS_EN_OASRC_96K) <<
					CS42L42_FS_EN_SHIFT);
			/* Set the input/output internal MCLK clock ~12 MHz */
			snd_soc_component_update_bits(component, CS42L42_IN_ASRC_CLK,
					CS42L42_CLK_IASRC_SEL_MASK,
					CS42L42_CLK_IASRC_SEL_12 <<
					CS42L42_CLK_IASRC_SEL_SHIFT);
			snd_soc_component_update_bits(component,
					CS42L42_OUT_ASRC_CLK,
					CS42L42_CLK_OASRC_SEL_MASK,
					CS42L42_CLK_OASRC_SEL_12 <<
					CS42L42_CLK_OASRC_SEL_SHIFT);
			if (pll_ratio_table[i].mclk_src_sel == 0) {
				/* Pass the clock straight through */
				snd_soc_component_update_bits(component,
@@ -756,6 +740,39 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
	return -EINVAL;
}

static void cs42l42_src_config(struct snd_soc_component *component, unsigned int sample_rate)
{
	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
	unsigned int fs;

	/* Don't reconfigure if there is an audio stream running */
	if (cs42l42->stream_use)
		return;

	/* SRC MCLK must be as close as possible to 125 * sample rate */
	if (sample_rate <= 48000)
		fs = CS42L42_CLK_IASRC_SEL_6;
	else
		fs = CS42L42_CLK_IASRC_SEL_12;

	/* Set the sample rates (96k or lower) */
	snd_soc_component_update_bits(component,
				      CS42L42_FS_RATE_EN,
				      CS42L42_FS_EN_MASK,
				      (CS42L42_FS_EN_IASRC_96K |
				       CS42L42_FS_EN_OASRC_96K) <<
				      CS42L42_FS_EN_SHIFT);

	snd_soc_component_update_bits(component,
				      CS42L42_IN_ASRC_CLK,
				      CS42L42_CLK_IASRC_SEL_MASK,
				      fs << CS42L42_CLK_IASRC_SEL_SHIFT);
	snd_soc_component_update_bits(component,
				      CS42L42_OUT_ASRC_CLK,
				      CS42L42_CLK_OASRC_SEL_MASK,
				      fs << CS42L42_CLK_OASRC_SEL_SHIFT);
}

static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
	struct snd_soc_component *component = codec_dai->component;
@@ -846,6 +863,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
	unsigned int channels = params_channels(params);
	unsigned int width = (params_width(params) / 8) - 1;
	unsigned int val = 0;
	int ret;

	cs42l42->srate = params_rate(params);
	cs42l42->bclk = snd_soc_params_to_bclk(params);
@@ -899,7 +917,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
		break;
	}

	return cs42l42_pll_config(component);
	ret = cs42l42_pll_config(component);
	if (ret)
		return ret;

	cs42l42_src_config(component, params_rate(params));

	return 0;
}

static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
+1 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@
#define CS42L42_IN_ASRC_CLK		(CS42L42_PAGE_12 + 0x0A)
#define CS42L42_CLK_IASRC_SEL_SHIFT	0
#define CS42L42_CLK_IASRC_SEL_MASK	(1 << CS42L42_CLK_IASRC_SEL_SHIFT)
#define CS42L42_CLK_IASRC_SEL_6		0
#define CS42L42_CLK_IASRC_SEL_12	1

#define CS42L42_OUT_ASRC_CLK		(CS42L42_PAGE_12 + 0x0B)