Adding MAX98357A I2S DAC to a custom carrier board

Hi,

On a custom carrier board using a Verdin IMX8MP SoM we added a MAX98357a I2S audio DAC/AMP to be able to connect a small speaker to the board.
So far I ran into some issues trying to get data out on the I2S bus.

The card seems to be recognizes in Linux, based on the dmesg output:

[ 1.816719] debugfs: Directory ‘30c10000.sai’ with parent ‘max98357a’ already present!
[ 1.824786] asoc-simple-card sound-card: HiFi <-> 30c10000.sai mapping ok
[ 1.831624] asoc-simple-card sound-card: ASoC: no DMI vendor name!

and in alsamixed I see the sound card, which has no controls as expected.
But if I try to play audio or run speaker-test I get the following message:

speaker-test 1.2.1

Playback device is default
Stream paramet[ 298.905978] fsl-sai 30c10000.sai: ASoC: can’t open component 30c10000.sai: -6
ers are 48000Hz, S16_LE, 1 channels
Using 16 octaves of pink noise
ALSA lib …/…/…/alsa-lib-1.2.1.2/src/pcm/pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
Playback open error: -6,No such device or address

Could you give us some pointers on what this could be?

We are using Yocto, BSP 5.7.2 and I changed the following for the sound card:

I added the codec driver in Linux

│ Symbol: SND_SOC_MAX98357A [=y]                                                                                                      
  │ Type  : tristate                                                                                                                    
  │ Prompt: Maxim MAX98357A CODEC                                                                                                       
  │   Location:                                                                                                                         
  │     -> Device Drivers                                                                                                               
  │       -> Sound card support (SOUND [=y])                                                                                            
  │         -> Advanced Linux Sound Architecture (SND [=y])                                                                             
  │           -> ALSA for SoC audio support (SND_SOC [=y])                                                                              
  │ (6)         -> CODEC drivers     
  

And I added it to the device tree as follows:

	codec_ext: max98357a@0 {
		compatible = "maxim,max98357a";
		#sound-dai-cells = <0>;
		clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1>;
		clock-names = "mclk";
	};

	sound_card: sound-card {
		compatible = "simple-audio-card";
		simple-audio-card,bitclock-master = <&dailink_master>;
		simple-audio-card,format = "i2s";
		simple-audio-card,frame-master = <&dailink_master>;
		simple-audio-card,name = "max98357a";

		dailink_master: simple-audio-card,codec {
			sound-dai = <&codec_ext>;
			clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1>;
		};

		simple-audio-card,cpu {
			sound-dai = <&sai1>;
		};
	};

I also changed the asound.conf to the following:

pcm.speakerbonnet {
   type hw card 0
}

pcm.dmixer {
   type dmix
   ipc_key 1024
   ipc_perm 0666
   slave {
     pcm "speakerbonnet"
     period_time 0
     period_size 1024
     buffer_size 8192
     rate 44100
     channels 2
   }
}

ctl.dmixer {
    type hw card 0
}

pcm.softvol {
    type softvol
    slave.pcm "dmixer"
    control.name "PCM"
    control.card 0
}

ctl.softvol {
    type hw card 0
}

pcm.!default {
    type             plug
    slave.pcm       "softvol"
}

Best regards,

Rik

Hello @rikte

Maybe the post by eoin_oc1 in this post can help you :

Best regards,
Josep

Hi @rikte ,

Happy New Year :tada:

Were you able to solve this?

Best Regards
Kevin

Hi Kevin,

Due to the holidays I haven’t spend too much time on it, but I tried a few things:

I tried a device tree like in the post linked by Josep, or based on the following:
https://community.toradex.com/t/max98357a-on-imx7s-with-simple-audio-card/
Which for me looks like this:

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

	sound {
		compatible = "simple-audio-card";
		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 = <&sai1>;
		};

	};

But sadly with the same results.

Hello @rikte ,
In our blog section we have an article about MAX98357A and iMX6ULL. Unfortunately is only in Chinese, but I have asked internally to publish an English version too

Best regards,
Josep

Hi Joseph,

The blog was helpful, especially the last part concerning the clocks.
If I understand it correctly, and the translation via google is correct. The clock for sai is off, and the devmem2 command it used to turn it on.

Of course the CCM peripheral for the imx6ull and the imx8mp is very different, and there is no CCM Clock Output Source Register (CCM_CCOSR) register or such on the imx8mp.
Is the devmem2 command indeed to turn the clock on, and how would I do that for the imx8mp?

Hello @rikte ,
I passed your question internally to the author of the article. Meanwhile we ordered a MAX98357A to do some tests ourselves. We will keep you updated.

Best regards,
Josep

Hi @rikte , I used to bring up MAX98357A on Colibri iMX6ULL and on Verdin iMX8MP, I did the same again. Here is what I do.
First, max98357a driver needed to be added to Linux kernel.

~# zcat /proc/config.gz |grep MAX98357
CONFIG_SND_SOC_MAX98357A=m

Then in the device tree, the codec on our carrier board is disabled, add MAX98357A node and enable SAI3.
imx8mp-verdin-dahlia.dtsi (4.2 KB)

Finally, deploy the kernel module and device tree binary to the board. The kernel(Image.gz) itself may also need to be compiled.

With a reboot, MAX98357A connected to SAI3(SODIMM42, 44, 46) is listed in system and it is able to play an audio file.

~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: max98357a [max98357a], device 0: 30c30000.sai-HiFi HiFi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

~# aplay -D sysdefault:CARD=max98357a LRMonoPhase4.wav -vv
Playing WAVE 'LRMonoPhase4.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Plug PCM: Hardware PCM card 0 'max98357a' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 16384
  period_size  : 4096
  period_time  : 85333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 4096
  period_event : 0
  start_threshold  : 16384
  stop_threshold   : 16384
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
###############   +                                | 35%

Tips: MAX98357A is not 1.8V compatible. The level shift is required, e.g. X40/X39 on Verdin Development Board.

Hello @rikte ,
Did the answer from @benjamin.tx solve your issue? If so, could you mark his answer as solution?

Best regards,
Josep

Hi @josep.tx

I have not had time to try it, I will do so later this week and report back to you.

I had some time to gave it a try.

I checked out the kernel ( toradex_5.4-2.3.x-imx ) and set

CONFIG_SND_SOC_MAX98357A=y

This so it’s in the kernel and not a loadable module.
I used the exact device tree as supplied and aplay -l gives me the same result

~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: max98357a [max98357a], device 0: 30c30000.sai-HiFi HiFi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Sadly playing any audio gives a similar error as before.
I do not have the DAC hooked up to SAI3, but to SAI1 but as it’s a simple DAC with no feedback I think that should not be an issue and I should at least be able to play audio and see I2S data using a scope.

Could you tell me what version of the kernel and such you used, then we can try to recreate that on our side. Or perhaps for a test include the build kernel, module and dtb?

Best regards,

Rik

Hi @rikte . My kernel was also fetched from toradex_5.4-2.3.x-imx branch. It is 5.4.193. By default, SAI1 is routed to a codec NAU88C22YG on Verdin Development or WM8904CGEFL on Dahlia. The two carrier boards have their own device tree binaries where the codec is configured. The imx8mp-verdin-dahlia.dtsi provided above only uses SAI3. For SAI1, it should be modified. Which carrier board do you have now? And which device tree is applied? You can check it on the serial console during U-Boot loading.

## Executing script at 47000000
Loading DeviceTree: imx8mp-verdin-nonwifi-dev.dtb
88435 bytes read in 11 ms (7.7 MiB/s)
86 bytes read in 7 ms (11.7 KiB/s)
Applying Overlay: verdin-imx8mp_native-hdmi_overlay.dtbo
1860 bytes read in 15 ms (121.1 KiB/s)
Applying Overlay: verdin-imx8mp_lt8912_overlay.dtbo
1987 bytes read in 17 ms (113.3 KiB/s)
10643094 bytes read in 102 ms (99.5 MiB/s)

Hello @rikte ,
Were you able to solve your issue with the info provided by @benjamin.tx ?

Best regards,
Josep

Hi Josep,

Due to holidays on my side I have not been able to continue with this issue lately. I will let you know when I have.

Best regards,

Rik

Hi @rikte ,

Thanks for the update. @josep.tx is attending embedded world this week.

I will try to keep an eye on it here.

Best Regards
Kevin