We're trying to hook up a MAX98357a Amp/Codec to an i.MX 6Solo using the 'simple-audio-card' device tree abstraction. We see no errors in dmesg and the ALSA device is visible, we can play audio files using 'aplay' but speakers remain silent.
Using a scope we see that data is transmitted over the I2S interface but clock lines remain silent. We also tried the solution using 'imx-pt10ex' driver instead of simple-audio-card, as suggested in #384918, but this yielded the opposite behaviour: clocks turn on and off but not data transmitted.
The Amp/Codec is hooked up as I2S slave on Port 3. We're using the following DTS (only relevant parts):
codec: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
simple-audio-card,name = "TI3 Audio";
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 = <&ssi1 0>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
};
};
&audmux {
status = "okay";
ssi0 {
fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
fsl,port-config = <
(IMX_AUDMUX_V2_PTCR_SYN |
IMX_AUDMUX_V2_PTCR_TFSDIR |
IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT3_SSI_PINS_3) |
IMX_AUDMUX_V2_PTCR_TCLKDIR |
IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT3_SSI_PINS_3))
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT3_SSI_PINS_3)
>;
};
aud3 {
fsl,audmux-port = <MX31_AUDMUX_PORT3_SSI_PINS_3>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
>;
};
};
&ssi1 {
fsl,mode = "i2s-master";
status = "okay";
};
(I know 'ssi0' in audmux and 'ssi1' look inconsistent, however we had a different codec running fine with these definitions so we just kept them.)
Any ideas or advice what might be wrong? Thanks in advance!
解決済! 解決策の投稿を見る。
Thanks for the hint regarding SSI clock generation.
Well, I got it basically working now, with the following device tree entries:
codec: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
simple-audio-card,name = "TI3 Audio";
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 = <&ssi1>;
system-clock-frequency = <883200>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
};
};
&audmux {
status = "okay";
// Note: 'ssi1' (node of first SSI) corresponds to '_SSI0' below.
ssi1 {
fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
fsl,port-config = <
0x00000000
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT3_SSI_PINS_3)
>;
};
aud3 {
fsl,audmux-port = <MX31_AUDMUX_PORT3_SSI_PINS_3>;
fsl,port-config = <
(IMX_AUDMUX_V2_PTCR_TFSDIR |
IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
IMX_AUDMUX_V2_PTCR_TCLKDIR |
IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
>;
};
};
&ssi1 {
fsl,mode = "i2s-master";
assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_SSI1>;
assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <0>, <49152000>; // 48kHz on SSI1 clock
status = "okay";
};
The only thing that I don't understand about this is why I need to set the system clock of the CPU DAI to <883200> in order to get an LRCLK of 48 kHz.
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 my solution, posted here: linux device driver - Audio issue with IMX6 board (max98357a codec) - Stack Overflow
Thanks for the hint regarding SSI clock generation.
Well, I got it basically working now, with the following device tree entries:
codec: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
simple-audio-card,name = "TI3 Audio";
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 = <&ssi1>;
system-clock-frequency = <883200>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
};
};
&audmux {
status = "okay";
// Note: 'ssi1' (node of first SSI) corresponds to '_SSI0' below.
ssi1 {
fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
fsl,port-config = <
0x00000000
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT3_SSI_PINS_3)
>;
};
aud3 {
fsl,audmux-port = <MX31_AUDMUX_PORT3_SSI_PINS_3>;
fsl,port-config = <
(IMX_AUDMUX_V2_PTCR_TFSDIR |
IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
IMX_AUDMUX_V2_PTCR_TCLKDIR |
IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
>;
};
};
&ssi1 {
fsl,mode = "i2s-master";
assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_SSI1>;
assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <0>, <49152000>; // 48kHz on SSI1 clock
status = "okay";
};
The only thing that I don't understand about this is why I need to set the system clock of the CPU DAI to <883200> in order to get an LRCLK of 48 kHz.
Hi Alexander,
I am implementing the max98357a codec on an imx6s as you. Thank you for this guide. It help me to write the right thing on my device-tree files. After booting my linux OS, it finds no soundcards on the system. Can you give me some advice to complete implementation. I activated the driver of the codec and choose simple-audio-card on the kernel menuconfig but i did see a soundcard yet.
Thanks you in advance !
SC
Hi Alexander
one can check dts "assigned-clocks" for SSIn as in example on:
[alsa-devel] Simple-card without codec for testing purpose
Check what mode is used, master or slave, in latter case clock should be
provided from external codec. Also one can check with jtag ssi registers
using sect.61.8.4.1 SSI Clock and Frame Sync Generation i.MX6SDL Reference Manual
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6SDLRM.pdf
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------