声卡i2s支持各种模式

i2S 传输模式分为 I2S 标准模式, I2S 左对齐模式, I2S 右对齐模式,还有 TDM 模式, PCM 模式 。

I2S 标准模式 :

image.png

LRCK:帧同步时钟,其频率就是音频采样率,图中是一个周期的 LRCK,也就是采样率的倒数。在时钟的低电平传输左声道,在时钟的高电平传输右声道。

BCLK:位同步时钟。 BCLK_rate = sample_rate * slot * slot_width

  • sample_rate 是音频采样率,
  • slot 通道数(I2S 标准格式下,只能是 1 或 2),
  • slot_width 是传输单通道数据内最大的比特位。通常是 8/16/24/32bit 可选。

MCLK: CPU 输出频率给外部 codec 工作时钟,跟 I2S 模式无关

I2S 左对齐协议 :
image.png

I2S 左对齐模式:与 I2S 标准的差异,在 LRCK 发生翻转时就开始传输数据。

LRCK 为高电平时,表示第一个声道,低电平为第二个声道。 BCLK 电平在 LRCK 发生电平变化后从低电平开始。

I2S 右对齐协议 :
image.png

I2S 右对齐模式:与 I2S 标准的差异,声音数据 LSB 传输完成的同时, LRCLK 完成第二次翻转。LRCK 为高电平时,表示第一个声道,低电平为第二个声道。 BCLK 电平在 LRCK 发生电平变化后从低电平开始。

I2S 的 TDM 模式 :

I2S 标准 _TDM :

如果要传输超过两声道的数据,就需要使用 I2S 的 TDM 模式,因为各个厂家实现不一样 ,仅供参考。


image.png

与 I2S 标准协议差异就是可以传输多个通道,最高支持到 16 声道。

在 LRCK 的低电平传输左声道,高电平传输右声道。

可以看到在 Slot 传输两个通道时,就是标准 I2S 的传输。

BCLK_rate = sample_rate * slot * slot_width

I2S 左对齐 _TDM :
image.png

I2S 左对齐模式:与 I2S 标准的差异,在 LRCK 发生翻转时就开始传输数据。这种协议使用较少。

I2S 右对齐 _TDM :
image.png

I2S 右对齐模式:与 I2S 标准的差异,声音数据 LSB 传输完成的同时, LRCLK 完成第二次翻转。这种协议又被称为 sony 模式。

I2S 的 PCM 模式 :

PCM 接口包括四根信号:
PCM_CLK:数据时钟(位时钟)信号,类似 I2S 的 BCLK,频率等于采样率。
PCM_SYNC:帧同步信号,类似 I2S 的LRCK
PCM_IN:接收数据信号,类似 I2S 的 DIN
PCM_OUT:发送数据信号,类似 I2S 的 DOUT

一般应用场景:
PCM 模式通常用于 AP 处理器和通信 MODEM 之间传输语音数据。
AP 处理器和蓝牙之间也是通过 PCM 模式来传输语音数据。拨打电话的蓝牙数据走的是 PCM 模式,播放音乐蓝牙数据走的是串口,不是 PCM 模式传输。

PCM 接口和 I2S 接口引脚一致,帧同步时钟、位时钟。

  • 根据数据相对帧同步时钟 LRCK 的位置, PCM 模式分为两种基本模式。
    DSP_MODE_A:数据在 LRCK 有效后, BCLK 的第 2 个上升沿有效。
    DSP_MODE_B:数据在 LRCK 有效后, BCLK 的第 1 个上升沿有效。

  • 根据帧同步时钟宽度的大小, PCM 又分为两种模式。
    短帧: LRCK width 等于 1 个 BCLK。
    长帧: LRCK width 大于 1 个 BCLK,小于 LRCK 周期

短针示图:

image.png

LRCK width = 1 个 BCLK,就是上图中 LRCK 的高电平,对应一个 BCLK 的宽度。这种就是短帧模式。
帧同步时钟宽度为一个位时钟周期,数据在 LRCK 有效后, BCLK 的第二个上升有效,又是**DSP_MODE_A **模式。

长针示图:

image.png

LRCK width = 2 个 BCLK,就是上图中 LRCK 的高电平,对应两个 BCLK 的宽度。这种就是长帧模式。
帧同步时钟宽度为两个位时钟周期,数据在 LRCK 有效后, BCLK 的第一个上升有效,又是**DSP_MODE_B **模式。
短帧,长帧:BCLK = LRCK * (slot * slot_width)

PCM短针配置实例(R818_Linux&RTL8821c):

蓝牙固件自行和模组厂商确认。

daudio1:daudio@0x05091000 {
    mclk_div    = <0x01>;
    frametype   = <0x00>;
    tdm_config  = <0x00>;
    sign_extend     = <0x00>;
    tx_data_mode    = <0x00>;
    rx_data_mode    = <0x00>;
    msb_lsb_first   = <0x00>;
    pcm_lrck_period = <0x20>;
    slot_width_select = <0x10>;
    pinctrl-0 = <&daudio1_pins_a>;
    pinctrl-1 = <&daudio1_pins_b>;
    status = "okay";
};

各配置说明:

  • mclk_div:1/2/4…176/192:输出 mclk。设置外部codec的时钟,这里的频率就是pll_audio/mclk_div。该值根据外接codec需要的mclk的频率来配置。
    示例:
    pll_audio 一般为 24.576M 或者 22.5792M,外接的codec需要 MCLK,频率为3.072M 或者 2.8224M,那么mclk_div就要设置为8。
  • frametype:配置一个时钟帧的长度,0表示短帧,1个时钟的长度。1表示长帧,2个时钟的长度,默认配置0就行。
  • tdm_config:tdm模式的配置,0表示pcm模式,1表示i2s模式。这里要使用i2s的pcm模式,所以要配置为0。
  • sign_extend:0:(Zero Padding,高位补零)、1:(Sign Extend,符号扩展)。
  • tx_data_mode:TX端数据的格式。表示发送,也就是输出信号。0: 16bit linear PCM;1: reserved;2: 8bit u-law;3: 8bit a-law
  • rx_data_modeRX端数据格式配置。表示发送,也就是输入信号。同上
  • msb_lsb_first:数据传输有效位选择,数据传输有效位选择,0: MSB 高 bit 发生至低 bit。 1: LSB 低 bit 发生至高 bit。,通常配置为0
  • pcm_lrck_period: BCLK:16/32/64/128/256,lrck 数据位宽,表示一个LRCK时钟后BCLK的个数。
    BCLK = LRCK * (slot * slot_width)
  • slot_width_select:可选值:8bit/16bit/32bit 采样位深(宽度):必须大于或等于采样精度,一般等于最高支持采样精度。

最大通道数(pcm 模式) = pcm_lrck_period / slot_width_select;

最大采样位深= slot_width_select;

snddaudio1:sound@4 {
    /*sunxi,snddaudio-codec = "ac107.1-0036";*/
    /*sunxi,snddaudio-codec-dai = "ac107-pcm1";*/
    audio_format    = <0x04>;
    daudio_master   = <0x01>;
    signal_inversion  = <0x01>;
    status = "okay";
};
  • audio_format:配置i2s/pcm协议格式。
    i2s协议格式有i2sright_jleft_j,分别表示i2s标准格式i2s右对齐i2s左对齐,对应1-3
    pcm协议的格式有dsp_adsp_b,分别表示MSB在LRCK上升沿后的第二个BCLK上升沿出现(DSP_MODE_A)短针,MSB在LRCK上升沿后的第一个BCLK上升沿出现(DSP_MODE_B)长针。对应4-5

    • I2S vs 左对齐:I2S延迟一个时钟开始传输,左对齐直接开始。
    • 右对齐:数据低位对齐,填充高位方向。
    • DSP_A vs DSP_B:区别在于MSB出现的时钟周期(A延迟1个周期,B无延迟)。
  • daudio_master1:表示SOC做从slave、codec做主master,4:表示SOC做主master、codec做从slave。

  • signal_inversion:信号采样模式。 normal & invert

    1: SND_SOC_DAIFMT_NB_NF (BCLK 正常模式, LRCK 正常模式)
    2: SND_SOC_DAIFMT_NB_IF (BCLK 正常模式, LRCK 翻转模式)
    3: SND_SOC_DAIFMT_IB_NF (BCLK 翻转模式, LRCK 正常模式)
    4: SND_SOC_DAIFMT_IB_IF (BCLK 翻转模式, LRCK 翻转模式)

分频系数求取方法
LRCLK同步时钟分频系数、位时钟分频系数BCLK_DIV计算方法如下所示:

  • 公式1:LRCLK同步时钟分频系数 = PLL/采样率

  • 公式2:对于PCM模式:位时钟分频系数BCLK_DIV= PLL/采样率/pcm_lrck_period

  • 公式3:对于I2S模式:位时钟分频系数BCLK_DIV= PLL/采样率/pcm_lrck_period * 2

由公式1可知,分频系数除了与采样率、pcm_lrck_period有关外,还与PLL时钟有关。通过时钟树获取I2S/PCM的父时钟PLL的大小,获取方法与关键信息如下:

#mount -t debugfs none /sys/kernel/debug/
#cat /sys/kernel/debug/clk/clk_summary
 pll_audiox4                           7            7    90316800          0 0
    codec_dac_1x                       1            1    22579200          0 0
    i2s2                               2            2    22579200          0 0
    i2s1                               1            1    22579200          0 0
    codec_4x                           0            0    90316800          0 0
    dmic                               0            0    90316800          0 0
    spdif                              0            0    90316800          0 0
    i2s3                               0            0    90316800          0 0
    i2s0                               0            0    90316800          0 0
    pll_audiox2                        0            0    45158400          0 0
    pll_audio                          2            2    22579200          0 0
    pll_audiox8                        0            0   180633600          0 0

pll_audiox4的PLL 时钟大小为90316800。根据公式1,PLL除以采样率16000,得到同步时钟的分频系数clk_div;声卡是PCM模式,借助公式2计算BCLK_DIV= PLL÷(16000*pcm_lrck_period)= 176.

查找源码或者规格书来确认分频是否在其范围内:

#BCLK_DIV分频系数取值范围为1、2、4、6、8、12、16、24、32、48、64、96、128、176、192....
image.png
对于PCM模式,pcm_lrck_period (0x20)表示一个 LRCK 中BCLK的个数,配置中为32 。对于I2S模式,pcm_lrck_period表示半个LRCK 中BCLK的个数。该字段调整可配置为 16/32/64/128/256 个 bclk。
配置设备树时,可以适当增大pcm_lrck_period,增大该字段后slot个数会增多,该模块的有效数据在第一个slot,其他slot并不影响数据通信。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容