大家好,欢迎来到IT知识分享网。
Linux kernel版本:3.4.2
Overview
ASoC主要由3部分组成:
(1)Codec驱动,这一部分只关系Codec本身,与CPU相关的特性不由此部分操作
(2)平台驱动,这一部分只关心CPU本身,不关系Codec,它主要处理了两个问题:DMA引擎和SoC解除的PCM、IIS或AC’97数字接口控制。
(3)板驱动,这一部分将平台驱动和Codec驱动绑定在一起,描述了板一级的硬件特征
下面以实例来分析函数的调用过程:
machine: sound\soc\samsung\s3c24xx_uda134x.c platform: sound\soc\samsung\s3c24xx-i2s.c codec: sound\soc\codecs\uda134x.c
抓住小尾巴dai_link:
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", };
Platform
CPU DAI
.cpu_dai_name = "s3c24xx-iis", // 2440(CPU)的哪个DAI接口
下面是搜到的"s3c24xx-iis"
信息,有platform_driver和platform_device,匹配后会执行driver的probe函数:
.probe = s3c24xx_iis_dev_probe
,在注册时会把DMA的file_operation操作函数集注册到soc-core中。
linux-3.4.2\sound\soc\samsung\s3c24xx-i2s.c
s3c24xx_iis_dev_probe(struct platform_device *pdev) snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);//Register a DAI with the ASoC core list_add(&dai->list, &dai_list); //把cpu dai添加到dai_list中,在snd_soc_instantiate_cards中会去遍历dai_list
CPU DMA
.platform_name= "samsung-audio", // 2440(CPU)的哪个DMA驱动程序
下面是搜到的"samsung-audio"
信息,有platform_driver和platform_device,匹配后会执行driver的probe函数:
.probe = samsung_asoc_platform_probe
,在注册时会把DMA的file_operation操作函数集注册到soc-core中。
linux-3.4.2\sound\soc\samsung\dma.c
samsung_asoc_platform_probe(struct platform_device *pdev) snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform); list_add(&platform->list, &platform_list);
套路和cpu dai是一样的,在snd_soc_register_platform()函数中把platform->list
加到platform_list
中,然后在snd_soc_instantiate_cards()
中遍历platform_list
注册设备。
总结: 通过machine中的snd_soc_dai_link
中的platform_name和cpu_dai_name分别查找平台的dma设备驱动和cpu侧的dai驱动。最终会将这dai保存到component->dai_list中,platform保存到platform_list当中。然后将component放入到component_list链表中。这些数据会在Machine代码的开始过程中进行匹配操作。
Codec
codec: sound\soc\codecs\uda134x.c
sound\soc\codecs\uda134x.c uda134x_codec_probe(struct platform_device *pdev) snd_soc_register_codec(&pdev->dev,&soc_codec_dev_uda134x, &uda134x_dai, 1); -->snd_soc_instantiate_cards() list_add(&codec->list, &codec_list); snd_soc_register_dais(dev, dai_drv, num_dai); list_add(&dai->list, &dai_list);
Mechine
mechine担负着定义dai_link结构体,注册逻辑设备的神圣使命。在Asoc结构中,声卡的注册过程如下:
devm_snd_soc_register_card --> snd_soc_register_card --> ①soc_init_dai_link ②snd_soc_instantiate_card-->③snd_card_register();
当codec、dai、platform的device name和driver name匹配时,就会执行对应Driver的probe()函数。
在machine: sound\soc\samsung\s3c24xx_uda134x.c
中,mechine的platform_driver和platform_device名字匹配后就会执行Driver的probe()函数。
Mechine中向Linux平台设备总线注册名为“soc-audio” 的设备
该函数里的Platform 指的是Linux设备总线模型中的概念呦! static int s3c24xx_uda134x_probe(struct platform_device *pdev) {
// 为snd soc card申请一个名为"soc-audio"的platform_device结构体 s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1); // 把snd_soc_card结构体作为私有数据填充到platform_device结构体中; platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x); // 把snd soc card "soc-audio"注册到platform设备总线上。 ret = platform_device_add(s3c24xx_uda134x_snd_device); }
对应的”soc-audio” platform_driver在soc-core.c (sound\soc)z中定义:
/* ASoC platform driver */ static struct platform_driver soc_driver = {
.driver = {
.name = "soc-audio", .owner = THIS_MODULE, .pm = &snd_soc_pm_ops, }, .probe = soc_probe, .remove = soc_remove, }; // 在其入口函数中将结构体注册进platform_driver中 static int __init snd_soc_init(void) {
return platform_driver_register(&soc_driver); } module_init(snd_soc_init);
当“soc-audio”的Driver和Device匹配后,会执行sound\soc\soc-core.c-->struct soc_driver.probe = soc_probe()
函数。
/* probes a new socdev */ static int soc_probe(struct platform_device *pdev) {
// 在machine: sound\soc\samsung\s3c24xx_uda134x.c中在s3c24xx_uda134x_probe()中 // 已经在把snd_soc_card结构体填充到了device的私有数据中,这里再取出来用来向内核注册Driver struct snd_soc_card *card = platform_get_drvdata(pdev); /* Bodge while we unpick instantiation */ card->dev = &pdev->dev; // 向Asoc core注册声卡设备 ret = snd_soc_register_card(card); --->>> snd_soc_instantiate_card() }
下面看下函数调用
snd_soc_register_card(struct snd_soc_card *card) snd_soc_instantiate_cards(void) soc_bind_dai_link(card, i);//从dai_list中遍历cpu dai,codec dai snd_card_create(...., card->owner, 0, &card->snd_card); /* 下面开始执行一些probe函数,比如codec, dai, platform(dma)等file_operation中的结构体 */ card->probe(card); soc_probe_dai_link(card, i, order); snd_card_register(card->snd_card);
在ALSA时,我们分析过这个函数,这样就完美的和ALSA接轨了。在snd_card_register()
向内核注册逻辑设备。
/ * snd_card_register - register the soundcard * @card: soundcard structure * * This function registers all the devices assigned to the soundcard. * Until calling this, the ALSA control interface is blocked from the * external accesses. Thus, you should call this function at the end * of the initialization of the card. * * Returns zero otherwise a negative error code if the registration failed. */ int snd_card_register(struct snd_card *card)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/157908.html