当编解码器是控制器驱动程序的辅助编解码器时,应使用编解码器接口。此接口是由编解码器驱动程序公开的 FIDL 协议。在这种安排中,编解码器驱动程序不会直接公开流式传输接口,而是通过控制器的编解码器接口进行配置。本文档是面向驱动程序作者的参考文档,定义了编解码器驱动程序必须实现且控制器可以使用的接口合约。
符号和术语
在本文档中:
- 所有指数均从 0 开始。
- 包含 n 个元素的向量表示为
<x0,x1,...,xn-1>,例如,包含两个元素 5 和 6 的向量表示为<5,6>。 - 向量可以嵌套,即
<<5,6>,<7,8>>表示包含 2 个向量的向量。
| 术语 | 定义 |
|---|---|
| 频道 | 单个音频样本源或目标,通常由单个扬声器呈现或由单个麦克风捕获。在 DAI 中,每个帧都将在固定数量的槽中包含固定数量的渠道的样本。 |
| 编解码器 | 一种真实或虚拟设备,可将信号从数字/模拟编码/解码为模拟/数字,包括所有组合,例如数字到数字。编解码器的示例包括 DAC-放大器组合和 ADC 转换器。 |
| 控制器 | 系统中用于管理音频信号的部分,例如 SOC 的音频子系统或独立的声卡。 |
| DAI | 数字音频接口。音频硬件之间的接口,例如控制器和编解码器之间的 TDM 或 PDM 链路。 |
| Frame | DAI 中数据、帧同步和 SCLK 的单个时间点的表示。 |
| 帧同步 | 用于标记帧边界的 DAI 信号,也称为 LRCLK、SYNC。 |
| 帧格式 | 帧的数据、帧同步和 SCLK 排列,例如数据线中相对于样本的帧同步位置。 |
| Mclk | 主时钟,一种有时需要提供给编解码器的 DAI 信号。有时,Sclk 用作 Mclk(或 Mclk 从编解码器内的 Sclk 派生而来)。 |
| PDM | 脉冲密度调制。用于表示模拟信号的调制形式,例如用于数字麦克风接口。 |
| 示例 | 在特定时间采集的声音的数字表示形式。 |
| Sclk | 一种用于标记数据线(时钟)位传输的 DAI 信号,也称为 SCK、BCLK。 |
| Slot | 帧内为样本预留的位。一个 slot 可能比容纳样本所需的空间更大,例如,32 位 slot 容纳 24 位或 16 位样本。 |
| TDM | 时分多路复用。将不同的数据流多路复用到一个音频接口中,包括 Sclk、帧同步以及输入和输出数据信号。 |
基本操作
编解码器提供的功能分为:
控制器负责配置和控制编解码器。编解码器会宣传其功能,控制器会确定如何使用这些功能,如下所述。控制器可以控制编解码器的状态,例如通过重置功能。需要重置才能使编解码器进入初始化状态。 请注意,编解码器驱动程序应像任何其他驱动程序一样执行自己的关闭操作。
编解码器是向控制器提供编解码器协议的复合设备。预计只有一个控制器使用编解码器的协议,而一个控制器可以同时使用多个编解码器。
simple-codec 库有助于编写和使用实现编解码器协议的简单编解码器驱动程序。
协议定义
编解码器协议在 codec.fidl 中以 FIDL 形式定义。
请注意,由于 FDF 目前不提供直接获取用于通信的 FIDL 渠道的方法,因此我们在 fuchsia.hardware.audio 中定义了一种通过 Banjo 获取渠道的方法。
许多编解码器协议操作都是“即发即弃”的,也就是说,它们不期望收到回复。如果编解码器协议操作有回复,则在收到函数的回复之前,该操作不会被视为已完成;除非回复包含状态 ZX_OK,否则该操作不会被视为已成功完成。
主要控制
控制器可以随时通过发出 Reset 函数来重置编解码器。
GetInfo 函数从编解码器检索信息,包括:
- 编解码器单元的唯一且持久的标识符,例如序列号或连接路径。
- 制造商名称。
- 商品名称。
可以使用 Start 和 Stop 函数随时启动和停止编解码器操作。默认情况下,编解码器状态为停止,因此必须至少发出一次“开始”命令,编解码器才能完全正常运行。停止编解码器操作可用于安全地更改 DAI 配置,避免编解码器操作出现故障或错误。
桥接模式
在启动时,驱动程序可能会配置为将设备设置为桥接模式,也可能不会。 驱动程序只会宣传在当前配置模式下支持的 DAI 格式。因此,支持的 DAI 格式列表可能会因驱动程序启动配置而异。
DAI 格式
与 DAI 格式相关的协议函数允许编解码器列出其支持的 DAI 格式。支持的格式可能包括多种采样格式、速率等。每种编解码器都会宣传其支持的功能,而控制器会强制规定每种编解码器要使用的 DAI 格式。
为了解给定编解码器支持哪些格式,控制器使用 GetDaiFormats 函数。编解码器会回复一个 DaiSupportedFormats 向量,其中每个 DaiSupportedFormats 都包含:
- 一个渠道数量向量。此属性列出了编解码器支持的声道数,例如
<2,4,6,8>。立体声编解码器报告一个包含一个元素<2>的向量。请注意,如果某个编解码器采用一个声道并将其内容输出到所有输出(例如,立体声放大器的输出为 2),则会报告一个包含一个元素<1>的向量;如果该编解码器支持一个或两个输入声道,则会报告一个包含两个元素<1,2>的向量。 - 示例格式的向量。DAI 示例格式,例如
PCM_SIGNED。 - 帧格式的向量,例如
STEREO_LEFT和STEREO_RIGHT。 - 一个速率向量。帧速率,例如 44100、48000 和 96000。
- 每个 slot 的位数。DAI 中每个 slot 的位数,例如每个 slot 32 位。
- 每个样本的位数向量。样本宽度,例如每个样本 24 位。
如果无法用一个 DaiSupportedFormats 来描述编解码器支持的所有组合,则编解码器会在返回的向量中返回多个 DaiSupportedFormats。
例如,如果某个 DaiSupportedFormats 允许以 48KHz 采样率进行 32 位采样,并允许以 96KHz 采样率进行 16 位采样,但不允许以 96KHz 采样率进行 32 位采样,则编解码器将回复 2 个 DaiSupportedFormats:<<32bits>,<48KHz>> 和 <<16bits>,<96KHz>>。为简单起见,此示例忽略了除速率和每样本位数以外的参数。如果编解码器支持 48 或 96KHz 的 16 位或 32 位采样,则编解码器将回复 1 DaiSupportedFormats:<<16bits,32bits>,<48KHz,96KHz>>。
此外,还假设每个样本的位数始终小于或等于每个时段的位数。因此,编解码器可以报告 <<16bits_per_slot,32bits_per_slot>,<16bits_per_sample,32bits_per_sample>>,但这并不意味着它报告的是 16 位样本上每样本 32 位有效,它仅指定 3 个有效组合:
- 16 位 slot,含 16 位样本
- 32 位时隙,32 位样本
- 32 位时隙,16 位样本
控制器会根据编解码器在 IsBridgeable 和 GetDaiFormat 中提供的信息、控制器支持的格式以及任何其他要求,通过 SetDaiFormat 函数指定要在 DAI 中使用的格式。此函数接受一个用于指定以下内容的参数:
- 频道数量。这是要在 DAI 中使用的渠道数量(例如,TDM 总线上的渠道数量,即“通过线路”)。对于 I2S,此值必须为 2。
- 要使用的渠道的向量。这是编解码器要使用的 DAI 中的声道。对于 I2S,这必须是一个具有 2 个索引
<0,1>的向量,即使用左声道和右声道。在桥接模式下,此属性将仅列出编解码器要使用的一个声道,例如,如果将编解码器的立体声放大器输出桥接到 I2S DAI 右声道的单个电单声道输出,则此属性将仅列出声道<1>。如果未桥接,则配置为在SetDaiFormat中具有一个通道的具有多个电气输出的编解码器应在其所有输出上复制此单声道输入中的样本。 - 示例格式。
- 一种帧格式。
- 帧速率。
- 每个 slot 的位数。
- 每个样本的位数。
SetDaiFormat 成功后,DAI 格式配置即视为完成,并且可以通过 DAI 发送样本。
增益控制
通过任何给定编解码器获得的相关支持由编解码器在响应 GainFormat 结构中的 GetGainFormat 函数时返回。控制器可以使用 SetGainState 函数控制编解码器中的增益、静音和 AGC 状态。
客户端可以使用 WatchGainState 命令请求编解码器向其发送有关增益状态变化的异步通知。驱动程序将回复客户端发送的第一个 |WatchGainState|,并且在增益状态发生变化(与最近报告的状态不同)之前,不会响应后续的客户端 |WatchGainState| 调用。
插头检测
如果驱动程序在 GetPlugDetectCapabilites 中发送了 CAN_ASYNC_NOTIFY 标志,客户端可以使用 WatchPlugState 命令请求编解码器向其发送有关插头状态变化的异步通知。未设置 CAN_ASYNC_NOTIFY 标志的编解码器驱动程序可以忽略客户端发送的 WatchPlugState。如果驱动程序设置了 CAN_ASYNC_NOTIFY,则会回复客户端发送的第一个 |WatchPlugState|,并且在插头状态发生变化(与最近报告的状态不同)之前,不会响应后续的客户端 |WatchPlugState| 调用。
信号处理
在音频信号处理中定义。