cancel
Showing results for 
Search instead for 
Did you mean: 

Help in creating a simple soundcard with I2S (or SAI if necessary)

AJank.2
Associate III

Hi,

I'm working on creating a simple soundcard with a simple codec called pcm5102a which is a part of the kernel source. My board is the STM32MP135F-DK. I2S seems to be enough for this purpose however if you think that SAI will work better, then I'll take advice on that happily as well.

The current configuration is as in the attached audio_test.zip with I2S1 enabled and SPI1 Clock Mux set to PLL3Q instead of the default PLL4P (all set in the STM32CubeMX). The configuration is inserted into the build with a new machine and it does build without any problems. It's only after the boot that aplay -l doesn't list any soundcards, moreover below message is visible in the dmesg output:

 

 

[    3.600504] st,stm32-i2s 44004000.audio-controller: Could not get x8k parent clock: -2
[    3.607136] st,stm32-i2s: probe of 44004000.audio-controller failed with error -2

 

 

I read that the x8k is one of the clocks necessary for audio handling, however can't figure out how to fix that.

Below are the most important parts regarding the soundcard configuration:

 

 

/ {    sound {
        compatible = "audio-graph-card";
        label = "STM32MP1-audio-test-card";
        routing =
            "Playback" , "MCLK"; /* Set a route between "MCLK" and "playback" DAPM widgets */
        dais = <&i2s1_port>;
        status = "okay";
    };
};

&i2s1{
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2s1_pins_mx>;
	pinctrl-1 = <&i2s1_sleep_pins_mx>;
	status = "okay";

	/* USER CODE BEGIN i2s1 */
    #clock-cells = <0>;
    clocks = <&rcc SPI1>, <&rcc SPI1_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>;
    clock-names = "pclk", "i2sclk", "x8k", "x11k";
    #sound-dai-cells = <1>;

	i2s1_port: port {
        #address-cells = <1>;
        #size-cells = <0>;
		i2s1_endpoint: endpoint {
            system-clock-frequency = <48000>;
            system-clock-direction-out;
            frame-master;
            bitclock-master;
			format = "i2s";
			mclk-fs = <256>;
            remote-endpoint = <&codec_endpoint>;
		};
	};

    codec: pcm5102a {
        compatible = "ti,pcm5102a";
        #sound-dai-cells = <0>;
        clocks = <&i2s1>;     /* The codec is a consumer of I2S2 master clock */
        clock-names = "MCLK"; /* Feed MCLK codec clock with I2S2 master clock provider */

        codec_port: pcm5102a_port {
            codec_endpoint: endpoint{
                remote-endpoint = <&i2s1_endpoint>;
            };
        };
    };
	/* USER CODE END i2s1 */
};

 

 

 

 

19 REPLIES 19

@AJank.2 ,
Just to be sure, in the kernel menuconfig, did you well activate your codec as a module ? (It seems strange to not see nor soundcard or dmesg error appearing).
the config is CONFIG_SND_SOC_PCM5102A=m

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.

Moreover, As the codec is not driven by nor I2C or SPI, its node should be placed in the root node of your device tree, for example, below you sound node. (I do not know the impact if you place it in the i2s node).

Rgs,
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.

The codec is activated as a build-in, with CONFIG_SND_SOC_PCM5102a=y kernel option, defined in the same fragment file as the I2S configuration.

Okay, that sounds like something I have to check immediately! I'll get back to you with results.

I did implement the pcm5102a codec node in the root node and finally there's some real response, take look at this dmesg output:

root@stm32mp13-audiotest:~# dmesg | grep audio
[    0.063117] platform pcm5102a: Fixing up cyclic dependency with 44004000.audio-controller
[    3.611251] st,stm32-i2s 44004000.audio-controller: No cache defaults, reading back from HW
[    3.896085] st,stm32-i2s 44004000.audio-controller: No cache defaults, reading back from HW
[   83.003602] systemd[1]: Hostname set to <stm32mp13-audiotest>.
[   94.073575] brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.st,stm32mp135f-audio_test_cubemx-mx.bin failed with error -2
[   94.327495] asoc-audio-graph-card sound: ASoC: no source widget found for MCLK
[   94.365825] asoc-audio-graph-card sound: ASoC: Failed to add route MCLK -> direct -> Playback
[   94.443149] asoc-audio-graph-card sound: parse error -19

 I'll search the forum to learn if anyone had similar route problems, it also seems that part of the configuration mixes up the syntax, right? I guess that parse error is related to syntax.

Meanwhile, do you have any further advice?

@AJank.2 ,
Well it is going forward !

I am not an audio expert, but if I remember well, I think that the additional DPAM Widget needs to be declared inside the codecs driver. In your case for example it should be something like:

static const struct snd_soc_dapm_widget aic31xx_dapm_mclk_widgets[] = {
	SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, mclk_event,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};

If you want a reference taken by ST, you can take a look at the cirrus,cs42l51 codecs driver.

I hope that it will help you.
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.
AJank.2
Associate III

Thank you for help @Erwan SZYMANSKI, I managed to add the dapm MCLK supply widget to the codec driver and it does show up in the output of aplay -l. There some issues with playback with speaker-test, so perhaps the configuration isn't perfect yet, but there's definitely some progress made.
Thanks!

AJank.2
Associate III

Interestingly is seems that creating a new DAPM supply node isn't the only solution. Deleting the routing part from the audio-graph sound card device tree node seems to make things work as well. I got speaker-test to work with the audio-graph sound card and the pcm5102a.c codec.

like below:

    sound {
        compatible = "audio-graph-card";
        label = "STM32MP1-audio-test-card";
        dais = <&i2s1_port>;
        status = "okay";
    };
MWoło.2
Senior II

Hi AJank.2,

I try Your dts configuration and Your last suggestion but for me, it's not working. Do You use hardware like

MWoo2_0-1688589080289.jpeg

If yes which lines have You connected?

Do this configuration is correct?

&i2s1{
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2s1_pins_mx>;
	pinctrl-1 = <&i2s1_sleep_pins_mx>;
	status = "okay";

	/* USER CODE BEGIN i2s1 */
    #clock-cells = <0>;
    clocks = <&rcc SPI1>, <&rcc SPI1_K>, <&scmi_clk CK_SCMI_PLL3_Q>, <&scmi_clk CK_SCMI_PLL3_R>;
    clock-names = "pclk", "i2sclk", "x8k", "x11k";
    #sound-dai-cells = <1>;

	i2s1_port: port {
        #address-cells = <1>;
        #size-cells = <0>;
		i2s1_endpoint: endpoint {
            /* system-clock-frequency = <48000>; */
            /* system-clock-direction-out; */
            /* frame-master; */
            /* bitclock-master; */
			format = "i2s";
			mclk-fs = <256>;
            remote-endpoint = <&codec_endpoint>;
		};
	};

    codec: pcm5102a {
        compatible = "ti,pcm5102a";
        #sound-dai-cells = <0>;
        clocks = <&i2s1>;     /* The codec is a consumer of I2S2 master clock */
        clock-names = "MCLK"; /* Feed MCLK codec clock with I2S2 master clock provider */

        codec_port: port {
            codec_endpoint: endpoint {
                remote-endpoint = <&i2s1_endpoint>;
            };
        };
    };
	/* USER CODE END i2s1 */
};

Thanks in advanced

BR Michal

This discussion was quite extensive, so I guess it's not easy to read through all of it :D
My hardware is different, it's the STM32MP135F-DK board.
The main outcomes of the discussion are that the codec node has to be defined in the root node of the Device Tree, so you should move it outside of the I2S1 node. The other thing is that the default audio-graph sound card doesn't really require the routing section for it to work - just delete it. The routing may actually make things harder for you (it did for me, it required the DAPM supply node). Try below:

 

/{ /* this is the root node */
    sound {
        compatible = "audio-graph-card";
        label = "STM32MP1-audio-test-card";
        dais = <&i2s1_port>;
        status = "okay";
    };

    codec: pcm5102a-codec {
        compatible = "ti,pcm5102a";
        #sound-dai-cells = <0>;
        clocks = <&i2s1>;     /* The codec is a consumer of I2S2 master clock */
        clock-names = "MCLK"; /* Feed MCLK codec clock with I2S2 master clock provider */

        codec_port: port {
            codec_endpoint: endpoint {
                remote-endpoint = <&i2s1_endpoint>;
            };
        };
    };
}; /* root node closes here */

 

Leave the I2S1I node configuration as is and I think you're good to go.