SoundWire 子系统概述¶
SoundWire 是 MIPI 联盟在 2015 年批准的新接口。SoundWire 用于传输通常与音频功能相关的数据。SoundWire 接口经过优化,可将音频设备集成到移动或受移动启发的系统中。
SoundWire 是一种具有数据和时钟线的 2 针多点接口。它有助于开发低成本、高效、高性能的系统。SoundWire 接口的广泛主要功能包括
通过单个双针接口传输所有有效负载数据通道、控制信息和设置命令。
通过使用 DDR(双倍数据速率)数据传输来降低时钟频率,从而降低功耗。
时钟缩放和可选的多数据通道,可在数据速率方面提供广泛的灵活性以满足系统要求。
设备状态监控,包括向主设备发送中断式警报。
SoundWire 协议最多支持 11 个从接口。所有接口共享包含数据和时钟线的公共总线。每个从设备最多可支持 14 个数据端口。13 个数据端口专用于音频传输。数据端口 0 专用于批量控制信息的传输,每个音频数据端口(1..14)最多可在发送或接收模式下支持 8 个通道(通常为固定方向,但规范允许配置方向)。带宽限制为 ~19.2..24.576Mbits/s,不允许同时传输 11*13*8 个通道。
下图显示了 SoundWire 主设备和两个从设备之间的连接示例。
+---------------+ +---------------+
| | Clock Signal | |
| Master |-------+-------------------------------| Slave |
| Interface | | Data Signal | Interface 1 |
| |-------|-------+-----------------------| |
+---------------+ | | +---------------+
| |
| |
| |
+--+-------+--+
| |
| Slave |
| Interface 2 |
| |
+-------------+
术语¶
MIPI SoundWire 规范使用术语“设备”来指代主接口或从接口,这当然可能会令人困惑。在本概述和代码中,我们仅使用术语接口来指代硬件。我们遵循 Linux 设备模型,将总线上连接的每个从接口映射为由特定驱动程序管理的设备。Linux SoundWire 子系统提供了一个框架,用于实现 SoundWire 从驱动程序,该驱动程序具有 API,允许第三方供应商启用特定于实现的函数,而常见的设置/配置任务由总线处理。
总线:实现 SoundWire Linux 总线,该总线处理 SoundWire 协议。对所有 MIPI 定义的从寄存器进行编程。表示 SoundWire 主设备。系统中可能存在多个总线实例。
从设备:注册为 SoundWire 从设备(Linux 设备)。多个从设备可以注册到总线实例。
从驱动程序:控制从设备的驱动程序。MIPI 指定的寄存器由总线直接控制(并通过主驱动程序/接口传输)。任何特定于实现的从寄存器都由从驱动程序控制。在实践中,预计从驱动程序依赖 regmap,而不是请求直接寄存器访问。
编程接口(SoundWire 主接口驱动程序)¶
SoundWire 总线支持 SoundWire 主实现和 SoundWire 从设备的编程接口。所有代码都使用 SoC 设计人员和第三方供应商常用的“sdw”前缀。
每个 SoundWire 主接口都需要注册到总线。总线实现 API 以读取标准主 MIPI 属性,并在主操作中提供回调,供主驱动程序实现其自己的提供功能信息的功能。此时未实现 DT 支持,但由于可以使用 device_property_
API 启用功能,因此添加 DT 支持应该很简单。
主接口以及主接口功能是基于板文件、DT 或 ACPI 注册的。
以下是用于注册 SoundWire 总线的总线 API
int sdw_bus_master_add(struct sdw_bus *bus,
struct device *parent,
struct fwnode_handle)
{
sdw_master_device_add(bus, parent, fwnode);
mutex_init(&bus->lock);
INIT_LIST_HEAD(&bus->slaves);
/* Check ACPI for Slave devices */
sdw_acpi_find_slaves(bus);
/* Check DT for Slave devices */
sdw_of_find_slaves(bus);
return 0;
}
这将为 Master 设备初始化 sdw_bus 对象。“sdw_master_ops”和“sdw_master_port_ops”回调函数提供给总线。
“sdw_master_ops”由总线使用,以硬件特定的方式控制总线。它包括总线控制功能,例如在总线上发送 SoundWire 读取/写入消息、设置时钟频率和流同步点 (SSP)。“sdw_master_ops”结构从总线中抽象出主设备的硬件详细信息。
“sdw_master_port_ops”由总线使用,以设置主接口端口的端口参数。MIPI 规范未定义主接口端口寄存器映射,因此总线调用“sdw_master_port_ops”回调函数来执行“端口准备”、“端口传输参数设置”、“端口启用和禁用”等端口操作。然后,主驱动程序的实现可以执行特定于硬件的配置。
编程接口(SoundWire 从驱动程序)¶
MIPI 规范要求每个从接口公开一个唯一的 48 位标识符,该标识符存储在 6 个只读 dev_id 寄存器中。此 dev_id 标识符包含供应商和部件信息,以及一个用于区分相同组件的字段。目前未使用其他类字段。从驱动程序是针对特定的供应商和部件标识符编写的,总线会根据这两个 ID 枚举从设备。从设备和驱动程序匹配是基于这两个 ID 完成的。在设备和驱动程序 ID 成功匹配后,总线会调用从驱动程序的探测。在主设备和从设备之间强制执行父/子关系(逻辑表示与物理连接一致)。
有关主设备/从设备依赖项的信息存储在平台数据、板文件、ACPI 或 DT 中。MIPI 软件规范为具有多个主接口的控制器定义了额外的 link_id 参数。dev_id 寄存器仅在链路的范围内是唯一的,并且 link_id 在控制器的范围内是唯一的。dev_id 和 link_id 在系统级别不一定是唯一的,但父/子信息用于避免歧义。
static const struct sdw_device_id slave_id[] = {
SDW_SLAVE_ENTRY(0x025d, 0x700, 0),
{},
};
MODULE_DEVICE_TABLE(sdw, slave_id);
static struct sdw_driver slave_sdw_driver = {
.driver = {
.name = "slave_xxx",
.pm = &slave_runtime_pm,
},
.probe = slave_sdw_probe,
.remove = slave_sdw_remove,
.ops = &slave_slave_ops,
.id_table = slave_id,
};
对于功能,总线实现 API 以读取标准从 MIPI 属性,并在从操作中提供回调,供从驱动程序实现自己的提供功能信息的功能。总线需要知道一组从功能来编程从寄存器和控制总线重新配置。
未来要做的增强功能¶
批量寄存器访问 (BRA) 传输。
多数据通道支持。
链接¶
SoundWire MIPI 规范 1.1 可在以下网址获得:https://members.mipi.org/wg/All-Members/document/70290
SoundWire MIPI DisCo(发现和配置)规范可在以下网址获得:https://www.mipi.org/specifications/mipi-disco-soundwire
(可通过注册公开访问,或者 MIPI 成员可直接访问)
MIPI 联盟制造商 ID 页面:mid.mipi.org