介绍

架构

Realtek 的音频驱动程序遵循 Linux 的 ALSA 系统芯片 (ASoC) 架构。ASoC 为嵌入式系统芯片处理器和便携式音频编解码器提供了更好的 ALSA 支持。

  • ALSA - 高级 Linux 声音架构。

  • ASoC - 芯片上的 ALSA 系统。

ASoC 基本上将嵌入式音频系统分为三个可重用的组件驱动:

  • 编码驱动器(Codec driver) - 编解码器驱动是平台无关的,包含音频控制、音频接口功能、编解码器 DAPM 定义和编解码器 IO 功能。

  • 平台驱动器(Platform driver) - 平台驱动包含该平台的音频 DMA 引擎和音频接口驱动。

  • 机器驱动器(Machine driver) - 机器驱动处理任何特定于机器的控制和音频事件,例如在开始播放时打开功放。

Realtek 的音频驱动实现了上述所有组件,其架构在下图中进行了说明。

../../rst_linux/4_multimedia/figures/audio_driver_arch.svg

实现

Realtek 音频驱动的实现位于以下目录中。

驱动位置

介绍

<linux>/sound/soc/realtek/machine.c

机器驱动器。

描述我们使用的编解码器、DMA、CPU DAI、编解码器 DAI 驱动。

<linux>/sound/soc/realtek/dma.c

DMA 驱动器。

<linux>/sound/soc/realtek/sport.c

CPU DAI 驱动程序,即音频编解码器的 SPORT 驱动程序。

<linux>/sound/soc/realtek/ameba_sport.c

SPORT 控制 API 的实现。

<linux>/sound/soc/realtek/ameba_audio_clock.c

PLL 时钟框架。

<linux>/sound/soc/realtek/ameba_audio_clock_driver.c

PLL 时钟驱动器。

<linux>/sound/soc/codecs/ameba-codec.c

编解码器 DAI 驱动程序和编解码器驱动程序。

<linux>/sound/soc/codecs/ameba_audio.c

编解码器控制 API 的实现。

其中 <linux> 指的是 SDK 中的内核 linux 目录,对于内核版本 5.4.x,它是 <sdk>/kernel/linux-5.4,对于内核版本 6.6.x,它是 <sdk>/kernel/linux-6.6以下内容同理

  • 音频驱动的 Kconfig: <linux>/sound/soc/Kconfig

    source "sound/soc/realtek/Kconfig"
    
  • 音频驱动的 Makefile: <linux>/sound/soc/Makefile

    obj-$(CONFIG_SND_SOC)   += realtek/
    
  • 音频驱动设备

    音频驱动程序在被集成到系统中时,通过 /dev/snd 向用户空间导出标准 ALSA 设备。请在运行时检查 /dev/snd 中的以下设备节点列表,以确认音频驱动程序是否正常工作。

设备节点

介绍

controlC0

用于音频的控制设备节点。

用于设置音量、静音、输出设备切换以及输入麦克风编号选择。

pcmC0D0p

用于 SPORT0 和内部音频编解码器输出的设备节点。

pcmC0D1c

用于 SPORT1 和内部音频编解码器输入的设备节点。

pcmC0D2p

用于 SPORT2 I2S 输出的设备节点。

pcmC0D2c

用于 SPORT2 I2S 输入的设备节点。

pcmC0D3p

用于 SPORT3 I2S 输出的设备节点。

pcmC0D3c

用于 SPORT3 I2S 输入的设备节点。

该实现支持以下音频类型:

  • 音频播放:目前支持使用 pcmC0D0ppcmC0D2ppcmC0D3p 播放以下音频类型。

    设备节点

    音频类型

    支持的格式

    pcmC0D0p

    音频格式

    • SNDRV_PCM_FORMAT_S16_LE

    • SNDRV_PCM_FORMAT_S24_LE

    pcmC0D0p

    声道

    • Mono

    • Stereo

    pcmC0D0p

    采样率

    • 8000

    • 11025

    • 16000

    • 22050

    • 32000

    • 44100

    • 48000

    • 88200

    • 96000

    pcmC0D2p & pcmC0D3p

    音频格式

    • SNDRV_PCM_FORMAT_S16_LE

    • SNDRV_PCM_FORMAT_S20_LE

    • SNDRV_PCM_FORMAT_S24_LE

    • SNDRV_PCM_FORMAT_S32_LE

    pcmC0D2p & pcmC0D3p

    声道

    • Mono

    • Stereo

    • Quad multi-io

    • Quad TDM

    • 6 channel TDM

    • 6 channel multi-io

    • 8 channel TDM

    • 8 channel multi-io

    pcmC0D2p & pcmC0D3p

    采样率

    • 8000

    • 11025

    • 16000

    • 22050

    • 32000

    • 44100

    • 48000

    • 88200

    • 96000

  • 音频采集:目前支持使用 pcmC0D1cpcmC0D2cpcmC0D3c 采集以下音频类型。

    设备节点

    音频类型

    支持的格式

    pcmC0D1c

    音频格式

    • SNDRV_PCM_FORMAT_S16_LE

    • SNDRV_PCM_FORMAT_S24_LE

    pcmC0D1c

    声道

    • mono

    • Stereo

    • 4 Channel (2 Channel Mic Data + 2 Channel Reference Data)

    pcmC0D1c

    采样率

    • 8000

    • 11025

    • 16000

    • 22050

    • 32000

    • 44100

    • 48000

    • 88200

    • 96000

    pcmC0D2c & pcmC0D3c

    音频格式

    • SNDRV_PCM_FORMAT_S16_LE

    • SNDRV_PCM_FORMAT_S20_LE

    • SNDRV_PCM_FORMAT_S24_LE

    • SNDRV_PCM_FORMAT_S32_LE

    pcmC0D2c & pcmC0D3c

    声道

    • Mono

    • Stereo

    • Quad multi-io

    • Quad TDM

    • 6 channel TDM

    • 6 channel multi-io

    • 8 channel TDM

    • 8 channel multi-io

    pcmC0D2c & pcmC0D3c

    采样率

    • 8000

    • 11025

    • 16000

    • 22050

    • 32000

    • 44100

    • 48000

    • 88200

    • 96000

  • 音频控制:目前支持使用 controlC0 的以下音频控制设置。

    控制号

    类型

    编号

    名字

    默认值

    介绍

    0

    INT

    2

    DAC Volume

    128, 128

    左/右声道音量[0~175]

    1

    BOOL

    2

    DAC Mute

    Off, Off

    左/右声道静音

    • Off: 非静音

    • On: 静音

    2

    INT

    1

    AD0 Volume

    47

    ADC0 音量[0~175]

    3

    INT

    1

    AD1 Volume

    47

    ADC1 音量[0~175]

    4

    INT

    1

    AD2 Volume

    47

    ADC2 音量[0~175]

    5

    INT

    1

    AD3 Volume

    47

    ADC3 音量[0~175]

    6

    INT

    1

    AD4 Volume

    47

    ADC4 音量[0~175]

    7

    INT

    1

    AD5 Volume

    47

    ADC5 音量[0~175]

    8

    INT

    1

    AD6 Volume

    47

    ADC6 音量[0~175]

    9

    INT

    1

    AD7 Volume

    47

    ADC7 音量[0~175]

    10

    BYTE

    5

    MICBST AMIC1-5 GAIN

    06, 06, 06, 06, 06

    5个AMICS的增益

    增益可能是 (0, 1, 2, 3, 4, 5, 6, 7, 8)

    11

    INT

    2

    Zero Dect Timeout

    0, 0

    左/右声道零检测超时

    • 0: 1024*16 采样

    • 1: 1024*32 采样

    • 2: 1024*64 采样

    • 3: 64 采样

    12

    INT

    1

    Choice Device

    0

    • 0: 扬声器输出

    • 1: 耳机输出

    13

    INT

    1

    Choice MIC 0:AMIC 1:DMIC

    0

    • 0: 从AMIC录音

    • 1: 从DMIC录音

    14

    BYTE

    8

    Choice AMIC tdm-8 slot

    01, 02, 03, 03, 03, 03, 03, 03

    定义用于捕获数据的AMIC数量

    15

    BYTE

    8

    Choice DMIC tdm-8 slot

    01, 02, 03, 04, 04, 04, 04, 04

    定义用于捕获数据的DMIC数量

配置

设备树配置

音频设备树使音频驱动程序在不同的硬件上更具灵活性。用户可以根据具体硬件更改设备树。注意,更改设备树后,请确保它与其他模块没有冲突。

在本节中,<dts_dir> 表示设备树文件的目录,对于内核 5.4.x,该目录为 <sdk>/kernel/linux-5.4/arch/arm/boot/dts,而对于内核 6.6.x,该目录为 <sdk>/kernel/linux-6.6/arch/arm/boot/dts/realtek/ameba

放大器配置

根据不同的板子,更改放大器使能引脚的以下设备树 GPIO 配置。

  1. 修改 <dts_dir>/rtl8730e-pinctrl.dtsi

    audio_ext_amp_pins:audio_ext_pin@0 {
    pins {
       pinmux = <REALTEK_PINMUX('B', 7, GPIO)>;  //using PB7 for amplifier enable pin
          ……
       };
    };
    
  2. 在设备树中更改产品的放大器 pinmux 设置。例如,如果你启动 generic_rtl8730elh_va8-eng,请更改 <dts_dir>/rtl8730elh-va8-generic.dts

    &codec{
       pinctrl-names = "default";
       pinctrl-0 = <&audio_ext_amp_pins>;
       ext_amp_gpio = <&gpiob 7 0>;
    };
    

SPORT 多 IO 配置

SPORT2/SPORT3 I2S 用于与外部音频编解码器进行数据传输。它可以是 TDM 或多 IO。请根据你板子的硬件进行配置。

rtl8730elh-va8 演示板和通用项目的设备树配置为例。

  • 例如:如何将 SPORT2 设置为多 IO 模式。

    修改 <dts_dir>/rtl8730elh-va8-generic.dts

    &sport2 {
       rtk,sport-multi-io = <1>;
    };
    
  • 例如:如何将 SPORT3 设置为 TDM 模式。

    修改 <dts_dir>/rtl8730elh-va8-generic.dts

    &sport3 {
       rtk,sport-multi-io = <0>;
    };
    

SPORT MCLK 输出倍频设置

SPORT2/SPORT3 I2S 用于与外部音频编解码器进行数据传输。一些外部音频编解码器需要 SPORT 提供 MCLK 给它们。它们可能有以下要求:

External audio codec MCLK = multiplier * sport_MCLK

在这种情况下,在设备树中添加倍频信息以通知 SPORT 驱动程序,以便 SPORT 驱动程序能够根据特定的数据流采样率计算正确的 PLL 时钟。

rtl8730elh-va8 演示板、通用项目的设备树配置为例:

修改 <dts_dir>/rtl8730elh-va8-generic.dts

&sport2 {
   rtk,sport-mclk-multiplier = <256>
};

设置 SPORT MCLK 最大值

SPORT2/SPORT3 I2S 用于与外部音频编解码器进行数据传输。一些外部音频编解码器需要 SPORT 为其提供 MCLK。它们可能会有如下要求:

External audio codec MCLK <= fixed_sport_MCLK

在这种情况下,在 DTS 中添加 MCLK 的最大值,以通知 SPORT 驱动程序该信息,使 SPORT 驱动程序能够为特定的数据流采样率计算正确的 PLL 时钟。

rtl8730elh-va8 演示板、通用项目的设备树配置为例:

修改 <dts_dir>/rtl8730elh-va8-generic.dts

&sport2 {
   rtk,sport-mclk-fixed-max = <12288000>;
};

要注意的是:rtk,sport-mclk-multiplierrtk,sport-mclk-fixed-max 不应同时设置,否则可能会导致驱动程序混淆。

SPORT 模式设置

SPORT 支持主模式和从模式。

在项目的设备树中设置您需要的正确模式。例如,如果您启动的是 generic_rtl8730elh_va8-eng,请更改 <dts_dir>/rtl8730elh-va8-generic.dts

&sport2 {
   rtk,sport-mode = <0>; // 0,soc is master. 1, soc is slave.
};

SPORT Pinmux 设置

SPORT2/SPORT3 的 I2S 需要设置引脚复用,以便与外部编解码器进行交互。

  1. I2S 引脚复用设置在 <dts_dir>/rtl8730e-pinctrl.dtsi 中。如果您的开发板引脚复用设置不同,请进行配置。例如:

    i2s2_pins: i2s2@0 {
       pins {
          pinmux = <REALTEK_PINMUX('B', 14, I2S2)>,//change your pinmux
          <REALTEK_PINMUX('B', 15, I2S2)>,  //change your pinmux
          <REALTEK_PINMUX('B', 16, I2S2)>,  //change your pinmux
          <REALTEK_PINMUX('B', 17, I2S2)>,  //change your pinmux
          <REALTEK_PINMUX('B', 18, I2S2)>,  //change your pinmux
          <REALTEK_PINMUX('B', 19, I2S2)>,  //change your pinmux
          <REALTEK_PINMUX('B', 20, I2S2)>;  //change your pinmux
          bias-disable;  //bias-disable/bias-pull-up/bias-pull-down
          slew-rate = <0>;
          drive-strength = <0>;
       };
    };
    i2s3_pins: i2s3@0 {
       pins {
          pinmux = <REALTEK_PINMUX('B', 7, I2S3)>, //change your pinmux
          <REALTEK_PINMUX('B', 8, I2S3)>,   //change your pinmux
          <REALTEK_PINMUX('B', 9, I2S3)>,   //change your pinmux
          <REALTEK_PINMUX('B', 29, I2S3)>,  //change your pinmux
          <REALTEK_PINMUX('B', 30, I2S3)>,  //change your pinmux
          <REALTEK_PINMUX('B', 31, I2S3)>,  //change your pinmux
          <REALTEK_PINMUX('C', 0, I2S3)>;   //change your pinmux
          bias-disable;  //bias-disable/bias-pull-up/bias-pull-down
          slew-rate = <0>;
          drive-strength = <0>;
       };
    };
    

请确保在项目的设备树中使用 I2S 引脚复用。例如,如果您启动的是 generic_rtl8730elh_va8-eng 并需要在 SPORT2 中使用 i2s2_pins,请在 <dts_dir>/rtl8730elh-va8-generic.dts 的 SPORT2 部分中添加 I2S。

&sport2 {
   pinctrl-names = "default";
   spinctrl-0 = <&i2s2_pins>;
};

DMIC 配置

DMIC 默认情况下未启用。如果您想测试 DMIC,请按照以下步骤操作:

<dts_dir>/rtl8730e-pinctrl.dtsi 中有两组 DMIC 引脚复用。请选择您使用的一组,您也可以根据您的硬件进行更改。

dmic_pins_a: dmic@0 { // Fixed for EV730EL0_3V0 demo board
   pins {
      pinmux = <REALTEK_PINMUX('B', 21, DMIC)>,//change your pinmux
      <REALTEK_PINMUX('B', 22, DMIC)>;  //change your pinmux
      bias-disable;  //bias-disable/bias-pull-up/bias-pull-down
      slew-rate = <0>;
      drive-strength = <0>;
   };
};
dmic_pins_b: dmic@1 {
   pins {
      pinmux = <REALTEK_PINMUX('B', 16, DMIC)>, //change your pinmux
      <REALTEK_PINMUX('B', 17, DMIC)>,  //change your pinmux
      <REALTEK_PINMUX('B', 18, DMIC)>,  //change your pinmux
      <REALTEK_PINMUX('B', 19, DMIC)>,  //change your pinmux
      <REALTEK_PINMUX('B', 20, DMIC)>;  //change your pinmux
      bias-disable;  //bias-disable/bias-pull-up/bias-pull-down
      slew-rate = <0>;
      drive-strength = <0>;
   };
};

请确保在项目的设备树中使用 DMIC 引脚复用。例如,如果您启动的是 generic_rtl8730elh_va8-eng 并需要使用 dmic_pins_a,请更改 <dts_dir>/rtl8730elh-va8-generic.dts

&codec{
   pinctrl-names = "default", "default";
   pinctrl-0 = <&audio_ext_amp_pins>;
      pinctrl-1 = <&dmic_pins_a>;
      ext_amp_gpio = <&gpiob 7 0>;
};

编译配置

音频驱动的配置默认已设置为 y

要更改音频驱动的配置,请输入命令,然后按顺序选择菜单。

make kernel_menuconfig
../../rst_linux/4_multimedia/figures/audio_kernel_menuconfig.svg

接口(APIs)

用户空间 API

音频驱动程序导出两层接口以满足客户的需求。

API 层

介绍

tinyalsa 或 ALSA-lib API

高级Linux声音架构的第三方用户空间API

ALSA open/close/ioctl API

标准Linux驱动程序API

这两层接口的关系如下所示。

../../rst_linux/4_multimedia/figures/audio_driver_api_layers.png

ALSA 核心 API

音频驱动程序向用户空间导出标准的 ALSA API。

接口

介绍

open

打开一个ALSA设备 (pcmC0D0p, pcmC0D1c, pcmC0D2p, pcmC0D2c, pcmC0D3p, pcmC0D3c, controlC0)

close

关闭一个ALSA设备

ioctl

与ALSA驱动程序交互以读取、写入流或设置音量/静音

tinyalsa API

tinyalsa 是一个用于在 Linux 内核中与 ALSA 进行接口的小型库。它是开源的。

其目的是:

  • 提供基本的 PCM 和混音器 API。

  • 避免支持复杂和不必要的操作,这些操作可以在更高级别上处理。

控制 API

以下是一些用于设置控制元素值的常用 API。

接口

介绍

mixer_open

打开一个混音器

mixer_close

关闭一个混音器

mixer_get_num_ctls

获取混音器控件的数量

mixer_get_ctl

获取特定ID的混音器控件

mixer_ctl_get_name

获取混音器控件的名称

mixer_get_ctl_by_name

按名称获取混音器控件

mixer_ctl_get_value

获取混音器控件的值

mixer_ctl_set_value

设置混音器控件的值

mixer_ctl_set_array

设置混音器控件的数组值

参考 github tinyalsa 获取更多有关 API 的细节。

以下是一个示例,展示了如何使用控件 API 设置音量。

  1. 创建音量控制的字符串:

    char mixer_ctl_name[128] = "DAC Volume";
    
  2. 调用 mixer_open 打开 /dev/snd/controlC0

    struct mixer * mixer = mixer_open(0);
    if (!mixer) {
       ALOGE("%s: Unable to open the mixer card");
    }
    
  3. 按名称获取混音器控件:

    struct mixer_ctl * ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
    if (!ctl) {
       ALOGE("%s: Could not get ctl for %s", __func__, mixer_ctl_name);
       return -EINVAL;
    }
    
  4. 设置混音器控件的音量:

    int volume[2];
    volume[0] = MAX_VOLUME;//175
    volume[1] = MAX_VOLUME;//175
    mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
    
  5. 如果用不到混音器,关闭它:

    mixer_close(mixer);
    mixer = NULL;
    

PCM API

以下是一些常用的 PCM 相关 API。

接口

介绍

pcm_open

打开一个PCM

pcm_close

关闭一个PCM

pcm_write

将PCM原始数据写入驱动程序

pcm_read

从驱动中获取PCM的原始数据

以下是一个示例,展示了如何使用 PCM API 渲染音频流。

  1. 创建输出流的配置:

    struct pcm_config pcm_output_config = {
       .channels = 2,
       .rate = DEFAULT_OUT_SAMPLING_RATE,
       .period_size = SHORT_PERIOD_SIZE,
       .period_count = SHORT_PERIOD_COUNT,
       .format = PCM_FORMAT_S16_LE,
       .start_threshold = 0,
       .avail_min = 0,
    };
    
  2. 使用步骤 1 中创建的配置打开播放设备节点 /dev/snd/pcmC0D0p。

    struct pcm *out_pcm pcm_open(0, 0, PCM_OUT | PCM_MONOTONIC, &pcm_output_config);
    
  3. 把音频原始数据写入 ALSA 驱动:

    if (out_pcm) {
       ret = pcm_write(out_pcm, (void *)buffer, bytes);
    }else {
       ALOGE("out pcm is NULL!!!");
    }
    
  4. 写完之后,关闭 PCM 设备节点:

    if(out_pcm) {
       pcm_close(out_pcm);
       out_pcm = NULL;
    }
    

ALSA-lib API

ALSA-lib 是一个与 Linux 内核中的 ALSA 接口的标准库。它是开源的。

其目的是:

  • 该库提供内核 API 的全部功能。

  • 该库在可用性上进行了重大改进,使应用程序代码更简单、更美观。

  • 未来的修复或兼容性代码可能会放在库代码中,而不是内核驱动中。

控制 API

以下是一些常用的控制 API。

接口

介绍

snd_ctl_open

打开声音控制卡

snd_ctl_close

关闭声音控制卡

snd_ctl_elem_info_get_id

获取 CTL 元素 id/信息的 CTL 元素标识符

snd_ctl_elem_info_set_id

设置 CTL 元素 id/信息的 CTL 元素标识符

snd_ctl_elem_info

获取 CTL 元素信息

snd_ctl_elem_read

获取 CTL 元素值

snd_ctl_elem_write

设置 CTL 元素值

参考 Alsa project control interface 获得更多有关 API 的细节。

控制实现的示例可以参考 alsa-utils 中的代码: fwk/third_party/alsa-lib/alsa-utils-1.2.5.1/alsactl

PCM API

以下是一些常用的 PCM 相关 API。

接口

介绍

snd_pcm_open

打开 PCM

snd_pcm_close

关闭 PCM

snd_pcm_info

获取 PCM 句柄的一般(静态)信息

snd_pcm_hw_params

安装一个 PCM 硬件配置

snd_pcm_prepare

准备 PCM 以供使用

snd_pcm_readi

从 PCM 读取交错帧

snd_pcm_writei

往 PCM 写入交错帧

参考 Alsa project pcm interface 获取更多有关 API 的细节。

PCM 实现的例子可以参考 alsa-utils 中的代码: fwk/third_party/alsa-lib/alsa-utils-1.2.5.1/aplay

Audio-clock API

对于内部音频编解码器,SPORT0 用于播放,SPORT1 用于录制。音频输入时钟为 XTAL 40M。

对于外部音频编解码器,SPORT2SPORT3 用于播放和录制。音频输入时钟可以是 XTAL 40M 或音频 PLL。如果您将 Sport MCLK 输出倍频器设置 为 DTS Configuration,且该值不为 0,音频驱动程序将自动选择合适的音频 PLL 时钟。

音频时钟 API 的目的是:

  • 提供 API 供用户获取 SPORT0SPORT3 的当前时钟。

  • 提供 API 供用户实现音频 PLL 的微调。

要使用音频时钟 API,请将头文件复制到您的包含路径:<linux>/include/uapi/sound/rtk_audio_pll.h

音频时钟 API 是通过标准设备节点接口调用的。

接口

介绍

open

打开音频 PLL 时钟设备:/dev/audio_pll_clk。

close

关闭音频 PLL 时钟设备。

ioctl

与音频时钟驱动程序交互以获取时钟信息或进行微调。

rtk_audio_pll.h 描述了两个重要的结构:

  • struct micro_adjust_params 用于实现微调。

  • struct audio_clock_info 用于获取 SPORT0SPORT3 的当前时钟。

    struct micro_adjust_params {
       /*can be PLL_24P576M, PLL_45P158M, or PLL_98P304M*/
       unsigned int clock;
       /*can be #define PLL_AUTO, PLL_FASTER, or PLL_SLOWER*/
       unsigned int action;
       /*can be any value between 0-1000*/
       unsigned int ppm;
    };
    struct audio_clock_info {
       /*user sets sport_index, to tell kernel which sport's clock info it needs*/
       unsigned int sport_index;
       /*user gets clock info from kernel for the sport_index he sets*/
       unsigned int clock;
    };
    

以下是获取 SPORT2 时钟信息的示例。

  1. 打开音频 PLL 设备节点,并获取 fd。

    #define AUDIO_PLL_DEV "/dev/audio_pll_clk"
    int fd = open(AUDIO_PLL_DEV, O_RDWR);
    
  2. 使用命令 AUDIO_PLL_GET_CLOCK_FOR_SPORT 进行 ioctl 操作以获取时钟信息。

    Note that the info.sport_index should be set by application, so that driver will know which SPORT’s clock to get. However, the sport_index is a concept of hardware, you may wonder which SPORT is using. Check the PCM device node, for example, if audio is playing through audio device node pcmC0D2p, then it’s using SPORT2, so set info.sport_index = 2.

    The relationship may be got from Implementarion Audio driver devices.

    struct audio_clock_info info;
    info.sport_index = 2;
    ioctl(fd, AUDIO_PLL_GET_CLOCK_FOR_SPORT, &info);
    
  3. 如果设备节点不再使用,关闭它。

    close(fd);
    

以下是实现 98.304M PLL 时钟微调的示例。

  1. 打开音频 PLL 设备节点,并获取文件描述符(fd)。

    fd = open(AUDIO_PLL_DEV, O_RDWR);
       if(fd == -1) {
          printf("open %s fail \n", AUDIO_PLL_DEV);
    }
    
  2. 使用命令 AUDIO_PLL_MICRO_ADJUST 进行 ioctl 操作以实现微调。

    在这种情况下,你应将要调整的时钟放入 params.clock,将操作 (PLL_FASTERPLL_AUTOPLL_SLOWER) 放入 params.action,并将 ppm 放入 params.ppm

    以 98.304M 为例:

    PLL_AUTO: reset to auto 98.304M
    PLL_FASTER: PLL clock faster than 98.304M
    PLL_SLOWER: PLL clock slower than 98.304M
    

    这些操作不会导致叠加。例如,设置一次 PLL_FASTER 为 800ppm 和设置两次 PLL_FASTER 为 800ppm,结果是相同的。params.ppm 表示时钟漂移,预期的时钟差等于 \(98.304M * ppm/1000000\)

    struct micro_adjust_params params;
    params.clock = PLL_98P304M;
    params.action = PLL_FASTER;
    params.ppm = 800;
    ioctl(fd, AUDIO_PLL_MICRO_ADJUST, &params);
    
  3. 如果设备节点不再使用,关闭它。

    close(fd);
    

测试示例位于 tests/audio_pll 中。

调试工具

tinyalsa

tinyalsa 是一个用于测试 tinyalsa-lib 的开源工具。

tinymix

tinymix 是一个用于设置混音器控制的工具。

tinymix [options] [control name/#] [value to set]

它的选项如下所示:

选项

介绍

-D,–card

使用指定的卡号代替 0。

-a,–all-values

显示控制的所有可能值/范围。

-t, –tabs-only

用制表符分隔所有输出列/值。

-v, –value-only

仅显示所选控件的值。

  • 如果您想选择输出设备,请按如下设置:

    tinymix "Choice Device 0: Spk   1: HEAPHONE" 0
    
  • 如果您想设置输出音量,请按如下操作:

    tinymix "DAC Volume" 100 100
    
  • 如果您想设置零检测超时值,请按如下操作:

    tinymix " Zero Dect TimeOut" 1 1
    
  • 如果您想更改 2 通道麦克风数据+2 通道参考数据的麦克风编号,请按如下设置:

    tinymix "Choice tdm-4 slot" 01 02 03 03
    //chose amic1(mic-left),amic2(mic-right),amic3(ref-left),amic3(ref-right)
    
  • 如果您想将系统静音,请按如下操作:

    tinymix "DAC Mute" On
    

tinyplay

tinyplay 是一个用于播放 PCM 原始数据的工具。

tinyplay file.wav [options]

它的选项如下所示:

选项

介绍

-D, –card

使用给定的声卡编号代替0。

-d,–device

使用给定的设备编号代替 0。

-p, –period-size|-

使用给定的周期大小。

-n, –period-count|

使用给定的周期计数。

如果你想播放一个波形,设置如下:

tinyplay ./file.wav -D 0 -d 0 -p 1024 -n 4

tinycap

tinycap 是一个用于捕获 PCM 原始数据的工具。

tinycap file.wav [options]

它的选项如下所示:

选项

介绍

-D, –card

使用指定的声卡编号代替0。

-d,–device

使用指定的设备编号代替0。

-c, –channels

使用指定的通道数。

-r, –rate

使用指定的采样率。

-b, –bits

使用指定的格式位。

-p, –period-size

使用指定的周期大小。

-n, –period-count

使用指定的周期数量。

-T, –capture-time

采集数据的时间。

如果你想捕捉一个波形,请按以下设置:

tinycap ./file.wav -D 0 -d 1 -r 48000 -T 10

tinyhostless

tinyhostless 是一种工具,用于捕获和发送原始数据,以便立即回放。

tinyhostless [options]

它的选项如下所示:

选项

介绍

-D,–card

使用给定的卡片。

-P,–playback-device

使用指定的设备进行播放。

-C,–capture-device

使用指定的设备进行捕获。

-p,–period-size

使用指定的周期大小。

-n,–period-count

使用指定的周期数量。

-c,–channel count

使用指定的声道数量。

-r,–sample-rate

使用指定的采样率。

-l,–should-loop

是否需要循环。

-T,–playback-capture-time

回放捕获时间。

如果您想捕获并立即将捕获的原始数据发送到回放,请按如下设置:

tinyhostless -D 0 -P 0 -C 1 -p 1024 -n 4 -c 2 -r 16000 -l -T 10

tinyalsa-extension

Realtek 演示工具用于测试回放和捕获,主要用于捕获 4 通道麦克风数据和参考数据。

tinydownchplay

此测试工具仅用于以下情况:用户使用 tinycap 或 record 捕获 4 通道的原始数据,其中包括 2 通道的麦克风数据或 2 通道的参考数据。然后,用户希望分别播放 2 通道的麦克风数据或 2 通道的参考数据。 Then user wants to separately play 2 channel-microphone data, or 2 channel-reference data.

它的用法是:

tinydownchplay file.wav [options]

它的选项如下所示:

选项

介绍

-D, –card

使用给定的声卡编号替代0。

-d,–device

使用给定的设备编号替代0。

-p, –period-size|-

使用给定的周期大小。

-n, –period-count|

使用给定的周期计数。

-c, –target-play-channel-count

目标播放通道数。

-s, –target-play-source

选择0以播放4通道原始数据中的前2通道原始数据。

选择1以播放4通道原始数据中的后2通道原始数据。

  • 如果您想播放 2 通道麦克风原始数据,请进行如下设置:

    tinydownchplay ./file.wav -D 0 -d 0 -p 1024 -n 4 -c 2 -s 0
    
  • 如果您想播放 2 通道参考原始数据,请进行如下设置:

    tinydownchplay ./file.wav -D 0 -d 0 -p 1024 -n 4 -c 2 -s 1
    

tinylooptest

此测试工具仅用于 88 针测试板,在这种情况下:用户想快速检查 4 通道原始数据采集是否正常。

它的用法是:

tinylooptest [options]

如果您从左侧扬声器听到参考数据,并从右侧扬声器听到 AMIC 数据,这意味着测试成功。

它的选项如下所示:

选项

介绍

-D,–card

使用给定的卡。

-P,–playback-device

使用给定的设备进行回放。

-C,–capture-device

使用给定的设备进行捕获。

-p,–period-size

使用给定的周期大小。

-n,–period-count

使用给定的周期数量。

-c,–channel count

使用给定的声道数量。

-r,–sample-rate

使用给定的采样率。

-l,–should-loop

是否需要循环。

-T,–playback-capture-time

回放捕获时间。

如果你想测试 4 声道数据捕获,请按以下方式设置:

tinylooptest -D 0 -P 0 -C 1 -p 1024 -n 4 -c 4 -r 16000 -l -T 10

ALSA-util

标准的 ALSA 工具用于调试 ALSA-lib。

amixer

amixer 是一个用于设置混音器控件的工具。

amixer <options> [command]

它的选项如下所示:

选项

介绍

-c,–card

选择卡。

-D,–device

选择设备。

cget cID

获取一个控件的控制内容。

cset cID P

设置一个控件的控制内容。

controls

显示指定声卡的所有控件。

contents

显示指定卡片的所有控件的内容。

以下是设置音量的示例:

amixer cset numid=1,iface=MIXER,name='DAC Volume' 175 175

以 DAC 音量为例来测试 ALSA 插件:

amixer -D your_ctl_name cset numid=1,iface=MIXER,name='DAC Volume' 175 175

备注

在此步骤之前,请将您的文件 asound.conf 添加到板载的 /etc 目录中。

aplay

aplay 是一个用于播放音频原始数据的工具。

aplay [OPTION]... [FILE]...

它的选项如下所示:

选项

介绍

-D, –device

通过名称选择PCM。

-t, –file-type

设置文件类型,例如:wav、raw……

-f, –format

设置文件格式。

-c,–channel count

获取一个控件的控制内容。

-r,–sample rate

设置文件的采样率。

–period-size

获取周期大小。

–buffer-size

获取ALSA缓存大小。

以下是在 pcmC0D2p 上播放音频波形的示例:

aplay -D hw:0,2 --period-size=1024 --buffer-size=4096 -t wav ./file.wav

测试 ALSA 插件:

aplay -Dplug:your_plug_name --period-size=1024 --buffer-size=4096 -t wav ./file.wav

备注

在此步骤之前,请将您的文件 asound.conf 添加到板上的 /etc 目录中。

arecord

arecord 是一个用于捕获麦克风数据的工具。

arecord [OPTION]... [FILE]...

它的选项如下所示:

选项

介绍

-D, –device

通过名称选择 PCM。

-t, –file-type

设置文件类型,例如:wav,raw……

-f, –format

设置文件格式

-c,–channel count

获取一个控件的内容。

-r,–sample rate

设置文件的采样率。

-d,–duration

设置录音时间。

–period-size

设置周其大小。

–buffer-size

设置ALSA缓存大小。

以下是通过 pcmC0D1c 捕获音频波形数据的示例:

arecord -D hw:0,1 -d 10 -r 48000 -f S16_LE -c 2 --period-size=1024 --buffer-size=4096 -t wav ./test.wav

测试 ALSA 插件:

arecord -Dplug:your_plug_name -d 5 -r 48000 -f S16_LE -c 2 --period-size=1024 --b
uffer-size=4096 -t wav ./test.wav

备注

在此步骤之前,请将您的文件 asound.conf 添加到板载的 /etc 目录中。