On Sun, Oct 20, 2024 at 09:37:06AM -0700, anish kumar wrote:
> Updated documentation to provide more details
> for codec-to-codec connection.
>
> Signed-off-by: anish kumar <yesanishhere@xxxxxxxxx>
> ---
The patch doesn't seem to apply cleanly for me, my system doesn't
seem to like:
Content-Type: text/plain; charset="y"
Not sure if that is a problem on my end or yours, but I am not
familiar with that encoding.
> v2: Fixed the compilation error reported by Sphinx
> Documentation/sound/soc/codec-to-codec.rst | 296 +++++++++++++--------
> 1 file changed, 190 insertions(+), 106 deletions(-)
>
> diff --git a/Documentation/sound/soc/codec-to-codec.rst b/Documentation/sound/soc/codec-to-codec.rst
> index 0418521b6e03..9d65fc74856a 100644
> --- a/Documentation/sound/soc/codec-to-codec.rst
> +++ b/Documentation/sound/soc/codec-to-codec.rst
> @@ -1,115 +1,199 @@
> -==============================================
> -Creating codec to codec dai link for ALSA dapm
> -==============================================
> +Codec-to-Codec Connections in ALSA
> +====================================
>
> -Mostly the flow of audio is always from CPU to codec so your system
> -will look as below:
> -::
> +An ALSA-based audio system typically involves playback and capture
> +functionalities, where users may require audio file playback through
functionality would probably parse slightly better.
> +speakers or recording from microphones. However, certain systems
> +necessitate audio data routing directly between components, such as FM
> +radio to speakers, without CPU involvement. For such scenarios, ALSA
It would probably be more accurate to say "ASoC provides", I mean
I guess ASoC is a part of ALSA but this is definitely an ASoC
level feature.
> +provides a mechanism known as codec-to-codec connections, leveraging
> +the Dynamic Audio Power Management (DAPM) framework to facilitate
> +direct data transfers between codecs.
>
> - --------- ---------
> - | | dai | |
> - CPU -------> codec
> - | | | |
> - --------- ---------
> +Introduction
> +------------
>
> -In case your system looks as below:
> -::
> +In most audio systems, audio data flows from the CPU to the codec. In
> +specific configurations, such as those involving Bluetooth codecs,
> +audio can be transmitted directly between codecs without CPU
> +intervention. ALSA supports both architectures, and for systems that
> +do not involve the CPU, it utilizes codec-to-codec digital audio
> +interface (DAI) connections. This document discusses the procedure
> +for establishing codec-to-codec DAI links to enable such
> +functionalities.
>
> +Audio Data Flow Paths
> +----------------------
> +
> +In a typical configuration, audio flow can be visualized as follows:
> +
> +.. code-block:: text
> +
> + --------- ---------
> + | | dai | |
> + CPU -------> codec
> + | | | |
> + --------- ---------
> +
> +In more intricate setups, the system may not involve the CPU but
> +instead utilizes multiple codecs as shown below. For instance,
> +Codec-2 acts as a cellular modem, while Codec-3 connects to a
> +speaker. Audio data can be received by Codec-2 and transmitted to
> +Codec-3 without CPU intervention, demonstrating the ideal conditions
> +for establishing a codec-to-codec DAI connection.
> +
> +.. code-block:: text
> +
> + ---------
> + | |
> + codec-1 <---cellular modem
> + | |
> ---------
> - | |
> - codec-2
> - | |
> - ---------
> - |
> - dai-2
> - |
> - ---------- ---------
> - | | dai-1 | |
> - CPU -------> codec-1
> - | | | |
> - ---------- ---------
> - |
> - dai-3
> - |
> - ---------
> - | |
> - codec-3
> - | |
> + |
> + dai-1
> + ↓
> + ---------- ---------
> + | |cpu_dai | |
> + dummy CPU -------> codec-2
Bringing the "dummy" into this is quite misleading, that really
relates to DPCM setups. DPCM lets one select any number of back
ends to service a given front end PCM, and often are abused to
achieve things that should really be implemented as C2C links.
> + | | | |
> + ---------- ---------
> + |
> + dai-3
> + ↓
> + ---------
> + | |
> + codec-3 ---->speaker
> + | |
> ---------
>
> -Suppose codec-2 is a bluetooth chip and codec-3 is connected to
> -a speaker and you have a below scenario:
> -codec-2 will receive the audio data and the user wants to play that
> -audio through codec-3 without involving the CPU.This
> -aforementioned case is the ideal case when codec to codec
> -connection should be used.
> -
> -Your dai_link should appear as below in your machine
> -file:
> -::
> -
> - /*
> - * this pcm stream only supports 24 bit, 2 channel and
> - * 48k sampling rate.
> - */
> - static const struct snd_soc_pcm_stream dsp_codec_params = {
> - .formats = SNDRV_PCM_FMTBIT_S24_LE,
> - .rate_min = 48000,
> - .rate_max = 48000,
> - .channels_min = 2,
> - .channels_max = 2,
> - };
> -
> - {
> - .name = "CPU-DSP",
> - .stream_name = "CPU-DSP",
> - .cpu_dai_name = "samsung-i2s.0",
> - .codec_name = "codec-2,
> - .codec_dai_name = "codec-2-dai_name",
> - .platform_name = "samsung-i2s.0",
> - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> - | SND_SOC_DAIFMT_CBM_CFM,
> - .ignore_suspend = 1,
> - .c2c_params = &dsp_codec_params,
> - .num_c2c_params = 1,
> - },
> - {
> - .name = "DSP-CODEC",
> - .stream_name = "DSP-CODEC",
> - .cpu_dai_name = "wm0010-sdi2",
> - .codec_name = "codec-3,
> - .codec_dai_name = "codec-3-dai_name",
> - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> - | SND_SOC_DAIFMT_CBM_CFM,
> - .ignore_suspend = 1,
> - .c2c_params = &dsp_codec_params,
> - .num_c2c_params = 1,
> - },
> -
> -Above code snippet is motivated from sound/soc/samsung/speyside.c.
> -
> -Note the "c2c_params" callback which lets the dapm know that this
> -dai_link is a codec to codec connection.
> -
> -In dapm core a route is created between cpu_dai playback widget
> -and codec_dai capture widget for playback path and vice-versa is
> -true for capture path. In order for this aforementioned route to get
> -triggered, DAPM needs to find a valid endpoint which could be either
> -a sink or source widget corresponding to playback and capture path
> +Creating Codec-to-Codec Connections in ALSA
> +----------------------------------------------
> +
> +To create a codec-to-codec DAI in ALSA, a ``snd_soc_dai_link`` must be
> +added to the machine driver before registering the sound card.
> +During this registration, the core checks for the presence of
> +``c2c_params`` within the ``snd_soc_dai_link``, determining whether
> +to classify the DAI link as codec-to-codec.
> +
> +While establishing the PCM node, the ALSA core inspects this
> +parameter. Instead of generating a user-space PCM node, it creates
> +an internal PCM node utilized by kernel drivers. Consequently,
I am not sure I like the description of this as an internal PCM
node, I guess in some ways the core does use the same structures
it would for a PCM node, but it isn't really a PCM node. I
do like that you have added the additional note this will not be
visible through procfs though.
> +running ``cat /proc/asound/pcm`` will yield no visible PCM nodes.
> +
> +After this setup, the ALSA core invokes the DAPM core to connect a
Again really ASoC core here.
> +single ``cpu_dai`` with both ``codec_dais``. Boot-up logs will
> +display messages similar to:
That is definitely not what should be happening with a C2C link.
In the system you showed the diagram for above there should be a
connection between the CPU and codec-2, then two separate links
between codec-2 and codecs 1 and 3. No links should be present
between the CPU and codecs 1 or 3.
> +
> +.. code-block:: bash
> +
> + ASoC: registered pcm #0 codec2codec(Playback Codec)
> + multicodec <-> cpu_dai mapping ok
> + connected DAI link Dummy-CPU:cpu_dai -> codec-1:dai_1
> + connected DAI link Dummy-CPU:cpu_dai -> codec-2:dai_2
> +
Yeah this is definitely mixing in a fair amount of DPCM stuff and
does not match the rest of the description.
> +To trigger this DAI link, a control interface is established by the
> +DAPM core during internal DAI creation. This interface links to
> +the ``snd_soc_dai_link_event`` function, which is invoked when a
> +path connects in the DAPM core. A mixer must be created to trigger
> +the connection, prompting the DAPM core to evaluate path
> +connections and call the ``snd_soc_dai_link_event`` callback with
> +relevant events.
> +
> +It is important to note that not all operations defined in
> +``snd_soc_dai_ops`` are invoked as codec-to-codec connections offer
> +limited control over DAI configuration. For greater control, a
> +hostless configuration is recommended. The operations typically
It is not clear to me what a "hostless configuration" is here.
> +executed in codec-to-codec setups include startup, ``hw_params``,
> +``hw_free``, digital mute, and shutdown from the
> +``snd_soc_dai_ops`` structure.
> +
> +Code Changes for Codec-to-Codec
> +----------------------------------
> +
> +The DAI link configuration in the machine file should resemble the
> +following code snippet:
> +
> +.. code-block:: c
> +
> + /*
> + * This PCM stream only supports 24-bit, 2 channels, and
> + * 48kHz sampling rate.
> + */
> + static const struct snd_soc_pcm_stream dsp_codec_params = {
> + .formats = SNDRV_PCM_FMTBIT_S24_LE,
> + .rate_min = 48000,
> + .rate_max = 48000,
> + .channels_min = 2,
> + .channels_max = 2,
> + };
> +
> + static struct snd_soc_dai_link dai_links[] = {
> + {
> + .name = "CPU-DSP",
> + .stream_name = "CPU-DSP",
> + .cpu_dai_name = "samsung-i2s.0",
> + .codec_name = "codec-2",
> + .codec_dai_name = "codec-2-dai_name",
> + .platform_name = "samsung-i2s.0",
> + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> + | SND_SOC_DAIFMT_CBM_CFM,
> + .ignore_suspend = 1,
> + .c2c_params = &dsp_codec_params,
> + .num_c2c_params = 1,
> + },
> + {
> + .name = "DSP-CODEC",
> + .stream_name = "DSP-CODEC",
> + .cpu_dai_name = "wm0010-sdi2",
> + .codec_name = "codec-3",
> + .codec_dai_name = "codec-3-dai_name",
> + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> + | SND_SOC_DAIFMT_CBM_CFM,
> + .ignore_suspend = 1,
> + .c2c_params = &dsp_codec_params,
> + .num_c2c_params = 1,
> + },
> + };
> +
> +This snippet draws inspiration from the configuration found in
> +``sound/soc/samsung/speyside.c``. The inclusion of the
> +``c2c_params`` indicates to the DAPM core that the DAI link is a
> +codec-to-codec connection.
> +
> +In the DAPM core, a route is established between the CPU DAI
> +playback widget and the codec DAI capture widget for playback, with
> +the reverse applying to the capture path. To trigger these routes,
> +DAPM requires valid endpoints, which can be either sink or source
> +widgets corresponding to the playback and capture paths,
> respectively.
>
> -In order to trigger this dai_link widget, a thin codec driver for
> -the speaker amp can be created as demonstrated in wm8727.c file, it
> -sets appropriate constraints for the device even if it needs no control.
> -
> -Make sure to name your corresponding cpu and codec playback and capture
> -dai names ending with "Playback" and "Capture" respectively as dapm core
> -will link and power those dais based on the name.
> -
> -A dai_link in a "simple-audio-card" will automatically be detected as
> -codec to codec when all DAIs on the link belong to codec components.
> -The dai_link will be initialized with the subset of stream parameters
> -(channels, format, sample rate) supported by all DAIs on the link. Since
> -there is no way to provide these parameters in the device tree, this is
> -mostly useful for communication with simple fixed-function codecs, such
> -as a Bluetooth controller or cellular modem.
> +To activate this DAI link widget, a lightweight codec driver for
> +the speaker amplifier can be implemented, following a similar
> +strategy to that in ``wm8727.c``. This driver should set the
> +necessary constraints for the device, even with minimal control
> +requirements.
Would actually be nice to include the note that any codec driver
should be fine, the original text does kinda give the impression
one would have to write a "thin codec driver" but if you already
have a driver thin or otherwise that would be fine. Perhaps
better to rephrase as a codec driver being required.
> +
> +It's crucial to append “Playback” and “Capture” suffixes to the
> +respective CPU and codec DAI names for playback and capture, as
> +the DAPM core links and powers these DAIs based on their naming
> +conventions.
Are you sure this is true? I could be wrong but I don't expect
the naming is critical in hooking up a c2c DAI.
> +
> +In a codec-to-codec scenario involving multiple codecs (above
> +bootup logs are for multicodec scenario), it is not feasible to
> +control individual codecs using dummy kcontrols or DAPM widgets.
I really am not sure what this means. What are we controlling
using dummy kcontrols? Why are we not using the real kcontrols
from the codec to control the codec?
> +This limitation arises because the CPU DAI is statically
> +connected to all codecs. Consequently, when a path is enabled,
Which it shouldn't be?
> +the DAPM core does not verify all the widgets that may be linked
> +to the mixer widget. It’s important to note that the mixer widget
> +serves as the trigger for these paths.
> +
> +Simple-audio-card configuration
> +----------------------------------
> +A dai_link in a "simple-audio-card" will automatically be
> +detected as codec-to-codec when all DAIs on the link belong to
> +codec components. The dai_link will be initialized with the
> +subset of stream parameters (channels, format, sample rate)
> +supported by all DAIs on the link. Since there is no way to
> +provide these parameters in the device tree, this is mostly useful
> +for communication with simple fixed-function codecs, such as a
> +Bluetooth controller or cellular modem.
> --
> 2.39.3 (Apple Git-146)
>
>
Thanks,
Charles
[Index of Archives]
[Pulseaudio]
[Linux Audio Users]
[ALSA Devel]
[Fedora Desktop]
[Fedora SELinux]
[Big List of Linux Books]
[Yosemite News]
[KDE Users]