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