SoundWire 子系统概述

SoundWire 是 MIPI 联盟在 2015 年批准的新接口。SoundWire 用于传输通常与音频功能相关的数据。SoundWire 接口经过优化,可将音频设备集成到移动或受移动启发的系统中。

SoundWire 是一种具有数据和时钟线的 2 针多点接口。它有助于开发低成本、高效、高性能的系统。SoundWire 接口的广泛主要功能包括

  1. 通过单个双针接口传输所有有效负载数据通道、控制信息和设置命令。

  2. 通过使用 DDR(双倍数据速率)数据传输来降低时钟频率,从而降低功耗。

  3. 时钟缩放和可选的多数据通道,可在数据速率方面提供广泛的灵活性以满足系统要求。

  4. 设备状态监控,包括向主设备发送中断式警报。

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 属性,并在从操作中提供回调,供从驱动程序实现自己的提供功能信息的功能。总线需要知道一组从功能来编程从寄存器和控制总线重新配置。

未来要做的增强功能

  1. 批量寄存器访问 (BRA) 传输。

  2. 多数据通道支持。