sound/soc/codecs/hdac_hda.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/hdac_hda.c
Extension
.c
Size
18226 bytes
Lines
678
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 (strstr(cpcm->name, pcm_name)) {
			if (strcmp(pcm_name, "Analog") == 0) {
				if (strstr(cpcm->name, "Alt Analog"))
					continue;
			}
			return cpcm;
		}
	}

	dev_err(dai->dev, "%s: didn't find PCM for DAI %s\n", __func__, dai->name);
	return NULL;
}

static bool is_hdmi_codec(struct hda_codec *hcodec)
{
	struct hda_pcm *cpcm;

	list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
		if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
			return true;
	}

	return false;
}

static int hdac_hda_codec_probe(struct snd_soc_component *component)
{
	struct hdac_hda_priv *hda_pvt =
			snd_soc_component_get_drvdata(component);
	struct hdac_device *hdev = &hda_pvt->codec->core;
	struct hda_codec *hcodec = hda_pvt->codec;
	struct hda_codec_driver *driver = hda_codec_to_driver(hcodec);
	struct hdac_ext_link *hlink;
	int ret;

	hlink = snd_hdac_ext_bus_get_hlink_by_name(hdev->bus, dev_name(&hdev->dev));
	if (!hlink) {
		dev_err(&hdev->dev, "%s: hdac link not found\n", __func__);
		return -EIO;
	}

	snd_hdac_ext_bus_link_get(hdev->bus, hlink);

	/*
	 * Ensure any HDA display is powered at codec probe.
	 * After snd_hda_codec_device_new(), display power is
	 * managed by runtime PM.
	 */
	if (hda_pvt->need_display_power)
		snd_hdac_display_power(hdev->bus,
				       HDA_CODEC_IDX_CONTROLLER, true);

	ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card,
				       hdev->addr, hcodec, true);
	if (ret < 0) {
		dev_err(&hdev->dev, "%s: failed to create hda codec %d\n", __func__, ret);
		goto error_no_pm;
	}

#ifdef CONFIG_SND_HDA_PATCH_LOADER
	if (loadable_patch[hda_pvt->dev_index] && *loadable_patch[hda_pvt->dev_index]) {
		const struct firmware *fw;

		dev_info(&hdev->dev, "Applying patch firmware '%s'\n",
			 loadable_patch[hda_pvt->dev_index]);
		ret = request_firmware(&fw, loadable_patch[hda_pvt->dev_index],
				       &hdev->dev);
		if (ret < 0)
			goto error_no_pm;
		if (fw) {
			ret = snd_hda_load_patch(hcodec->bus, fw->size, fw->data);
			if (ret < 0) {
				dev_err(&hdev->dev, "%s: failed to load hda patch %d\n", __func__, ret);
				goto error_no_pm;
			}
			release_firmware(fw);
		}
	}
#endif
	/*
	 * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver
	 * hda_codec.c will check this flag to determine if unregister
	 * device is needed.
	 */
	hdev->type = HDA_DEV_ASOC;

	/*
	 * snd_hda_codec_device_new decrements the usage count so call get pm
	 * else the device will be powered off
	 */

Annotation

Implementation Notes