1.嵌入式音频系统硬件连接
下图所示的嵌入式设备使用IIS将音频数据发送给编解码器。对编解码器的I/O寄存器的编程通过IIC总线进行。
2.音频体系结构-ALSA
ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构
在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。
3.ALSA设备文件
ALSA驱动核心会创建和管理一些设备节点,比如:
/dev/snd/controlC0: 一个控制结点,(应用程序用它来控制声卡,例如通道选择,音量的控制等)
/dev/snd/pcmC0D0p:用于播放的pcm设备
/dev/snd/pcmC0D0c:用于录音的pcm设备
C0D0代表的是声卡0中的设备0,最后一个c代表capture,最后一个p代表playback。
4.声卡的建立流程
第一步,创建snd_card的一个实例
snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下.
第二步,创建声卡的功能部件(逻辑设备),例如PCM, Mixer等,并将逻辑设备与步骤一创建的声卡绑定
通常, alsa-driver的已经提供了一些常用的部件的创建函数,PCM ---- snd_pcm_new()、CONTROL -- snd_ctl_create()
第三步,将声卡注册进ALSA框架
经过以上的创建步骤之后,声卡的逻辑结构如下图所示:
5.PCM设备的创建
对于一个pcm设备,可以生成两个设备文件,一个用于playback,一个用于capture,代码中也确定了他们的命名规则:
新建一个pcm设备的过程:
Control设备和PCM设备一样,都属于声卡下的逻辑设备。用户空间的应用程序通过alsa-lib访问该Control设备,读取或设置control的状态,从而达到控制音频Codec进行各种Mixer等控制操作。
要自定义一个Control,我们首先要定义3各回调函数:info,get和put。然后,定义一个snd_kcontrol_new结构:
-
static
struct snd_kcontrol_new my_control __devinitdata = {
-
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-
.name =
"PCM Playback Switch",
-
.index =
0,
-
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-
.private_value =
0xffff,
-
.info = my_control_info,
-
.get = my_control_get,
-
.put = my_control_put
-
};
iface字段指出了control的类型
我们需要在我们的驱动程序初始化时主动调用snd_pcm_new()函数创建pcm设备,而control设备则在snd_card_create()内被创建,snd_card_create()通过调用snd_ctl_create()函数创建control设备节点。所以我们无需显式地创建control设备,只要建立声卡,control设备被自动地创建。
7.移动设备中的ALSA(ASoC)
ASoC--ALSA System on Chip ,是为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。ASoC不能单独存在,它建立在标准ALSA驱动之上,必须和标准的ALSA驱动框架相结合才能工作。
在软件层面, ASoC也把嵌入式设备的音频系统同样分为3大部分, Machine, Platform和Codec
Machine驱动:跟单板相关,绑定Platform和Codec驱动,即表明使用的是哪个Platform,哪个CPU DAI、DMA、Codec和Codec DAI。
Platform驱动 :它包含了该SoC平台的音频DMA和音频接口DAI的配置和控制( I2S, PCM等等)
Codec驱动 :它包含了一些音频的控件( Controls),音频接口, DAMP(动态音频电源管理)的定义和某些Codec IO功能。所有的Codec驱动都要提供以下特性:
8.ASoC架构中的Machine
ASoC把声卡注册为Platform Device。
Machine驱动在一个重要的数据结构snd_soc_dai_link中,指定了Platform、 Codec、 codec_dai、 cpu_dai的名字,稍后Machine驱动将会利用这些名字去匹配已经在系统中注册的platform, codec, dai,这些注册的部件都是在另外相应的Platform驱动和Codec驱动的代码文件中定义的,这样看来, Machine驱动的设备初始化代码无非就是选择合适Platform和Codec以及dai,用他们填充以上几个数据结构,然后注册Platform设备即可。
platform总线会匹配这两个名字相同的device和driver,同时会触发soc_probe的调用,它正是整个ASoC驱动初始化的入口。
在soc_probe函数中会完成以下任务:
9.ASoC架构中的Codec
在移动设备中, Codec的作用可以归结为4种,分别是:
描述Codec的最主要的几个数据结构分别是:
snd_soc_codec, snd_soc_codec_driver, snd_soc_dai, snd_soc_dai_driver,其中的snd_soc_dai和snd_soc_dai_driver在ASoC的Platform驱动中也会使用到, Platform和Codec的DAI通过snd_soc_dai_link结构,在Machine驱动中进行绑定连接。
Codec驱动的步骤: