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个重要结构体的链表头
[cpp] static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
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声卡设备
[cpp] 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;
};
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
[cpp] 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;
};
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中定义了一个平台设备驱动
[cpp] static struct platform_driver soc_driver = {
.driver = {
.name = "soc-audio",
.owner = THIS_MODULE,
.pm = &soc_pm_ops,
},
.probe = soc_probe,
.remove = soc_remove,
};
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且设备名必须
补充:软件开发 , C++ ,