sound/soc/sdw_utils/soc_sdw_utils.c

Source file repositories/reference/linux-study-clean/sound/soc/sdw_utils/soc_sdw_utils.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sdw_utils/soc_sdw_utils.c
Extension
.c
Size
62198 bytes
Lines
2167
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 (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
				*dai_index = j;
				return &codec_info_list[i];
			}
		}
	}

	return NULL;
}
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, "SND_SOC_SDW_UTILS");

static int asoc_sdw_find_codec_info_dai_index(const struct asoc_sdw_codec_info *codec_info,
					      const char *dai_name)
{
	int i;

	for (i = 0; i < codec_info->dai_num; i++) {
		if (!strcmp(codec_info->dais[i].dai_name, dai_name))
			return i;
	}

	return -ENOENT;
}

int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_card *card = rtd->card;
	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
	struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
	struct asoc_sdw_codec_info *codec_info;
	struct snd_soc_dai *dai;
	struct sdw_slave *sdw_peripheral;
	const char *spk_components = NULL;
	int dai_index;
	int ret;
	int i;

	for_each_rtd_codec_dais(rtd, i, dai) {
		if (is_sdw_slave(dai->component->dev))
			sdw_peripheral = dev_to_sdw_dev(dai->component->dev);
		else if (dai->component->dev->parent && is_sdw_slave(dai->component->dev->parent))
			sdw_peripheral = dev_to_sdw_dev(dai->component->dev->parent);
		else
			continue;

		codec_info = asoc_sdw_find_codec_info_sdw_id(&sdw_peripheral->id);
		if (!codec_info)
			return -EINVAL;

		dai_index = asoc_sdw_find_codec_info_dai_index(codec_info, dai->name);
		WARN_ON(dai_index < 0);

		/*
		 * A codec dai can be connected to different dai links for capture and playback,
		 * but we only need to call the rtd_init function once.
		 * The rtd_init for each codec dai is independent. So, the order of rtd_init
		 * doesn't matter.
		 */
		if (codec_info->dais[dai_index].rtd_init_done)
			continue;

		dev_dbg(card->dev, "%#x/%s initializing for %s/%s\n",
			codec_info->part_id, codec_info->dais[dai_index].dai_name,
			dai->component->name, dai->name);

		/*
		 * Add card controls and dapm widgets for the first codec dai.
		 * The controls and widgets will be used for all codec dais.
		 */

		if (i > 0)
			goto skip_add_controls_widgets;

		if (codec_info->dais[dai_index].controls) {
			ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
							codec_info->dais[dai_index].num_controls);
			if (ret) {
				dev_err(card->dev, "%#x-%#x controls addition failed: %d\n",
					codec_info->vendor_id, codec_info->part_id, ret);
				return ret;
			}
		}
		if (codec_info->dais[dai_index].widgets) {
			ret = snd_soc_dapm_new_controls(dapm,
							codec_info->dais[dai_index].widgets,
							codec_info->dais[dai_index].num_widgets);
			if (ret) {
				dev_err(card->dev, "%#x-%#x widgets addition failed: %d\n",
					codec_info->vendor_id, codec_info->part_id, ret);
				return ret;

Annotation

Implementation Notes