ASOC框架(二)
前言
在前面ASOC框架(一)我们知道ASOC被分为Machine,Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,ASoC的一切都从Machine驱动开始,包括声卡的注册,绑定Platform和Codec驱动等等,我们之前说过写一个ALSA声卡驱动的步骤有如下三步:
1 . snd_card_create
2 . 初始化:创建逻辑设备 snd_pcm_new
3 . snd_card_register
我们说过ASOC已经是对ALSA的封装,所以以上步骤我们可以不用自己去做,ASOC帮我们做好了,我们往下看
代码分析
1.platform
1.1
s3c24xx-i2s.c : 把s3c24xx_i2s_dai放入链表dai_list, .name = "s3c24xx-iis",
s3c24xx_iis_dev_probe
snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
list_add(&dai->list, &dai_list);
1.2
sound/soc/samsung/dma.c:把samsung_asoc_platform放入了链表platform_list, .name = "samsung-audio",
samsung_asoc_platform_probe
snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);
list_add(&platform->list, &platform_list);
2.codec
2.1
uda134x.c
uda134x_codec_probe
snd_soc_register_codec(&pdev->dev,&soc_codec_dev_uda134x, &uda134x_dai, 1);
struct snd_soc_codec *codec;
codec->driver = codec_drv; = &soc_codec_dev_uda134x
snd_soc_register_dais(dev, dai_drv, num_dai); // uda134x_dai
list_add(&dai->list, &dai_list); : 把uda134x_dai放入了链表dai_list
list_add(&codec->list, &codec_list);
上面的注册就形成了下面的链表,我们应该选择哪个DAI,哪个platform,哪个code来作为我们的声卡呢,这就是通过machine部分来决定的,我们下面看到machine部分
machine部分
ASoC把声卡注册为Platform Device,我们以装配有uda134x的一款Samsung的开发板SMDK为例子做说明,我们看到初始化入口soc_probe()
私有数据
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
.name = "UDA134X",
.stream_name = "UDA134X",
.codec_name = "uda134x-codec",
.codec_dai_name = "uda134x-hifi",
.cpu_dai_name = "s3c24xx-iis",
.ops = &s3c24xx_uda134x_ops,
.platform_name = "samsung-audio",
};
该函数获取私有数据,然后注册该私有数据,我们看到snd_soc_register_card函数
int snd_soc_register_card(struct snd_soc_card *card)
{
......
card->rtd = devm_kzalloc(card->dev,
sizeof(struct snd_soc_pcm_runtime) *
(card->num_links + card->num_aux_devs),
GFP_KERNEL);
for (i = 0; i < card->num_links; i++)
card->rtd[i].dai_link = &card->dai_link[i];
list_add(&card->list, &card_list);
snd_soc_instantiate_cards();//实例化声卡
}
我们进去snd_soc_instantiate_cards函数看看
static void snd_soc_instantiate_cards(void)
{
struct snd_soc_card *card;
list_for_each_entry(card, &card_list, list)
snd_soc_instantiate_card(card);
}
我们进去snd_soc_instantiate_card函数看后发现,该函数首先利用card->instantiated来判断该卡是否已经实例化,如果已经实例化则直接返回,否则遍历每一对dai_link,进行codec,platform,dai的绑定工作,在源码里面,CPU这一侧有很多个DAI,在声卡芯片这边有不同的声卡芯片,我们具体要用哪个DAI,哪个声卡,就需要进行绑定工作,根据我们的私有数据中的名字从中找到我们需要绑定的,接着会调用 snd_card_create , snd_pcm_new,snd_card_register