函数snd_soc_register_dais()分析

本文详细介绍了snd_soc_register_dais()函数的工作原理及流程,该函数用于向ASoC core注册数字音频接口(DAI)。文章深入解析了DAI的注册过程,包括内存分配、名称创建、设备初始化等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数snd_soc_register_dais()主要作用是向ASoC core注册DAIs(Digital Audio Interface).

一个codec可能支持多种DAIs(Digital Audio Interface),如AC97,I2S,PCM,最近的项目中,一般只使用I2S。但是,代码中是支持多个DAIs(Digital Audio Interface),函数的第3个参数”count“就是DAIs(Digital Audio Interface)的数目。

下面一起来看看这个函数是如何运行的,

1. 上面我们提到,代码中是支持多个DAIs(Digital Audio Interface),函数的第3个参数”count“就是DAIs(Digital Audio Interface)的数目。函数刚开始就有一个for循环来实现这个功能,

	for (i = 0; i < count; i++) {
2. 下面是为DAIs(Digital Audio Interface)设备的结构体申请内核空间并初始化,

		dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
		if (dai == NULL) {
			ret = -ENOMEM;
			goto err;
		}
3. 下面是为每一个DAIs(Digital Audio Interface)创建一个名称

		/* create DAI component name */
		dai->name = fmt_multiple_name(dev, &dai_drv[i]);
		if (dai->name == NULL) {
			kfree(dai);
			ret = -EINVAL;
			goto err;
		}

4. 下面是对DAIs(Digital Audio Interface)设备结构体的初始化,包括dev/driver/id

		dai->dev = dev;
		dai->driver = &dai_drv[i];
		if (dai->driver->id)
			dai->id = dai->driver->id;
		else
			dai->id = i;
		dai->dapm.dev = dev;
		if (!dai->driver->ops)
			dai->driver->ops = &null_dai_ops;
5. 下面首先从列表(list)获取codec设备,并与DAI(Digital Audio Interface)关联起来,之后把DAI(Digital Audio Interface)也存放到列表中。

		list_for_each_entry(codec, &codec_list, list) {
			if (codec->dev == dev) {
				dev_dbg(dev, "ASoC: Mapped DAI %s to "
					"CODEC %s\n", dai->name, codec->name);
				dai->codec = codec;
				break;
			}
		}

		if (!dai->codec)
			dai->dapm.idle_bias_off = 1;

		list_add(&dai->list, &dai_list);
至此,DAI(Digital Audio  Interface)与codec也已经关联起来。函数snd_soc_register_dais()到此结束。


下面是snd_soc_dai结构体定义,

/*
 * Digital Audio Interface runtime data.
 *
 * Holds runtime data for a DAI.
 */
struct snd_soc_dai {
	const char *name;
	int id;
	struct device *dev;
	void *ac97_pdata;	/* platform_data for the ac97 codec */

	/* driver ops */
	struct snd_soc_dai_driver *driver;

	/* DAI runtime info */
	unsigned int capture_active:1;		/* stream is in use */
	unsigned int playback_active:1;		/* stream is in use */
	unsigned int symmetric_rates:1;
	struct snd_pcm_runtime *runtime;
	unsigned int active;
	unsigned char probed:1;

	struct snd_soc_dapm_widget *playback_widget;
	struct snd_soc_dapm_widget *capture_widget;
	struct snd_soc_dapm_context dapm;

	/* DAI DMA data */
	void *playback_dma_data;
	void *capture_dma_data;

	/* Symmetry data - only valid if symmetry is being enforced */
	unsigned int rate;

	/* parent platform/codec */
	struct snd_soc_platform *platform;
	struct snd_soc_codec *codec;

	struct snd_soc_card *card;

	struct list_head list;
	struct list_head card_list;
};


snd_soc_dai_driver结构体定义如下,

/*
 * Digital Audio Interface Driver.
 *
 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
 * operations and capabilities. Codec and platform drivers will register this
 * structure for every DAI they have.
 *
 * This structure covers the clocking, formating and ALSA operations for each
 * interface.
 */
struct snd_soc_dai_driver {
	/* DAI description */
	const char *name;
	unsigned int id;
	int ac97_control;
	unsigned int base;

	/* DAI driver callbacks */
	int (*probe)(struct snd_soc_dai *dai);
	int (*remove)(struct snd_soc_dai *dai);
	int (*suspend)(struct snd_soc_dai *dai);
	int (*resume)(struct snd_soc_dai *dai);
	/* compress dai */
	bool compress_dai;

	/* ops */
	const struct snd_soc_dai_ops *ops;

	/* DAI capabilities */
	struct snd_soc_pcm_stream capture;
	struct snd_soc_pcm_stream playback;
	unsigned int symmetric_rates:1;

	/* probe ordering - for components with runtime dependencies */
	int probe_order;
	int remove_order;
};







解析这个函数:int snd_soc_register_card(struct snd_soc_card *card) 2717 { 2718 int i, ret; 2719 struct snd_soc_pcm_runtime *rtd; 2720 2721 if (!card->name || !card->dev) 2722 return -EINVAL; 2723 2724 for (i = 0; i < card->num_links; i++) { 2725 struct snd_soc_dai_link *link = &card->dai_link[i]; 2726 2727 ret = soc_init_dai_link(card, link); 2728 if (ret) { 2729 dev_err(card->dev, "ASoC: failed to init link %s\n", 2730 link->name); 2731 return ret; 2732 } 2733 } 2734 2735 dev_set_drvdata(card->dev, card); 2736 2737 snd_soc_initialize_card_lists(card); 2738 2739 INIT_LIST_HEAD(&card->dai_link_list); 2740 card->num_dai_links = 0; 2741 2742 INIT_LIST_HEAD(&card->rtd_list); 2743 card->num_rtd = 0; 2744 2745 INIT_LIST_HEAD(&card->dapm_dirty); 2746 INIT_LIST_HEAD(&card->dobj_list); 2747 card->instantiated = 0; 2748 mutex_init(&card->mutex); 2749 mutex_init(&card->dapm_mutex); 2750 mutex_init(&card->dapm_power_mutex); 2751 2752 ret = snd_soc_instantiate_card(card); 2753 if (ret != 0) 2754 return ret; 2755 2756 /* deactivate pins to sleep state */ 2757 list_for_each_entry(rtd, &card->rtd_list, list) { 2758 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 2759 int j; 2760 2761 for (j = 0; j < rtd->num_codecs; j++) { 2762 struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; 2763 if (!codec_dai->active) 2764 pinctrl_pm_select_sleep_state(codec_dai->dev); 2765 } 2766 2767 if (!cpu_dai->active) 2768 pinctrl_pm_select_sleep_state(cpu_dai->dev); 2769 } 2770 2771 return ret; 2772 } 2773 EXPORT_SYMBOL_GPL(snd_soc_register_card);
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值