Skip to content

Commit f36e8ed

Browse files
TE-N-ShengjiuWangbroonie
authored andcommitted
ASoC: fsl-asoc-card: Remove fsl_asoc_card_set_bias_level function
With this case: aplay -Dhw:x 16khz.wav 24khz.wav There is sound distortion for 24khz.wav. The reason is that setting PLL of WM8962 with set_bias_level function, the bias level is not changed when 24khz.wav is played, then the PLL won't be reset, the clock is not correct, so distortion happens. The resolution of this issue is to remove fsl_asoc_card_set_bias_level. Move PLL configuration to hw_params and hw_free. After removing fsl_asoc_card_set_bias_level, also test WM8960 case, it can work. Fixes: 708b435 ("ASoC: fsl: Add Freescale Generic ASoC Sound Card with ASRC support") Signed-off-by: Shengjiu Wang <[email protected]> Acked-by: Nicolin Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 8e34f1e commit f36e8ed

File tree

1 file changed

+70
-84
lines changed

1 file changed

+70
-84
lines changed

sound/soc/fsl/fsl-asoc-card.c

Lines changed: 70 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct cpu_priv {
7373
* @codec_priv: CODEC private data
7474
* @cpu_priv: CPU private data
7575
* @card: ASoC card structure
76+
* @streams: Mask of current active streams
7677
* @sample_rate: Current sample rate
7778
* @sample_format: Current sample format
7879
* @asrc_rate: ASRC sample rate used by Back-Ends
@@ -89,6 +90,7 @@ struct fsl_asoc_card_priv {
8990
struct codec_priv codec_priv;
9091
struct cpu_priv cpu_priv;
9192
struct snd_soc_card card;
93+
u8 streams;
9294
u32 sample_rate;
9395
snd_pcm_format_t sample_format;
9496
u32 asrc_rate;
@@ -151,21 +153,17 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
151153
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
152154
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
153155
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
156+
struct codec_priv *codec_priv = &priv->codec_priv;
154157
struct cpu_priv *cpu_priv = &priv->cpu_priv;
155158
struct device *dev = rtd->card->dev;
159+
unsigned int pll_out;
156160
int ret;
157161

158162
priv->sample_rate = params_rate(params);
159163
priv->sample_format = params_format(params);
164+
priv->streams |= BIT(substream->stream);
160165

161-
/*
162-
* If codec-dai is DAI Master and all configurations are already in the
163-
* set_bias_level(), bypass the remaining settings in hw_params().
164-
* Note: (dai_fmt & CBM_CFM) includes CBM_CFM and CBM_CFS.
165-
*/
166-
if ((priv->card.set_bias_level &&
167-
priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) ||
168-
fsl_asoc_card_is_ac97(priv))
166+
if (fsl_asoc_card_is_ac97(priv))
169167
return 0;
170168

171169
/* Specific configurations of DAIs starts from here */
@@ -174,14 +172,76 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
174172
cpu_priv->sysclk_dir[tx]);
175173
if (ret && ret != -ENOTSUPP) {
176174
dev_err(dev, "failed to set sysclk for cpu dai\n");
177-
return ret;
175+
goto fail;
178176
}
179177

180178
if (cpu_priv->slot_width) {
181179
ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2,
182180
cpu_priv->slot_width);
183181
if (ret && ret != -ENOTSUPP) {
184182
dev_err(dev, "failed to set TDM slot for cpu dai\n");
183+
goto fail;
184+
}
185+
}
186+
187+
/* Specific configuration for PLL */
188+
if (codec_priv->pll_id && codec_priv->fll_id) {
189+
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
190+
pll_out = priv->sample_rate * 384;
191+
else
192+
pll_out = priv->sample_rate * 256;
193+
194+
ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
195+
codec_priv->pll_id,
196+
codec_priv->mclk_id,
197+
codec_priv->mclk_freq, pll_out);
198+
if (ret) {
199+
dev_err(dev, "failed to start FLL: %d\n", ret);
200+
goto fail;
201+
}
202+
203+
ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
204+
codec_priv->fll_id,
205+
pll_out, SND_SOC_CLOCK_IN);
206+
207+
if (ret && ret != -ENOTSUPP) {
208+
dev_err(dev, "failed to set SYSCLK: %d\n", ret);
209+
goto fail;
210+
}
211+
}
212+
213+
return 0;
214+
215+
fail:
216+
priv->streams &= ~BIT(substream->stream);
217+
return ret;
218+
}
219+
220+
static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
221+
{
222+
struct snd_soc_pcm_runtime *rtd = substream->private_data;
223+
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
224+
struct codec_priv *codec_priv = &priv->codec_priv;
225+
struct device *dev = rtd->card->dev;
226+
int ret;
227+
228+
priv->streams &= ~BIT(substream->stream);
229+
230+
if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) {
231+
/* Force freq to be 0 to avoid error message in codec */
232+
ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
233+
codec_priv->mclk_id,
234+
0,
235+
SND_SOC_CLOCK_IN);
236+
if (ret) {
237+
dev_err(dev, "failed to switch away from FLL: %d\n", ret);
238+
return ret;
239+
}
240+
241+
ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
242+
codec_priv->pll_id, 0, 0, 0);
243+
if (ret && ret != -ENOTSUPP) {
244+
dev_err(dev, "failed to stop FLL: %d\n", ret);
185245
return ret;
186246
}
187247
}
@@ -191,6 +251,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
191251

192252
static const struct snd_soc_ops fsl_asoc_card_ops = {
193253
.hw_params = fsl_asoc_card_hw_params,
254+
.hw_free = fsl_asoc_card_hw_free,
194255
};
195256

196257
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -254,75 +315,6 @@ static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
254315
},
255316
};
256317

257-
static int fsl_asoc_card_set_bias_level(struct snd_soc_card *card,
258-
struct snd_soc_dapm_context *dapm,
259-
enum snd_soc_bias_level level)
260-
{
261-
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
262-
struct snd_soc_pcm_runtime *rtd;
263-
struct snd_soc_dai *codec_dai;
264-
struct codec_priv *codec_priv = &priv->codec_priv;
265-
struct device *dev = card->dev;
266-
unsigned int pll_out;
267-
int ret;
268-
269-
rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
270-
codec_dai = asoc_rtd_to_codec(rtd, 0);
271-
if (dapm->dev != codec_dai->dev)
272-
return 0;
273-
274-
switch (level) {
275-
case SND_SOC_BIAS_PREPARE:
276-
if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
277-
break;
278-
279-
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
280-
pll_out = priv->sample_rate * 384;
281-
else
282-
pll_out = priv->sample_rate * 256;
283-
284-
ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id,
285-
codec_priv->mclk_id,
286-
codec_priv->mclk_freq, pll_out);
287-
if (ret) {
288-
dev_err(dev, "failed to start FLL: %d\n", ret);
289-
return ret;
290-
}
291-
292-
ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->fll_id,
293-
pll_out, SND_SOC_CLOCK_IN);
294-
if (ret && ret != -ENOTSUPP) {
295-
dev_err(dev, "failed to set SYSCLK: %d\n", ret);
296-
return ret;
297-
}
298-
break;
299-
300-
case SND_SOC_BIAS_STANDBY:
301-
if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
302-
break;
303-
304-
ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
305-
codec_priv->mclk_freq,
306-
SND_SOC_CLOCK_IN);
307-
if (ret && ret != -ENOTSUPP) {
308-
dev_err(dev, "failed to switch away from FLL: %d\n", ret);
309-
return ret;
310-
}
311-
312-
ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id, 0, 0, 0);
313-
if (ret) {
314-
dev_err(dev, "failed to stop FLL: %d\n", ret);
315-
return ret;
316-
}
317-
break;
318-
319-
default:
320-
break;
321-
}
322-
323-
return 0;
324-
}
325-
326318
static int fsl_asoc_card_audmux_init(struct device_node *np,
327319
struct fsl_asoc_card_priv *priv)
328320
{
@@ -611,7 +603,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
611603
/* Diversify the card configurations */
612604
if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
613605
codec_dai_name = "cs42888";
614-
priv->card.set_bias_level = NULL;
615606
priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq;
616607
priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq;
617608
priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
@@ -628,26 +619,22 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
628619
priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
629620
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
630621
codec_dai_name = "wm8962";
631-
priv->card.set_bias_level = fsl_asoc_card_set_bias_level;
632622
priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
633623
priv->codec_priv.fll_id = WM8962_SYSCLK_FLL;
634624
priv->codec_priv.pll_id = WM8962_FLL;
635625
priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
636626
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
637627
codec_dai_name = "wm8960-hifi";
638-
priv->card.set_bias_level = fsl_asoc_card_set_bias_level;
639628
priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO;
640629
priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO;
641630
priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
642631
} else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
643632
codec_dai_name = "ac97-hifi";
644-
priv->card.set_bias_level = NULL;
645633
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
646634
priv->card.dapm_routes = audio_map_ac97;
647635
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
648636
} else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
649637
codec_dai_name = "fsl-mqs-dai";
650-
priv->card.set_bias_level = NULL;
651638
priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
652639
SND_SOC_DAIFMT_CBS_CFS |
653640
SND_SOC_DAIFMT_NB_NF;
@@ -657,7 +644,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
657644
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
658645
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
659646
codec_dai_name = "wm8524-hifi";
660-
priv->card.set_bias_level = NULL;
661647
priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
662648
priv->dai_link[1].dpcm_capture = 0;
663649
priv->dai_link[2].dpcm_capture = 0;

0 commit comments

Comments
 (0)