批量寄存器访问 (BRA)¶
约定¶
本文档中使用的大写单词是有意的,指的是 SoundWire 1.x 规范中的概念。
简介¶
SoundWire 1.x 规范提供了一种通过回收部分音频带宽来加速命令/控制传输的机制。 批量寄存器访问 (BRA) 协议是基于批量有效负载传输 (BPT) 定义的标准解决方案。
常规控制通道使用 Column 0,并且只能通过写入/读取命令每帧发送/检索一个字节。 对于典型的 48kHz 帧速率,只能传输 48kB/s。
可选的批量寄存器访问功能可以传输高达 12 Mbits/s 的速率,并将传输时间缩短几个数量级,但具有多个设计约束
每帧只能支持读取或写入传输,每帧有 10 字节的开销(标头和页脚响应)。
读取/写入操作应在同一帧中从/向连续的寄存器地址进行。 碎片化的寄存器空间会降低协议的效率,因为它需要安排在不同帧中的多个 BRA 传输。
目标外围设备应支持可选的数据端口 0,同样,管理器应公开类似音频的端口,以使用采样间隔、HSTART、HSTOP 等概念将 BRA 数据包插入到音频有效负载中。
BRA 传输效率取决于可用带宽。 如果没有正在进行的音频传输,则可以回收整个帧(减去 Column 0)用于 BRA。 帧形状也会影响效率:由于 Column0 不能用于 BTP/BRA,因此帧应依赖于大量列并最大限度地减少行数。 总线时钟应尽可能高。
每帧传输的位数应为 8 位的倍数。 如果需要,应在数据末尾插入填充位。
常规的读取/写入命令可以与 BRA 传输并行发出。 这对于处理警报、插孔检测或在固件下载期间更改音量非常方便,但必须避免使用两个独立的协议访问同一地址,以避免未定义的行为。
某些实现可能无法处理 BRA 协议的带宽,例如,在 SoundWire IP 背后存在慢速 I2C 总线的情况下。 在这种情况下,可能需要及时间隔或进行流量控制。
每个 BRA 数据包在要传输有效数据时应标记为“活动”。 这允许软件分配 BRA 流,但在处理结果或准备下一批数据时,或者允许外围设备处理之前的传输时,不传输/丢弃数据。 此外,可以在数据未准备好时提前启动 BRA 传输。
每帧最多可以传输 470 个字节。
地址用 32 位表示,不依赖于用于 Column 0 中常规命令/控制协议的分页寄存器。
错误检查¶
固件下载是批量寄存器访问协议的关键用法之一。 为了确保二进制数据完整性不受传输或编程错误的影响,每个 BRA 数据包提供
一个 7 字节标头的 CRC。 此 CRC 帮助外围设备检查它是否被寻址,并设置起始地址和字节数。 外围设备在字节 7 中提供响应。
数据块(不包括标头)上的 CRC。 此 CRC 作为数据包中的倒数第二个字节传输,在页脚响应之前。
- 标头响应可以是以下之一
确认
否定确认
未就绪
- 页脚响应可以是以下之一
确认
否定确认(CRC 失败)
良好(操作完成)
错误(操作失败)
示例帧¶
下面的示例未按比例绘制,并且为了清楚起见做出了简化假设。 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 流进行处理,可能并行 - 链接实际上是独立的。
不支持的功能¶
批量寄存器访问规范提供了许多已知实现不支持的功能,例如
由外围设备启动的传输。 BRA 启动器始终是管理器设备。
基于“NotReady”标头响应的流量控制功能和重传需要在 SoundWire IP 中进行额外的缓冲,并且未实现。
双向处理¶
BRA 协议可以处理写入和读取,并且在每个数据包中,标头和页脚响应由外围目标设备提供。 在外围设备上,BRA 协议由单个 DP0 数据端口处理,并且在低级别,总线所有权将针对标头/页脚响应以及读取期间传输的数据而发生变化。
在主机端,大多数实现依赖于类似端口的概念,其中两个 FIFO 并行地消耗/生成数据传输(主机 -> 外围设备和外围设备 -> 主机)。 这些 FIFO 消耗/产生的数据量不对称,因此硬件通常插入标记以帮助软件和硬件解释原始数据
每个数据包通常都有
一个“数据包开始”指示符。
一个“数据包结束”指示符。
一个数据包标识符,用于关联请求和传输的数据,以及每个帧的错误状态
硬件实现可以在帧级别检查错误,并在出现错误时重试传输。 但是,对于流量控制情况,这需要在硬件中进行额外的缓冲和智能处理。 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 支持不需要此模型
SoundWire DAI 主要是 SoundWire 数据端口的包装器,可能在数据端口后面添加了一些模拟或音频转换功能。 在 BRA 的上下文中,DP0 是目标。 DP0 寄存器是标准的,可以盲目地进行编程,而无需知道哪个外围设备连接到每个链接。 此外,如果一个链接上有多个外围设备,并且其中一些设备不支持 DP0,则用于编程 DP0 寄存器的写入命令将生成无害的 COMMAND_IGNORED 响应,这些响应将与支持 DP0 的外围设备的响应进行线或运算。 换句话说,DP0 编程可以使用广播命令完成,并且有关目标设备的信息只能添加到 BRA 标头中。
在 CPU 级别,DAI 概念对于 BRA 没有用; 机器驱动程序不会创建依赖于 DP0 的 dailink。 唯一需要的概念是端口的概念。
流概念依赖于一组 master_rt 和 slave_rt 概念。 所有这些实体都代表端口而不是 DAI。
假设每个链接使用单个 BRA 流,则该流可以连接主端口以及所有外围 DP0 端口。
BRA 传输仅在单个管理器/链接的上下文中才有意义,因此 BRA 流处理不依赖于常规 DAI 链接允许的多链路聚合概念。
音频 DMA 支持¶
某些 DMA(例如 HDaudio)需要设置音频格式字段。 反过来,此格式用于定义可接受的突发。 BPT/BRA 支持与这些定义不完全兼容,因为读取和写入命令之间的格式和带宽可能会有所不同。
此外,在 Intel HDaudio Intel 平台上,需要使用与 BPT/BRA 传输带宽匹配的 PCM 格式来编程 DMA。 该格式基于 192kHz 32 位采样,并且通道数有所不同以调整带宽。 通道的概念完全是名义上的,因为数据不是典型的音频 PCM。 编程此类通道有助于保留足够的带宽并调整 FIFO 大小以避免 xrun。
对齐要求当前不在核心级别而是在平台级别强制执行,例如,对于 Intel,数据大小必须是 32 字节的倍数。