[PATCH] ASoC: fsl-asoc-card: dummy codec compatibility integration for use with S/PDIF controller
Hello,
Following some work to reduce the impact of audio resampling in Linux, we would like to use the ASRC of the i.MX8 SoCs with the S/PDIF controller. With that aim, this series of patch for the machine driver fsl-asoc-card proposes to add compatibility with the dummy codec driver. This is a first step in using the S/PDIF controller with the ASRC, as the imx-spdif machine driver uses the dummy codec with the fsl_spdif DAI driver.
The five first patches add compatibility with the dummy codec through a new compatible, fsl,imx-audio-dummy-codec. Codec parameters are set with default values.
The remaining patches add configuration options through device tree for the codec parameters that can also impact the CPU DAI. These are usually hard-coded in fsl-asoc-card for each audio codec. Because this dummy codec could be use with other CPU DAI than the S/PDIF controller, these could need specific configuration.
This series of patch was successfully built for arm64 and x86 on top of the latest for-next branch of the ASoC git tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/ on the 28/08. These modifications have also been tested on an i.MX8MN evaluation board, with a linux kernel RT v6.1.26-rt8.
Regards, Elinor Montmasson
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add support for the new compatible fsl,imx-audio-dummy-codec. It allows using the fsl-asoc-card driver with the dummy codec provided by the kernel utilities instead of a real codec. For now the compatible is recognised and the codec driver names are set, but a sound card with this compatible will still be deferred during initialisation.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 76b5bfc288fd..c12a356a86d5 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -575,7 +575,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto fail; }
- codec_np = of_parse_phandle(np, "audio-codec", 0); + if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) + codec_np = NULL; + else + codec_np = of_parse_phandle(np, "audio-codec", 0); + if (codec_np) { struct platform_device *codec_pdev; struct i2c_client *codec_i2c; @@ -705,6 +709,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; if (codec_dev) priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL); + } else if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) { + codec_dai_name = "snd-soc-dummy-dai"; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL; @@ -806,7 +812,9 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_link[0].cpus->of_node = cpu_np; priv->dai_link[0].codecs->dai_name = codec_dai_name;
- if (!fsl_asoc_card_is_ac97(priv)) + if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) + priv->dai_link[0].codecs->name = "snd-soc-dummy"; + else if (!fsl_asoc_card_is_ac97(priv)) priv->dai_link[0].codecs->of_node = codec_np; else { u32 idx; @@ -931,6 +939,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-si476x", }, { .compatible = "fsl,imx-audio-wm8958", }, { .compatible = "fsl,imx-audio-nau8822", }, + { .compatible = "fsl,imx-audio-dummy-codec", }, {} }; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
On Fri, Sep 1, 2023 at 10:46 PM elinor.montmasson@savoirfairelinux.com wrote:
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add support for the new compatible fsl,imx-audio-dummy-codec. It allows using the fsl-asoc-card driver with the dummy codec provided by the kernel utilities instead of a real codec. For now the compatible is recognised and the codec driver names are set, but a sound card with this compatible will still be deferred during initialisation.
Add Mark
In the "Question about simple-audio-card with dummy CODEC" Mark said dummy codec may not be used. we should have a driver to describe the codec.
Best regards wang shengjiu
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com
sound/soc/fsl/fsl-asoc-card.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 76b5bfc288fd..c12a356a86d5 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -575,7 +575,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto fail; }
codec_np = of_parse_phandle(np, "audio-codec", 0);
if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec"))
codec_np = NULL;
else
codec_np = of_parse_phandle(np, "audio-codec", 0);
if (codec_np) { struct platform_device *codec_pdev; struct i2c_client *codec_i2c;
@@ -705,6 +709,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; if (codec_dev) priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL);
} else if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) {
codec_dai_name = "snd-soc-dummy-dai"; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
@@ -806,7 +812,9 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_link[0].cpus->of_node = cpu_np; priv->dai_link[0].codecs->dai_name = codec_dai_name;
if (!fsl_asoc_card_is_ac97(priv))
if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec"))
priv->dai_link[0].codecs->name = "snd-soc-dummy";
else if (!fsl_asoc_card_is_ac97(priv)) priv->dai_link[0].codecs->of_node = codec_np; else { u32 idx;
@@ -931,6 +939,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-si476x", }, { .compatible = "fsl,imx-audio-wm8958", }, { .compatible = "fsl,imx-audio-nau8822", },
{ .compatible = "fsl,imx-audio-dummy-codec", }, {}
}; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); -- 2.25.1
On lundi 11 septembre 2023 10:21:17 CEST Shengjiu Wang wrote:
Add Mark
In the "Question about simple-audio-card with dummy CODEC" Mark said dummy codec may not be used. we should have a driver to describe the codec.
Best regards wang shengjiu
Hello,
I'm following up since Elinor is currently absent. I had the opportunity to meet Mark and asked for his advice: we will modify the patchset to use the spdif_receiver and spdif_transceiver codecs instead of the dummy codec. Thanks for the review.
Best regards, Philip-Dylan Gleonec
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Prevent deferment during sound card initialisation when using the dummy codec. If the codec isn't an ac97, it is expected to have a device tree node for the codec. If not, the sound card initialisation is deferred. However, the dummy codec has no device tree node, thus we must handle this specific use case.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index c12a356a86d5..d656df0b0eea 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -748,7 +748,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) of_node_put(bitclkprovider); of_node_put(frameprovider);
- if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { + if (!fsl_asoc_card_is_ac97(priv) && !codec_dev + && !of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) { dev_dbg(&pdev->dev, "failed to find codec device\n"); ret = -EPROBE_DEFER; goto asrc_fail;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
The default dai format defined by DAI_FMT_BASE doesn't set if the codec is consumer or provider of the bit and frame clocks. As it is set by each existing configuration, set the codec as consumer of both bit and frame clock by default with the dummy codec.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index d656df0b0eea..d210147aebfe 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -711,6 +711,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL); } else if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) { codec_dai_name = "snd-soc-dummy-dai"; + priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Unset DAPM routes when using the dummy codec. The dummy codec doesn't provide DAPM widgets per design, as it doesn't represent any real hardware. Thus the default DAPM audio routes do not work because there is no Playback or Capture DAPM widget.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index d210147aebfe..5ef26ae512de 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -712,6 +712,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } else if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) { codec_dai_name = "snd-soc-dummy-dai"; priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; + priv->card.dapm_routes = NULL; + priv->card.num_dapm_routes = 0; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add the new DAPM audio map audio_map_asrc used with the dummy codec. The dummy codec doesn't have any Playback or Capture DAPM widgets. DAPM default audio maps are thus unused with it. However, when using the ASRC, DAPM routes between CPU DAI and ASRC are still required. The driver must then handle this use case.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 5ef26ae512de..d8f4412be308 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -148,6 +148,13 @@ static const struct snd_soc_dapm_route audio_map_rx[] = { {"ASRC-Capture", NULL, "CPU-Capture"}, };
+ +static const struct snd_soc_dapm_route audio_map_asrc[] = { + {"CPU-Playback", NULL, "ASRC-Playback"}, + {"ASRC-Capture", NULL, "CPU-Capture"}, +}; + + /* Add all possible widgets into here without being redundant */ static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line Out Jack", NULL), @@ -803,6 +810,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Drop the second half of DAPM routes -- ASRC */ if (!asrc_pdev) priv->card.num_dapm_routes /= 2; + else if (of_device_is_compatible(np, "fsl,imx-audio-dummy-codec")) { + /* Dummy codec doesn't provide Playback and Capture widgets */ + priv->card.dapm_routes = audio_map_asrc; + priv->card.num_dapm_routes = 2; + }
if (of_property_read_bool(np, "audio-routing")) { ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add new optional dts property "cpu-slot-width", which allows to set a custom TDM slot width in bits for the CPU DAI when using the dummy codec.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index d8f4412be308..12d01970850d 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -721,6 +721,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; priv->card.dapm_routes = NULL; priv->card.num_dapm_routes = 0; + of_property_read_u32(np, "cpu-slot-width", &priv->cpu_priv.slot_width); } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add new optional dts property "cpu-slot-num", which allows to set a custom number of TDM slots for the CPU DAI when using the dummy codec.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 12d01970850d..66bcb6aa498a 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -722,6 +722,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = NULL; priv->card.num_dapm_routes = 0; of_property_read_u32(np, "cpu-slot-width", &priv->cpu_priv.slot_width); + of_property_read_u32(np, "cpu-slot-num", &priv->cpu_priv.slot_num); } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add new optional dts properties "cpu-sysclk-dir-out" to set sysclk directions as "out" for the CPU DAI when using the dummy codec. This can be set for Tx and Rx. If not set, the direction is "in". The way values are used is up to the CPU DAI driver implementation.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index a60d78374ef3..4beb047de3bf 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -727,6 +727,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) (u32 *)&priv->cpu_priv.sysclk_freq[RX]); of_property_read_u32(np, "cpu-sysclk-freq-tx", (u32 *)&priv->cpu_priv.sysclk_freq[TX]); + priv->cpu_priv.sysclk_dir[RX] = + of_property_read_bool(np, "cpu-sysclk-dir-rx-out") ? + SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN; + priv->cpu_priv.sysclk_dir[TX] = + of_property_read_bool(np, "cpu-sysclk-dir-tx-out") ? + SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add documentation about new dts bindings following new support for compatible "fsl,imx-audio-dummy-codec".
Some CPU DAI don't require a real audio codec. The new compatible "fsl,imx-audio-dummy-codec" makes the driver use the dummy codec driver provided by the ASoC utils. It also allows to use not pre-configured audio codecs which don't require specific control through a codec driver.
The new dts properties give the possibility to set some parameters about the CPU DAI usually set through the codec configuration.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- .../bindings/sound/fsl-asoc-card.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index 4e8dbc5abfd1..2e081a62d29d 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -17,6 +17,9 @@ Note: The card is initially designed for those sound cards who use AC'97, I2S and PCM DAI formats. However, it'll be also possible to support those non AC'97/I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as long as the driver has been properly upgraded. + To use CPU DAIs that do not require a codec such as an S/PDIF controller, + or to use a DAI to output or capture raw I2S/TDM data, you can + use the compatible "fsl,imx-audio-dummy-codec".
The compatible list for this generic sound card currently: @@ -48,6 +51,8 @@ The compatible list for this generic sound card currently:
"fsl,imx-audio-nau8822"
+ "fsl,imx-audio-dummy-codec" + Required properties:
- compatible : Contains one of entries in the compatible list. @@ -56,6 +61,8 @@ Required properties:
- audio-cpu : The phandle of an CPU DAI controller
+Required, unless "fsl,imx-audio-dummy-codec" compatible is used: + - audio-codec : The phandle of an audio codec
Optional properties: @@ -88,6 +95,19 @@ Optional properties: - bitclock-inversion : dai-link uses bit clock inversion, for details see simple-card.yaml. - mclk-id : main clock id, specific for each card configuration.
+Optional, relevant only with the "fsl,imx-audio-dummy-codec" compatible: + + - cpu-slot-width : Indicates a specific TDM slot width in bits. + - cpu-slot-num : Indicates a specific number of TDM slots per frame. + + - cpu-sysclk-freq-rx : Frequency of the CPU DAI sys clock for Rx. + - cpu-sysclk-freq-tx : Frequency of the CPU DAI sys clock for Tx. + + - cpu-sysclk-dir-rx-out : Boolean property. Specifies sys clock direction + as 'out' on initialization for Rx. If not set, default direction is 'in'. + - cpu-sysclk-dir-tx-out : Boolean property. Specifies sys clock direction + as 'out' on initialization for Tx. If not set, default direction is 'in'. + Optional unless SSI is selected as a CPU DAI:
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
From: Elinor Montmasson elinor.montmasson@savoirfairelinux.com
Add new optional dts property "cpu-sysclk-freq" to set custom sysclk frequencies for the CPU DAI with the dummy codec. The way values are used is up to the CPU DAI driver implementation.
Signed-off-by: Elinor Montmasson elinor.montmasson@savoirfairelinux.com Co-authored-by: Philip-Dylan Gleonec philip-dylan.gleonec@savoirfairelinux.com --- sound/soc/fsl/fsl-asoc-card.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 66bcb6aa498a..a60d78374ef3 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -723,6 +723,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.num_dapm_routes = 0; of_property_read_u32(np, "cpu-slot-width", &priv->cpu_priv.slot_width); of_property_read_u32(np, "cpu-slot-num", &priv->cpu_priv.slot_num); + of_property_read_u32(np, "cpu-sysclk-freq-rx", + (u32 *)&priv->cpu_priv.sysclk_freq[RX]); + of_property_read_u32(np, "cpu-sysclk-freq-tx", + (u32 *)&priv->cpu_priv.sysclk_freq[TX]); } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL;
participants (3)
-
elinor.montmasson@savoirfairelinux.com
-
Philip-Dylan Gleonec
-
Shengjiu Wang