2. I2S/PCM总线协议:I2S时序、数据格式与主从模式配置

I2S(Inter-IC Sound)总线是嵌入式音频系统中连接SoC与Codec的事实标准串行接口。理解I2S的时序、数据格式以及主从模式是配置Codec驱动寄存器的基础。本章从物理层时序出发,逐步深入到数据对齐格式与模式配置。

2.1 I2S总线信号与基本时序

I2S总线由三条主要信号线组成,所有数据传输均与位时钟同步:

信号名称 缩写 方向(主模式) 功能描述
位时钟 BCLK / SCK 输出 每个脉冲对应一个数据位的传输,频率 = 采样率 × 位宽 × 通道数
帧时钟 LRCK / WS 输出 左右声道选择,高电平通常表示右声道,低电平表示左声道
串行数据 SD / DATA 双向 按位串行传输音频采样数据,通常为二进制补码格式

BCLK与LRCK的关系是I2S时序的核心:LRCK在BCLK的下降沿变化,而数据位在BCLK的上升沿被采样。标准I2S协议要求数据在LRCK变化后的第二个BCLK上升沿开始传输,且数据最高位(MSB)最先发送。

关键时序参数: BCLK频率 = fs × bits_per_sample × 2(立体声)。例如,48kHz采样率、16位立体声:BCLK = 48000 × 16 × 2 = 1.536 MHz。
I2S 基本时序波形图(48kHz / 16位 / 立体声) BCLK LRCK 左声道 (L) 右声道 (R) SD MSB LSB 说明: 1. LRCK 在 BCLK 下降沿变化,数据在 BCLK 上升沿被采样。 2. 数据从 LRCK 变化后的第 2 个 BCLK 上升沿开始传输,MSB 优先。

2.2 数据对齐格式:左对齐、右对齐与I2S标准

数据对齐格式决定了音频采样数据在BCLK周期内的放置位置。三种主流格式在嵌入式Linux驱动中均需支持,Codec的寄存器配置通常通过数字音频接口(DAI)格式选择位来切换。

格式名称 数据起始位置 MSB位置 典型应用
I2S标准(飞利浦标准) LRCK变化后的第2个BCLK上升沿 紧接起始位 最广泛,多数Codec默认支持
左对齐(Left Justified) LRCK变化后的第1个BCLK上升沿 起始位即为MSB 部分DAC/ADC,如CS43L22
右对齐(Right Justified) 数据在BCLK周期末尾对齐 MSB位于LSB之前,但整体靠右 日本厂商Codec,如AKM系列
驱动配置要点: 在Linux ALSA SoC框架中,通过 snd_soc_dai_set_fmt() 设置DAI格式。例如:SND_SOC_DAIFMT_I2S 对应I2S标准,SND_SOC_DAIFMT_LEFT_J 对应左对齐,SND_SOC_DAIFMT_RIGHT_J 对应右对齐。Codec侧寄存器通常位于 Digital Audio Interface Format 或 Serial Audio Data Format 寄存器中。
三种数据对齐格式对比(16位数据,BCLK周期示意) LRCK 数据位 无效/填充位 I2S标准 MSB 位14 ... 位1 LSB 填充 填充 ... 填充 第2个BCLK开始 左对齐 MSB 位14 ... 位1 LSB 填充 填充 ... 填充 第1个BCLK开始 右对齐 填充 填充 ... 填充 MSB 位14 ... 位1 LSB 数据对齐到BCLK周期末尾 说明:左对齐格式数据起始最早,适合低延迟场景;右对齐格式与早期DAC兼容性好;I2S标准在两者之间,兼容性最佳。 Codec寄存器通常通过 2-bit 字段选择格式:00=I2S, 01=左对齐, 10=右对齐。

2.3 主从模式配置

I2S总线的主从模式决定了BCLK和LRCK信号的生成方。在嵌入式系统中,SoC通常作为主设备,Codec作为从设备,但某些场景下Codec也可以作为主设备(例如USB音频桥接芯片)。

2.3.1 主模式(Master)

  • 职责: 生成BCLK和LRCK时钟信号,从设备同步于这些时钟。
  • 驱动配置: 在SoC侧设置 SND_SOC_DAIFMT_CBS_CFS(Codec作为从,SoC作为主)。
  • Codec寄存器: 通常需要将Codec的 Master/Slave 位设置为 Slave(0),并配置时钟分频器以匹配SoC输出的时钟。

2.3.2 从模式(Slave)

  • 职责: 接收外部BCLK和LRCK,不主动产生时钟。
  • 驱动配置: 在SoC侧设置 SND_SOC_DAIFMT_CBM_CFM(Codec作为主,SoC作为从)。
  • Codec寄存器: 将 Master/Slave 位设置为 Master(1),并配置内部PLL或时钟源以生成正确的BCLK/LRCK。
常见配置陷阱: 主从模式不匹配是I2S通信失败的常见原因。如果SoC和Codec都配置为主模式,总线将出现时钟冲突;如果都配置为从模式,则无时钟信号,数据无法传输。调试时首先检查 /sys/kernel/debug/asoc/ 下的DAI链路状态,确认时钟方向。

2.4 典型Codec寄存器配置示例

以Wolfson WM8960为例,其数字音频接口寄存器(地址0x04)的配置如下:

/* WM8960 数字音频接口寄存器 (0x04) 位定义 */
#define WM8960_IFACE_FORMAT_MASK    (3 << 0)   /* 位[1:0]:数据格式 */
#define WM8960_IFACE_FORMAT_I2S     (0 << 0)   /* 00: I2S标准 */
#define WM8960_IFACE_FORMAT_LEFT_J  (1 << 0)   /* 01: 左对齐 */
#define WM8960_IFACE_FORMAT_RIGHT_J (2 << 0)   /* 10: 右对齐 */
#define WM8960_IFACE_LRP            (1 << 2)   /* 位2:LRCK极性反转 */
#define WM8960_IFACE_BCP            (1 << 3)   /* 位3:BCLK极性反转 */
#define WM8960_IFACE_MS             (1 << 4)   /* 位4:主从选择,1=主,0=从 */
#define WM8960_IFACE_DL_MASK        (3 << 5)   /* 位[6:5]:数据字长 */
#define WM8960_IFACE_DL_16BIT       (0 << 5)   /* 00: 16位 */
#define WM8960_IFACE_DL_20BIT       (1 << 5)   /* 01: 20位 */
#define WM8960_IFACE_DL_24BIT       (2 << 5)   /* 10: 24位 */
#define WM8960_IFACE_DL_32BIT       (3 << 5)   /* 11: 32位 */

/* 配置示例:I2S标准、16位、从模式 */
snd_soc_component_write(component, 0x04,
    WM8960_IFACE_FORMAT_I2S |
    WM8960_IFACE_DL_16BIT |
    (0 << 4));  /* MS=0,从模式 */
寄存器配置流程: 在Codec驱动的 hw_params() 回调中,根据传入的采样率、位宽和DAI格式,动态计算并写入上述寄存器字段。注意:主从模式通常在 set_fmt() 回调中配置,而非 hw_params()。

2.5 调试与验证方法

  1. 示波器测量: 测量BCLK频率是否等于 fs × bits × channels;检查LRCK频率是否等于采样率;观察数据起始位置是否符合所选格式。
  2. ALSA调试文件系统: 查看 /proc/asound/card0/codec#0 中的寄存器转储,确认DAI格式寄存器值。
  3. 逻辑分析仪: 使用廉价逻辑分析仪捕获I2S总线,对比数据手册中的时序图。
  4. 驱动日志: 在 snd_soc_dai_set_fmt() 和 snd_soc_dai_hw_params() 中添加 dev_dbg() 打印,确认传入的参数值。

掌握I2S时序、数据格式和主从模式后,下一层就是Codec内部音频路径的寄存器配置——从数字接口到模拟输出的完整信号链路。