The STM32MP25 provides four Serial Audio Interfaces (SAI) each with two independent audio subblocks.

On the ConnectCore MP25 Development Kit, the SAI4 interface is connected to a Maxim 98089 low-power stereo codec.

  • SAI4 subblock B is master and generates the clock and the audio output to the codec (playback).

  • SAI4 subblock A is a synchronous slave that only uses the data line as input from the codec (recording).

The following features of the codec are available on the ConnectCore MP25 Development Kit:

  • Analog inputs: line-in A, line-in B, microphone:

    • Two line-in audio inputs through the LINE_IN_A_ and LINE_IN_B_ lines of the AUDIO and SPK connectors.

    • Microphone audio input through the MIC_ lines of the AUDIO connector.

  • Analog outputs: line-out, headphone, speakers:

    • Line-out audio output through the LINE_OUT_ lines of the AUDIO connector.

    • Headphone audio output through the on-board jack connector.

    • Speaker audio output through the SPKL_ and SPKR_ lines of the SPK connector.

  • Digital processing, filters, volume control, amplifiers.

Kernel configuration

You can manage the audio driver support through the following kernel configuration options:

  • STM32 SAI interface (Serial Audio Interface) support (CONFIG_SND_SOC_STM32_SAI)

  • ASoC Audio Graph sound card support (CONFIG_SND_AUDIO_GRAPH_CARD)

  • SoC Audio support for i.MX boards with max98088/max98089 (CONFIG_SND_SOC_IMX_MAX98088)

These options are enabled as built-in on the default ConnectCore MP25 kernel configuration file.

Kernel driver

The drivers for the audio interface and MAX98089 codec are located at:

File Description

sound/soc/stm/stm32_sai.c

SAI driver

sound/soc/stm/stm32_sai_sub.c

SAI subblock driver

sound/soc/generic/audio-graph-card.c

ASoC Audio Graph sound card driver

sound/soc/codecs/max98088.c

MAX98088/9 codec driver

Device tree bindings and customization

The SAI interface is documented at Documentation/devicetree/bindings/sound/st,stm32-sai.yaml.

The device tree must contain entries for:

  • The SAI interface

  • The interface between the SAI and the audio codec

  • The audio codec

Example: SAI4 on ConnectCore MP25 Development Kit

ConnectCore MP25 Development Kit device tree
&sai4 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&ccmp25_sai4a_pins>, <&ccmp25_sai4b_pins>;
	pinctrl-1 = <&ccmp25_sai4a_sleep_pins>, <&ccmp25_sai4b_sleep_pins>;
	status = "okay";

	sai4a: audio-controller@40340004 {
		/* Sub-block A is a slave of sub-block B */
		st,sync = <&sai4b 1>;
		/* Sub-block A is only capture (rx) */
		dmas = <&hpdma 79 0x43 0x12 0>;
		dma-names = "rx";
		clocks = <&rcc CK_KER_SAI4>, <&sai4b>;
		clock-names = "sai_ck", "mclk";
		status = "okay";

		sai4a_port: port {
			sai4a_endpoint: endpoint {
				remote-endpoint = <&max98089_in_endpoint>;
				format = "i2s";
				mclk-fs = <256>;
				dai-tdm-slot-num = <2>;
				dai-tdm-slot-width = <32>;
			};
		};
	};
	sai4b: audio-controller@40340024 {
		/* Sub-block B is master */
		#clock-cells = <0>;
		/* Sub-block B is only playback (tx) */
		dmas = <&hpdma 80 0x63 0x21 0>;
		dma-names = "tx";
		status = "okay";

		sai4b_port: port {
			sai4b_endpoint: endpoint {
				remote-endpoint = <&max98089_out_endpoint>;
				format = "i2s";
				mclk-fs = <256>;
				dai-tdm-slot-num = <2>;
				dai-tdm-slot-width = <32>;
			};
		};
	};
};
&pinctrl {
	[...]

	ccmp25_sai4a_pins: ccmp25-sai4a-1 {
		pins {
			pinmux = <STM32_PINMUX('D', 1, AF5)>; /* SAI4_SD_A */
			bias-disable;
		};
	};

	ccmp25_sai4a_sleep_pins: ccmp25-sai4a-sleep-1 {
		pins {
			pinmux = <STM32_PINMUX('D', 1, ANALOG)>; /* SAI4_SD_A */
		};
	};

	ccmp25_sai4b_pins: ccmp25-sai2b-0 {
		pins1 {
			pinmux = <STM32_PINMUX('I', 2, AF4)>, /* SAI4_SCK_B */
				 <STM32_PINMUX('I', 4, AF4)>, /* SAI4_FS_B */
				 <STM32_PINMUX('I', 0, AF4)>; /* SAI4_MCLK_B */
			slew-rate = <0>;
			drive-push-pull;
			bias-disable;
		};
		pins2 {
			pinmux = <STM32_PINMUX('I', 3, AF4)>; /* SAI4_SD_B */
			bias-disable;
		};
	};

	ccmp25_sai4b_sleep_pins: ccmp25-sai2b-sleep-0 {
		pins {
			pinmux = <STM32_PINMUX('I', 3, ANALOG)>, /* SAI4_SDO_B */
				 <STM32_PINMUX('I', 2, ANALOG)>, /* SAI4_SCK_B */
				 <STM32_PINMUX('I', 4, ANALOG)>, /* SAI4_FS_B */
				 <STM32_PINMUX('I', 0, ANALOG)>; /* SAI4_MCLK_B */
		};
	};

	[...]
};

Interface between SAI and audio codec

ConnectCore MP25 Development Kit device tree
/ {
[...]

	/* AUDIO */
	sound_max98089: sound-max98089 {
		compatible = "audio-graph-card";
		label = "ccmp25-dvk";
		dais = <&sai4b_port &sai4a_port>;
		status = "okay";
	};

[...]
};

Audio codec ({i2c_port} slave)

ConnectCore MP25 Development Kit device tree
&{i2c_port} {
	[...]

	max98089: codec@10 {
		compatible = "maxim,max98089";
		reg = <0x10>;
		clocks = <&sai4b>;
		clock-names = "mclk";
		#sound-dai-cells = <0>;
		#address-cells = <1>;
		#size-cells = <0>;
		status = "okay";

		max98089_port: port@0{
			reg = <0>;

			max98089_in_endpoint: endpoint@0 {
				remote-endpoint = <&sai4a_endpoint>;
				frame-master = <&max98089_in_endpoint>;
				bitclock-master = <&max98089_in_endpoint>;
			};

			max98089_out_endpoint: endpoint@1 {
				remote-endpoint = <&sai4b_endpoint>;
				frame-master = <&max98089_out_endpoint>;
				bitclock-master = <&max98089_out_endpoint>;
			};
		};
	};

	[...]
};

Using the audio interface

Audio controls

The audio codec is controlled from Linux via the ALSA framework. Digi Embedded Yocto provides an initial configuration that enables:

  • Line-in A

  • Line-in B

  • Microphone

  • Headphones

  • Speakers

  • Line-out

You can use the command line application alsamixer to manage these interfaces and their associated controls (volumes, gains, filters).

Audio playback

Since all output routes are enabled by default, any sound will play on headphones, speakers, and line-out.

To play a wav file:

# aplay sound.wav

To play an mp3 file:

# mpg123 sound.mp3

Audio recording

Since microphone, line-in A, and line-in B input routes are enabled by default, any recorded sound will mix the audio coming from these inputs.

To record a stereo WAV audio file with 10 seconds duration from line-in:

# arecord -f cd sound.wav --duration 10 -D "hw:0,1"

To record a mono WAV audio file from the microphone:

# arecord --format=S16_LE --channels=1 --rate=44100 micro.wav --duration=10 -D "hw:0,1"