ブログ:
Apalis iMX8 扩展外部 SGTL5000

2023年4月19日水曜日

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 * FsI2S_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 = <&reg_ex_auido_3v>;
       VDDIO-supply = <&reg_ex_auido_3v>;
       VDDD-supply = <&reg_ex_auido_1v8>;
       clocks = <&ex_audio_clk>;
   };

};


SGTL5000 使用外部的电源供电,所以也需要添加 VDDA-supplyVDDIO-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.1KHz16bit双声道文件,比特率=16*2*44.1K=1.4MHz。如下面示波器测量显示,CH1 LRCLKCH2 SCLK


SGTL5000 在播放时会根据音源文件调整工作参数,例如时钟,PLL 工作状态。可以通过 cat /sys/kernel/debug/regmap/5-000a/registers 命令查看寄存器配置。由于 SGTL5000 的已经被其驱动占用,所以无法使用 i2cget 读取寄存器。


例如寄存器 CHIP_CLK_CTRL 0x0004 的值为 0007bit3:2=0x01,表示采样频率为 44.1KHzBit 1:0 = 0x3,表示使用 PLL 。这是由于 44.1KHz 信号无法通过 12.28MHz 256384 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 源码中有非常多的示例可供用户参考。






記者: 胡珊逢,FAE,韬睿(上海)

コメントを投稿

Please login to leave a comment!
Have a Question?