批量寄存器访问 (BRA)

约定

本文档中使用的大写单词是有意的,指的是 SoundWire 1.x 规范中的概念。

简介

SoundWire 1.x 规范提供了一种通过回收部分音频带宽来加速命令/控制传输的机制。 批量寄存器访问 (BRA) 协议是基于批量有效负载传输 (BPT) 定义的标准解决方案。

常规控制通道使用 Column 0,并且只能通过写入/读取命令每帧发送/检索一个字节。 对于典型的 48kHz 帧速率,只能传输 48kB/s。

可选的批量寄存器访问功能可以传输高达 12 Mbits/s 的速率,并将传输时间缩短几个数量级,但具有多个设计约束

  1. 每帧只能支持读取或写入传输,每帧有 10 字节的开销(标头和页脚响应)。

  2. 读取/写入操作应在同一帧中从/向连续的寄存器地址进行。 碎片化的寄存器空间会降低协议的效率,因为它需要安排在不同帧中的多个 BRA 传输。

  3. 目标外围设备应支持可选的数据端口 0,同样,管理器应公开类似音频的端口,以使用采样间隔、HSTART、HSTOP 等概念将 BRA 数据包插入到音频有效负载中。

  4. BRA 传输效率取决于可用带宽。 如果没有正在进行的音频传输,则可以回收整个帧(减去 Column 0)用于 BRA。 帧形状也会影响效率:由于 Column0 不能用于 BTP/BRA,因此帧应依赖于大量列并最大限度地减少行数。 总线时钟应尽可能高。

  5. 每帧传输的位数应为 8 位的倍数。 如果需要,应在数据末尾插入填充位。

  6. 常规的读取/写入命令可以与 BRA 传输并行发出。 这对于处理警报、插孔检测或在固件下载期间更改音量非常方便,但必须避免使用两个独立的协议访问同一地址,以避免未定义的行为。

  7. 某些实现可能无法处理 BRA 协议的带宽,例如,在 SoundWire IP 背后存在慢速 I2C 总线的情况下。 在这种情况下,可能需要及时间隔或进行流量控制。

  8. 每个 BRA 数据包在要传输有效数据时应标记为“活动”。 这允许软件分配 BRA 流,但在处理结果或准备下一批数据时,或者允许外围设备处理之前的传输时,不传输/丢弃数据。 此外,可以在数据未准备好时提前启动 BRA 传输。

  9. 每帧最多可以传输 470 个字节。

  10. 地址用 32 位表示,不依赖于用于 Column 0 中常规命令/控制协议的分页寄存器。

错误检查

固件下载是批量寄存器访问协议的关键用法之一。 为了确保二进制数据完整性不受传输或编程错误的影响,每个 BRA 数据包提供

  1. 一个 7 字节标头的 CRC。 此 CRC 帮助外围设备检查它是否被寻址,并设置起始地址和字节数。 外围设备在字节 7 中提供响应。

  2. 数据块(不包括标头)上的 CRC。 此 CRC 作为数据包中的倒数第二个字节传输,在页脚响应之前。

标头响应可以是以下之一
  1. 确认

  2. 否定确认

  3. 未就绪

页脚响应可以是以下之一
  1. 确认

  2. 否定确认(CRC 失败)

  3. 良好(操作完成)

  4. 错误(操作失败)

示例帧

下面的示例未按比例绘制,并且为了清楚起见做出了简化假设。 BRA 数据包中的不同块不需要从新的 SoundWire 行开始,并且数据规模可能会有所不同。

+---+--------------------------------------------+
+   |                                            |
+   |             BRA HEADER                     |
+   |                                            |
+   +--------------------------------------------+
+ C |             HEADER CRC                     |
+ O +--------------------------------------------+
+ M |             HEADER RESPONSE                |
+ M +--------------------------------------------+
+ A |                                            |
+ N |                                            |
+ D |                 DATA                       |
+   |                                            |
+   |                                            |
+   |                                            |
+   +--------------------------------------------+
+   |             DATA CRC                       |
+   +--------------------------------------------+
+   |             FOOTER RESPONSE                |
+---+--------------------------------------------+

假设帧使用 N 列,则可以通过将 DP0 寄存器设置为

  • HSTART = 1

  • HSTOP = N - 1

  • 采样间隔 = N

  • 字长 = N - 1

寻址限制

标头中指定的设备编号遵循 SoundWire 定义,并且允许广播和组寻址。 目前,Linux 实现一次仅允许单个 BPT 传输到单个设备。 稍后可能会重新考虑这一点,作为将相同固件发送到多个设备的优化,但这仅对单链路解决方案有益。

在多个外围设备连接到不同管理器的情况下,SoundWire 规范不支持广播和组寻址。 每个设备必须使用单独的 BRA 流进行处理,可能并行 - 链接实际上是独立的。

不支持的功能

批量寄存器访问规范提供了许多已知实现不支持的功能,例如

  1. 由外围设备启动的传输。 BRA 启动器始终是管理器设备。

  2. 基于“NotReady”标头响应的流量控制功能和重传需要在 SoundWire IP 中进行额外的缓冲,并且未实现。

双向处理

BRA 协议可以处理写入和读取,并且在每个数据包中,标头和页脚响应由外围目标设备提供。 在外围设备上,BRA 协议由单个 DP0 数据端口处理,并且在低级别,总线所有权将针对标头/页脚响应以及读取期间传输的数据而发生变化。

在主机端,大多数实现依赖于类似端口的概念,其中两个 FIFO 并行地消耗/生成数据传输(主机 -> 外围设备和外围设备 -> 主机)。 这些 FIFO 消耗/产生的数据量不对称,因此硬件通常插入标记以帮助软件和硬件解释原始数据

每个数据包通常都有

  1. 一个“数据包开始”指示符。

  2. 一个“数据包结束”指示符。

  3. 一个数据包标识符,用于关联请求和传输的数据,以及每个帧的错误状态

硬件实现可以在帧级别检查错误,并在出现错误时重试传输。 但是,对于流量控制情况,这需要在硬件中进行额外的缓冲和智能处理。 Linux 支持假定如果在其中一个响应中检测到单个错误,则取消整个传输。

所需的抽象

在管理器级别没有标准寄存器或强制实现,因此低级别的 BPT/BRA 详细信息必须隐藏在管理器特定的代码中。 例如,编解码器驱动程序不知道上面的 Cadence IP 格式。

同样,编解码器驱动程序不应知道帧大小。 CRC 的计算和响应的处理由帮助程序和管理器特定的代码处理。

主机 BRA 驱动程序也可能对为 DMA 分配的页面或其他主机-DSP 通信协议有限制。 编解码器驱动程序不应意识到任何这些限制,因为它可能会与管理器 IP 的不同实现结合使用。

BRA 和常规读取/写入之间的并发

现有的“nread/nwrite”API 已经依赖于起始地址和字节数的概念,因此可以使用“提示”请求使用 BPT/BRA 来扩展此 API。

但是,BRA 传输可能相当长,并且使用单个互斥锁进行常规读取/写入和 BRA 是一个阻碍。 控制/命令和 BRA 传输的独立操作是一项基本要求,例如,在使用现有的 regmap 接口下载固件时更改音量级别。 但是,集成必须确保使用命令/控制协议和 BRA 协议不会同时访问同一地址。

此外,“sdw_msg”结构硬编码支持基于本机 32 位地址的 BPT/BRA 支持无关的 16 位地址和分页寄存器。 使用“sdw_bpt_msg”的单独 API 更有意义。

加速所有初始化任务的一种可能策略是启动 BRA 传输以进行固件下载,然后与命令通道并行处理所有“常规”读取/写入,最后等待 BRA 传输完成。 这将允许一定程度的重叠,而不是纯粹的顺序解决方案。 因此,BRA API 必须支持异步传输并公开一个单独的等待函数。

外围设备/总线接口

BPT/BRA 的总线接口由两个函数组成

  • sdw_bpt_send_async(bpt_message)

    此函数使用管理器实现定义的功能(通常是 DMA 或 IPC 协议)发送数据。

    当前不支持排队,调用者需要等待请求的传输完成。

  • sdw_bpt_wait()

    此函数等待编解码器驱动程序在“send_async”阶段提供的整个消息。 较小块的中间状态将不会提供回给编解码器驱动程序,只会提供一个返回代码。

Regmap 使用

现有的编解码器驱动程序依赖于 regmap 将固件下载到外围设备。 regmap 公开了一个类似于上面建议的 send/wait API 的异步接口,因此在高层次上,将 BRA 和 regmap 结合起来似乎很自然。 regmap 层可以检查 BRA 是否可用,并在后一种情况下使用常规的读写命令通道。

regmap 集成将在第二步中处理。

BRA 流模型

对于常规音频传输,机器驱动程序公开了一个连接 CPU DAI(s) 和 Codec DAI(s) 的 dailink。

BRA 支持不需要此模型

  1. SoundWire DAI 主要是 SoundWire 数据端口的包装器,可能在数据端口后面添加了一些模拟或音频转换功能。 在 BRA 的上下文中,DP0 是目标。 DP0 寄存器是标准的,可以盲目地进行编程,而无需知道哪个外围设备连接到每个链接。 此外,如果一个链接上有多个外围设备,并且其中一些设备不支持 DP0,则用于编程 DP0 寄存器的写入命令将生成无害的 COMMAND_IGNORED 响应,这些响应将与支持 DP0 的外围设备的响应进行线或运算。 换句话说,DP0 编程可以使用广播命令完成,并且有关目标设备的信息只能添加到 BRA 标头中。

  2. 在 CPU 级别,DAI 概念对于 BRA 没有用; 机器驱动程序不会创建依赖于 DP0 的 dailink。 唯一需要的概念是端口的概念。

  3. 流概念依赖于一组 master_rt 和 slave_rt 概念。 所有这些实体都代表端口而不是 DAI。

  4. 假设每个链接使用单个 BRA 流,则该流可以连接主端口以及所有外围 DP0 端口。

  5. BRA 传输仅在单个管理器/链接的上下文中才有意义,因此 BRA 流处理不依赖于常规 DAI 链接允许的多链路聚合概念。

音频 DMA 支持

某些 DMA(例如 HDaudio)需要设置音频格式字段。 反过来,此格式用于定义可接受的突发。 BPT/BRA 支持与这些定义不完全兼容,因为读取和写入命令之间的格式和带宽可能会有所不同。

此外,在 Intel HDaudio Intel 平台上,需要使用与 BPT/BRA 传输带宽匹配的 PCM 格式来编程 DMA。 该格式基于 192kHz 32 位采样,并且通道数有所不同以调整带宽。 通道的概念完全是名义上的,因为数据不是典型的音频 PCM。 编程此类通道有助于保留足够的带宽并调整 FIFO 大小以避免 xrun。

对齐要求当前不在核心级别而是在平台级别强制执行,例如,对于 Intel,数据大小必须是 32 字节的倍数。