SSM2603 on i.MX8MM at SAI2 with external clock, kernel 6.1

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SSM2603 on i.MX8MM at SAI2 with external clock, kernel 6.1

Jump to solution
384 Views
DaxTailor
Contributor II

Hi,

we are using the i.MX8MM with an SSM2603 codec on the SAI2 interface.

When we try to play sound, with aplay we got the following error:

   ssm2602 1-001b: ASoC: error at snd_soc_dai_hw_params on ssm2602-hifi: -22

The ssm2603 gets its MCLK form an external 12MHz clock generator, the 12MHz
is also connected to the i.MX8MM on SAI2_MCLK.

The BSP is from our CPU module vendor (KaRo) but it is based on the NXP BSP.
Yocto mickledore with kernel 6.1.36.

This is the DT overlay we are using:

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/imx8mm-clock.h>
#include "imx8mm-pinfunc.h"

&{/chosen} {
        overlays {
                m6-ssm2602;
        };
};

&{/} {

i2s_mclk: fixed-12000000 {
        compatible = "fixed-clock";
        #clock-cells = <0>;
        clock-frequency = <12000000>;
        clock-accuracy = <20000>;
};

sound {
    //#address-cells = <1>;
    //#size-cells = <0>;
    compatible = "simple-audio-card";
    simple-audio-card,name = "ssm2603-audio";
    simple-audio-card,format = "i2s";
    simple-audio-card,frame-master = <&cpudai>;
    simple-audio-card,bitclock-master = <&cpudai>;

    cpudai: simple-audio-card,cpu {
        sound-dai = <&sai2>;
    };
    simple-audio-card,codec {
        sound-dai = <&ssm2603>;
        //clocks = <&clk IMX8MM_CLK_SAI2_ROOT>;
        //clock-names = "mclk";
    };    
};

};

&i2c2 {
    ssm2603: ssm2603@1b {
        #sound-dai-cells = <0>;
        compatible = "adi,ssm2603";
        reg = <0x1b>;
        status = "okay";
    };
};

&sai2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sai2>;
        fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
        clocks = <&clk IMX8MM_CLK_SAI2_IPG>, 
                 <&i2s_mclk>,
                 <&clk IMX8MM_CLK_DUMMY>, 
                 <&clk IMX8MM_CLK_DUMMY>;
        clock-names = "bus", "mclk1", "mclk2", "mclk3";
        //assigned-clocks = <&clk IMX8MM_CLK_SAI2>;
	//assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
	//assigned-clock-rates = <12000000>;
        //fsl,sai-asynchronous;
        status = "okay";
};

&iomuxc {
        pinctrl_sai2: sai2grp {
                fsl,pins = <
                        MX8MM_IOMUXC_SAI2_MCLK_SAI2_MCLK        0x00
                        MX8MM_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC     0xd6
                        MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC     0xd6
                        MX8MM_IOMUXC_SAI2_TXC_SAI2_TX_BCLK      0xd6
                        MX8MM_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0    0xd6
                        MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0    0xd6
                >;
        };
};

&spdif1 {
        status = "disabled";
};

Has someone an idea what the problem could be?
In an other post on this forum I found a hint on a undocumented bit that has to be set to switch the SAI MCLK into external clock mode. Unfortunately the post does not show how.

Thanks,
Dax

Labels (1)
0 Kudos
1 Solution
309 Views
DaxTailor
Contributor II

Now its working. I changed the sound part in the DT as follow:

sound {
    status = "okay";
    compatible = "simple-audio-card";
    sai-controllers = <&sai2>;
    simple-audio-card,name = "ssm2603-audio";
    simple-audio-card,format = "i2s";
    simple-audio-card,bitclock-master = <&dalink_cpu>; 
    simple-audio-card,frame-master = <&dalink_cpu>; 
    dalink_cpu: simple-audio-card,cpu {
        sound-dai = <&sai2>;
     	dai-tdm-slot-num = <2>;
        dai-tdm-slot-width = <32>;
    };
    dalink_codec: simple-audio-card,codec {
        sound-dai = <&ssm2603>;
        #clocks = <&clk IMX8MM_CLK_SAI2>;
        system-clock-frequency = <11289600>;
    };        
};

Two changes are made. First the bitclock and frame master is now bound to the cpu. And 2nd on the cpu there are dai-tdm-... entries. I copied them form imx8mm-evk.dtsi file.
No idea what there are for, but as long as it works...

@JorgeCas Thanks for your support. I think this can be closed now.

View solution in original post

5 Replies
339 Views
DaxTailor
Contributor II

After the HW Team disabled the external clock generator, I changed the DT overlay as follow:

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/imx8mm-clock.h>
#include "imx8mm-pinfunc.h"

&{/chosen} {
        overlays {
                m6-ssm2602;
        };
};

&{/} {

sound {
    status = "okay";
    compatible = "simple-audio-card";
    sai-controllers = <&sai2>;
    simple-audio-card,name = "ssm2603-audio";
    simple-audio-card,format = "i2s";
    simple-audio-card,bitclock-master = <&dalink_master>; 
    simple-audio-card,frame-master = <&dalink_master>; 
    simple-audio-card,mclk-fs = <32>;
    simple-audio-card,cpu {
        sound-dai = <&sai2>;
    };
    dalink_master: simple-audio-card,codec {
        sound-dai = <&ssm2603>;
        #clocks = <&clk IMX8MM_CLK_SAI2>;
        system-clock-frequency = <11289600>;
    };        
};

};

&i2c2 {
    ssm2603: ssm2603@1b {
        #sound-dai-cells = <0>;
        compatible = "adi,ssm2603";
        reg = <0x1b>;
        status = "okay";
    };
};

&sai2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sai2>;
        fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
        assigned-clocks = <&clk IMX8MM_CLK_SAI2>;
	assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL2_OUT>;
	#assigned-clock-rates = <12000000>;
        assigned-clock-rates = <11289600>;
        clocks = <&clk IMX8MM_CLK_SAI2_IPG>, 
                 <&clk IMX8MM_CLK_DUMMY>,
                 <&clk IMX8MM_CLK_SAI2_ROOT>,
                 <&clk IMX8MM_CLK_DUMMY>,
                 <&clk IMX8MM_CLK_DUMMY>,
                 <&clk IMX8MM_AUDIO_PLL1_OUT>,
                 <&clk IMX8MM_AUDIO_PLL2_OUT>
        ;
        clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k";
        fsl,sai-mclk-direction-output;
        //fsl,sai-asynchronous;
        status = "okay";
};

&iomuxc {
        pinctrl_sai2: sai2grp {
                fsl,pins = <
                        MX8MM_IOMUXC_SAI2_MCLK_SAI2_MCLK        0xd6  // 14
                        MX8MM_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0    0xd6  // 15
                        MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0    0xd6  // 16
                        MX8MM_IOMUXC_SAI2_TXC_SAI2_TX_BCLK      0xd6  // 17
                        MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC     0xd6  // 18
                        MX8MM_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC     0xd6  // 77
                >;
        };
};

&spdif1 {
        status = "disabled";
};

Now playing a wav file I get errors from aplay:

root@qsxm-mm60:~# aplay -vvv -t wav squeak.wav 
ALSA lib /usr/src/debug/alsa-lib/1.2.8-r0/src/pcm/pcm_hw.c:1722:(snd_pcm_hw_open) open '/dev/snd/pcmC0D0p' failed (-22): Invalid argument
aplay: main:831: audio open error: Invalid argument

I check the /dev/snd/pcmC0D0p device. It is present and not used by any other application.

root@qsxm-mm60:~# ls -l /dev/snd
total 0
drwxr-xr-x 2 root root       60 Mar  3  2023 by-path
crw-rw---- 1 root audio 116,  0 Mar  3  2023 controlC0
crw-rw---- 1 root audio 116, 24 Mar  3  2023 pcmC0D0c
crw-rw---- 1 root audio 116, 16 Mar  3  2023 pcmC0D0p
crw-rw---- 1 root audio 116, 33 Mar  3  2023 timer

Is there a driver missing? The only module in this context is the codec driver witch is loaded, anything else is build in the kernel.

root@qsxm-mm60:~# lsmod
Module                  Size  Used by
snd_soc_ssm2602_i2c    16384  1
sha256_generic         16384  0
libsha256              16384  1 sha256_generic
snd_soc_ssm2602        24576  1 snd_soc_ssm2602_i2c
cfg80211              442368  0
imx_sdma               40960  2
virt_dma               20480  1 imx_sdma

The reason imx_sdma drive is a module is because the firmware was loaded about a minute after booting when it is compiled into the kernel. Maybe that is a problem, SAI2 is using DMA.

BTW. alasmixer is working and shows some volume slider and switches. I assume that means the codec chip and driver is working.

I hope someone has an idea what I could do to get this working.
Thanks.

0 Kudos
359 Views
JorgeCas
NXP TechSupport
NXP TechSupport

Hello, I hope you are doing well.

That error is related to the clock configuration. Do you want to use CODEC as master and i.MX as slave, right?

If yes, that configuration has not been tested on our EVKs, maybe you could try to use your CODEC as slave and i.MX as master and use EVK device tree as reference.

Also, I do not know if your CODEC needs a specific driver provided by manufacturer as occurs with some TI CODECs.

Best regards.

0 Kudos
341 Views
DaxTailor
Contributor II

Thanks for the reply,

there is a driver for the codec in the kernel and the codec chip is found by i2cdetect and the ssm2602 driver module is loaded.

> Do you want to use CODEC as master and i.MX as slave, right?

There is an external 12MHz clock generator on the board connected to the codec and the SAI2 MCLK input. Today we will remove the 12MHz clock chip to see if the will help.

Meanwhile I made a change to the DT and the error is gone. Here the change:

sound {
    status = "okay";
    compatible = "simple-audio-card";
    sai-controllers = <&sai2>;
    simple-audio-card,name = "ssm2603-audio";
    simple-audio-card,dai-link@0 {
        format = "i2s";
        cpu {
                sound-dai = <&sai2>;
                system-clock-frequency = <12000000>;
        };
        codec {
                sound-dai = <&ssm2603>;
                frame-master;
                bitclock-master;
                system-clock-frequency = <12000000>;
        };
    };    
};

I think putting the both master clocks into the codec node fixed the problem.

But now there is a other problem. aplay hangs if i try to play a wave file. Stopping aplay with CTRL-C the following error shows:

root@qsxm-mm60:~# aplay squeak.wav 
Playing WAVE 'squeak.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
^CAborted by signal Interrupt...
aplay: pcm_write:2127: write error: Interrupted system call

Any idea where to look to fix this problem?
I think that has something to do with the audio clocks?

Thanks.

0 Kudos
336 Views
JorgeCas
NXP TechSupport
NXP TechSupport

Hello,

 

Removing crystal oscillator and using CODEC in slave mode, you should be able to use our EVK device tree as reference since that configuration have been tested.

 

"pcm_write:2057: write error: Input/output error" could occur due to incorrect clock settings.

 

Please try probing MCLK and check with the oscilloscope. Maybe a clock configuration of your driver is causing the error.

 

Best regards.

310 Views
DaxTailor
Contributor II

Now its working. I changed the sound part in the DT as follow:

sound {
    status = "okay";
    compatible = "simple-audio-card";
    sai-controllers = <&sai2>;
    simple-audio-card,name = "ssm2603-audio";
    simple-audio-card,format = "i2s";
    simple-audio-card,bitclock-master = <&dalink_cpu>; 
    simple-audio-card,frame-master = <&dalink_cpu>; 
    dalink_cpu: simple-audio-card,cpu {
        sound-dai = <&sai2>;
     	dai-tdm-slot-num = <2>;
        dai-tdm-slot-width = <32>;
    };
    dalink_codec: simple-audio-card,codec {
        sound-dai = <&ssm2603>;
        #clocks = <&clk IMX8MM_CLK_SAI2>;
        system-clock-frequency = <11289600>;
    };        
};

Two changes are made. First the bitclock and frame master is now bound to the cpu. And 2nd on the cpu there are dai-tdm-... entries. I copied them form imx8mm-evk.dtsi file.
No idea what there are for, but as long as it works...

@JorgeCas Thanks for your support. I think this can be closed now.