cancel
Showing results for 
Search instead for 
Did you mean: 

Need help with SAI DeviceTree - STM32MP135F - TI TLV320AIC3254

skarayigit
Associate III

Hi,

I need help to setup the DeviceTree for our custom board using STM32MP135FAE7 and TI TLV320AIC3254.

I have read the Wiki about SAI and read and tried to implement SAI using these posts as reference:

No Luck.

And also got confused about where to put the Codec. On the Wiki Page here shows codec under i2c node but on this post there is a comment from @Erwan SZYMANSKI saying that codec should be under root not I2C or I2S. How should I decide where to put it, is it depending on the IC ? What am I missing?

and following those comments, I have enabled the configs related to codec in the config file and updated the kernel and they show up.

CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
CONFIG_SND_SOC_TLV320AIC32X4_SPI=m

root@stm32mp1:~# lsmod
Module Size Used by
cfg80211 663552 0
usb_f_ncm 24576 2
u_ether 20480 1 usb_f_ncm
libcomposite 49152 10 usb_f_ncm
stm32_adc 36864 0
stm32_timer_trigger 20480 1 stm32_adc
stm32_lptimer_trigger 16384 1 stm32_adc
snd_soc_stm32_sai_sub 28672 0
snd_soc_audio_graph_card 16384 0
snd_soc_simple_card_utils 20480 1 snd_soc_audio_graph_card
stm32_adc_core 20480 0
snd_soc_tlv320aic32x4_spi 16384 0
snd_soc_tlv320aic32x4_i2c 16384 0
snd_soc_tlv320aic32x4 36864 2 snd_soc_tlv320aic32x4_spi,snd_soc_tlv320aic32x4_i2c
snd_soc_core 184320 4 snd_soc_audio_graph_card,snd_soc_simple_card_utils,snd_soc_tlv320aic32x4,snd_soc_stm32_sai_sub
snd_soc_stm32_sai 16384 0
snd_pcm_dmaengine 16384 1 snd_soc_core
ac97_bus 16384 1 snd_soc_core
snd_pcm 98304 5 snd_pcm_dmaengine,snd_soc_simple_card_utils,snd_soc_tlv320aic32x4,snd_soc_core,snd_soc_stm32_sai_sub
snd_timer 28672 1 snd_pcm
snd 57344 5 snd_timer,snd_soc_tlv320aic32x4,snd_soc_core,snd_pcm,snd_soc_stm32_sai_sub
soundcore 16384 1 snd
sch_fq_codel 20480 4
ip_tables 24576 0
x_tables 24576 1 ip_tables
ipv6 503808 40

But I don't get any error messages or anything related with the soundcard except the messages below:

root@stm32mp1:~# dmesg |grep sound
root@stm32mp1:~# dmesg |grep audio
[ 0.056931] platform ti-codec: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a024
[ 0.056977] platform ti-codec: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a004
root@stm32mp1:~# dmesg |grep sai
[ 0.056931] platform ti-codec: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a024
[ 0.056977] platform ti-codec: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a004

Here is my devicetree related to SAI part:

/ { /* ROOT */
sound {
        compatible = "audio-graph-card";
        label = "Prove-Audio-Card";
        // routing =
        //  "Playback" , "MCLK",
        //  "Capture", "MCLK";
        dais = <&sai1a_port>;
        status = "okay";
    };
    codec: ti-codec {
        compatible = "ti,tlv320aic32x4";
        #sound-dai-cells = <0>;
        reset-gpios = <&gpioc 0 GPIO_ACTIVE_LOW>;
        ldoin-supply = <&scmi_vdd>;
        iov-supply = <&scmi_vdd>;
        dv-supply = <&scmi_vdd>;
        av-supply = <&scmi_v1v8_periph>;
        clocks = <&sai1a>;
        clock-names = "mclk";
       
tlv320aic32x4_port: port {
            #address-cells = <1>;
            #size-cells = <0>;
            tlv320aic32x4_tx_endpoint: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&sai1a_endpoint>;
                frame-master;               /* codec is master */
                bitclock-master;
            };
            tlv320aic32x4_rx_endpoint: endpoint@1 {
                reg = <1>;
                remote-endpoint = <&sai1b_endpoint>;
                frame-master;               /* codec is master */
                bitclock-master;
            };
        };
    };
};
&i2c5{

    pinctrl-names = "default", "sleep";

    pinctrl-0 = <&i2c5_pins_mx>;

    pinctrl-1 = <&i2c5_sleep_pins_mx>;

    status = "okay";

    /* USER CODE BEGIN i2c5 */

    i2c-scl-rising-time-ns = <185>;

    i2c-scl-falling-time-ns = <20>;

    clock-frequency = <400000>;

   

    /* spare dmas for other usage */

    /delete-property/dmas;

    /delete-property/dma-names;

    /* USER CODE END i2c5 */

};
 
&sai1{

    pinctrl-names = "default", "sleep";

    pinctrl-0 = <&sai1a_pins_mx>, <&sai1b_pins_mx>;

    pinctrl-1 = <&sai1a_sleep_pins_mx>, <&sai1b_sleep_pins_mx>;

    status = "okay";

    /* USER CODE BEGIN sai1 */

    clocks = <&rcc SAI1>, <&scmi_clk CK_SCMI_PLL3_Q>, <&scmi_clk CK_SCMI_PLL3_R>;

    clock-names = "pclk", "x8k", "x11k";

    // #sound-dai-cells = <1>;

    /* USER CODE END sai1 */

    sai1a:audio-controller@4400a004{

        status = "okay";

        /* USER CODE BEGIN sai1a */

        #sound-dai-cells = <0>;

        compatible = "st,stm32-sai-sub-a";

        dma-names = "tx";

        #clock-cells = <0>;

        clocks = <&rcc SAI1_K>;

        clock-names = "sai_ck";

        sai1a_port: port {

            sai1a_endpoint: endpoint {

                remote-endpoint = <&tlv320aic32x4_tx_endpoint>;

                format = "i2s";

                mclk-fs = <256>;

                dai-tdm-slot-num = <2>;

                dai-tdm-slot-width = <32>;

            };

        };

        /* USER CODE END sai1a */

    };

    sai1b:audio-controller@4400a024{

        status = "okay";

        /* USER CODE BEGIN sai1b */

        #sound-dai-cells = <0>;

        dma-names = "rx";               /* SAI set as receiver */

        st,sync = <&sai1a 1>;           /* SAI1B is slave of SAI1A */

        clocks = <&rcc SAI1_K>, <&sai1a>;

        clock-names = "sai_ck", "mclk";

        sai1b_port: port {

            sai1b_endpoint: endpoint {

                remote-endpoint = <&tlv320aic32x4_rx_endpoint>;

                format = "i2s";

                mclk-fs = <256>;

                dai-tdm-slot-num = <2>;

                dai-tdm-slot-width = <32>;

            };

        };

    };

};
&pinctrl {
    i2c5_pins_mx: i2c5_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('F', 3, AF4)>, /* I2C5_SDA */
                     <STM32_PINMUX('H', 13, AF4)>; /* I2C5_SCL */
            bias-disable;
            drive-open-drain;
            slew-rate = <0>;
        };
    };
    i2c5_sleep_pins_mx: i2c5_sleep_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('F', 3, ANALOG)>, /* I2C5_SDA */
                     <STM32_PINMUX('H', 13, ANALOG)>; /* I2C5_SCL */
        };
    };
    sai1a_pins_mx: sai1a_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('A', 4, AF12)>, /* SAI1_SCK_A */
                     <STM32_PINMUX('A', 5, AF6)>, /* SAI1_SD_A */
                     <STM32_PINMUX('C', 3, AF10)>, /* SAI1_MCLK_A */
                     <STM32_PINMUX('E', 4, AF6)>; /* SAI1_FS_A */
            bias-disable;
            drive-push-pull;
            slew-rate = <0>;
        };
    };
    sai1a_sleep_pins_mx: sai1a_sleep_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* SAI1_SCK_A */
                     <STM32_PINMUX('A', 5, ANALOG)>, /* SAI1_SD_A */
                     <STM32_PINMUX('C', 3, ANALOG)>, /* SAI1_MCLK_A */
                     <STM32_PINMUX('E', 4, ANALOG)>; /* SAI1_FS_A */
        };
    };
    sai1b_pins_mx: sai1b_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('A', 0, AF6)>; /* SAI1_SD_B */
            bias-disable;
            drive-push-pull;
            slew-rate = <0>;
        };
    };
    sai1b_sleep_pins_mx: sai1b_sleep_mx-0 {
        pins {
            pinmux = <STM32_PINMUX('A', 0, ANALOG)>; /* SAI1_SD_B */
        };
    };
};

And my clock settings:

root@stm32mp1:~# cat /sys/kernel/debug/clk/clk_summary |grep sai
sai2 0 0 0 104450000 0 0 50000 N
sai1 0 2 0 104450000 0 0 50000 N
sai2_k 0 0 0 24000000 0 0 50000 N
sai1_k 0 0 0 24000000 0 0 50000 N
sai1a_mclk 0 0 0 0 0 0 50000 ?

 

6 REPLIES 6
Erwan SZYMANSKI
ST Employee

Hello @skarayigit ,
Did you try to launch your audio playback ? For me this is normal to not see clock activation until you do not try to play your audio track or record.

Kind regards,
Erwan.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
skarayigit
Associate III

Hi @Erwan SZYMANSKI ,

Thank you for your quick reply. No soundcard appears in my system. 

I've just configured for S/PDIF to try if I get any audio card, it is a success. If I configure it for S/PDIF and use it for rx and use sai1a for tx. I got a audio card and I was able to play some audio file and i can see the digital signal on the oscilloscope. 

Does my devicetree seems OK? node placements?  I have also attached my full devicetree below. 

I am expecting to see the soundcard on the system to confirm that the devicetree setted up correctly that part correctly, even if its not working properly and play audio. Am I wrong to expect to see soundcard on the system?

Best Regards

Hello @skarayigit ,
In your situation, your codec is driven by I2C (or SPI I guess, but I suppose I2C is the default interface). If this codec is driven by I2C, indeed it has to be placed under your I2C interface node (that will drive it).

Please check this configuration from another post with a quite similar codec: https://community.st.com/t5/stm32-mpus-embedded-software/stm32mp135-sai-missing-clock-error-at-boot-time/m-p/55114#M43

Kind regards,
Erwan.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
skarayigit
Associate III

Hello @Erwan SZYMANSKI ,

Thank you for the clarification about the I2C node. I have placed my codec under I2C node. I do not get any errors or messages while booting up. However, I still do not have any soundcard or devices in the linux. What should I do next? Do I have problems with my device tree?

Here is some messages that might help:

root@stm32mp1:~# dmesg |grep audio
[ 3.739023] i2c 9-0018: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a024
[ 3.746728] i2c 9-0018: Fixed dependency cycle(s) with /soc/sai@4400a000/audio-controller@4400a004
root@stm32mp1:~# cat /proc/asound/cards
--- no soundcards ---
root@stm32mp1:~# cat /proc/asound/devices
33: : timer
root@stm32mp1:~# cat /proc/asound/pcm
root@stm32mp1:~# cat /proc/asound/modules
root@stm32mp1:~# cat /sys/kernel/debug/asoc/
components dais
root@stm32mp1:~# cat /sys/kernel/debug/asoc/dais
4400a024.audio-controller
4400a004.audio-controller
tlv320aic32x4-hifi
snd-soc-dummy-dai
root@stm32mp1:~# cat /sys/kernel/debug/asoc/components
4400a024.audio-controller
4400a024.audio-controller
4400a004.audio-controller
4400a004.audio-controller
tlv320aic32x4.9-0018
snd-soc-dummy
snd-soc-dummy

root@stm32mp1:~# lsmod
Module Size Used by
cfg80211 663552 0
usb_f_ncm 24576 2
u_ether 20480 1 usb_f_ncm
stm32_adc 36864 0
libcomposite 49152 10 usb_f_ncm
stm32_timer_trigger 20480 1 stm32_adc
stm32_lptimer_trigger 16384 1 stm32_adc
snd_soc_stm32_sai_sub 28672 1
snd_soc_tlv320aic32x4_spi 16384 0
snd_soc_tlv320aic32x4_i2c 16384 0
snd_soc_audio_graph_card 16384 0
snd_soc_simple_card_utils 20480 1 snd_soc_audio_graph_card
snd_soc_tlv320aic32x4 36864 2 snd_soc_tlv320aic32x4_spi,snd_soc_tlv320aic32x4_i2c
snd_soc_core 184320 4 snd_soc_audio_graph_card,snd_soc_simple_card_utils,snd_soc_tlv320aic32x4,snd_soc_stm32_sai_sub
snd_pcm_dmaengine 16384 1 snd_soc_core
ac97_bus 16384 1 snd_soc_core
snd_pcm 98304 5 snd_pcm_dmaengine,snd_soc_simple_card_utils,snd_soc_tlv320aic32x4,snd_soc_core,snd_soc_stm32_sai_sub
snd_timer 28672 1 snd_pcm
snd 57344 5 snd_timer,snd_soc_tlv320aic32x4,snd_soc_core,snd_pcm,snd_soc_stm32_sai_sub
soundcore 16384 1 snd
stm32_adc_core 20480 0
snd_soc_stm32_sai 16384 0
sch_fq_codel 20480 4
ip_tables 24576 0
x_tables 24576 1 ip_tables
ipv6 503808 38

Here is my related DT (updated):

 / * in the root */

sound: sound {
        compatible = "audio-graph-card";
        label = "STM32MP135F-DK";
        routing =
            "Playback" , "MCLK",
            "Capture", "MCLK";
        dais = <&sai1a_port &sai1b_port>;
        status = "okay";
    };
&i2c5{
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&i2c5_pins_mx>;
    pinctrl-1 = <&i2c5_sleep_pins_mx>;
    status = "okay";

    /* USER CODE BEGIN i2c5 */
    i2c-scl-rising-time-ns = <185>;
    i2c-scl-falling-time-ns = <20>;
    clock-frequency = <400000>;
    #address-cells = <1>;
    #size-cells = <0>;
   
    /* spare dmas for other usage */
    /delete-property/dmas;
    /delete-property/dma-names;

    tlv320aic32x4: tlv320aic32x4@18 {
        compatible = "ti,tlv320aic32x4";
        reg = <0x18>;
        // #sound-dai-cells = <0>;
        reset-gpios = <&gpioc 0 GPIO_ACTIVE_LOW>;
        ldoin-supply = <&scmi_vdd>;
        iov-supply = <&scmi_vdd>;
        clocks = <&sai1a>;
        clock-names = "mclk";
        status = "okay";

        port {
            #address-cells = <1>;
            #size-cells = <0>;
            tlv320aic32x4_tx_port: port@0 {
                reg = <0>;
                tlv320aic32x4_tx_endpoint: endpoint {
                    remote-endpoint = <&sai1a_endpoint>;
                    frame-master;               /* codec is master */
                    bitclock-master;
                };
            };
            tlv320aic32x4_rx_port: port@1 {
                reg = <1>;
                tlv320aic32x4_rx_endpoint: endpoint {
                    remote-endpoint = <&sai1b_endpoint>;
                    frame-master;               /* codec is master */
                    bitclock-master;
                };
            };
        };
    };
    /* USER CODE END i2c5 */
};
 
&sai1{
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&sai1a_pins_mx>, <&sai1b_pins_mx>;
    pinctrl-1 = <&sai1a_sleep_pins_mx>, <&sai1b_sleep_pins_mx>;
    status = "okay";

    /* USER CODE BEGIN sai1 */
    clocks = <&rcc SAI1>, <&scmi_clk CK_SCMI_PLL3_Q>, <&scmi_clk CK_SCMI_PLL3_R>;
    clock-names = "pclk", "x8k", "x11k";
    #sound-dai-cells = <1>;
    /* USER CODE END sai1 */

    sai1a:audio-controller@4400a004{
        status = "okay";

        /* USER CODE BEGIN sai1a */
        compatible = "st,stm32-sai-sub-a";
        #clock-cells = <0>;
        dma-names = "tx";
        clocks = <&rcc SAI1_K>;
        clock-names = "sai_ck";

        sai1a_port: port {
            sai1a_endpoint: endpoint {
                remote-endpoint = <&tlv320aic32x4_tx_endpoint>;
                format = "i2s";
                mclk-fs = <512>;
               
                // mclk-fs = <256>;
                // dai-tdm-slot-num = <2>;
                // dai-tdm-slot-width = <16>;
            };
        };
        /* USER CODE END sai1a */
    };

    sai1b:audio-controller@4400a024{
        status = "okay";

        /* USER CODE BEGIN sai1b */
        compatible = "st,stm32-sai-sub-b";
        dma-names = "rx";
        st,sync = <&sai1a 1>;
        clocks = <&rcc SAI1_K>, <&sai1a>;
        clock-names = "sai_ck", "MCLK";

        sai1b_port: port {
            sai1b_endpoint: endpoint {
                remote-endpoint = <&tlv320aic32x4_rx_endpoint>;
                format = "i2s";
                mclk-fs = <512>;

                // mclk-fs = <256>;
                // dai-tdm-slot-num = <2>;
                // dai-tdm-slot-width = <16>;
            };
        };
        /* USER CODE END sai1b */
    };
};

 

skarayigit
Associate III

Hello @Erwan SZYMANSKI,

Any update?

Erwan SZYMANSKI
ST Employee

Hello @skarayigit ,
Sorry for my late answer.
The best way to understand what happens is to not work eyes closed on the issue. I suggest you either activate available debug traces or add your own logs in the soundcard driver to understand what is going wrong, and then give us more input to see where does it fail. You can as well activate debug in stm32_sai_sub.c driver to get it more verbose. 

Can you also put your complete dmesg log here ? 

Kind regards,
Erwan.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.