这篇文章我是转载自http://blog.csdn.net/sunruichen/article/details/8568273,UML图画得相当不错。
(1)CODEC驱动:由内核源代码sound/soc/codecs/uda134x.c实现,功能如下:
A: snd_soc_codec 结构体是对CODEC本身I/O控制以及动态音频电源管理(Dynamic Audio Power Management,DAPM)的描述。它描述I2C、SPI或AC’97如何读写CODEC寄存器并容纳DAPM链表,核心成员为read()、write()、hw_write()、hw_read()、dapm_widgets、dapm_paths等。
B: CODEC DAI(Digital Audio Interfaces)和配置PCM,由结构体snd_soc_dai来描述,形容playback、capture的属性以及DAI接口的操作。
C: 描述CODEC的时钟、PLL以及各式设置,主要包括set_sysclk()、set_pll()、set_clkdiv()、set_fmt()等成员函数。
D:宏来描述CODEC的mixer控制,这组宏可以方便地将mixer名和对应的寄存器进行绑定
(2)平台驱动:由内核源代码sound/soc/s3c24xx/s3c24xx-i2s.c实现CPU端的DAI驱动,由sound/soc/s3c24xx/s3c24xx_pcm.c实现CPU端的DMA驱动
首先,在ASoC平台驱动部分,同样存在着CODEC驱动中的snd_soc_dai、snd_soc_dai_ops、snd_soc_ops(这个结构体在linux2.6.32.2中已经交给snd_soc_dai_ops结构体来描述)这3个结构体的实例用于描述DAI和DAI上操作,不过不同的是,在平台驱动中,它们只描述CPU相关的部分而不描述CODEC。除此之外,在ASoC平台驱动中,必须实现完整的DMA驱动,即传统ALSA的snd_pcm_ops结构体成员函数trigger()、pointer()等。因此ASoC平台驱动通常由DAI和DMA两部分组成:
snd_soc_dai、snd_soc_dai_ops、snd_soc_ops这3个结构体和在CODEC驱动中一样,只是在这里只描述CPU相关的部分,对CPU中设计到的寄存器进行设置;
(3)板驱动:由内核源代码sound/soc/s3c24xx/s3c24xx_uda134x.c实现,它将第一部分和第二部分进行绑定。这个绑定用数据结构snd_soc_dai_link描述.
(4) 在以上三部分之上的是ASoC核心层,由内核源代码中的sound/soc/soc-core.c实现,查看其源代码发现它完全是一个传统的ALSA驱动。
ASoC被分为Machine(link),Platfor(cpu)m和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口(DAI)把音频数据传送给Codec进行处理,最终由Codec输出驱动耳机或者是喇叭的音信信号。
machine文件的名字一般是platform_codec这样的形式,它主要用来连接platform和codec,缺少了它的platform和codec是工作不了的。
ASoC有把Platform(CPU)驱动分为两个部分:snd_soc_platform_driver和snd_soc_dai_driver。其中,platform_driver负责管理音频数据,把音频数据通过dma或其他操作传送至cpu dai中,dai_driver则主要完成cpu一侧的dai的参数配置,同时也会通过一定的途径把必要的dma等参数与snd_soc_platform_driver进行交互。
Codec驱动的代码要做到平台无关性,要使得Machine(link)驱动能够使用该Codec,Codec驱动的首要任务就是确定snd_soc_codec和snd_soc_dai的实例,并把它们注册到系统中,注册后的codec和dai才能为Machine驱动所用。
上面为sound的执行时序图(非常重要) 另外,在linux3.0中将platform(link)改为snd_soc_card这个数据结构。
从上面来看,音频完全和上节所讲的SD卡的驱动架构(card-core-host)一样,也是linux通用的驱动架构分层方式,四层:
第一层:core层只关心软件功能实现,不考虑CPU 和具体的外设,为最上层.
第二层:CPU层由各平台厂商提供代码.
第三层:cpu和外设适配层.
第四层:具体的外设驱动,由外设厂家提供代码.
(Android的分层完全借签了linux的分层架构).
理解了上述原理,不管的是USB芯片,还是ac97等等其它芯片,原理都是一样的,core不变,cpu针对不同类型的外设有处理,不同外设驱动由厂家提供,再加不同的link层来链接cpu和外设. 无论哪个平台何种外设驱动都是一样的,不同的可能由于特别简单的驱动,可能会将core之下的三层合二为一,或合三为一.
声卡驱动到此为至,网上有个系列声卡文章<Linux ALSA声卡驱动之*>共八篇写得很详细,建议做音频驱动的一定要看一下。网址:http://blog.csdn.net/droidphone/article/details/6271122
综上所述,所有做linux开发移植的,第一件事,就是要确定分层架构,规划好每层的代码放在哪里,已有的代码是哪些,针对自已的cpu和外设(以及特有的软件功能core),需要添加的代码有哪些。