i2S 传输模式分为 I2S 标准模式, I2S 左对齐模式, I2S 右对齐模式,还有 TDM 模式, PCM 模式 。
I2S 标准模式 :
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 左对齐协议 :
I2S 左对齐模式:与 I2S 标准的差异,在 LRCK 发生翻转时就开始传输数据。
LRCK 为高电平时,表示第一个声道,低电平为第二个声道。 BCLK 电平在 LRCK 发生电平变化后从低电平开始。
I2S 右对齐协议 :
I2S 右对齐模式:与 I2S 标准的差异,声音数据 LSB 传输完成的同时, LRCLK 完成第二次翻转。LRCK 为高电平时,表示第一个声道,低电平为第二个声道。 BCLK 电平在 LRCK 发生电平变化后从低电平开始。
I2S 的 TDM 模式 :
I2S 标准 _TDM :
如果要传输超过两声道的数据,就需要使用 I2S 的 TDM 模式,因为各个厂家实现不一样 ,仅供参考。
与 I2S 标准协议差异就是可以传输多个通道,最高支持到 16 声道。
在 LRCK 的低电平传输左声道,高电平传输右声道。
可以看到在 Slot 传输两个通道时,就是标准 I2S 的传输。
BCLK_rate = sample_rate * slot * slot_width
。
I2S 左对齐 _TDM :
I2S 左对齐模式:与 I2S 标准的差异,在 LRCK 发生翻转时就开始传输数据。这种协议使用较少。
I2S 右对齐 _TDM :
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 周期
短针示图:
LRCK width = 1 个 BCLK,就是上图中 LRCK 的高电平,对应一个 BCLK 的宽度。这种就是短帧模式。
帧同步时钟宽度为一个位时钟周期,数据在 LRCK 有效后, BCLK 的第二个上升有效,又是**DSP_MODE_A **模式。
长针示图:
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_mode:RX端数据格式配置。表示发送,也就是输入信号。同上
- 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协议格式有i2s,right_j,left_j,分别表示i2s标准格式,i2s右对齐,i2s左对齐,对应1-3
pcm协议的格式有dsp_a,dsp_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_master:1:表示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....
对于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并不影响数据通信。