Unverified Commit eed4872a authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown
Browse files

ASoC: SOF: ipc4-topology: Advertise passthrough capable PCMs (using ChainDMA)



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: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: default avatarPierre-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: default avatarMark Brown <broonie@kernel.org>
parent 7ff01ca7
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -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];