alsa音频架构2-ASoc

设计ASoc的目的是为嵌入式系统片上处理器音频单元或外部的音频解码芯片提供更好的ALSA支持

ASoC有多个组件组成snd_soc_platform/snd_soc_codec/snd_soc_dai/snd_soc_card以及ALSA的snd_pcm

snd_soc_platform和snd_soc_codec就行平台与设备的关系缺一不可,snd_soc_card是它们实例化的一个对象

snd_soc_dai是snd_soc_platform和snd_soc_codec的数字音频接口,snd_soc_codec的dai为codec_dai,snd_soc_platform的dai为cpu_dai

snd_pcm是snd_soc_card实例化后注册的声卡类型

在sound/soc/soc-core.c中初始化了上面提到的4个重要结构体的链表头

static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);

 

第九部分 soc声卡设备snd_soc_card

1.soc声卡设备

struct snd_soc_card {
	const char *name;	//设备名
	struct device *dev;	//设备文件
	struct snd_card *snd_card;	//所属声卡
	struct module *owner;
	struct list_head list;
	struct mutex mutex;
	bool instantiated;	//实例化标志
	int (*probe)(struct platform_device *pdev);
	int (*remove)(struct platform_device *pdev);
	/* the pre and post PM functions are used to do any PM work before and after the codec and DAI's do any PM work. */
	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
	int (*resume_pre)(struct platform_device *pdev);
	int (*resume_post)(struct platform_device *pdev);
	/* callbacks */
	int (*set_bias_level)(struct snd_soc_card *,enum snd_soc_bias_level level);
	long pmdown_time;
	/* CPU <--> Codec DAI links  */
	struct snd_soc_dai_link *dai_link;	//dai link
	int num_links;
	struct snd_soc_pcm_runtime *rtd;
	int num_rtd;
	struct work_struct deferred_resume_work;
	/* lists of probed devices belonging to this card */
	struct list_head codec_dev_list;
	struct list_head platform_dev_list;
	struct list_head dai_dev_list;
};

snd_soc_card包含了snd_card,可以理解为声卡驱动的一个封装.

2.soc pcm

struct snd_soc_pcm_runtime  {
	struct device dev;			//设备文件
	struct snd_soc_card *card;	//soc声卡设备
	struct snd_soc_dai_link *dai_link;	//dai link
	unsigned int complete:1;
	unsigned int dev_registered:1;
	/* Symmetry data - only valid if symmetry is being enforced */
	unsigned int rate;
	long pmdown_time;
	/* runtime devices */
	struct snd_pcm *pcm;	//pcm结构体
	struct snd_soc_codec *codec;	//codec设备
	struct snd_soc_platform *platform;	//soc平台设备
	struct snd_soc_dai *codec_dai;	//dai设备 codec
	struct snd_soc_dai *cpu_dai;	//dai设备 cpu
	struct delayed_work delayed_work;
};

snd_soc_pcm_runtime结构体中包含一个snd_pcm结构体,所以可以认为它是pcm声卡设备的一个封装,其次他也是Asoc各个组件的一个关系网点

3.soc声卡设备的匹配过程

在sound/soc/soc-core.c中定义了一个平台设备驱动

static struct platform_driver soc_driver = {
	.driver		= {
		.name		= "soc-audio",
		.owner		= THIS_MODULE,
		.pm		= &soc_pm_ops,
	},
	.probe		= soc_probe,
	.remove		= soc_remove,
};

我们知道平台设备驱动和平台设备的匹配靠.driver.name名字,也就是在另一处代码中必须定义了平台设备platform_device且设备名必须为"soc-audio",

这样平台设备和驱动才能匹配,才会调用平台驱动的probe方法,既soc_probe

所以一般声卡的驱动程序中会按以下格式设计平台设备

int ret;
static struct platform_device *xxx;
xxx=platform_device_alloc("soc-audio", 0);	//分配平台驱动
//平台资源的添加
ret=platform_device_add(xxx);	//添加平台设备
if(ret)
	platform_device_put(xxx);	//增加引用计数

 

4.匹配调用的probe方法soc_probe

static int soc_probe(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);	//获取soc声卡设备
	int ret = 0;
	/* Bodge while we unpick instantiation */
	card->dev = &pdev->dev;
	INIT_LIST_HEAD(&card->dai_dev_list);		//初始化dai_dev_list链表
	INIT_LIST_HEAD(&card->codec_dev_list);		//初始化codec_dev_list链表
	INIT_LIST_HEAD(&card->platform_dev_list);	//初始化platform_dev_list链表
	ret = snd_soc_register_card(card);	//注册soc声卡设备
	if (ret != 0) {
		dev_err(&pdev->dev, "Failed to register card\n");
		return ret;
	}
	return 0;
}

这里调用了snd_soc_register_card注册了soc声卡设备

5.注册soc声卡设备

static int snd_soc_register_card(struct snd_soc_card *card)
{
	int i;
	if (!card->name || !card->dev)
		return -EINVAL;
	card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links,GFP_KERNEL);	//分配多个soc pcm内存
	if (card->rtd == NULL)
		return -ENOMEM;
	for (i = 0; i < card->num_links; i++)
		card->rtd[i].dai_link = &card->dai_link[i];	//dai link数组
	INIT_LIST_HEAD(&card->list);	
	card->instantiated = 0;	//soc声卡实例化标志设置为0
	mutex_init(&card->mutex);

	mutex_lock(&client_mutex);
	list_add(&card->list, &card_list);	//添加soc声卡到全局card_list链表
	snd_soc_instantiate_cards();	//实例化所有soc声卡
	mutex_unlock(&client_mutex);
	dev_dbg(card->dev, "Registered card '%s'\n", card->name);
	return 0;
}




最终调用snd_soc_instantiate_cards实例化所有声卡

 

第十部分 soc平台 snd_soc_platform

1.soc平台设备

struct snd_soc_platform {
	const char *name;	//设备名
	int id;	//设备id
	struct device *dev;	//设备文件
	struct snd_soc_platform_driver *driver;	//soc平台驱动
	unsigned int suspended:1; /* platform is suspended */
	unsigned int probed:1;	//"probe"标志
	struct snd_soc_card *card;	//soc声卡设备
	struct list_head list;
	struct list_head card_list;
};

2.soc平台驱动

struct snd_soc_platform_driver {
	int (*probe)(struct snd_soc_platform *);
	int (*remove)(struct snd_soc_platform *);
	int (*suspend)(struct snd_soc_dai *dai);
	int (*resume)(struct snd_soc_dai *dai);
	/* pcm creation and destruction */
	int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,struct snd_pcm *);
	void (*pcm_free)(struct snd_pcm *);
	snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,struct snd_soc_dai *);
	/* platform stream ops */
	struct snd_pcm_ops *ops;
};

3.注册soc平台驱动

int snd_soc_register_platform(struct device *dev,struct snd_soc_platform_driver *platform_drv)
{
	struct snd_soc_platform *platform;	//声明soc平台设备
	dev_dbg(dev, "platform register %s\n", dev_name(dev));
	platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);	//分配soc平台内存
	if (platform == NULL)
			return -ENOMEM;
	/* create platform component name */
	platform->name = fmt_single_name(dev, &platform->id);	//设置soc平台设备名及id
	if (platform->name == NULL) {
		kfree(platform);
		return -ENOMEM;
	}
	platform->dev = dev;	//设备文件
	platform->driver = platform_drv;	//捆绑soc平台设备驱动
	mutex_lock(&client_mutex);
	list_add(&platform->list, &platform_list);	//添加到全局platform_list链表
	snd_soc_instantiate_cards();	//实例化所有soc声卡设备
	mutex_unlock(&client_mutex);
	pr_debug("Registered platform '%s'\n", platform->name);
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_register_platform);

注册soc平台驱动需要驱动自己去调用snd_soc_register_platform注册.


最终调用snd_soc_instantiate_cards实例化所有声卡

4.注销soc平台驱动

void snd_
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: alsa-driver-1.2.7.tar.bz2 是一个音频驱动程序的压缩包。Alsa是Advanced Linux Sound Architecture(高级Linux音频架构)的缩写。它是一个开源的音频驱动程序,为Linux操作系统提供音频功能。该驱动程序被设计用来支持各种声音卡、音频控制器和其他音频设备。 alsa-driver-1.2.7.tar.bz2 是Alsa驱动程序的源代码压缩包。通过将其解压缩,可以获取驱动程序的源代码文件。 要安装alsa-driver-1.2.7.tar.bz2,首先需要在Linux系统中安装必要的编译工具和开发库。然后,您可以使用终端进入解压缩后的文件夹,并运行一系列的命令以编译和安装该驱动程序。 安装成功后,您可以配置和管理硬件设备的音频设置,如音量控制、声道配置和输入输出设备的选择。Alsa驱动程序提供了用于控制和操作音频功能的命令行工具和应用程序接口(API),允许开发者和系统管理员对音频设备进行配置和调整。 总之,alsa-driver-1.2.7.tar.bz2 是一个允许在Linux操作系统上实现音频功能的驱动程序源代码。通过安装和配置该驱动程序,您可以享受到高质量的音频体验,并根据需要进行各种音频设置和调整。 ### 回答2: alsa-driver-1.2.7.tar.bz2是一个用于Linux操作系统的音频驱动程序。ALSA代表高级Linux声音体系结构(Advanced Linux Sound Architecture),它是Linux操作系统中最常用的音频架构之一。 该驱动程序文件是.tar.bz2格式的压缩文件。.tar表示该文件是一个压缩的归档文件,而.bz2表示该文件使用bzip2压缩算法进行压缩。 该驱动程序的版本号为1.2.7,表示这是alsa-driver的第1.2.7个稳定版本。每个新版本通常包含修复漏洞、改进性能、增加新功能等更新。 安装alsa-driver-1.2.7.tar.bz2需要进行以下步骤: 1. 解压文件:使用tar命令解压.tar.bz2文件,例如使用命令tar -xjf alsa-driver-1.2.7.tar.bz2。 2. 进入解压后的目录:cd alsa-driver-1.2.7。 3. 配置驱动程序:运行./configure命令,该命令会检查系统环境并配置驱动程序。 4. 编译驱动程序:运行make命令,该命令会编译驱动程序。 5. 安装驱动程序:运行make install命令,该命令会将驱动程序安装到系统中。 6. 配置系统:根据具体需要,可能需要进行一些额外的配置,例如修改配置文件或加载驱动程序。 安装完成后,alsa-driver-1.2.7将提供音频驱动程序,使得Linux系统能够正常支持音频设备。这将使用户能够播放音乐、观看视频、进行语音通话等各种音频相关的操作。 总之,alsa-driver-1.2.7.tar.bz2是一个用于Linux操作系统的音频驱动程序文件,安装它可以使得系统支持音频设备,并提供各种音频功能。 ### 回答3: alsa-driver-1.2.7.tar.bz2是一个压缩文件,其中包含了ALSA(Advanced Linux Sound Architecture)音频驱动的源代码和相关文件。它是用于Linux操作系统的音频驱动程序。 ALSA是Linux内核中的一种声音处理架构,旨在提供细致、稳定且高质量的音频处理和音频设备驱动。alsa-driver-1.2.7.tar.bz2是ALSA音频驱动的一个版本。 该压缩文件中的源代码可以用于编译和安装ALSA音频驱动程序。首先,需要解压缩该文件。然后,通过进入解压缩后的目录,使用特定的命令和选项进行编译和安装。编译和安装成功后,系统将具有新的ALSA音频驱动程序,以支持各种音频设备。 ALSA音频驱动是Linux系统中实现音频功能的关键组件之一。它负责与硬件设备进行通信,并提供音频输入和输出的功能。安装最新版本的ALSA驱动可以提升音频系统的性能和稳定性,同时支持更多的音频设备和功能。 总而言之,alsa-driver-1.2.7.tar.bz2是一个压缩文件,其中包含了ALSA音频驱动的源代码和相关文件,可用于编译和安装ALSA音频驱动程序,以提供高质量的音频功能和支持各种音频设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值