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):

  1. codecs必须定义,codecs->name和codecs->of_node必须定义其一,不可以都定义,也不可以都不定义。codecs->dai_name必须定义

  2. 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进行匹配。

  3. 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文件名