當前位置:編程學習大全網 - 源碼下載 - 基於NXP iMX6ULL 擴展音頻解碼器 MAX98357A

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

By Toradex胡珊逢

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

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

Colibri iMX6ULL?總***有三個SAI?接口,這裏使用SAI2?連接?MAX98357A。

根據上面的連接關系,對應修改?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 0x1F089MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088MX6UL_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 Module(CCM)。

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

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

對於音頻文件,可以計算出所需的?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?的頻率範圍內。

完成上面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,4?分頻輸出196608000Hz?的?pll4_audio_div。MUX?之後通過pred 4?分頻輸出49152000Hz,再通過podf 2?分頻輸出24576000Hz?的SAI2_CLK_ROOT,為SAI2?模塊運行提供時鐘信號。

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

root@colibri-imx6ull:~# cat /sys/kernel/debug/clk/clk_summarypll4 ?0 0 0 ?786432000 ?0 0 ?50000pll4_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 ?50000pll4_audio_div 0 0 0 ?196608000 ?0 0 ?50000sai2_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 ?50000sai2 ?0 0 0 24576000 ?0 0 ?50000

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

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

根據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

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

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

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?和揚聲器就可以聽到播放的音頻文件。

/v_show/id_XNTgzMjUxMTg2NA==.html

總結

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

  • 上一篇:QQ寵物社區裏所有的遊戲有什麽,在哪
  • 下一篇:學生宿舍管理系統,C++源碼
  • copyright 2024編程學習大全網