您现在的位置是:首页 >技术杂谈 >基于NXP iMX8处理器扩展外部 SGTL5000 音频接口网站首页技术杂谈
基于NXP iMX8处理器扩展外部 SGTL5000 音频接口
By Toradex胡珊逢
Apalis iMX8 计算机模块的数字音频接口 SAI(Synchronous Audio Interface)可以配置为 AC97、I2S格式,用于连接外部音频编解码器。文章接下来将介绍在 Linux BSP v6 上如何扩展第二路 SGTL5000。
iMX8 处理器具有多路 SAI 通道,SAI1 已经被模块片上的 SGTL5000 使用,SAI0 通道引出到模块金手指上,并且是兼容 Apalis 标准数字音频接口,该通道在基于其他 CPU 的 Apalis 模块也可以直接使用。因此,我们选择 SAI0 扩展外部 SGTL5000。
SGTL5000 面向 iMX8 处理器的接口主要是 I2S 和时钟信号。
Apalis iMX8 的 SAI0 通道可以直接连接 SGTL5000 的 I2S 接口。但是 MXM3_194 引脚上没有时钟信号。对于外部音频编解码器如果需要时钟输入,如 SGTL5000 的 SYS_MCLK,可以选择 MXM3_215 引脚,或者采用外部时钟源,如晶振。
SGTL5000 在 master mode 时可以向 Apalis iMX8 输出 I2S_LRCLK 和 I2S_SCLK 信号。 当SYS_MCLK = SupportedRates * Fs,I2S_LRCLK 可以和 SYS_MCLK 同步。如果无法满足,SGTL5000 则会使用内部的 PLL 产生符合音源的 I2S_LRCLK 频率。PLL 的使用会增加 额外的功耗。PLL 的时钟输入也来自 SYS_MCLK,可以支持 8.0 到 27MHz 频率。
外部 SGTL5000 原理图如下,其中使用一个12.28MHz 的外部有源晶振。
接下来修改 device tree 添加 SGTL5000 的相关配置。
imx8-apalis-v1.1.dtsi 的 I2C3 节点添加 SGTL5000 的 I2C 配置。
---------------------------------------
/* Apalis I2C3 (CAM) */
&i2c3 {
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpi2c3>;
status = "okay";
external_sgtl5000: audio-codec@a {
#sound-dai-cells = <0>;
compatible = "fsl,sgtl5000";
reg = <0xa>;
//micbias-resistor-k-ohms = <2>;
micbias-voltage-m-volts = <2250>;
VDDA-supply = <®_ex_auido_3v>;
VDDIO-supply = <®_ex_auido_3v>;
VDDD-supply = <®_ex_auido_1v8>;
clocks = <&ex_audio_clk>;
};
};
---------------------------------------
SGTL5000 使用外部的电源供电,所以也需要添加 VDDA-supply,VDDIO-supply 和 VDDD-supply。
---------------------------------------
reg_ex_auido_3v: regulator-ex-audio-3v {
compatible = "regulator-fixed";
regulator-name = "ex-audio-3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
reg_ex_auido_1v8: regulatorex-audio-1v8 {
compatible = "regulator-fixed";
regulator-name = "+V1.8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
---------------------------------------
以及外部时钟定义。
---------------------------------------
ex_audio_clk: sgtl5000_12M {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <12288000>;
};
---------------------------------------
在原有的 sound 节点后再增加一个 外部 SGTL5000 的 sound_external。
---------------------------------------
sound_external {
compatible = "simple-audio-card";
simple-audio-card,bitclock-master = <&dailink_master_external>;
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&dailink_master_external>;
simple-audio-card,name = "external-sgtl5000";
simple-audio-card,cpu {
sound-dai = <&sai0>;
};
dailink_master_external: simple-audio-card,codec {
sound-dai = <&external_sgtl5000>;
system-clock-frequency = <12288000>;
};
};
---------------------------------------
配置 sai0 节点。
---------------------------------------
&sai0 {
assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
<&sai0_lpcg 0>;
assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai0>;
#sound-dai-cells = <0>;
//fsl,txm-rxs;
};
---------------------------------------
最后在 imx8-apalis-ixora-v1.2.dtsi 里启用 SAI0。
---------------------------------------
&sai0 {
status = "okay";
};
---------------------------------------
参考这里重新编译和部署 device tree 。上面提到的 patch 文件下载。重新启动后检查外部 SGTL5000 挂载情况。在I2C-5 通道上已经发现地址为 0x0a 的设备。
---------------------------------------
root@apalis-imx8-06852111:/tmp# i2cdetect -y -r 5
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- UU -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
---------------------------------------
相应的驱动也加载。
---------------------------------------
root@apalis-imx8-06852111:/tmp# dmesg|grep sgtl
[ 2.128045] sgtl5000 3-000a: sgtl5000 revision 0x11
[ 2.264861] sgtl5000 5-000a: sgtl5000 revision 0x11
---------------------------------------
检查声卡设备,发现 sysdefault:CARD=externalsgtl500。
---------------------------------------
root@apalis-imx8-06852111:/tmp# aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
sysdefault:CARD=externalsgtl500
external-sgtl5000, 59040000.sai-sgtl5000 sgtl5000-0
Default Audio Device
sysdefault:CARD=apalisimx8qmsgt
apalis-imx8qm-sgtl5000, 59050000.sai-sgtl5000 sgtl5000-0
Default Audio Device
sysdefault:CARD=imxspdif
imx-spdif, S/PDIF PCM snd-soc-dummy-dai-0
Default Audio Device
---------------------------------------
使用 BSP 默认的音频文件播放。
---------------------------------------
root@apalis-imx8-06852111:/tmp# aplay -D sysdefault:CARD=externalsgtl500 ~/sound/Gong.wav
---------------------------------------
如果音量小的话,使用 alsamixer 调整。按F6 选择外部 SGTL5000。
Gong.wav 是一个采样率44.1KHz,16bit双声道文件,比特率=16*2*44.1K=1.4MHz。如下面示波器测量显示,CH1 是LRCLK,CH2 是 SCLK。
SGTL5000 在播放时会根据音源文件调整工作参数,例如时钟,PLL 工作状态。可以通过 cat /sys/kernel/debug/regmap/5-000a/registers 命令查看寄存器配置。由于 SGTL5000 的已经被其驱动占用,所以无法使用 i2cget 读取寄存器。
例如寄存器 CHIP_CLK_CTRL 0x0004 的值为 0007。bit3:2=0x01,表示采样频率为 44.1KHz。Bit 1:0 = 0x3,表示使用 PLL 。这是由于 44.1KHz 信号无法通过 12.28MHz 的 256、384或 512 倍分频得到,所以只能使用 PLL 产生。
外部 SGTL5000 的录音功能可以使用下面命令。
---------------------------------------
root@apalis-imx8-06852111:/tmp# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 44100 -t wav mic.wav
---------------------------------------
其中 hw:0,0 可以 aplay -l 命令查看对应声卡的 card, subdevice 序号。
---------------------------------------
root@apalis-imx8-06852111:/tmp# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: externalsgtl500 [external-sgtl5000], device 0: 59040000.sai-sgtl5000 sgtl5000-0 [59040000.sai-sgtl5000 sgtl5000-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
---------------------------------------
总结
Apalis iMX8 的数字音频接口可以非常方便地扩展音频编解码器,具体的引脚分配、device tree 配置等需要结合所使用的音频编解码器,有些可能会十分简单,如 MAX98357A,其甚至不需要 I2C 和 SYS_MCLK 就可以直接工作。Apalis iMX8 所使用的 Linux kernel 源码中有非常多的示例可供用户参考。