工控網首頁
>

應用設計

>

基于NXP iMX6ULL 擴展音頻解碼器 MAX98357A

基于NXP iMX6ULL 擴展音頻解碼器 MAX98357A

Colibri iMX6ULL 是 Toradex 面向低成本設備推出的 Arm 計算機模塊。該產品沒有音頻編****,無法直接輸出模擬音頻信號。本文將介紹如何使用模塊的數字音頻 I2S 接口擴展 MAX98357A,包括如何配置 device tree 和時鐘。

 Colibri iMX6ULL 模塊上的 i.MX 6ULL SoC 通過 synchronous audio interfaces SAI接口提供數字音頻接口,可以支持 AC97 或者 I2S 以連接外部音頻編****。MAX98357A 是一款易于使用的音頻****,片上帶有 類功放。無需 I2C 配置和外部 MCLK 時鐘,進一步簡化電路設計。接下來我們使用 Colibri iMX6ULL 搭配 Colibri Evaluation Board,安裝 Linux BSP 5.4 為例進行說明。

Colibri iMX6ULL 總共有三個 SAI 接口,這里使用 SAI2 連接 MAX98357A。

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web860.png 

 

根據上面的連接關系,對應修改 device tree。在 imx6ull-colibri-eval-v3.dtsi中首先增加一個 codec_ext 節點。

---------------------------------------------

codec_ext: max98357a@0 {     compatible = "maxim,max98357a";     #sound-dai-cells =<0>; };

---------------------------------------------

然后再添加一個 simple audio card 的節點 sound。其中的 sound-dai 引用了上面的定義的 codec_ext。

---------------------------------------------

sound {     compatible = "simple-audio-card";     status = "okay";     simple-audio-card,name = "max98357a";     simple-audio-card,format = "i2s";     simple-audio-card,bitclock-master = <&dailink_master_cpu>;     simple-audio-card,frame-master = <&dailink_master_cpu>;     simple-audio-card,codec {         sound-dai = <&codec_ext>;     };     dailink_master_cpu: simple-audio-card,cpu {         sound-dai = <&sai2>;     }; };

---------------------------------------------

 

上面的 sound 節點中使用了 sai2,因此接下來需要對 sai2進行初始化。

---------------------------------------------

&sai2 {     pinctrl-names = "default";     pinctrl-0 = <&pinctrl_sai2>;     assigned-clocks = <&clks imx6ul_clk_sai2_sel="">,               <&clks imx6ul_clk_pll4_audio_div="">;     assigned-clock-parents = <&clks imx6ul_clk_pll4_audio_div="">;     assigned-clock-rates =<2>,<196608000>;     fsl,sai-asynchronous;     /*fsl,sai-mclk-direction-output;*/     status = "okay"; };

---------------------------------------------

 

這里有幾個關鍵的參數。pinctrl_sai2 配置了引腳復用關系。對于 MAX98357A 實際上只需要前面三個引腳,如前面表格中列出的連接關系。MX6UL_PAD_JTAG_TMS__SAI2_MCLK  MX6UL_PAD_JTAG_TMS__CCM_CLKO1 為了方便測試相關時鐘信號。而這兩個其實是同一個引腳,只是復用功能選擇不同。sound 節點中 fsl,sai-mclk-direction-output; 參數同樣也是為了測試 SAI  MCLK 輸出,配合 MX6UL_PAD_JTAG_TMS__SAI2_MCLK 輸出 SAI MCLK,但該信號并不用于 MAX98357A。

---------------------------------------------

pinctrl_sai2: sai2grp {         fsl,pins = <             MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK    0x1F089             MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC    0x17088             MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA    0x11088             /*MX6UL_PAD_JTAG_TMS__SAI2_MCLK        0x17088*/             MX6UL_PAD_JTAG_TMS__CCM_CLKO1   0x17088         >;     }; };

---------------------------------------------

 

sound 節點中還有三個重要屬性,assigned-clocks,assigned-clock-parents  assigned-clock-rates。在介紹這些屬性前,我們簡單了解下 iMX6ULL  Clock Controller ModuleCCM。

CCM 負責產生和控制 iMX6ULL 上每個模塊運行所需的時鐘信號,包括從 Arm CPU 核心到各種外設如 USB、Audio、網絡等。由于每個模塊需要的時鐘各不相同,從高頻到低頻,因此 CCM 內部有多個 PLL 以及分頻器提供多種頻率的時鐘信號。對于本次使用的 SAI 模塊,根據 iMX6ULL 芯片手冊 Figure 18-2. Clock Tree - Part 1,其時鐘關系如下。

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web1952.png 

 

SAI2_CLK_ROOT 通過 MUX 可以選擇三個來源,分別是 PLL3,PLL4,PLL5。中間會有多個不同位數的分頻器,將 PLL 輸出較高的時鐘逐級降為較低的頻率。這些分頻器并不需要手動設置,CCM 驅動會根據期望輸出的頻率自動計算合適的分頻比例。SAI2_CLK_ROOT 最終為 SAI2 模塊提供運行時鐘信號。在 SAI 內部,時鐘信號經過內部的分頻器后產生 I2S  bit block 以及幀同步信號 sync。

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web2173.png 

對于音頻文件,可以計算出所需的 bit clock。例如對于一個雙通道,16bit,48K采樣率的音頻文件,bit clock = 16x2x48000 = 1536000。這個數值是我們所需的最終目標時鐘。根據上面的圖示, bit clock 源自于 PLL4。根據 iMX6ULL 芯片手冊 18.5.1.3.4 Audio/video PLL 章節, PLL 的頻率范圍從 650MHz  1.3GHz。以 1536000 為基數,取其整數 512 倍,得到 786432000。即 786432000 經過總共 512 倍分頻后可以產生 1536000 bit clock 信號。這時我們再回顧 sai2 節點中的一些時鐘屬性。

---------------------------------------------

assigned-clocks = <&clks imx6ul_clk_sai2_sel="">,             <&clks imx6ul_clk_pll4_audio_div="">; assigned-clock-parents = <&clks imx6ul_clk_pll4_audio_div="">; assigned-clock-rates =<2>,<196608000>;

---------------------------------------------

 

IMX6UL_CLK_SAI2_SEL 設置的 CCM_CSCMR1 寄存器中的 SAI2_CLK_SEL 位。這里設置為 2, 選擇 PLL4 作為時鐘源。IMX6UL_CLK_PLL4_AUDIO_DIV 為 PLL4 分頻后的時鐘,設置為 19660800,這個數值是 1536000 的 24 倍。而 PLL4 在分頻前為 786432000,這是 IMX6UL_CLK_PLL4_AUDIO_DIV  4 ,在其 650MHz  1.3GHz 的頻率范圍內。

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web2763.png 

 

完成上面 device tree 修改后,重新編譯,并更新到 Colibri iMX6ULL。下面命令可以直接在模塊上覆蓋原來的 dtb 文件。

---------------------------------------------

root@colibri-imx6ull:~# ubiupdatevol /dev/ubi0_1 imx6ull-colibri-eval-v3.dtb

---------------------------------------------

 

重啟后可以看到 max98357a 音頻設備。

---------------------------------------------

root@colibri-imx6ull:~# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: max98357a [max98357a], device 0: 202c000.sai-HiFi HiFi-0 []   Subdevices: 1/1   Subdevice #0: subdevice #0

---------------------------------------------

 

同時在 clock tree 中也可以看到 sai2 相關時鐘。PLL4 輸出 786432000,分頻輸出 196608000Hz  pll4_audio_div。MUX 之后通過 pred 4 分頻輸出 49152000Hz,再通過 podf 2 分頻輸出 24576000Hz  SAI2_CLK_ROOT, SAI2 模塊運行提供時鐘信號。

---------------------------------------------

root@colibri-imx6ull:~# cat /sys/kernel/debug/clk/clk_summary     pll4                              0        0        0   786432000          0     0  50000        pll4_bypass                    0        0        0   786432000          0     0  50000           pll4_audio                  0        0        0   786432000          0     0  50000              pll4_post_div            0        0        0   196608000          0     0  50000                 pll4_audio_div        0        0        0   196608000          0     0  50000                    sai2_sel           0        0        0   196608000          0     0  50000                       sai2_pred       0        0        0    49152000          0     0  50000                          sai2_podf       0        0        0    24576000          0     0  50000                             sai2       0        0        0    24576000          0     0  50000

---------------------------------------------

CCM 提供了兩個引腳 CCM_CLKO1 和 CCM_CLKO2 可以輸出相關時鐘進行測試。在上面的 device tree SAI2 節點引腳配置中我們也使能該引腳 MX6UL_PAD_JTAG_TMS__CCM_CLKO1 0x17088。

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web3255.png 

 

根據 CCM_CCOSR 寄存器 CLKO2_SEL ,sai2_clk_root 位于 CCM_CLKO2, CLK_OUT_SEL 位允許 CCM_CLKO1 上輸出 CCM_CLKO1  CCM_CLKO2。因此,可以通過向 CCM_CCOSR 寄存器寫入 0x01130180, 模塊 SODIMM 71 引腳上啟用 CCM_CLKO1 ,輸出 sai2_clk_root 信號。在 Colibri iMX6ULL 上運行下面命令。

---------------------------------------------

root@colibri-imx6ull:~# devmem2 0x020c4060 w 0x01130180

---------------------------------------------

 

 Colibri iMX6ULL 上用下面命令播放一個雙通道,16bit,48K采樣率的音頻文件,此時測量 SODIMM 71 引腳上輸出的波形。

---------------------------------------------

root@colibri-imx6ull:~# aplay -D sysdefault:CARD=max98357a LRMonoPhase4.wav -vv

---------------------------------------------

 

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web3615.png 

上面圖中可以看到波形頻率為 24.5MHz。即 PLL4 經過多次分頻后產生的時鐘。再次播放上面的音頻文件,測量 SODIMM 31  bit clock  SODIMM 23 幀同步 sync 信號 

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web3721.png 

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web3723.png 

bit clock 頻率為 1.53MHz,幀同步 sync  48KHz。這也是上面計算雙通道,16bit,48K采樣率的音頻 bit clock 數值。這些信號的實際輸出都符合預期。如果開啟 SAI 驅動的調試日志輸出功能,在播放音頻文件后還可以發現其他的一些信息。在 SAI 驅動源碼的第一行添加 #define DEBUG,然后重編譯 zImage。

---------------------------------------------

[   49.838293] fsl-sai 202c000.sai: clk_rate 0 Hz,  mclk_clk id 0 [   49.838316] fsl-sai 202c000.sai: clk_rate 24576000 Hz,  mclk_clk id 1 [   49.838328] fsl-sai 202c000.sai: ratio 16 for freq 1536000Hz based on clock 24576000Hz [   49.838351] fsl-sai 202c000.sai: best fit: clock id=1, ratio=16, deviation=0

---------------------------------------------

 

1536000Hz  bit clock 是通過 24576000Hz 進行 16 分頻得到的。這是因為在 SAI 內部還有一個分頻器可以對 sai2_clk_root 再次分頻從而輸出合適的 bit clock。I2S2_TCR2 寄存器地址 0x0202c008的最后 7  DIV 可以配置該分頻器。分頻數值為 (DIV + 1)x2。讀取該寄存器,DIV 值為 7,進行 16 分頻。對應上面 SAI 驅動調試日志的 “ratio 16 for freq 1536000Hz based on clock 24576000Hz”。

---------------------------------------------

root@colibri-imx6ull:~# devmem2 0x0202c008 w /dev/mem opened. Memory mapped at address 0x76f4b000. Read at address  0x0202C008 (0x76f4b008): 0x07000007

---------------------------------------------

 

最后接上 MAX98357A 和揚聲器就可以聽到播放的音頻文件。

https://v.youku.com/v_show/id_XNTgzMjUxMTg2NA==.html

基于NXP iMX6ULL 擴展音頻**** MAX98357A_web4721.png 

 

總結

通過擴展 MAX98357A 我們介紹了 iMX6 ULL SoC 音頻驅動 SAI 的工作原理,以及如何配置 device tree 和測試方法。借鑒該方法,用戶也可以擴展其他基于 I2S 的音頻編****。


審核編輯(
王靜
)
投訴建議

提交

查看更多評論
其他資訊

查看更多

UBI只讀文件系統

通過Ycoto Project定制嵌入式Ycoto Linux鏡像

在嵌入式 Linux 設備上使用 Flutter 開發圖形界面

TorizonQt容器中文顯示

IoT 安全系列博文第三篇 軟件更新安全:常見的錯誤