sound/soc/codecs/hda.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/hda.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/hda.c
Extension
.c
Size
11048 bytes
Lines
397
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 (!pcm->stream[dir].substreams) {
			dev_info(dev, "skipping playback dai for %s\n", pcm->name);
			goto capture_dais;
		}

		stream->stream_name =
			devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name,
				       snd_pcm_direction_name(dir));
		if (!stream->stream_name)
			return -ENOMEM;
		stream->channels_min = pcm->stream[dir].channels_min;
		stream->channels_max = pcm->stream[dir].channels_max;
		stream->rates = pcm->stream[dir].rates;
		stream->formats = pcm->stream[dir].formats;
		stream->subformats = pcm->stream[dir].subformats;
		stream->sig_bits = pcm->stream[dir].maxbps;

capture_dais:
		dir = SNDRV_PCM_STREAM_CAPTURE;
		stream = &drvs[i].capture;
		if (!pcm->stream[dir].substreams) {
			dev_info(dev, "skipping capture dai for %s\n", pcm->name);
			continue;
		}

		stream->stream_name =
			devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name,
				       snd_pcm_direction_name(dir));
		if (!stream->stream_name)
			return -ENOMEM;
		stream->channels_min = pcm->stream[dir].channels_min;
		stream->channels_max = pcm->stream[dir].channels_max;
		stream->rates = pcm->stream[dir].rates;
		stream->formats = pcm->stream[dir].formats;
		stream->subformats = pcm->stream[dir].subformats;
		stream->sig_bits = pcm->stream[dir].maxbps;
	}

	*drivers = drvs;
	return 0;
}

static int hda_codec_register_dais(struct hda_codec *codec, struct snd_soc_component *component)
{
	struct snd_soc_dai_driver *drvs = NULL;
	struct snd_soc_dapm_context *dapm;
	struct hda_pcm *pcm;
	int ret, pcm_count = 0;

	if (list_empty(&codec->pcm_list_head))
		return -EINVAL;
	list_for_each_entry(pcm, &codec->pcm_list_head, list)
		pcm_count++;

	ret = hda_codec_create_dais(codec, pcm_count, &drvs);
	if (ret < 0)
		return ret;

	dapm = snd_soc_component_to_dapm(component);

	list_for_each_entry(pcm, &codec->pcm_list_head, list) {
		struct snd_soc_dai *dai;

		dai = snd_soc_register_dai(component, drvs, false);
		if (!dai) {
			dev_err(component->dev, "register dai for %s failed\n", pcm->name);
			return -EINVAL;
		}

		ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
		if (ret < 0) {
			dev_err(component->dev, "create widgets failed: %d\n", ret);
			snd_soc_unregister_dai(dai);
			return ret;
		}

		snd_soc_dai_init_dma_data(dai, &pcm->stream[0], &pcm->stream[1]);
		drvs++;
	}

	return 0;
}

static void hda_codec_unregister_dais(struct hda_codec *codec,
				      struct snd_soc_component *component)
{
	struct snd_soc_dai *dai, *save;
	struct hda_pcm *pcm;

	for_each_component_dais_safe(component, dai, save) {

Annotation

Implementation Notes