2. I2S 总线协议详解
I2S(Inter-IC Sound)总线是数字音频设备间传输 PCM 音频数据最常用的串行总线标准,由 Philips 公司于 1986 年提出。在 Linux 音频驱动中,I2S 是 CPU 侧 I2S 控制器与外部 Codec 之间音频数据流的主干道。理解 I2S 物理层信号定义、时序关系以及数据对齐格式,是正确配置设备树中 #sound-dai-cells、format 等属性的前提。
2.1 I2S 物理层信号定义
标准 I2S 总线由三条主要信号线组成,所有信号均与位时钟同步。
| 信号名称 | 缩写 | 方向(典型) | 功能描述 |
|---|---|---|---|
| 位时钟 | BCLK (Bit Clock) | 主设备 → 从设备 | 每个脉冲对应一个数据位的传输。频率 = 采样率 × 位宽 × 通道数。 |
| 帧时钟 / 字选择 | LRCLK (Left/Right Clock) | 主设备 → 从设备 | 指示当前数据属于左声道还是右声道。频率 = 采样率。 |
| 串行数据 | SD (Serial Data) | 双向(通常 TX/RX 分离) | 承载音频采样数据的串行位流。可以是输入(SDI)或输出(SDO)。 |
2.2 标准 I2S 时序图
标准 I2S 协议规定:SD 数据在 BCLK 的下降沿变化,在上升沿被接收端采样。LRCLK 在左声道时为低电平,右声道时为高电平(或相反,取决于具体实现,但标准 Philips 协议为:左声道 LRCLK = 0,右声道 LRCLK = 1)。数据从 LRCLK 跳变后的第二个 BCLK 上升沿开始传输,且 MSB 优先。
下图展示了标准 I2S 模式下传输一个立体声帧(左声道 + 右声道)的时序关系:
2.3 左对齐与右对齐格式对比
除了标准 I2S 格式,许多 Codec 和 SoC 还支持 左对齐(Left-Justified) 和 右对齐(Right-Justified) 格式。它们的核心区别在于 数据 MSB 相对于 LRCLK 跳变沿的位置。
| 特性 | 标准 I2S (Philips) | 左对齐 (Left-Justified) | 右对齐 (Right-Justified) |
|---|---|---|---|
| MSB 起始位置 | LRCLK 跳变后的第 2 个 BCLK | LRCLK 跳变后的第 1 个 BCLK | LRCLK 跳变后的最后一个 BCLK 周期 |
| 数据与帧时钟关系 | 延迟 1 个 BCLK | 与 LRCLK 边沿对齐 | 与 LRCLK 边沿右对齐 |
| 典型应用 | Philips 标准 Codec | ADI、TI 部分 Codec | 部分 DSP 或老旧 Codec |
| 设备树配置 | format = "i2s" |
format = "left_j" |
format = "right_j" |
下图直观对比了这三种格式在一个左声道数据帧内的起始位置差异(以 8 位数据为例,实际通常为 16/24/32 位):
format 属性(例如 Codec 要求左对齐但配置为标准 I2S)会导致音频数据错位,表现为声音严重失真或完全无声。务必查阅 Codec 数据手册确认其支持的格式。
2.4 I2S 数据格式与位宽
除了对齐格式,I2S 还涉及数据位宽和有效位宽的概念。常见配置如下:
- 数据位宽(Data Width): 每个 BCLK 周期传输的位数,通常为 16、24 或 32 位。
- 有效位宽(Sample Width): 实际音频采样数据的位数。例如 24 位数据可能放在 32 位槽位中。
- 槽位宽度(Slot Width): 每个声道占用的 BCLK 周期数。当槽位宽度大于有效位宽时,多余位通常填充 0。
在设备树中,这些参数通过 dai-tdm-slot-width、dai-tdm-slot-num 等属性配置,或由 sound-dai 的 dai-format 隐含决定。
2.5 I2S 主从模式与时钟极性
I2S 总线可以配置为 主机模式(Master) 或 从机模式(Slave):
| 模式 | BCLK / LRCLK 产生者 | 典型场景 |
|---|---|---|
| CPU 主模式 | CPU I2S 控制器 | CPU 作为音频时钟源,Codec 作为从设备 |
| CPU 从模式 | 外部 Codec 或 PLL | Codec 内部 PLL 产生时钟,CPU 同步接收 |
时钟极性(BCLK 和 LRCLK 的有效边沿)也需匹配。设备树中通过 bitclock-inversion 和 frame-inversion 属性调整。
&i2s1 {
status = "okay";
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&i2s1_pins>;
assigned-clocks = <&clk IMX8MM_CLK_SAI1>;
assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
assigned-clock-rates = <24576000>; /* 48kHz * 32 * 2 * 8 */
};
&wm8960 {
status = "okay";
#sound-dai-cells = <0>;
compatible = "wlf,wm8960";
reg = <0x1a>;
clocks = <&clk IMX8MM_CLK_SAI1>;
clock-names = "mclk";
assigned-clocks = <&clk IMX8MM_CLK_SAI1>;
assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
assigned-clock-rates = <24576000>;
};
&sound {
compatible = "simple-audio-card";
simple-audio-card,name = "imx8mm-wm8960";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&cpu_dai>;
simple-audio-card,frame-master = <&cpu_dai>;
simple-audio-card,mclk-fs = <512>;
cpu_dai: simple-audio-card,cpu {
sound-dai = <&i2s1>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&wm8960>;
};
};
2.6 本章小结
- I2S 总线由 BCLK、LRCLK 和 SD 三条信号线组成,BCLK 频率由采样率、位宽和通道数决定。
- 标准 I2S 时序中,数据 MSB 在 LRCLK 跳变后的第 2 个 BCLK 开始传输,下降沿变化、上升沿采样。
- 左对齐 格式 MSB 从第 1 个 BCLK 开始;右对齐 格式 MSB 在帧末尾。设备树中通过
format属性区分。 - 主从模式、时钟极性、位宽配置必须在 CPU 和 Codec 之间完全匹配,否则音频无法正常工作。