sound/soc/sof/intel/hda-dai.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/intel/hda-dai.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/intel/hda-dai.c
Extension
.c
Size
24596 bytes
Lines
961
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret < 0) {
			dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n",
				flags, w->name);
			return ret;
		}
	}

	return 0;
}
EXPORT_SYMBOL_NS(hda_dai_config, "SND_SOC_SOF_INTEL_HDA_COMMON");

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)

static struct snd_sof_dev *dai_to_sdev(struct snd_pcm_substream *substream,
				       struct snd_soc_dai *cpu_dai)
{
	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);

	return widget_to_sdev(w);
}

static const struct hda_dai_widget_dma_ops *
hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
{
	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
	struct snd_sof_widget *swidget;
	struct snd_sof_dev *sdev;
	struct snd_sof_dai *sdai;

	/*
	 * this is unlikely if the topology and the machine driver DAI links match.
	 * But if there's a missing DAI link in topology, this will prevent a NULL pointer
	 * dereference later on.
	 */
	if (!w) {
		dev_err(cpu_dai->dev, "%s: widget is NULL\n", __func__);
		return NULL;
	}

	sdev = widget_to_sdev(w);
	swidget = w->dobj.private;
	if (!swidget) {
		dev_err(sdev->dev, "%s: swidget is NULL\n", __func__);
		return NULL;
	}

	if (sdev->dspless_mode_selected)
		return hda_select_dai_widget_ops(sdev, swidget);

	sdai = swidget->private;

	/* select and set the DAI widget ops if not set already */
	if (!sdai->platform_private) {
		const struct hda_dai_widget_dma_ops *ops =
			hda_select_dai_widget_ops(sdev, swidget);
		if (!ops)
			return NULL;

		/* check if mandatory ops are set */
		if (!ops || !ops->get_hext_stream)
			return NULL;

		sdai->platform_private = ops;
	}

	return sdai->platform_private;
}

static int
hda_link_dma_cleanup(struct snd_pcm_substream *substream,
		     struct hdac_ext_stream *hext_stream,
		     struct snd_soc_dai *cpu_dai, bool release)
{
	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
	struct sof_intel_hda_stream *hda_stream;
	struct hdac_ext_link *hlink;
	struct snd_sof_dev *sdev;
	int stream_tag;

	if (!ops) {
		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
		return -EINVAL;
	}

	sdev = dai_to_sdev(substream, cpu_dai);

	hlink = ops->get_hlink(sdev, substream);
	if (!hlink)
		return -EINVAL;

Annotation

Implementation Notes