Audio技术积累
ALSA内核框架分成三个部分,Platform、Codec、和Machine。Platform 是cpu_dai 、Codec 是 codec_dai 、然后通过Machine 里面的dai_link 把两个关联起来。dai口就是音频数据传输的接口,在软件上用dai这个词来描述,在硬件上可以是pcm接口,可以是i2c接口、也可以是其他的音频传输接口。
Native ALSA Application:tinyplay/tinycap/tinymix,这些用户程序直接调用 alsa 用户库接口来实现放音、录音、控制。
ALSA Library API:alsa 用户库接口,常见有 tinyalsa、alsa-lib。
ALSA CORE:alsa 核心层,向上提供逻辑设备(PCM/CTL/MIDI/TIMER/…)系统调用,向下驱动硬件设备(Machine/I2S/DMA/CODEC)。
ASoC CORE:asoc 是建立在标准 alsa core 基础上,为了更好支持嵌入式系统和应用于移动设备的音频 codec 的一套软件体系。ASoC,ALSA System on Chip。
Hardware Driver:音频硬件设备驱动,由三大部分组成,分别是 Machine、Platform、Codec。
Platform:Platform驱动程序包括音频DMA引擎驱动程序,数字音频接口(DAI)驱动程序(例如I2S,AC97,PCM)以及该平台的任何音频DSP驱动程序。
cpu dai:在嵌入式系统里面通常指CPU的I2S、PCM总线控制器,负责将音频数据从I2S tx FIFO搬运到CODEC(回放的情形,录制则方向相反)。cpu_dai通过snd_soc_register_dai()来注册。
注:DAI是Digital Audio Interface的缩写,分为cpu_dai和codec_dai,这两者通过I2S/PCM总线连接;
AIF是Audio Interface的缩写,一般分为I2S和PCM接口。
pcm dma:负责将dmabuffer中的音频数据搬运到I2S tx FIFO,这部分的逻辑比较复杂,以下几篇会对它详细阐述。音频dma驱动通过snd_soc_register_platform()来注册。值得留意的是:某些情形下是不需要dma操作的,比如Modem和CODEC直连,因为Modem本身已经把数据送到PCM FIFO了,这时只需启动codec_dai接收数据即可;该情形下,Machine驱动dai_link中需要指定.platform_name = “snd-soc-dummy”, 这是虚拟出来的platform驱动,实现见sound/soc/soc-utils.c。
Codec:Codec驱动程序独立于平台,包含音频控件,音频接口功能,编解码器DAPM定义和编解码器IO功能。如果需要,该类可扩展至BT,FM和MODEM IC。Codec类驱动程序应该是可以在任何体系结构和机器上运行的通用代码。
对于Playback来说,userspace送过来的PCM数据是经过抽样量化出来的数字信号,在codec经过DAC转换成模拟信号送到外放耳机输出,这样我们就可以听到声音了。Codec字面意思是编解码器,但芯片里面的功能部件很多,常见的有AIF、DAC、ADC、Mixer、PGA、Line-in、Line-out,有些高端的codec芯片还有EQ、DSP、SRC、DRC、AGC、Echo canceller、Noise suppression等部件。
注:DAPM,Dynamic Audio Power Management,动态音频电源管理,为移动Linux设备设计,使得音频系统任何时候都工作在最低功耗状态。
Machine:Machine 驱动程序充当描述和绑定其他组件驱动程序以形成ALSA“声卡设备”的粘合剂。它可以处理任何机器特定的控制和机器级音频事件(例如,在播放开始时打开放大器)。
Machine 可以理解为对开发板的抽象,开发板可能包括多个声卡,对应Machine部分包含多个link。
Machine 指某一款机器,它把cpu_dai、codec_dai、modem_dai各个音频接口通过定义dai_link链结起来,然后注册snd_soc_card。和上面两个不一样,Platform和CODEC驱动一般是可以重用的,而Machine有它特定的硬件特性,几乎是不可重用的。所谓的硬件特性指:DAIs之间的链结;通过某个GPIO打开Amplifier;通过某个GPIO检测耳机插拔;使用某个时钟如MCLK/External OSC作为I2S、CODEC模块的基准时钟源等等。
dai_link:machine驱动中定义的音频数据链路,它指定用到的cpu_dai、codec_dai、platform、codec分别是什么。
3. PCM数据流
对于回放(Playback)的情形,PCM数据流向大致如下:
对于Linux来说,由于分为 user space 和kernel space,而且两者之间不能随便互相访问。因此用户如果播放音频,则需要调用copy_from_user()将用户数据从user space拷贝到kernel space (DMA Buffer)。
DMA 负责将DMA Buffer中的音频数据搬运到I2S TX FIFO。
通过I2S总线,将音频数据传送到Codec。
Codec内部经过DAC转换,将模拟信号传到扬声器SPK(头戴式耳机HP、耳塞式耳机Earp)
对于录音(Capture)的情形,PCM数据流向是方向如下:
platform驱动: platform驱动为cpu部分的控制代码,其抽象出两个结构体snd_soc_dai_driver和snd_soc_platform_driver;
codec驱动: codec驱动是编解码器部分的控制代码,其抽象出两个结构体分别为snd_soc_dai_driver和snd_soc_codec_driver;
machine驱动: machine驱动是控制管理platform和codec之间的连接匹配,管理控件(controls)、部件(widgets)以及routes,其抽象的结构体为snd_soc_card。