ASoC: SOF: ipc4-topology: Advertise passthrough capable PCMs (using ChainDMA)
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Fri, 26 Apr 2024 15:39:02 +0000 (10:39 -0500)
committerMark Brown <broonie@kernel.org>
Mon, 29 Apr 2024 15:16:36 +0000 (00:16 +0900)
If a PCM is set to use ChainDMA then add it to the card->components string
after a marker of iec61937-pcm:, for example on current HDA platforms where
HDMI is set to use ChainDMA:
iec61937-pcm:5,4,3 (the order of the PCM ids can differ)

UCM is expected to parse and use this property to allow applications to
use bytestream passthrough in a standard way.

Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20240426153902.39560-6-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc4-topology.c

index c29c1de4e9258331c166bd66b07e8b54d7957bf7..a972b2b5122a388b8086e14de80c6dcce504d7c6 100644 (file)
@@ -407,6 +407,52 @@ static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swi
        }
 }
 
+static int
+sof_ipc4_update_card_components_string(struct snd_sof_widget *swidget,
+                                      struct snd_sof_pcm *spcm, int dir)
+{
+       struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
+       struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
+       struct snd_soc_component *scomp = spcm->scomp;
+       struct snd_soc_card *card = scomp->card;
+       const char *pt_marker = "iec61937-pcm";
+
+       /*
+        * Update the card's components list with iec61937-pcm and a list of PCM
+        * ids where ChainDMA is enabled.
+        * These PCMs can be used for bytestream passthrough.
+        */
+       if (!pipeline->use_chain_dma)
+               return 0;
+
+       if (card->components) {
+               const char *tmp = card->components;
+
+               if (strstr(card->components, pt_marker))
+                       card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+                                                         "%s,%d",
+                                                         card->components,
+                                                         spcm->pcm.pcm_id);
+               else
+                       card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+                                                         "%s %s:%d",
+                                                         card->components,
+                                                         pt_marker,
+                                                         spcm->pcm.pcm_id);
+
+               devm_kfree(card->dev, tmp);
+       } else {
+               card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+                                                 "%s:%d", pt_marker,
+                                                 spcm->pcm.pcm_id);
+       }
+
+       if (!card->components)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
 {
        struct sof_ipc4_available_audio_format *available_fmt;
@@ -452,6 +498,10 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
        if (!spcm)
                goto skip_gtw_cfg;
 
+       ret = sof_ipc4_update_card_components_string(swidget, spcm, dir);
+       if (ret)
+               goto free_available_fmt;
+
        if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
                struct snd_sof_pcm_stream *sps = &spcm->stream[dir];