音频设置和开发#

本主题涉及 ASoC 驱动程序、音频集线器硬件、USB 音频以及与 NVIDIA® IGX Orin 设备上的音频相关的其他事项。

IGX Orin 的 ASoC 驱动程序#

高级 Linux 声音架构 (ALSA) 为 Linux 操作系统提供音频功能。NVIDIA ALSA 片上系统 (ASoC) 驱动程序使 ALSA 能够与不同的 NVIDIA SoC 无缝协作。平台无关和通用组件由上游 Linux 社区维护。

有关 ALSA 的更多详细信息,请访问 ALSA 项目

IGX Orin 设备公开了多个可用于音频功能的接口。有关支持的接口的信息,请参阅 I/O 和外部接口

ALSA#

ALSA 框架是 Linux 内核的一部分,由 Linux 社区支持和维护。这使得通过设计利用 NVIDIA 音频路由支持的驱动程序,将框架适配到 IGX Orin 设备成为可能。ALSA 包括声卡驱动程序的集合,包括实际的编解码器驱动程序,并且可以支持添加新的编解码器驱动程序。

ALSA 包括库和实用程序,可以在 Linux 用户空间中实现更精细的音频控制。这些库控制音频应用程序,而无需直接与内核空间驱动程序交互。这些库包括

  • amixer

  • aplay

  • arecord

下图说明了 ALSA 软件层次结构。

ALSA software hierarchy

平台驱动程序和编解码器驱动程序的功能是

  • tegra210-admaif : 表示音频 DMA (ADMA) 和音频集线器 (AHUB) 之间接口的内核驱动程序

  • tegra210-<xxxx> : 表示 AHUB 中各种硬件加速器的内核驱动程序

  • tegra210-ahub : 帮助配置各种硬件加速器之间音频路由的内核驱动程序

有关这些模块的更多信息,请参阅 AHUB 模块部分。

用户空间 ALSA 应用程序通过用户空间库提供的 API 与 ALSA 内核(内核空间)交互,这些库初始化音频管道后端的实际硬件编解码器。

DAPM#

ALSA 旨在支持各种功能,包括但不限于动态音频路由到可用的 PCM 设备。ALSA 内核中提供此支持的组件称为 动态音频电源管理 (DAPM)。DAPM 通过控制音频子系统中各个编解码器块的电源流入和流出,最大限度地降低功耗。DAPM 以小部件(影响音频电源的组件)的形式提供开关或内核控件,以打开和关闭模块的电源,并从用户空间应用程序(如 aplayarecordamixer)操作寄存器位。

有关 DAPM 的更多详细信息,请参阅 ASoC DAPM

在软件层次结构方面,DAPM 是 ALSA 内核的一部分,它管理编解码器模块的功耗。有关详细信息,请参阅 ALSA 下的 ALSA 软件层次结构图。

有关更多信息,请参阅 时钟和电源管理

设备树#

设备树是一种数据结构,用于描述平台上的设备。它在启动时传递给操作系统,以避免在操作系统中硬编码组件详细信息。这使得在不重建内核的情况下更改硬件配置变得更加容易。

设备树由节点和属性组成。每个节点都可以有属性或子节点。每个属性都包含一个名称和一个或多个值。设备树结构必须以正确的格式编写,以便操作系统可以解析数据结构。

一个简单的设备树示例可在 使用设备树实例化编解码器驱动程序中找到。

ASoC 驱动程序#

ASoC 驱动程序为嵌入式片上系统处理器(例如 DSP、AHUB)和便携式音频编解码器提供更好的 ALSA 支持。它由以下组件组成

  • 平台驱动程序:负责 PCM 注册并与 PCM 驱动程序接口。ADMAIF 是平台驱动程序。

  • 编解码器驱动程序:通常是通用的、硬件无关的组件,用于配置编解码器。IGX Orin ASoC 将其扩展到后续章节中描述的一些内部模块。

    编解码器驱动程序必须至少有一个输入或一个输出。

    驱动程序架构提供了一种定义用户自己的 DAPM 小部件进行电源管理和 kcontrols 进行用户空间寄存器设置的方法。

  • 机器驱动程序:通过绑定平台和编解码器组件来注册声卡。

ASoC 使用通用结构 snd_soc_component_driver,它同时表示平台和编解码器组件。这最终取决于驱动程序实现的接口。例如,平台组件也实现 PCM 接口,而编解码器组件可以忽略它。因此,在顶层,平台和编解码器都被称为 ASoC 组件。在本文档中,只要需要通用引用,也使用相同的术语。

有关编写机器驱动程序和识别声卡的详细信息,请参阅 ASoC 机器驱动程序

音频集线器硬件架构#

音频处理引擎 (APE) 是一个独立的硬件块,负责处理 IGX Orin 处理器的所有音频需求,CPU 的监督最少。其音频集线器 (AHUB) 包含许多硬件加速器和一个 DMA 引擎。本节概述了

  • SoC 内部的音频集线器硬件架构

  • ASoC 驱动程序的软件架构

此图总结了 ASoC 的硬件架构。

Audio Hub (AHUB) hardware architecture

音频集线器包含下表所示的几个其他模块,它捕获了处理器的 AHUB 功能。后续章节将详细介绍每个模块。

模块

组件

实例

混音器

混音器

1x

AMX

音频多路复用器

4x

ADX

音频解复用器

4x

SFC

采样频率转换器

4x

MVC

主音量控制

2x

ADMA

音频直接内存访问

1x(32 个通道)

ADMAIF

AHUB 直接内存访问接口

1x(20 个 TX 和 RX 通道)

XBAR

交叉开关;通过其他模块路由音频样本

1x

音频集线器中的模块支持各种类型的音频设备,这些设备有望与应用程序处理器接口,例如

  • 蜂窝基带设备

  • 不同类型的音频 CODEC

  • 蓝牙® 模块

  • 数字麦克风

  • 数字扬声器

音频集线器支持这些设备的不同接口和信号质量要求。

  • 每个 AHUB 模块至少有一个 RX 端口或一个 TX 端口或两者都有。

  • RX 端口从 XBAR 接收数据,TX 端口将数据发送到 XBAR。因此,XBAR 是一个交换机,音频输入可以馈送到多个输出,具体取决于用例。

  • 每个 ADMAIF 都有 TX 和 RX FIFO,支持同时播放和捕获。ADMA 将数据传输到 ADMAIF FIFO,用于所有音频路由场景。

    有关动态音频路由示例,请参阅 用法和示例

ASoC 驱动程序软件架构#

IGX Orin 的 ASoC 驱动程序的软件架构利用硬件支持的功能并符合 ALSA 框架。

如前所述,ASoC 驱动程序包括平台、编解码器和机器驱动程序。这些驱动程序的作用在下面简要描述,并在后续章节中更详细地描述。

ASoC 驱动程序为平台和编解码器驱动程序提供 NVIDIA 音频集线器 (AHUB) 硬件加速。AHUB 直接内存访问接口 (ADMAIF) 实现为平台驱动程序,具有用于播放和捕获的 PCM 接口。其余 AHUB 模块,如交叉开关 (XBAR)、多路复用器 (AMX)、解复用器 (ADX) 和内部集成电路声音 (I2S),实现为编解码器驱动程序。每个驱动程序都通过数字音频接口 (DAI) 连接到 XBAR,在机器驱动程序内部形成音频集线器。

机器驱动程序探测实例化声卡设备并注册 ADMAIF 公开的所有 PCM 接口。启动后,但在使用这些接口进行音频播放或捕获之前,用户必须设置 XBAR 内部的音频路径。默认情况下,XBAR 在启动时没有路由连接,也没有完整的 DAPM 路径来打开相应小部件的电源。XBAR 驱动程序为所有音频组件引入 MUX 小部件,并允许通过用户空间使用 ALSA amixer 实用程序中的 kcontrols 进行自定义路由。如果音频路径不完整,则 DAPM 路径未关闭,硬件设置未应用,并且听不到音频输出。

有关如何设置路由以及如何在 PCM 接口上播放或捕获的更多详细信息,请参阅 用法和示例

平台驱动程序#

平台驱动程序初始化并实例化 AHUB 内部的播放和捕获端口。

用户必须连接部分或全部这些端口以形成完整的音频路由路径。有关完整音频路径的示例,请参阅 用法和示例中的示例。请注意,完整音频路径设置中还有其他元素,这些元素将在后续章节中讨论;平台驱动程序设置的播放/捕获端口只是一个子集。

ADMAIF#

ADMAIF 是 IGX Orin ASoC 设计中的平台驱动程序。它实现通过 snd_soc_component_driver 结构公开的必需 PCM 接口。这些接口通过与 SoC DMA 引擎的上游 API 交互来帮助执行 DMA 操作。ADMAIF 平台驱动程序定义 DAI 并将其注册到 ASoC 内核。

ADMAIF 通道映射到

  • /dev/snd/pcmC1D<n>p 用于播放

  • /dev/snd/pcmC1D<n>c 用于捕获

其中 <n> 是通道号减 1。例如

  • ADMAIF1 映射到 pcmC1D0p 用于播放,以及 pcmC1D0c 用于捕获。

  • ADMAIF2 映射到 pcmC1D1p 用于播放,以及 pcmC1D1c 用于捕获。

编解码器驱动程序#

编解码器驱动程序的概述在 ASoC 驱动程序中介绍。在 ASoC 驱动程序实现中,除了 ADMAIF 之外,其余 AHUB 模块都实现为编解码器驱动程序。它们的职责包括

  • 通过定义 DAI 与其他模块接口

  • 定义 DAPM 小部件并建立 DAPM 路由以进行动态电源切换

  • 根据需要公开额外的 kcontrols,供用户空间实用程序动态控制模块行为

使用设备树实例化编解码器驱动程序#

根据架构,以下目录中的 Makefile 有条件地将所需的设备树结构文件编译为 DTB 文件

$KERNEL_TOP/arch/arm64/boot/dts/

刷新内核时,刷新脚本会选择适当的特定于板的 DTB 文件,以便在启动期间进行解析,并且实例化设备树中列出的 ASoC 编解码器。要将新设备添加到设备树,请编辑 DTS 文件,然后再次刷新目标。DTS 文件名可以从相应的 DTB 文件名中识别出来,DTB 文件位于 /boot/dtb 目标目录中。

例如

If ``/boot/dtb/kernel_tegra234-p3740-0002+p3701-0008-nv.dtb`` is the platform DTB,
the corresponding DTS file is
``hardware/nvidia/t23x/nv-public/nv-platform/tegra234-p3740-0002+p3701-0008-nv.dts``.

要添加新设备,请添加设备名称以及基地址和状态 "okay"

ahub@2900800 {
    status = "okay";
    i2s@2901000 {
        status = "okay";
    };
};

XBAR#

XBAR 编解码器驱动程序为所有接口模块定义 RX、TX 和 MUX 小部件:ADMAIF、AMX、ADX、I2S、混音器、SFC 和 MVC。MUX 小部件永久路由到结构 snd_soc_dapm_route 内部的相应 TX 小部件。

XBAR 互连是通过根据需要使用 ALSA amixer 实用程序将任何 RX 小部件块连接到任何 MUX 小部件块来完成的。这些小部件的 get 和 put 处理程序已实现,以便通过在硬件 MUX 寄存器中设置适当的位来存储音频连接。

混音器控制#

如果声卡在启动后可用,则表明机器驱动程序已成功绑定所有编解码器驱动程序和平台驱动程序。在物理编解码器上获得音频输出之前的剩余步骤包括使用 MUX 小部件建立 DAPM 路径,以便将数据从特定输入模块路由到特定输出模块。输入和输出模块取决于适用的用例。这为复杂的用例提供了灵活性。

此命令实现内部 AHUB 路径“ADMAIF1 RX 到 XBAR 到 I2S1 TX”

$ amixer –c APE cset name='I2S1 Mux' 'ADMAIF1'

有关各种 AHUB 模块的用法和示例,请参阅 用法和示例

AMX#

音频多路复用器 (AMX) 模块可以将最多四个流(每个流最多 16 个通道,每个通道最多 32 位)多路复用到最多 16 个通道(每个通道最多 32 位)的时分复用 (TDM) 流中。AMX 有四个 RX 端口用于从 XBAR 接收数据,一个 TX 端口用于将多路复用输出传输到 XBAR。每个端口都作为 DAI 公开,如下图中的实线所示。路由是使用 DAPM 小部件建立的,如虚线所示。

Audio multiplexer (AMX) module

AMX 代码驱动程序支持以下功能

  • 可以将最多四个输入流(每个流最多 16 个通道)多路复用,并生成一个最多 16 个通道的输出流

  • 可以从四个输入帧中的任何字节组合组装输出帧(“字节 RAM”)

  • 为第一个输出帧的数据同步提供两种模式

    • 等待全部模式:等待所有启用的输入流都有数据,然后再形成第一个输出帧。

    • 等待任何模式:只要任何启用的输入流中有数据可用,就开始形成第一个输出帧。

字节映射配置#

输出流中的每个字节都唯一映射到四个输入流之一中的字节。从输入流到输出流的字节映射可通过 AMX 模块中的字节映射进行软件配置。

字节映射中的每个字节都使用以下字段进行编码

字段

描述

输入流

7:6

标识字节映射自的输入流(0 到 3),其中 0 是 RxCIF0,依此类推。

输入流通道

5:2

标识字节映射自的输入流通道(0 到 15),其中 0 是通道 0,依此类推。

输入流字节

1:0

标识字节映射自的输入流通道中的字节(0 到 3),其中 0 是字节 0,依此类推。

由于支持的最大输出帧大小为 16 个样本(来自 16 个通道),每个样本 32 位,因此字节映射组织为 16 个字,每个字 4 个字节(32 位)。每个字代表一个输入通道,字中的每个字节代表输入通道可能映射到的一个输出通道。

如果输出帧仅从两个输入通道获取样本,则只需编程字 0 和字 1 中的字节。如果输出帧从所有 16 个通道获取样本,则必须编程所有 16 个字中的字节。

输出帧样本大小决定了每个字中必须编程哪些字节。如果输出帧中每个通道的样本大小为 16 位,则只需编程字节映射中每个字的字节 0 和字节 1。如果输出帧中每个通道的样本大小为 32 位,则必须编程每个字的全部四个字节。

请记住以下几点

  • 输入字节必须按顺序映射到输出字节。例如,如果输入帧字节 0 和 1 都映射到输出帧,则字节 1 必须映射到输出帧中字节 0 之后的位置。

  • 并非输入帧中的所有字节都需要映射到输出帧。

  • 输出帧中的每个字节都有一个软件可配置的启用标志。如果清除特定字节的启用标志,则字节映射中相应的映射将被忽略,并且该字节将填充零。

混音器控制#

混音器控件由各自的编解码器驱动程序为 AMX 的每个实例注册,并用于配置音频数据的路径、特性和处理方法。下表列出了特定于实例的混音器控件。

混音器控件 *

描述

可能的值

AMX<i> RX<j> Mux

选择 AMX 输入从中接收数据的 AHUB 客户端设备。

运行此命令以获取可能的值

amixer -c APE cget name="AMX<i> RX<j> Mux"

AMX<i> 输入<j> 音频通道

指定输入流的通道数。

0-16

AMX<i> 输出音频通道

指定输出流的通道数。

0-16

AMX<i> 字节映射 <byte_num>

指定字节映射(请参阅 字节映射配置)。

0-255

* <i> 指的是 AMX 客户端的实例 ID,<j> 指的是输入端口 ID。

AMX 模块的用法和示例可以在 示例:AMX 中找到。

ADX#

音频解复用器 (ADX) 模块可以将单个 TDM 流(最多 16 个通道,每个通道最多 32 位)解复用到四个流(每个流最多 16 个通道和 32 位)中。ADX 的 RX 端口从 XBAR 接收输入数据,四个 TX 端口将解复用输出传输到 XBAR。每个端口都作为 DAI 公开,用实线表示,路由是使用 DAPM 小部件建立的,如下图中的虚线所示。

Audio demultiplexer (ADX) module

ADX 有一个输入 RxCIF,它提供输入流。核心逻辑根据字节映射从该输入流中选择字节,并形成输出流,这些输出流被定向到 TxCIF FIFO,以便传输到 AHUB 中的下游模块。

ADX 解复用器支持以下功能

  • 将最多 16 个通道的一个输入流解复用到最多 16 个通道的四个输出流中

  • 组装包含来自输入帧的任何字节组合的输出帧(“字节 RAM”)。字节 RAM 设计与 AMX 中的相同,只是数据流的方向相反。

字节映射配置#

每个输出流中的每个字节都映射自输入流中的一个字节。从输入流到输出流的字节映射可通过 ADX 模块中的字节映射进行软件配置。

字段

描述

输出流

7:6

指定字节映射到的输出流,其中 0 表示 TxCIF0,依此类推。

输出流通道

5:2

指定字节映射到的输出流通道,其中 0 表示通道 0,依此类推。

输出流字节

1:0

指定字节映射到的输出流通道中的字节,其中 0 表示字节 0,依此类推。

由于每个流的最大支持输出帧大小为 16 个通道,每个样本 32 位,因此字节映射组织为 16 个字,每个字 32 位(4 个字节)。

每个字代表输入帧中的一个通道。因此,如果输入帧只有两个通道,则只需编程字 0 和字 1 中的字节,而如果输入帧有 16 个通道(允许的最大值),则必须编程所有 16 个字中的字节。

输入帧样本大小决定了每个字中必须编程的字节。如果输入帧中每个通道的样本大小为 16 位,则只需编程每个字的字节 0 和字节 1。如果输入帧中每个通道的样本大小为 32 位,则必须编程每个字的全部四个字节。

请记住以下几点

  • 输入字节必须按顺序映射到输出字节。例如,如果输入帧字节 0 和 1 都映射到输出帧,则字节 1 必须映射到输出帧中字节 0 之后的位置。

  • 并非输入帧中的所有字节都需要映射到输出帧。

  • 输出帧中的每个字节都有一个软件可配置的启用标志。如果清除特定字节的启用标志,则字节映射中相应的映射将被忽略,并且该字节将填充零。

混音器控制#

混音器控件由各自的编解码器驱动程序为 ADX 的每个实例注册,并用于配置音频数据的路径、特性和处理方法。下表列出了 ADX 模块的每个实例的特定于实例的混音器控件。

混音器控件 *

描述

可能的值

ADX<i> Mux

选择 ADX 输入从中接收数据的 AHUB 客户端设备。

使用此命令获取可能的值

amixer -c APE cget name="ADX<i> Mux"

ADX<i> 输入音频通道

配置输入流的通道数。

0-16

ADX<i> 输出<j> 音频通道

配置输出流的通道数。

0-16

ADX<i> 字节映射 <byte_num>

配置字节映射(请参阅 字节映射配置

0-255

* <i> 指的是 ADX 客户端的实例 ID,<j> 指的是输出端口 ID。

ADX 模块的用法和示例可以在 示例:ADX 中找到。

I2S#

I2S 编解码器驱动程序支持双向数据流,因此定义了 CIF 和 DAP RX/TX DAPM 小部件,其中 I2S 的 CIF 侧与 XBAR 接口,DAP 侧与 IGX Orin 设备上的物理编解码器接口。

使用这些 DAPM 小部件建立的 DAPM 路由在下图中显示为虚线。I2S 模块还公开内核控制以启用内部 I2S 环回。

I2S codec driver (I2S)

I2S 控制器实现全双工和半双工点对点串行接口。它可以与兼容 I2S 的产品接口,例如数字录音带设备、数字声音处理器、调制解调器和蓝牙芯片。

I2S 编解码器驱动程序支持以下功能

  • 可以作为主设备和从设备运行

  • 支持以下数据传输模式

    • LRCK 模式:I2S 模式、左对齐模式 (LJM) 或右对齐模式 (RJM)

    • FSYNC 模式:DSP A 或 B 模式

  • 可以发送和接收数据

    • 样本大小:8 位 (S8)、16 位 (S16_LE) 或 24/32 位 (S32_LE)

    • 采样率:8000、11025、16000、22050、24000、32000、44100、48000、88400、96000、176400 或 192000 Hz

    • 通道:LRCK 模式支持立体声数据;DSP A 和 B 模式支持 1 到 16 个通道

设备树条目#

此 I2S 节点条目在给定的芯片上启用给定的 I2S 实例

aconnect@2a41000 {
    compatible = "nvidia,tegra234-aconnect",
                 "nvidia,tegra210-aconnect";
    status = "okay";
    ...
    tegra_ahub: ahub@2900800 {
        compatible = "nvidia,tegra234-ahub";
        status = "okay";
        ...
        tegra_i2s1: i2s@2901000 {
            compatible = "nvidia,tegra234-i2s",
                         "nvidia,tegra210-i2s";
            reg = <0x0 0x2901000 0x0 0x100>;
            clocks = <&bpmp TEGRA234_CLK_I2S1>,
                     <&bpmp TEGRA234_CLK_I2S1_SYNC_INPUT>;
            clock-names = "i2s", "sync_input";
            assigned-clocks = <&bpmp TEGRA234_CLK_I2S1>;
            assigned-clock-parents =
                <&bpmp TEGRA234_CLK_PLLA_OUT0>;
            assigned-clock-rates = <1536000>;
            sound-name-prefix = "I2S1";
            #sound-dai-cells = <1>;
            nvidia,ahub-i2s-id = <0>;
            status = "okay";
        };
        ...
    };
};

上面的代码片段来自 IGX Orin 的设备树结构。地址和一些其他属性是 IGX Orin 设备特定的,并且可能被相应的 IGX Orin 设备树文件引用。在 I2S 的情况下,上面的设备条目指定了设备所需的时钟名称、每个时钟的来源以及属于设备的寄存器基地址和地址范围。可以调整其他属性(如 fsync-width)以适应用例的要求。

混音器控制#

混音器控件由各自的编解码器驱动程序为 I2S 的每个实例注册,并用于配置音频数据的路径、特性和处理方法。下表列出了特定于实例的混音器控件。

混音器控件 *

描述

可能的值

I2S<i> 环回

启用内部 I2S 环回。

OnOff

I2S<i> 播放音频位格式

配置播放样本位的长度。

16 或 32

I2S<i> 捕获音频位格式

配置捕获样本位的长度。

16 或 32

I2S<i> 客户端位格式

配置客户端侧播放/捕获样本位的长度

16 或 32

I2S<i> FSYNC 宽度

以位时钟为单位配置帧同步信号的宽度。

0-255

I2S<i> 采样率

配置音频流的采样率。

8000、11025、16000、22500、24000、32000、44100、48000、88400、96000、176400 或 192000 Hz

I2S<I> 播放音频通道

配置音频播放流的通道数。

0-16

I2S<I> 捕获音频通道

配置音频捕获流的通道数。

0-16

I2S<I> 客户端通道

配置客户端侧音频播放/捕获流的通道数

0-16

I2S<i> 捕获立体声到单声道

配置应用于捕获流的立体声到单声道转换方法。

CH0CH1AVG

I2S<i> 捕获单声道到立体声

配置应用于捕获流的单声道到立体声转换方法。

ZeroCopy

I2S<i> 播放立体声到单声道

配置应用于播放流的立体声到单声道转换方法。

CH0CH1AVG

I2S<i> 播放单声道到立体声

配置应用于播放流的单声道到立体声转换方法。

ZeroCopy

I2S<i> 播放 FIFO 阈值

配置 CIF 的 FIFO 阈值以开始播放。

0-63

I2S<i> BCLK 比率阈值

I2S BCLK(位时钟)乘数

1、2 …

I2S<i> 编解码器帧模式

配置 I2S 帧模式。dsp-a 指的是 1 的数据偏移,dsp-b 指的是 0 的数据偏移。

Nonei2sleft-jright-jdsp-adsp-b

I2S<i> 编解码器主模式

配置 I2S 编解码器的操作模式(位主模式、位从模式帧从模式或帧主模式)。

Nonecbm-cfmcbs-cfs

I2S<i> Mux

选择 I2S 输入从中接收数据的 AHUB 客户端设备。

使用此命令获取可能的值

amixer -c APE cget name="I2S<i> Mux"

* <i> 指的是 ADX 客户端的实例 ID,<j> 指的是输出端口 ID。

有关 I2S 模块的用法和示例,请参阅 示例:I2S

混音器#

混音器混合来自任何 10 个输入端口(从 XBAR 接收数据)的音频流到任何 5 个输出端口(将数据传输到 XBAR)。下图显示了混音器的 DAPM 小部件和路由。混音器驱动程序还公开了 RX Gain 和 Mixer Enable 作为额外的 kcontrols,分别用于设置每个输入流的音量和全局启用或禁用混音器。

Mixer module
支持的功能#
  • 支持混合最多 10 个输入流

  • 支持五个输出,每个输出可以是 10 个输入流的任意组合的混合

  • 可以发送和接收

    • 采样大小:8、16、24 或 32

    • 采样率:8000、11025、16000、22500、24000、32000、44100、48000、88400、96000 或 192000 Hz

    • 通道:1-8

  • 每个流也提供固定增益

混音器控制#

混音器控制由相应的编解码器驱动程序为混音器的每个实例注册。它们用于配置音频数据的路径、特性和处理方法。下表列出了实例特定的混音器控制。

混音器控件 *

描述

可能的值

MIXER1 RX<i> Mux

选择 I2S 输入从中接收数据的 AHUB 客户端设备。

运行此命令以获取可能的值

amixer -c APE cget name="MIXER1 RX<i> Mux"

MIXER1 混音器启用

启用混音器。

OnOff

MIXER1 Adder<j> RX<i>

在加法器 <j> 上启用输入流 <i>

OnOff

MIXER1 RX<i> 音频通道

配置输入流的通道数。

0-8

MIXER1 TX<j> 音频通道

配置输出流的通道数。

0-8

MIXER1 RX<i> 增益

配置输入流在加法器中相加之前的增益。

0-131072

MIXER1 RX<i> 瞬时增益

配置输入流在加法器中相加之前的增益。

0-131072

* <i> 指的是混音器的输入端口,<j> 指的是混音器的输出端口。

有关混音器模块的使用和示例,请参阅 示例:混音器

SFC#

采样频率转换器 (SFC) 将输入采样频率转换为所需的采样率。 SFC 有一个输入端口和一个输出端口,它们连接到 XBAR。

Sampling Frequency Converter (SFC) module
支持的功能#
  • 高达两个通道(立体声)的流的采样频率转换

  • 极低延迟(最大延迟小于 125 微秒)

  • 支持的频率转换如下表所示。当输入和输出频率相同时,频率转换将被绕过。

支持的频率转换#

Fs 输入 →

8

11.025

16

22.05

24

32

44.1

48

88.2

96

176.4

192

Fs 输出 ↓

8

不适用

11.025

不适用

16

不适用

22.05

不适用

24

不适用

32

不适用

44.1

不适用

48

不适用

88.2

不适用

96

不适用

176.4

不适用

192

不适用

SFC 的混音器控制#

混音器控制由相应的编解码器驱动程序为 SFC 的每个实例注册。它们用于配置音频数据的路径、特性和处理方法。下表列出了实例特定的混音器控制。

混音器控件 *

描述

可能的值

SFC<i> Mux

选择 I2S 输入从中接收数据的 AHUB 客户端设备。

使用此命令获取可能的值

amixer -c APE cget name="SFC<i> Mux"

SFC<i> 初始化

启用 SFC 的实例。

OnOff

SFC<i> 输入采样率

配置输入流的采样率。

8000、11025、16000、22050、24000、32000、44100、48000、88200、96000、176400 或 192000  Hz

SFC<i> 输出采样率

配置输出流的采样率。

8000、11025、16000、22050、24000、32000、44100、48000、88200、96000、176400 或 192000 Hz

SFC<i> 输入音频通道

配置输入流的通道数。

1, 2

SFC<i> 输出音频通道

配置输入流的通道数。

1, 2

SFC<i> 输入音频位格式

配置输入流的采样大小。

16 或 32

SFC<i> 输出音频位格式

配置输出流的采样大小。

16 或 32

SFC<I> 输入立体声转单声道

配置输入流的立体声转单声道转换

CH0CH1AVG

SFC<I> 输入单声道转立体声

配置输入流的单声道转立体声转换

ZeroCopy

SFC<I> 输出立体声转单声道

配置输出流的立体声转单声道转换

CH0CH1AVG

SFC<I> 输出单声道转立体声

配置输出流的单声道转立体声转换

ZeroCopy

* <i> 指的是 SFC 的实例 ID。

有关 SFC 模块的使用和示例,请参阅 示例:SFC

MVC#

MVC(音量控制)对数字信号路径应用增益或衰减。 MVC 模块是一个通用模块。它可以用于应用音量控制

  • 到输入或输出数字信号路径

  • 每个流和所有流(主音量控制)

下图显示了 MVC 的 DAPM 组件和路由。

Primary volume control (MVC) module
支持的功能#
  • 数据格式的可编程音量增益

    • 采样大小:8、16、24 或 32 位

    • 采样率:8000、11025、16000、22050、24000、32000、44100、48000、88400、96000、176400 或 192000 Hz

    • 通道:1-8

  • 音量控制的可编程曲线斜坡

  • 单独的静音和取消静音控制

混音器控制#

混音器控制由相应的编解码器驱动程序为 MVC 的每个实例注册。它们用于配置音频数据的路径、特性和处理方法。下表列出了实例特定的混音器控制。

混音器控件 *

描述

可能的值

MVC<i> 音量

配置主音量

0 到 16000

(表示 -120 到 +40 dB,比例因子为 100x)

MVC<i> 通道<j> 音量

配置特定通道的音量

0 到 16000

(表示 -120 到 +40 dB,比例因子为 100x)

MVC<i> 静音

启用/禁用主静音

OnOff

MVC<i> 每通道静音掩码

控制特定通道的静音/取消静音

0 到 255

MVC<i> 曲线类型

配置音量斜坡曲线类型

PolyLinear

MVC<i> 音频通道

配置通过 MVC 的音频数据的通道

0-8

MVC<i> 音频位格式

配置通过 MVC 的输入音频数据的采样大小

16 或 32

MVC<i> 位

配置通过 MVC 的输出音频数据的采样大小

OSR_64OSR_128OSR_256

MVC<i> Mux

选择 MVC 输入接收数据的 AHUB 客户端设备。

使用此命令获取可能的值

amixer -c APE cget name="MVC<i> Mux"

* <i> 指的是 MVC 客户端的实例 ID,<j> 指的是通道号

有关 MVC 模块的使用和示例,请参阅 示例:MVC

AHUB 客户端 TX 端口名称#

这是 AHUB 客户端 TX 端口名称的列表。

AHUB 客户端

TX 端口名称 *

ADMAIF

ADMAIF<i>

I2S

I2S<i>

AMX

AMX<i>

ADX

ADX<i> TX1ADX<i> TX2ADX<i> TX3ADX<i> TX4

SFC

SFC<i>

MVC

MVC<i>

MIXER

MIXER1 TX1MIXER1 TX5

* <i> 代表给定 AHUB 客户端的实例 ID。

ASoC 机器驱动程序#

ASoC 机器驱动程序通过链接每个模块公开的 DAI 来连接编解码器驱动程序和 PCM 驱动程序。它实例化声卡(ASoC 架构中的软件组件)。

ASoC 核心中的结构 snd_soc_dai_link 定义了一个链接,该链接连接来自不同模块的两个 DAI。这种链接称为 DAI 链接。给定的机器驱动程序可以有一个或多个 DAI 链接,这些链接在运行时连接以形成音频路径。

简而言之,ASoC 机器驱动程序的功能是:

  • 从 DT 解析所有 DAI 链接。这些链接包括 SoC 内部 DAI 链接(XBAR 和各种 AHUB 模块之间的链接)以及 IGX Orin 设备特定的 SoC I/O 模块与外部音频编解码器之间的 DAI 链接。

  • 从设备树 (DT) 解析 DAPM 组件和路由,这些组件和路由是将机器源/宿组件与编解码器端点连接起来所必需的。例如,机器组件是为耳机插孔、扬声器和麦克风定义的。这些组件又映射到相应的音频编解码器输入和输出。

  • 配置音频处理引擎 (APE) 子系统和编解码器时钟。

  • 传播运行时 PCM 参数,例如 sample-ratesample-size

IGX Orin ASoC 机器驱动程序位于内核源代码存档中的以下位置

kernel/nvidia-oot/sound/soc/tegra/tegra_machine_driver.c

所有 DAI 链接都在 <kernel_source>/sound/soc/tegra/machine_drivers/ 中定义

hardware/nvidia/t23x/nv-public/overlay/tegra234-soc-audio-dai-links.dtsi

所有 I/O DAI 链接默认连接到虚拟端点。即使没有外部设备,这也允许 SoC 驱动接口引脚。这些具有 phandle 引用,可以轻松地用于覆盖特定属性。简而言之,如果用户想要连接到特定的外部编解码器,则必须覆盖设备树中相应的 DAI 链接。

例如,I2S1 DAI 连接到虚拟编解码器,如下所示

i2s1_to_codec: nvidia-audio-card,dai-link@76 {
    status = "okay";

    format = "i2s";
    link-type = <C2C_LINK>;
    i2s1_cpu: cpu {
        sound-dai = <&tegra_i2s1 I2S_DAP>;
    };
    codec {
        sound-dai = <&tegra_i2s1 I2S_DUMMY>;
    };
};

DAI 节点的定义#

I2S 接口的每个 DAI 链接都必须由 DAI 节点定义,该节点是声音节点的子节点。 DAI 节点的总体格式在 ASoC 机器驱动程序 中描述。

对于每个 I2S 接口 DAI 链接,您必须配置以下属性

  • bitclock-masterframe-master:可选布尔值;指定编解码器是主设备还是从设备。如果存在这些属性,则编解码器是 I2S 位时钟和帧主设备,如果不存在,则是 I2S 从设备。

  • format:配置 CPU/CODEC 通用音频格式。该值可以是 i2sright_jleft_jdsp_adsp_b

  • bclk-ratio:用于配置 I2S 位时钟速率的整数。 I2S 位时钟速率是此值和流采样率的乘积。值为 0 会产生与 1 相同的时钟速率。

  • srate:PCM 数据流采样率

  • bit-format:数据流采样大小

  • num-channel:数据流通道数

时钟和电源管理#

以下 debugfs 节点列表(从 /sys/kernel/debug/clk/clk_summary 获取)显示了 IGX Orin 的 ASoC 驱动程序在空闲状态下的时钟树,此时没有音频播放或捕获操作正在进行。

时钟

enable_cnt

prepare_cnt

速率

req_rate

精度

相位

i2s6_sync_input

0

0

0

0

0

0

i2s5_sync_input

0

0

0

0

0

0

i2s4_sync_input

0

0

0

0

0

0

i2s3_sync_input

0

0

0

0

0

0

i2s2_sync_input

0

0

0

0

0

0

i2s1_sync_input

0

0

0

0

0

0

dmic4_sync_clk

0

0

0

0

0

0

dmic3_sync_clk

0

0

0

0

0

0

dmic2_sync_clk

0

0

0

0

0

0

dmic1_sync_clk

0

0

0

0

0

0

i2s6_sync_clk

0

0

0

0

0

0

i2s5_sync_clk

0

0

0

0

0

0

i2s4_sync_clk

0

0

0

0

0

0

i2s3_sync_clk

0

0

0

0

0

0

i2s2_sync_clk

0

0

0

0

0

0

i2s1_sync_clk

0

0

0

0

0

0

pll_a1

0

0

600000000

600000000

0

0

ape

0

0

150000000

150000000

0

0

apb2ape

0

0

150000000

150000000

0

0

pll_a

0

0

258000000

258000000

0

0

dmic4

0

0

12285714

12285714

0

0

dmic3

0

0

12285714

12285714

0

0

dmic2

0

0

12285714

12285714

0

0

dmic1

0

0

12285714

12285714

0

0

i2s6

0

0

23454545

23454545

0

0

i2s5

0

0

23454545

23454545

0

0

i2s4

0

0

23454545

23454545

0

0

i2s3

0

0

23454545

23454545

0

0

i2s2

0

0

23454545

23454545

0

0

i2s1

0

0

23454545

23454545

0

0

ahub

0

0

86000000

86000000

0

0

各个模块(AMX、ADX、AFC、SFC、MIXER 等)的时钟由 APE 时钟内部驱动。

所有编解码器驱动程序(I2S、XBAR 等)的时钟在空闲状态下都已关闭。当音频播放或捕获开始时,它们会被打开。

动态 PLL_A 速率更新#

PLL_A 是 IGX Orin 处理器为音频需求提供的时钟源。其主要功能是为 I2S 模块提供时钟。 AUD_MCLK 时钟也来自 PLL_A

IGX Orin 设备支持两个采样率系列

  • 8 Kbps 的倍数 (8x):8000、16000、24000、32000、48000、96000 和 192000 Hz

  • 11.025 Kbps 的倍数 (11.025x):11025、22050、44100、88200 和 176400 Hz

单个 PLL_A 基准速率无法支持这两个速率系列。因此,8x 和 11.025x 使用单独的基准速率。机器驱动程序在运行时根据传入流的采样率设置 PLL_A 的速率。因此,用户可以播放和捕获上面列表中任一速率的声音。

高清晰度音频#

IGX Orin 设备通过板载 HDMI 和 DP 端口支持一个或多个高清晰度音频 (HDA) 接口。这些接口可用于在电视和 A/V 接收器等设备上执行高质量音频渲染。这些 HDA 接口在 IGX Orin 上可用

  • 一个 DP 输出(可以支持单流或多流)

  • 一个用于 HDMI-IN 的 HDMI 输入。

HDMI 和 DP 接口可以使用相应的连接器进行连接。

支持的功能#

IGX Orin 高清晰度音频支持以下功能

  • 符合高清晰度音频规范修订版 1.0

  • 支持 HDMI 1.3a 和 DP

  • 音频格式支持

    • 通道:2 到 8

    • 采样大小:16 位 (S16_LE) 或 24 位 (S32_LE)

    • 采样率

      • 32000、44100、48000、88200、96000、176400 或 192000 Hz (HDMI)

      • 32000、44100、48000、88200 或 96000 Hz (DP)

如果在播放高分辨率音频格式(使用多通道输出或高采样率)时遇到问题,即使您的显示器支持音频格式,这也是因为可用的音频带宽取决于 HDMI 配置,并随着更高的显示分辨率而增加。

如果您在播放高分辨率音频格式时遇到问题,NVIDIA 建议您将显示分辨率设置为至少与下表中的音频格式相对应的级别。此表取自 HDMI 1.3a 规范文档

注意

双通道 PCM 永远不能超过 192 kHz。更高的值表示可用于压缩流的更高帧速率。

建议的显示分辨率#

显示分辨率

格式时序

像素重复

最大 fs 8 通道 (Hz)

最大帧速率 2 通道压缩

SuperAudio CD 通道数

VGA

640 x 480p

48000

192

2

240p

1440 x 240p

2

88200

192

2

240p

2880 x 240p

4

192000

768

8

480i

1440 x 480i

2

88200

192

2

480i

2880 x 480i

4

192000

768

8

480p

720 x 480p

48000

192

2

480p

1440 x 480p

2

176400

384

8

480p

2880 x 480p

4

192000

768

8

720p

1280 x 720p

192000

768

8

1080i

1920 x 1080i

192000

768

8

1080p

1920 x 1080p

192000

768

8

软件驱动程序详细信息#

HDA 接口可通过标准 ALSA 接口访问。使用 aplay 实用程序进行音频渲染

$ aplay -Dhw:HDA,<devID> <wav_in>

其中

  • <deviceID> 是声音接口的设备 ID。

  • <wav_in> 是要播放的声音文件的名称。它应该是一个 .wav 文件。

以下是有关驱动程序使用的一些更多详细信息

  • 所有 HDA 接口都在一张卡下可用。

  • /proc/asound/cards 读取卡详细信息。

  • 要查看 /proc/asound/card<n>/ 下可用的 PCM 设备(即 HDA 接口)。

  • AHUB 支持 S16_LE 格式的 16 位音频,以及 S32_LE 格式的 20 或 24 位音频。

USB 音频#

所有 IGX Orin 设备都提供 USB 主机接口,用于连接各种 USB 设备,包括 USB 音频设备,如扬声器、麦克风和耳机。

支持的功能#

IGX Orin 高清晰度音频支持以下功能

  • 通道:最多 8 个

  • 采样大小:16 位 (S16_LE) 或 24 位 (S24_3LE)

  • 采样率:32000、44100、48000、88200、96000、176400 或 192000  Hz

支持的音频格式由连接的 USB 音频设备决定。

软件驱动程序详细信息#

USB 音频可通过标准 ALSA 接口访问。分别使用 aplayarecord 实用程序来渲染和捕获音频

$ aplay -Dhw:<cardID>,<devID> <file_wav>
$ arecord -Dhw:<cardID>,<devID> -r <rate> -c <chan> -f <format> <file_wav>

其中

  • <cardID> 是卡 ID,一个标识声卡类型的字符串:APEHDA

  • <devID> 是设备 ID。

  • <file_wav> 是输入文件(对于 aplay)或输出文件(对于 arecord)的名称。它必须是一个 WAV 文件。

  • <rate> 是采样率。

  • <chan> 是音频通道数。

  • <format> 是采样格式

以下是有关驱动程序使用的一些更多详细信息

  • USB 音频卡在连接 USB 设备(例如 USB 耳机)时枚举。

  • /proc/asound/cards 读取卡详细信息。

  • 要查看 /proc/asound/card<n>/ 下可用的 PCM 设备。

内置音频编解码器#

播放和捕获插孔端口在内部连接到 IGX Orin 上的 RT5640 编解码器。

支持的音频格式#

IGX Orin ASoC 驱动程序支持以下格式

  • 采样大小:8 位 (S8)、16 位 (S16_LE) 或 24/32 位 (S32_LE)

  • 采样率:8000、11025、16000、22050、24000、32000、44100、48000、88400、96000、176400 或 192000 Hz

  • 通道:1 或 2

使用指南#

要建立通过接头的播放或录音的音频路由,需要为 IGX Orin 设备和板载编解码器配置多个 ALSA 混音器控件。默认情况下,音频路由设置为 线路输出麦克风 路径。

播放和捕获命令#

播放

$ aplay -D hw:APE,0 <in_wav>

捕获

$ arecord -Dhw:APE,0 -c <channels> -r <rate> -f <format> -d <duration> <out_wav>

HDMI IN 捕获#

考虑到 HDMI IN 信号存在以开始音频捕获

# AHUB Mixer Controls (apply on IGX Orin)
$ amixer -c APE cset name="ADMAIF2 Mux" "I2S6"
$ amixer -c APE cset name="I2S6 codec master mode" "cbm-cfm"

# Start capture
$ arecord -Dhw:APE,1 -c 2 -r 48000 -f S16_LE -d 15 <out_wav>

使用和示例#

本节给出了设备 I/O 接口和 AHUB 模块如何在音频应用中使用的示例。

这显示了来自 IGX Orin 设备的声卡描述的转储。

注意

该示例使用特定的 ADMAIF,但您可以选择任何您想要的 ADMAIF。

$ cat /proc/asound/cards

 0 [HDA            ]: tegra-hda - NVIDIA IGX Orin HDA
                      NVIDIA Jetson IGX Orin HDA at 0x3518000 irq 122
 1 [APE            ]: tegra-ape - NVIDIA IGX Orin APE
                      Unknown-JetsonIGXOrinDeveloperKit-NotSpecified

对于每个声卡,转储显示:

  • 初始数字是声卡的索引,从 0 开始的顺序编号。

  • 方括号中的单词是卡 ID(“卡标识符”),一个标识声卡的字符串。尾随空格不是卡 ID 的一部分。

  • tegra-hdategra-ape 是 ALSA 卡驱动程序名称,即与声卡关联的机器驱动程序名称。在 IGX Orin 设备上,HDA 声卡使用 tegra-hda,APE 声卡使用 tegra-ape

  • “NVIDIA IGX Orin HDA” 和 “…APE”:声卡的简称,并被认为是声卡的名称。

  • “NVIDIA IGX Orin HDA at 0x3518000 irq 118” 和 “…APE”:声卡的长名称。

注意

该示例显示了两种类型的声卡,它们内置于 IGX Orin AHUB 架构中,并使用 NVIDIA 提供的驱动程序。 IGX Orin 设备可能具有其他类型。例如,如果您将 USB 耳机连接到设备,则转储也会显示 USB 声卡。

USB 声卡名称取决于声卡的供应商和型号。像上面这样的转储可以帮助您确定 USB 声卡的长名称。

下表列出了在不同的 IGX Orin 设备上用于 APE 和 HDA 卡的短名称。

板名称

APE 卡名称

HDA 卡名称

USB 卡名称

IGX Orin

NVIDIA IGX Orin APE

NVIDIA IGX Orin HDA

对于插入设备后的名称,运行 /proc/asound/cards

除了名称之外,每个声卡都有一个设备 ID,如下表所示。

对于 APE 卡,设备 ID 指的是正在使用的 ADMAIF 通道索引。 IGX Orin 设备有 20 个 ADMAIF 通道,每个通道都与一个播放设备和一个捕获设备相关联。每个设备的设备 ID 范围为 0 到 19。

要确定有多少声卡可用,请输入

$ cat /proc/asound/cards

此命令显示最后一个声卡的索引,该索引比声卡数量少 1。例如,如果 /proc/asound/cards 包含“2”,则 IGX Orin 设备有三个声卡,卡索引为 0、1 和 2。

要列出所有可用 PCM 声卡的设备 ID,请输入

$ ls /dev/snd/pcmC?D*

这是一种获取给定卡的可用设备 ID 的便捷方式。如果您知道卡的索引,则可以使用它来代替“?”。但是请注意,声卡索引是按照内核在启动时注册声卡的顺序分配的,因此给定的卡 ID 可能不代表每次启动都相同的卡。

要显示特定 PCM 声卡的描述,请输入

$ cat /dev/snd/pcmC<n>D<devID><f>

其中

  • <n> 是卡的索引,0 或 1。

  • <devID> 是卡的设备 ID

  • <f> 是此设备的功能,c 表示“捕获”,p 表示“播放”。

下表列出了 HDA 设备的端口到 <devID> 映射,其中不同的 HDA 端口映射到特定的 <devID> 值。

端口到设备 ID 映射

设备

端口名称

PCM 设备 ID

IGX Orin

DP

3(DP 单流)

3 和 7(DP 多流)

HDMI

HDMI IN

以下是几种不同类型接口的设备名称用法的示例。在这些示例中

  • <i><i−1> 分别是要使用的 ADMAIF 通道号,以及该数字减 1。

  • <in_wav><out_wav> 分别是输入和输出声音文件的路径名。两者都必须是 .wav 文件。

  • <rate> 是要使用的采样率。

  • <bits> 是每个采样的位数。

  • <channels> 是要使用的通道数。

示例:I2S#

这些示例说明了使用 I2S2 和 ADMAIF<i> 的各种 I/O 播放和捕获。

播放#

使用 I2S2 和 ADMAIF<i> 进行播放

$ amixer -c APE cset name="I2S2 Mux" ADMAIF<i>
$ aplay -D hw:APE,<i-1> <in_wav>

捕获#

使用 I2S2 和 ADMAIF<i> 进行捕获

$ amixer -c APE cset name="ADMAIF<i> Mux" I2S2
$ arecord -D hw:APE,<i-1> -r <rate> -c <channels> -f <sample_format> <out_wav>

内部环回#

使用 I2S2 和 ADMAIF<i> 进行内部环回

$ amixer -c APE cset name="I2S2 Mux" "ADMAIF<i>"
$ amixer -c APE cset name="ADMAIF<i> Mux" "I2S2"
$ amixer -c APE cset name="I2S2 Loopback" "on"
$ aplay -D hw:APE,<i-1> <in_wav> &
$ arecord -D hw:APE,<i-1> -r <rate> -c <channels> -f <sample_format> <out_wav>

多通道 (TDM) 捕获#

要在 I2S4 上通过 ADMAIF 执行 TDM 捕获,请输入以下命令

$ amixer -c APE cset name="ADMAIF<i> Mux" "I2S4"
$ amixer -c APE cset name="I2S4 codec master mode" "cbs-cfs"
$ amixer -c APE cset name="I2S4 codec frame mode" "dsp-a"
$ amixer -c APE cset name="I2S4 FSYNC width" 0
$ arecord -D hw:APE,<i-1> -r <rate> -c <channels> -f <sample_format> <out_wav>

其中

  • <i><i-1> 分别代表 ADMAIF 实例编号和该数字减 1。

  • 可以更改 I2S4 的最后一位数字以使用不同的通道。

请注意,“I2S4 编解码器帧模式”和“I2S4 fsync 宽度”必须根据编解码器数据表中的 I2S 时序图设置为相对于 fsync 和 fsync 宽度的数据偏移。“I2S4 编解码器主模式”必须按照操作模式(主/从)进行设置。有关混音器控件的更多详细信息,请参阅 编解码器驱动程序、I2S、混音器控件

示例:MVC#

以下示例显示了如何应用增益以及如何静音和取消静音流。 MVC 最多支持八个通道,并可以控制每个通道的增益和静音/取消静音。

将增益应用于播放流#

此命令模型显示了如何在 I2S 播放期间使用 MVC 模块来控制音量

$ amixer -c APE cset name="MVC1 Mux" ADMAIF<i>
$ amixer -c APE cset name="I2S1 Mux" MVC1
$ amixer -c APE cset name="MVC1 Volume" <Q8.24_Val>
$ aplay -D hw:APE,<i-1> <in_wav>

MVC 模块支持每通道音量控制。也就是说,它可以对每个通道应用不同的增益因子。要设置每通道音量,请使用此混音器控件

$ amixer -c APE cset name="MVC1 Channel<x> Volume" <Q8.24_Val>

其中 <x> 是 MVC 通道号(1、2 … 8)。

静音和取消静音通道#

此示例显示了如何在 I2S 播放期间静音和取消静音通道

$ amixer -c APE cset name="MVC1 Mux" ADMAIF<i>
$ amixer -c APE cset name="I2S1 Mux" MVC1
$ amixer -c APE cset name=”MVC1 Per Chan Mute Mask” <mask>
$ aplay -D hw:APE,<i-1> <in.wav>

其中 <mask> 是静音/取消静音掩码值。该掩码支持每通道静音控制。掩码的值可以是 0 到 255(0x0 到 0xFF);要静音流的通道n,请将位n设置为 1。同样,要取消静音流的通道n,请将位n设置为 0。

示例:AMX#

这些部分提供了复用两个和三个流以及将一个立体声流解复用为两个单声道流的使用示例。

复用两个流#

此示例显示了如何使用 AMX 模块来复用两个立体声流,ADMAIF1 和 ADAMIF2

$ amixer -c APE cset name="AMX2 RX1 Mux" "ADMAIF1"
$ amixer -c APE cset name="AMX2 RX2 Mux" "ADMAIF2"
$ amixer -c APE cset name="AMX2 Output Audio Channels" 4
$ amixer -c APE cset name="ADMAIF<i> Mux" AMX2
$ amixer -c APE cset name="ADMAIF<i> Playback Audio Channels" 4
$ amixer -c APE cset name="ADMAIF<i> Capture Audio Channels" 4
$ amixer -c APE cset name="ADMAIF<i> Playback Client Channels" 4
$ amixer -c APE cset name="ADMAIF<i> Capture Client Channels" 4
$ amixer -c APE cset name="AMX2 Byte Map 0" 0
$ amixer -c APE cset name="AMX2 Byte Map 1" 1
$ amixer -c APE cset name="AMX2 Byte Map 2" 2
$ amixer -c APE cset name="AMX2 Byte Map 3" 3
$ amixer -c APE cset name="AMX2 Byte Map 4" 4
$ amixer -c APE cset name="AMX2 Byte Map 5" 5
$ amixer -c APE cset name="AMX2 Byte Map 6" 6
$ amixer -c APE cset name="AMX2 Byte Map 7" 7
$ amixer -c APE cset name="AMX2 Byte Map 8" 64
$ amixer -c APE cset name="AMX2 Byte Map 9" 65
$ amixer -c APE cset name="AMX2 Byte Map 10" 66
$ amixer -c APE cset name="AMX2 Byte Map 11" 67
$ amixer -c APE cset name="AMX2 Byte Map 12" 68
$ amixer -c APE cset name="AMX2 Byte Map 13" 69
$ amixer -c APE cset name="AMX2 Byte Map 14" 70
$ amixer -c APE cset name="AMX2 Byte Map 15" 71
$ aplay -D hw:APE,0 <in1_wav>
$ aplay -D hw:APE,1 <in2_wav>
$ arecord -D hw:APE,<i-1> -r 48000 -c 4 -f S16_LE <out_wav>

示例:ADX#

此示例显示了如何使用 ADX 模块将 16 位立体声流解复用到 ADMAIF1 和 ADMAIF2 上

$ amixer -c APE cset name="ADX1 Mux" ADMAIF<i>
$ amixer -c APE cset name="ADX1 Input Audio Channels" 2
$ amixer -c APE cset name="ADMAIF1 Mux" "ADX1 TX1"
$ amixer -c APE cset name="ADMAIF2 Mux" "ADX1 TX2"
$ amixer -c APE cset name="ADX1 Output1 Audio Channels” 1
$ amixer -c APE cset name="ADX1 Output2 Audio Channels” 1
$ amixer -c APE cset name="ADX1 Byte Map 0" 0
$ amixer -c APE cset name="ADX1 Byte Map 1" 1
$ amixer -c APE cset name="ADX1 Byte Map 2" 2
$ amixer -c APE cset name="ADX1 Byte Map 3" 3
$ amixer -c APE cset name="ADX1 Byte Map 4" 64
$ amixer -c APE cset name="ADX1 Byte Map 5" 65
$ amixer -c APE cset name="ADX1 Byte Map 6" 66
$ amixer -c APE cset name="ADX1 Byte Map 7" 67
$ aplay -D hw:APE,<i-1> <in_wav>
$ arecord -D hw:APE,0 -r 48000 -c 1 -f S16_LE <out1_wav>
$ arecord -D hw:APE,1 -r 48000 -c 1 -f S16_LE <out2_wav>

示例:SFC#

此示例显示了如何执行从 48000 到 44100 Hz 的采样率转换,并使用 ADMAIF2 进行捕获,其中 ADMAIF3 馈送 SFC1 并生成采样频率转换后的输出

$ amixer -c APE cset name="SFC1 Mux" ADMAIF3
$ amixer -c APE cset name="ADMAIF2 Mux" SFC1
$ amixer -c APE cset name="SFC1 Input Sample Rate" 48000
$ amixer -c APE cset name="SFC1 Output Sample Rate" 44100
$ aplay -D hw:APE,2 <in_wav>
$ arecord -D hw:APE,1 -r 44100 -c <channels> -f <sample_format> <out_wav>

示例:混音器#

此示例显示了如何混合两个输入流,以通过混音器模块的 Adder1 生成单个输出流

$ amixer -c APE cset name="MIXER1 RX1 Mux" ADMAIF1
$ amixer -c APE cset name="MIXER1 RX2 Mux" ADMAIF2
$ amixer -c APE cset name="MIXER1 Adder1 RX1" 1
$ amixer -c APE cset name="MIXER1 Adder1 RX2" 1
$ amixer -c APE cset name="MIXER1 Mixer Enable" 1
$ amixer -c APE cset name="ADMAIF3 Mux" MIXER1 TX1
$ aplay -D hw:APE,0 <inputfile1.wav>
$ aplay -D hw:APE,1 <inputfile2.wav>
$ arecord -D hw:APE,2 -r <rate> -c <channels> -f <sample_format> <out_wav>

示例:HDMI/DP 播放#

此示例显示了如何在 HDMI/DP 设备(例如,带有扬声器的显示器)上执行播放

$ aplay -Dhw:HDA,<devID> <in_wav>

示例:USB#

以下部分提供了 USB 上的播放和捕获的使用示例。

播放#

此示例显示了如何在 USB 设备上执行播放

$ aplay -Dhw:<cardID>,<devID> <in_wav>

捕获#

此示例显示了如何在 USB 设备上执行捕获

$ arecord -Dhw:<cardID>,<devID> -r <rate> -c <channels> -f <sample_format> <out_wav>

故障排除#

本节介绍了一些在使用 ASoC 驱动程序时容易出现的问题,以及它们可能的原因和解决方案。

未找到声卡#

这有几个可能的原因。下面描述了一些典型的原因。在大多数情况下,dmesg 输出可以提供线索。

未找到源/宿组件#

dmesg 输出显示未找到“no source widget”或“no sink widget”,如以下示例日志所示

$ dmesg | grep "ASoC"

tegra-asoc: sound: ASoC: no source widget found for x OUT
tegra-asoc: sound: ASoC: Failed to add route x OUT -> direct -> Headphone Jack
tegra-asoc: sound: ASoC: no sink widget found for x IN
tegra-asoc: sound: ASoC: Failed to add route Mic Jack -> direct -> x IN

在上面的日志中,未找到 x OUT 和 x IN 组件。 ASoC 可能未实例化相应的编解码器。通过检查以下内容来确认这一点

$ cat /sys/kernel/debug/asoc/components

如果未实例化编解码器,则可能是以下原因之一:

  • Linux 内核配置中未启用编解码器。输入以下命令以确定是否启用了编解码器

    $ zcat /proc/config.gz | grep <codec_config>
    

    其中 <codec_config> 是表示 config.gz 中编解码器的配置的名称。如果它尚不可用,则用户必须定义它,并且您必须确保在 Linux 内核配置中启用它。

    输入以下命令以扫描所需的 I2C 总线,并确认正在探测编解码器

    $ i2cdetect -y -r <i2c-bus-number>
    

    如果扫描未指示编解码器存在,则可能是由于连接松动,或者编解码器可能连接到另一个 I2C 总线。要检查后一种原因,请扫描其余可用的 I2C 总线,识别连接到编解码器的总线,并将编解码器设备树节点放置在该 I2C 总线的 DT 节点中。

  • 组件的前缀(在本例中为 x)既不是与 DAI 链接的编解码器子节点的 prefix 条目中指定的前缀相同,也不是与相应编解码器设备节点的 sound-name-prefix 条目下指定的前缀相同。在这种情况下,请适当编辑或覆盖前缀。

CPU DAI 未注册#

dmesg 输出显示未找到“CPU DAI”

$ dmesg | grep "ASoC"
tegra-asoc: sound: ASoC: CPU DAI DAP not registered

在这种情况下,“DAP”是 I2S 到编解码器 DAI 链接的 CPU DAI。

ASoC 可能未实例化 I2S 编解码器。要确定是否实例化了编解码器,请输入命令

$ cat /sys/kernel/debug/asoc/components

如果 I2S 编解码器已实例化,则它的名称类似于 <addr>.i2s,其中 <addr> 是设备 DT 中使用的相应单元地址 (i2s@<addr>)。

识别故障点的 DAI 链路可以提供关于哪个 I2S 实例实例化失败的线索。因此,您可以通过在设备树结构 (DTS) 文件中提供合适的入口点来实例化 I2S 编解码器驱动程序,如使用设备树实例化编解码器驱动程序中所述。

声音不可听或未录制#

请按照以下步骤诊断问题

  1. 确定 DAPM 路径是否已完成。用户可能需要设置一些编解码器特定的混音器控制来启用播放或捕获。从编解码器供应商或编解码器数据手册中获取这些设置。为了跟踪 DAPM 路径,必须在用户运行播放或捕获用例之前启用 DAPM 跟踪事件,使用以下命令

    $ for i in `find /sys/kernel/debug/tracing/events -name "enable" | grep snd_soc_`; do echo 1 > $i; done
    

    如果 DAPM 路径未完成,则用例无法继续。DAPM 路径在以下文件中填充,并在设置时更新

    $ cat /sys/kernel/debug/tracing/trace_pipe | grep \*
    

    以下是通过 IGX Orin 上的麦克风插孔,经由 RT5640 音频编解码器、ADMAIF1 和 I2S1 进行录音的完整 DAPM 路径示例。另一个音频路径会产生类似的转储,具体取决于路径中定义的 widget。为了便于说明,这里是一个经过筛选的日志

    snd_soc_dapm_path: *CVB-RT AIF1 Capture <- (direct) <- CVB-RT AIF1TX
    snd_soc_dapm_path: *CVB-RT AIF1 Capture -> (direct) -> rt5640-playback-capture
    snd_soc_dapm_path: *CVB-RT AIF1TX -> (direct) -> CVB-RT AIF1 Capture
    [ ... ]
    snd_soc_dapm_path: *CVB-RT IN1N -> (direct) -> CVB-RT BST1
    snd_soc_dapm_path: *CVB-RT IN1P -> (direct) -> CVB-RT BST1
    snd_soc_dapm_path: *CVB-RT IN2N -> (direct) -> CVB-RT BST2
    snd_soc_dapm_path: *CVB-RT IN2N -> (direct) -> CVB-RT INR VOL
    snd_soc_dapm_path: *CVB-RT IN2P -> (direct) -> CVB-RT BST2
    snd_soc_dapm_path: *CVB-RT IN2P -> (direct) -> CVB-RT INL VOL
    snd_soc_dapm_path: *CVB-RT Mic Jack -> (direct) -> CVB-RT IN1P
    snd_soc_dapm_path: *CVB-RT Mic Jack -> (direct) -> CVB-RT IN2P
    [ ... ]
    snd_soc_dapm_path: *I2S4 CIF-Capture <- (direct) <- I2S4 TX
    snd_soc_dapm_path: *I2S4 CIF-Capture -> (direct) -> tegra-dlink-64-capture
    snd_soc_dapm_path: *I2S4 DAP-Playback -> (direct) -> I2S4 TX
    snd_soc_dapm_path: *I2S4 DAP-Playback <- (direct) <- rt5640-playback-capture
    snd_soc_dapm_path: *I2S4 XBAR-Playback -> (direct) -> I2S4 XBAR-RX
    snd_soc_dapm_path: *I2S4 XBAR-Playback <- (direct) <- tegra-dlink-64-capture
    

    用户必须确保从源 widget 到 sink widget 存在有效的 DAPM 路径。此转储给出了一个平台 DAPM 路径,其中包含在用例期间激活的所有组件。

  2. 确认音频接口的 status 属性在相应的设备树源文件中设置为 "okay"

    例如,对于 IGX Orin,设备树文件位于

    hardware/nvidia/t23x/nv-public/tegra234-p3701.dtsi
    

    另一种方法是使用以下命令从目标设备检查设备树条目,并找到已刷写的 .dts 文件

    $ dtc -I fs -O dts /proc/device-tree >/tmp/dt.log
    
  3. 使用示波器探测音频信号。

    例如,如果使用 I2S,探测帧同步 (FS) 和位时钟 (BCLK) 以验证时序是否正确。如果 I2S 正在发送数据,探测 FSBCLK 以验证它们是否按预期生成。

I2S 软件复位失败#

一个常见的问题是,当通过 I2S 接口开始播放或捕获时,I2S 软件复位失败。类似这样的错误消息会出现在 dmesg 日志中

tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -22

当 I2S 接口的时钟未激活时,就会发生此问题,因此软件复位失败。这通常发生在 I2S 接口是位时钟从设备,并且位时钟由外部设备(如编解码器)提供时。如果发生此问题,请检查在启动播放或捕获时是否启用了位时钟。

在播放或捕获期间观察到 XRUN#

XRUN 是音频循环缓冲区的下溢(播放时)或上溢(捕获时)。

在播放的情况下,CPU 写入音频循环缓冲区。DMA 读取它,并通过 AHUB 将数据发送到适当的音频接口(I2S 等)。

在捕获的情况下,DMA 将从 AHUB 接收的数据写入音频循环缓冲区,CPU 读取它。

XRUN 事件通常表明 CPU 无法跟上 DMA 的速度。在播放的情况下,DMA 读取过时的数据。在捕获的情况下,数据丢失。因此,XRUN 事件可能表示系统性能或延迟问题,这可能有很多不同的原因。

如果发生 XRUN,请尝试以下措施来确定是否存在性能问题

  • 通过运行 jetson_clocks.sh 启用最大性能。此脚本位于 IGX Orin 设备根文件系统的用户主目录中。

  • 使用 RAM 文件系统来读取和写入音频数据。IGX Orin 设备的默认根文件系统格式是启用了日志功能的 EXT4。在使用诸如 EXT4 等日志文件系统时,已经观察到延迟,并且可能导致 XRUN 事件。输入以下命令以创建一个简单的 100 MB RAM 文件系统

    $ sudo mkdir /mnt/ramfs
    $ sudo mount -t tmpfs -o size=100m tmpfs /mnt/ramfs
    
  • 用户可以增加音频循环缓冲区的大小,以减少系统延迟的影响。缓冲区的默认大小为 32 KB。缓冲区大小由 Linux 内核源文件中的结构 tegra_alt_pcm_hardwarebuffer_bytes_max 成员指定

    kernel/3rdparty/canonical/linux-jammy/kernel-source/sound/soc/tegra/tegra_pcm.c
    

音频爆音和咔嗒声#

爆音和咔嗒声可能在播放或捕获的开始或结束时发生,因为 I2S 在编解码器完全启动或关闭之前就开始发送或接收数据。

以下命令将数据传输或接收延迟指定的毫秒数

$ echo 10 | sudo tee /sys/kernel/debug/asoc/APE/dapm_pop_time

在 NVIDIA 开发者论坛上获取更多帮助#

如果以上步骤均无帮助,请在 NVIDIA 开发者论坛的相应版块发布查询,并提供以下信息

  1. 问题manifest的条件:采样率、采样宽度等。

  2. 混音器控制设置。输入以下命令以显示设置

    $ amixer – c <cardID> contents > ~/settings.txt
    
  3. 内核日志。输入以下命令以显示它

    $ dmesg > ~/kernel_log
    
  4. 设备树日志。输入以下命令以显示它

    $ dtc -I fs -O dts /proc/device-tree >/tmp/dt.log
    
  5. 示波器快照,在适当的分辨率下,有和没有编解码器的情况。

  6. 运行用例时正在使用的 I2S 的寄存器转储,例如

    $ cat /sys/kernel/debug/regmap/<addr>.i2s/registers > ~/reg_dump
    

    其中 <addr> 是 DT 中 I2S 设备的单元地址 (i2s@<addr>)。使用相同的方法查找相应的 regmap 路径。