一、以Amlogic V918D为例,介绍驱动中如何注册SOC DAI。
SOC DAI可以分为CPU DAI和CODEC DAI,一般声卡的一个DAI LINK中会包含一个CPU DAI和CODEC DAI。
以下面截取的dts中声卡的一个dai link为例:
auge_sound {
compatible = "amlogic, auge-sound-card";
aml-audio-card,name = "AML-AUGESOUND";
...
status = "okay";
aml-audio-card,dai-link@0 {
...
tdmacpu: cpu {
sound-dai = <&tdma>;
...
};
tdmacodec: codec {
sound-dai = <&dummy_codec>;
};
};
...
};
可以看出dai-link@0中包含的cpu dai是<&tdma>,codec dai是<&dummy_codec>。这两个也都是独立的platform device,可以分别找到其节点定义:
根据compatible字段在代码中找到对应的driver:
接下来将分别分析其probe函数。
二、CPU DAI的probe函数
static int aml_tdm_platform_probe(struct platform_device *pdev)
{
/* 设备树中的参数解析,省略不说 */
...
/* 注册component,在前一篇文章中介绍了该函数,实现的是:
1. 创建一个component并加入到全局的component_list中;
2. 将第2个参数即component_driver挂到component的driver成员上;
3. 创建一个soc dai并将其list成员加入到component的dai_list链表中;
4. 将第3个参数即dai_driver挂到soc dai的driver成员上;*/
ret = devm_snd_soc_register_component(dev, &aml_tdm_component,
&aml_tdm_dai[p_tdm->id], 1);
...
}
注册后的component结构示意图:
这里可能会有两个问题:
1、能看到component的driver和cpu dai的driver中都注册了".ops"回调,这些回调在什么时候会被调用呢?
2、cpu dai的driver中有".probe"回调即:aml_dai_tdm_probe,它又是在什么时候被调用呢?
三、CODEC DAI的probe函数
static int dummy_codec_platform_probe(struct platform_device *pdev)
{
...
/* 注册component,实现的是:
1. 创建一个component并加入到全局的component_list中;
2. 将第2个参数即component_driver挂到component的driver成员上;
3. 创建一个soc dai并将其list成员加入到component的dai_list链表中;
4. 将第3个参数即dai_driver挂到soc dai的driver成员上;*/
ret = devm_snd_soc_register_component(&pdev->dev,
&soc_codec_dev_dummy_codec,
&dummy_codec_dai, 1);
...
}
注册后的component结构示意图:
四、结束
1、以上就是注册SOC DAI(CPU DAI和CODEC DAI)的步骤。
2、所谓的SOC DAI,其实就是一个platform device,有其对应的platform driver,并在driver中注册对应的component结构体。
3、在更早一点的kernel版本中,是会有注册codec的接口的(snd_soc_register_codec),但是不知道从什么时候开始,好像都用devm_snd_soc_register_component了,以component的代替了codec。
4、那么component可以看做是用来承载SOC DAI的一个抽象部件,不管是CPU DAI还是CODEC DAI,都通过component_list串联在了一起。那么component和声卡以及pcm device有是什么关系呢?
5、在我理解看来,dai-link和pcm device一一对应,即有多少个dai-link就会产生多少个pcm device,所以,是pcm device是component的集合。而声卡又包含了很多dai-link,所以声卡又是pcm device的集合。