天天看點

AM335X添加聲霸卡驅動max98357a記錄_基于TI官方PSDK

0.硬體平台資訊

前篇文章有描述,我們自制硬體平台是使用OSD335X SM晶片,內建了AM335X,DDR3,PMIC,EEPROM。硬體設計上少了很多麻煩,及CPU,DDR測試上的很多麻煩。官方開發闆參考BBB開發闆設計。我們自制硬體有少許改動,是以基礎的DTS檔案,是基于BBB的DTS上修改。

聲霸卡晶片,我們選用的是MAX98357A,使用MCASP0,連接配接了MCASP0_ACLKX,MCASP0_AXR0,MCASP0_FSX。

1.查找驅動檔案

一般使用較多的晶片,LINUX源碼包中都包含有現成驅動,有其它廠商移植好的。原以為自己要寫的,但對LINUX整個驅動架構,開發都不了解,難度太大。是以第一步是找到現有驅動。

在ubuntu的shell中,定位到linux的源碼目錄。

輸入:find . “*.c” | grep “98357”

可以檢索出,源碼中所有名字帶“98357”的C檔案。

~/ti/ti-processor-sdk-linux-am335x-evm-06.03.00.106/board-support/linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85$ find . "*.c" | grep "98357"
./include/config/snd/soc/max98357a.h
./sound/soc/codecs/max98357a.c
./sound/soc/codecs/.max98357a.o.cmd
./sound/soc/codecs/max98357a.o
./sound/soc/amd/acp-da7219-max98357a.c
./sound/soc/intel/boards/kbl_da7219_max98357a.c
./sound/soc/intel/boards/glk_rt5682_max98357a.c
./sound/soc/intel/boards/skl_nau88l25_max98357a.c
./sound/soc/intel/boards/bxt_da7219_max98357a.c
./Documentation/devicetree/bindings/sound/max98357a.txt
find: `*.c': 沒有那個檔案或目錄

           

從以上輸出可以看出,源碼中包含了max98357a的驅動代碼。且驅動檔案在目錄:sound/soc/codecs中

如果沒有檢索出相應檔案。還可以輸入:find . -type f -name “*.c” | xargs grep --color -n “98357”

xargs可以把find檔案中的内容拿 出來檢索。這指令可以檢索出所有檔案中含指定字元串的檔案,并顯示内容,用特殊顔色标出字元串,并顯示行号。但要檢索檔案内容,速度較慢。

~/ti/ti-processor-sdk-linux-am335x-evm-06.03.00.106/board-support/linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85$ find . -type f -name "*.c" | xargs grep --color -n "98357"
./sound/soc/codecs/max98357a.c:12: * max98357a.c -- MAX98357A ALSA SoC Codec driver
./sound/soc/codecs/max98357a.c:30:static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
./sound/soc/codecs/max98357a.c:54:static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
./sound/soc/codecs/max98357a.c:58:static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
./sound/soc/codecs/max98357a.c:62:static int max98357a_component_probe(struct snd_soc_component *component)
./sound/soc/codecs/max98357a.c:75:static const struct snd_soc_component_driver max98357a_component_driver = {
./sound/soc/codecs/max98357a.c:76:	.probe			= max98357a_component_probe,

           

2.添加驅動,更改裝置樹等配置

這步先查找有人已加載max98357a成功的方法。參考網址:https://github.com/beagleboard/bb.org-overlays/issues/39。但按照此方法添加後我們的闆子并未有聲音輸出,遇到一系列問題,随後更進說明。

裝置樹修改過程 ~/ti/ti-processor-sdk-linux-am335x-evm-06.03.00.106/board-support/linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85/arch/arm/boot/dts/am335x-boneblack-common.dtsi:

引腳配置

mcasp0_pins: mcasp0_pins {
		pinctrl-single,pins = <
			//AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */  //後來了解,這個引腳是在使用外部時鐘晶片輸入才需要使用
			AM33XX_IOPAD(0x998, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0.mcasp0_axr0*/
			AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
			AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
			//AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */  //後來了解到,在使用外部時鐘晶片時,用到的時鐘使能引腳
		>;
	};
           

聲霸卡驅動 sound 分成3個部分:

To achieve all this, ASoC splits an embedded audio system into three components:

Codec driver: The codec driver is platform independent and contains audio controls, audio DAPM interface capabilities, codec DAPM definition and codec IO functions.

Platform driver: The platform driver contains the audio dma engine and audio interface drivers (e.g. I2S, AC97, PCM) for that platform.

Machine driver: The machine driver handles any machine specific controls and audio events i.e. turning on an DAPM at start of playback.

添加MCASP0裝置樹,即 Machine driver層:

&mcasp0	{
	#sound-dai-cells = <0>;
	pinctrl-names = "default";
	pinctrl-0 = <&mcasp0_pins>;
	status = "okay";
	op-mode = <0>;	/* MCASP_IIS_MODE */
	tdm-slots = <2>;
	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
			1 0 0 0	//4個數字,對應AXRn   n對應AXR引腳的一組 0-3。我們用的axr0,是以應該設定第一個數了,參考網址用的axr2,是以用的第3個數字
		>;
	tx-num-evt = <32>;
	rx-num-evt = <32>;
};
           

添加sound節點:

/ {
	clk_mcasp0_fixed: clk_mcasp0_fixed {
		#clock-cells = <0>;
		compatible = "fixed-clock";
		/*clock-frequency = <24576000>;*/
		clock-frequency = <12288000>;
	};

	clk_mcasp0: clk_mcasp0 {
		#clock-cells = <0>;
	//	compatible = "gpio-gate-clock";
		clocks = <&clk_mcasp0_fixed>;
	//	enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
	};

	max98357a: max98357a {//對應Codec driver
		#sound-dai-cells = <0>;
		status = "okay";

		compatible = "maxim,max98357a";
		/*sdmode-gpios = <&gpio1 14 0>;*/
	};
    //Platform driver:
	sound {
		compatible = "simple-audio-card";
		status = "okay";
		simple-audio-card,name = "TI BeagleBone Black";
		simple-audio-card,format = "i2s";
		simple-audio-card,bitclock-master = <&dailink0_master>;
		simple-audio-card,frame-master = <&dailink0_master>;
		dailink0_master: simple-audio-card,cpu {
			sound-dai = <&mcasp0>;
			clocks = <&clk_mcasp0>;	
		};

		simple-audio-card,codec {			
			sound-dai = <&max98357a 0>;			
		};
	}; 
           

一開始CLOCK配置和引腳配置,不知道CLOCK enable是什麼意思。看了這篇文章終于明白,最後才屏蔽了 clock 使能相關的,配置。https://e2e.ti.com/support/processors/f/791/t/875002?tisearch=e2e-sitesearch&keymatch=OCTVO-3P-AM335X%253A

MCASP0的配置,修改對應的AXR的TX,RX狀态也是參照這個了解的。

5.核心配置修改

查找預設配置檔案:/arch/arm/configs/tisdk_am335x-evm_defconfig。發現沒有我們驅動max98357a的配置檔案。menuconfig裡也沒有。是以需要自己添加配置,使能編譯。參照這篇文章:https://stackoverflow.com/questions/52970065/audio-issue-with-imx6-board-max98357a-codec/63342117#63342117

其中描述:

I had some trouble getting the sound card (MA98357a codec with the simple-audio-card) to work with a recent revision of the imx6q (i.MX 6 Quad), so I am sharing here my solution:

CONFIG_SND_SOC_MAX98357A needs to be enabled (associated with the compatible "maxim,max98357a"). But "by default" this option cannot be selected under make menuconfig. The associated Kconfig (sound/soc/codecs/Kconfig) needs to be patched. Replace:
           

config SND_SOC_MAX98357A

tristate

By:

config SND_SOC_MAX98357A

tristate “Maxim MAX98357A CODEC”

CONFIG_SND_SIMPLE_CARD needs to be enabled (associated with the compatible "simple-audio-card")
           

先修改sound/soc/codecs/Kconfig檔案,再修改tisdk_am335x-evm_defconfig。因為我們調用PSDK安裝目錄下的,make linux編譯,他會自動make tisdk_am335x-evm_defconfig。是以,menuconfig 時使用Kfonfig配置出來的會被删除,被tisdk_am335x-evm_defconfig重新配置替換。

3.1.menuconfig配置方法:

o enable/disable audio support, start the Linux Kernel Configuration tool:

$ make menuconfig 

Select Device Drivers from the main menu.

    ...
    ...
    Power management options --->
    [ ] Networking support --->
    Device Drivers --->
    File systems --->
    Kernel hacking --->
    ...
    ...

Select Sound card support as shown here:
    ...
    ...
    Multimedia devices --->
    Graphics support --->
<*> Sound card support --->
[*] HID Devices --->
[*] USB support --->
    ...
    ...


Select Advanced Linux Sound Architecture as shown here:

--- Sound card support
<*> Advanced Linux Sound Architecture --->
< > Open Sound System (DEPRECATED) --->

Select ALSA for SoC audio support as shown here:
    ...
    ...
[*] ARM sound devices --->
[*] SPI sound devices --->
<*> ALSA for SoC audio support --->

Select SoC Audio for TI81XX chip as shown here:

--- ALSA for SoC audio support
<*> SoC Audio for the Maxim MAX98357A CODEC
< > Build all ASoC CODEC drivers (NEW)

           

3.2. 修改tisdk_am335x-evm_defconfig方法:

添加:

# CONFIG_SND_SOC_MAX98373 is not set
CONFIG_SND_SOC_MAX98357A=y

CONFIG_SND_SIMPLE_CARD_UTILS=y//原來已使能
CONFIG_SND_SIMPLE_CARD=y//原來已使能

CONFIG_SND_DEBUG=y//打開Debug
           

其中,所有配置必須頂格寫。一開始犯了個錯誤空了一格,為和注釋行對齊,導緻配置不成功。

至此配置成功。在PSDK安裝目錄下:make linux

4.測試及問題解決

按3中更改的,把zImage 和 .dtb更新後測試。使用 aplay -vv 123.wav測試發現無輸出,且測試的音頻卡住 不動。如下:

[email protected]-evm:~# aplay -vv 123.wav 
Playing WAVE '123.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Rate conversion PCM (48000)
Converter: linear-interpolation
Protocol version: 10002
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 22050
  period_size  : 5512
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 5512
  period_event : 0
  start_threshold  : 22050
  stop_threshold   : 22050
  silence_threshold: 0
  silence_size : 0
  boundary     : 1445068800
Slave: Plug PCM: Hardware PCM card 0 'TI BeagleBone Black' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
  appl_ptr     : 0
  hw_ptr       : 0
#######+                                           | 12%
           

使用 ls /dev/snd檢視聲霸卡有無添加成功:

[email protected]-evm:~# ls /dev/snd     
by-path    controlC0  pcmC0D0p   timer
           

發現有controlC0 代表添加聲霸卡是成功識别到的。參考如下TI WIKI TI81XX PSP AUDIO Driver User Guide中的描述(WIKI還有兩個月伺服器就關閉了,是以網址就不帖了):

Device Interface

The operational interface in /dev/ contains three main types of devices:

PCM devices for recording or playing digitized sound samples,
CTL devices that allow manipulating the internal mixer and routing of the card, and,
MIDI devices to control the MIDI port of the card, if any.
           

Device Interface Name Description

/dev/snd/controlC0 Control devices (i.e. mixer, etc)

/dev/snd/pcmC0D0c PCM Card 0 Device 0 Capture device

/dev/snd/pcmC0D0p PCM Card 0 Device 0 Playback device

這時量硬體的3個引腳上均無波形,絕大機率可能是裝置樹沒配置好,導緻硬體沒工作起來。如果聲霸卡添加失敗,aplay不會有以上描述的調試資訊,會直接提示無聲霸卡。期間試了網上說能用的很多版本,都沒成功。

最後僅添加了以下這句,就有聲音輸出了:simple-audio-card,mclk-fs = <512>;添加在sound節點下,一會會放出完整能用的sound相關部分。但現在還不知道這句話的作用。

此時的播放的音樂,采樣率為 rate 48K的能正常播放,但其他采樣率的音頻播放,會相當于幾倍速播放,對比發現,是先軟體插值參與了。而後再播正常48K采樣率的音頻也無法播放。像是時鐘被修改了,或跳頻率采樣點了。在 aplay播放時,添加 --disable-resample屬性,就可以正常播放。聯想到之前配置時鐘輸入輸出配置時,有個時鐘輸出屬性。

[email protected]-evm:~# aplay -vv --disable-resample 123.wav 
           

最後嘗試,在simple-audio-card,cpu 節點下,添加system-clock-direction-out;後,開機第一次播放聲音正常。而後播放同樣異常。發現有篇文章描述的問題相同:https://e2e.ti.com/support/processors/f/791/t/936823?tisearch=e2e-sitesearch&keymatch=AM3352%3A%20McASP%20fsx%20start,像是MCASP時鐘不固定,運作後,時鐘被修改,出現偏差導緻,具體原因不詳。在/~.asoundrc,或/etc/asound.conf檔案中加入:

pcm.!default {
    type rate
    slave {
        pcm "plughw:0,0"
        rate 48000
    }
}
           

這時,播放音頻采樣率正常。

最後,裝置正常的裝置樹中,sound相關的節點如下:

clk_mcasp0_fixed: clk_mcasp0_fixed {
		#clock-cells = <0>;
		compatible = "fixed-clock";
		/*clock-frequency = <24576000>;*/
		clock-frequency = <12288000>;
	};

	clk_mcasp0: clk_mcasp0 {
		#clock-cells = <0>;
	//	compatible = "gpio-gate-clock";
		clocks = <&clk_mcasp0_fixed>;
	//	enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
	};

	max98357a: max98357a {
		#sound-dai-cells = <0>;
		status = "okay";

		compatible = "maxim,max98357a";
		/*sdmode-gpios = <&gpio1 14 0>;*/
	};

	sound {
		compatible = "simple-audio-card";
		status = "okay";
		simple-audio-card,name = "TI BeagleBone Black";
		simple-audio-card,format = "i2s";
		simple-audio-card,bitclock-master = <&dailink0_master>;
		simple-audio-card,frame-master = <&dailink0_master>;
		simple-audio-card,mclk-fs = <512>;
		dailink0_master: simple-audio-card,cpu {
			sound-dai = <&mcasp0>;
			clocks = <&clk_mcasp0>;	
			//system-clock-direction = "out";	
			system-clock-direction-out;
			//system-clock-frequency = <12000000>;	
			//dai-tdm-slot-num = <2>;
            		//dai-tdm-slot-width = <32>;

		};

		simple-audio-card,codec {			
			sound-dai = <&max98357a 0>;			
		};
	}; 
           

論壇也有寫法,把clk_mcasp0_fixed節點,直接添加到simple-audio-card,cpu節點,省略掉clk_mcasp0節點。但經過測試發現不行。必須如上所示的,才可以正常播放音頻。

繼續閱讀