[PATCH 2/2] ASoC: fsl-asoc-card: add support for generic I2S slave use-case

From: Arnaud Ferraris
Date: Thu Jul 02 2020 - 10:12:30 EST


This commit implements support for generic codecs with the SoC acting as
I2S slave, by implementing the new `fsl,imx-audio-i2s-slave` compatible
and related properties.

This is particularly useful when using a Bluetooth controller acting as
I2S master, but other simple or dummy codecs might benefit from it too.

Signed-off-by: Arnaud Ferraris <arnaud.ferraris@xxxxxxxxxxxxx>
---
sound/soc/fsl/fsl-asoc-card.c | 46 ++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 57ea1b072326..6076b963c873 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -166,12 +166,15 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
return 0;

/* Specific configurations of DAIs starts from here */
- ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), cpu_priv->sysclk_id[tx],
- cpu_priv->sysclk_freq[tx],
- cpu_priv->sysclk_dir[tx]);
- if (ret && ret != -ENOTSUPP) {
- dev_err(dev, "failed to set sysclk for cpu dai\n");
- return ret;
+ if (cpu_priv->sysclk_freq[tx] > 0) {
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0),
+ cpu_priv->sysclk_id[tx],
+ cpu_priv->sysclk_freq[tx],
+ cpu_priv->sysclk_dir[tx]);
+ if (ret && ret != -ENOTSUPP) {
+ dev_err(dev, "failed to set sysclk for cpu dai\n");
+ return ret;
+ }
}

if (cpu_priv->slot_width) {
@@ -475,11 +478,14 @@ static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
return 0;
}

- ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
- codec_priv->mclk_freq, SND_SOC_CLOCK_IN);
- if (ret && ret != -ENOTSUPP) {
- dev_err(dev, "failed to set sysclk in %s\n", __func__);
- return ret;
+ if (codec_priv->mclk_freq > 0) {
+ ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
+ codec_priv->mclk_freq,
+ SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP) {
+ dev_err(dev, "failed to set sysclk in %s\n", __func__);
+ return ret;
+ }
}

return 0;
@@ -620,6 +626,23 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->cpu_priv.slot_width = 32;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
+ } else if (of_device_is_compatible(np, "fsl,imx-audio-i2s-slave")) {
+ ret = of_property_read_string(np, "audio-codec-dai-name",
+ &codec_dai_name);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get codec DAI name\n");
+ ret = -EINVAL;
+ goto asrc_fail;
+ }
+ ret = of_property_read_u32(np, "audio-slot-width",
+ &priv->cpu_priv.slot_width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get slot width\n");
+ ret = -EINVAL;
+ goto asrc_fail;
+ }
+ priv->card.set_bias_level = NULL;
+ priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
} else {
dev_err(&pdev->dev, "unknown Device Tree compatible\n");
ret = -EINVAL;
@@ -763,6 +786,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)

static const struct of_device_id fsl_asoc_card_dt_ids[] = {
{ .compatible = "fsl,imx-audio-ac97", },
+ { .compatible = "fsl,imx-audio-i2s-slave", },
{ .compatible = "fsl,imx-audio-cs42888", },
{ .compatible = "fsl,imx-audio-cs427x", },
{ .compatible = "fsl,imx-audio-sgtl5000", },
--
2.27.0