6.8.4. 测试指南
6.8.4.1. 测试环境
6.8.4.1.1. 硬件
测试板:带有第三方codec芯片的测试板
PC:用于和测试板交互
串口线:连接测试板的调试串口
6.8.4.1.2. 软件
PC端串口终端软件
alsa-lib和alsa-utils第三方软件包
第三方codec驱动
创建声卡的machine驱动
6.8.4.2. 创建声卡
6.8.4.2.1. machine驱动
声卡的驱动分为三部分:platform驱动、codec驱动、machine驱动。对于本章节来说,platform驱动即I2S驱动。codec驱动一般会由codec厂家提供,内核中也提供了大量的codec驱动源码,可以选择相应的codec芯片进行测试,本章节会选用allwinner的ac102芯片。所以在测试前需要做的就是编写声卡的machine驱动,machine驱动实现platform驱动和codec驱动的耦合,创建声卡,同时确定cpu_dai和codec_dai的连接方式以及支持的格式、采样深度等信息。
创建声卡的一个非常重要的结构体是struct snd_soc_dai_link,该结构体用来指定platform和codec的耦合关系,主要的成员变量如下:
struct snd_soc_dai_link {
/* config - must be set by machine driver */
const char *name;
const char *stream_name;
struct snd_soc_dai_link_component *cpus;
unsigned int num_cpus;
struct snd_soc_dai_link_component *codecs;
unsigned int num_codecs;
struct snd_soc_dai_link_component *platforms;
unsigned int num_platforms;
/* format to set on init */
unsigned int dai_fmt;
/* machine stream operations */
const struct snd_soc_ops *ops;
...
};
dai_link中成员变量的一些定义规则(规则定义可参考snd_soc_dai_link结构体定义或函数soc_dai_link_sanity_check):
codecs必须定义,codecs->name和codecs->of_node必须定义其一,不可以都定义,也不可以都不定义。codecs->dai_name必须定义
cpus可不定义。但定义时,cpus->name和cpus->of_node二者定义其一,不可以都定义。cpus->dai_name可定义,也可不定义。cpus->name和cpus->of_node未定义时,将会通过cpus->dai_name进行匹配。cpus->dai_name未定义时,将会通过cpus->name或cpus->of_node进行匹配。
platforms可不定义。但定义时platforms->name和platforms->of_node二者定义其一,不可以都定义。platforms->dai_name在ALSA框架中并未使用。
ALSA框架中提供了一些宏,用来定义上述的一些成员变量,比较常用的是通过宏SND_SOC_DAILINK_DEFS进行定义。现在内核中比较通用的做法是通过SND_SOC_DAILINK_DEFS将成员变量定义为空,在声卡的probe函数中通过读取DTS定义cpus/codecs/platforms的of_node变量。这样做的优点是修改codec外部配置或连接方式时,只需编译DTS即可,不需要重新编译内核。
dai_fmt变量定义I2S和codec之间的音频数据传输方式。
ops定义machine驱动所支持的操作函数集。
将定义的struct snd_soc_dai_link结构体变量赋值给struct snd_soc_card结构体的dai_link成员变量,然后调用snd_soc_register_card即可完成声卡的注册,具体可参考内核中提供的一些machine驱动。
6.8.4.2.2. 声卡DTS配置
需要在DTS中配置声卡的结点,才能正确调用声卡的machine驱动。DTS中声卡的结点配置如下(以allwinner的ac102为例说明):
soundCard {
compatible = "zx,aic-ac102";
aic,codec-chip = <&ac102>;
aic,i2s-controller = <&i2s1>;
status = "okay";
};
machine驱动通过读取aic,codec-chip和aic,i2s-controller属性获取相应的i2s和codec结点。SOC一般是通过I2C接口对codec芯片进行控制,所以需要在I2C控制器下挂接codec芯片
&twi3 {
pinctrl-names = "default";
pinctrl-0 = <&twi3_pins_b>;
status = "okay";
ac102: ac102@33 {
compatible = "allwinner,ac102";
reg = <0x33>;
};
};
6.8.4.3. 音频测试
6.8.4.3.1. 测试音频播放
aplay test.wav
6.8.4.3.2. 测试音频录音
arecord -d 10 -f dat -t wav test.wav
-d:指定录音时长,单位为秒
-f:指定录制的格式,dat表示16bit小端数据,48K采样率,立体声
-t:指定生成的文件格式,为wav文件
test.wav:生成的wav文件名