I am trying to interface a max98357a audio codec to an i.MX8M Plus EVK running Linux. I made a breakout board to get the SAI pins from the audio connector. The codec seems to register correctly as a sound card using the simple-card driver, but I can't see any activity on the SAI3_BCLK line.
aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: MAX98357A [SAI3 MAX98357A], device 0: 30c30000, sai-HiFi HiFi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
cat /proc/asound/cards
0 [MAX98357A ]: SAI3_MAX98357A - SAI3 MAX98357A
SAI3 MAX98357A
I can't see any activity on the BCLK line when I use speaker-test or aplay test.wav
#include "imx8mp.dtsi"
/ {
codec: max98357a {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
sdmode-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&sdmode_en>;
simple-audio-card,name = "SAI3 MAX98357A";
simple-audio-card,format = "i2s";
simple-audio-card,widgets = "Speaker", "Speakers";
simple-audio-card,routing = "Speakers", "Speaker";
simple-audio-card,bitclock-master = <&cpu_dai>;
simple-audio-card,frame-master = <&cpu_dai>;
cpu_dai: simple-audio-card,cpu {
sound-dai = <&sai3>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
};
};
};
&sai3 {
#saund-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
status = "okay";
fsl,sai-asynchronous;
};
&sdma2 {
status = "okay";
};
&iomuxc {
imx8mm-som {
pinctrl_sai3: sai3grp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_TXFS_AUDIOMIX_SAI3_TX_SYNC 0xd6
MX8MP_IOMUXC_SAI3_TXC_AUDIOMIX_SAI3_TX_BCLK 0xd6
MX8MP_IOMUXC_SAI3_TXD_AUDIOMIX_SAI3_TX_DATA00 0xd6
>;
};
sdmode_en: sdmodegrp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x26
>;
};
};
};
Solved! Go to Solution.
I solved my issue.
There were two clock entries missing in the sai3 section.
&sai3 {
#saund-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_IPG>, <&clk IMX8MP_CLK_DUMMY>, <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>, <&clk IMX8MP_CLK_DUMMY>, <&clk IMX8MP_CLK_DUMMY>, <&clk IMX8MP_AUDIO_PLL1_OUT>, <&clk IMX8MP_AUDIO_PLL2_OUT>;
clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k";
assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
assigned-clock-parents = <&clk IMC8MP_AUDIO_PLL2_OUT>;
assigend-clock-rates = <183456000>;
fsl,sai-asynchronous;
status = "okay";
};
Now I can play wav, mp3, mp4
aplay test.wav
gst-launch-1.0 playbin uri=file:///video.mp4
gst-launch-1.0 playbin uri=file:///audio.mp3
Here my final DT.
#include "imx8mp.dtsi"
/ {
codec: max98357a {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
sdmode-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&sdmode_en>;
simple-audio-card,name = "SAI3 MAX98357A";
simple-audio-card,format = "i2s";
simple-audio-card,widgets = "Speaker", "Speakers";
simple-audio-card,routing = "Speakers", "Speaker";
simple-audio-card,bitclock-master = <&cpu_dai>;
simple-audio-card,frame-master = <&cpu_dai>;
cpu_dai: simple-audio-card,cpu {
sound-dai = <&sai3>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
clocks = <&clk IMX8MP_CLK_SAI3>;
};
};
};
&sai3 {
#saund-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
assigned-clock-parents = <&clk IMC8MP_AUDIO_PLL2_OUT>;
assigend-clock-rates = <183456000>;
fsl,sai-asynchronous;
status = "okay";
};
&sdma2 {
status = "okay";
};
&iomuxc {
imx8mm-som {
pinctrl_sai3: sai3grp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_TXFS_AUDIOMIX_SAI3_TX_SYNC 0x106
MX8MP_IOMUXC_SAI3_TXC_AUDIOMIX_SAI3_TX_BCLK 0x106
MX8MP_IOMUXC_SAI3_TXD_AUDIOMIX_SAI3_TX_DATA00 0x106
>;
};
sdmode_en: sdmodegrp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x166
>;
};
};
};
Now I can playback wav-files with aplay.
A further issue is that I only can playback one file. After the playback finished and I want to playback the file again I get the error message that fsl-asi 30c30000.sai is failed to derive required TX rate of 1411200. The only way to get it work is to reset my board.
I solved my issue.
There were two clock entries missing in the sai3 section.
&sai3 {
#saund-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_IPG>, <&clk IMX8MP_CLK_DUMMY>, <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>, <&clk IMX8MP_CLK_DUMMY>, <&clk IMX8MP_CLK_DUMMY>, <&clk IMX8MP_AUDIO_PLL1_OUT>, <&clk IMX8MP_AUDIO_PLL2_OUT>;
clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k";
assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
assigned-clock-parents = <&clk IMC8MP_AUDIO_PLL2_OUT>;
assigend-clock-rates = <183456000>;
fsl,sai-asynchronous;
status = "okay";
};
Now I can play wav, mp3, mp4
aplay test.wav
gst-launch-1.0 playbin uri=file:///video.mp4
gst-launch-1.0 playbin uri=file:///audio.mp3
After I add "clocks" to my codec_dai section I can see some frequency at the pins BCLK, LRCLK and DIN.
...
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
clocks = <&clk IMX8MP_CLK_SAI3>;
};
...
When I start speaker-test I can measure the following frequencies:
BCLK = 187,4kHz
LRCLK = 5,86kHz
DIN = 8-48kHz
So the LRCLK is BCLK divided by 32. That is in my opinion correct. But I can't hear any sound out of the speaker.
Hello weidong_sun,
thanks for reply. I did the widgets and routing in the DT.
...
simple-audio-card,widgets = "Speaker","Speakers";
simple-audio-card,routing = "Speakers", "Speaker";
...
I think it is correct. My codec offers the sink "Speaker", isn't it?
static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("Speaker"),
};
static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
{"Speaker", NULL, "HiFi Playback"},
};
I am thinking about the frequencies. In every example that I saw they use system-clock-frequency. But the DT documentation for simple-audio-card doesn't know that item. Is it only for SSI interface and SAI will do that on its own?
Thanks
Hi,
BCLK = 187,4kHz
LRCLK = 5,86kHz
DIN = 8-48kHz
do you konw the sample rate of your test.wav? 586KHZ?
Weidong
I use speaker-test and it puts out a rate of 48000Hz.
Stream parameters are 48000Hz, S16_LE, 1 channel
I also saw that the LRCLK was to low. The datasheet of MAX98357 says 7.6 to 8.4 kHz. The SAI3 CLK has 24MHz.
cat /sys/kernel/debug/clk/clk_summary | grep sai
So there is a factor of 130 between SAI3 clk and the BCLK. I assume that there is something wrong with the clocks.
I got my first sound
I add a assigned-clock-parents item to my sai-section
&sai3 {
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
status = "okay";
assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
assigend-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
fsl,sai-synchronous;
};
OK, got it.
good job!
Hi,
The following are my suggestions:
1. You'd better write a machine driver yourself.
2. single audio card driver
After checking your sound node, it seems that widget and routing are missing. This may be the root cause of the speaker's failure to output audio. Something like this:
simple-audio-card,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"MIC1", "Microphone Jack",
"MIC2", "Microphone Jack",
"Microphone Jack", "micbias1",
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
Yours may be different from the above, you need to determine them according to the widget and routing in the codec driver.
Hope above messages are helpful to you.
Have a nice day!
B.R,
weidong