2025-09-03 3:47 AM
I am using a som STM32MP255 digi connectcore board (CCMP25) for an audio application. I'm using the SAI2 lines for PCM. While playback gives me some signal, capture always results in inout/output error. For my application, the som will be the pcm slave, and there is an external master supplying the bitclock and FS. I am not using any real codecs and opted for dummy codecs for alsa to recognise. Below I'll paste the overlay (I have also attached my overlay) and some details for you guys to verify. I am not sure where I'm going wrong. The SCLK = 4.608MHz and FS = 96kHz are given by the master, the master streams pcm data. What I'm trying to achieve is 16 bit, 3 channel per frame sync.
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/regulator/st,stm32mp25-regulator.h>
#include "dt-bindings/pwm/pwm.h"
#include <dt-bindings/clock/st,stm32mp25-rcc.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = <&pinctrl>;
__overlay__ {
sai2a_pins_mx: sai2a_mx-0 {
pins {
pinmux = <STM32_PINMUX('G', 1, AF4)>; /* SAI2_SD_A */
/*<STM32_PINMUX('A', 6, AF4)>,*/ /* SAI2_FS_B (shared) */
/*<STM32_PINMUX('A', 9, AF4)>;*/ /* SAI2_SCK_B (shared) */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
};
sai2a_sleep_pins_mx: sai2a_sleep_mx-0 {
pins {
pinmux = <STM32_PINMUX('G', 1, ANALOG)>; /* SAI2_SD_A */
};
};
sai2b_pins_mx: sai2b_mx-0 {
pins {
pinmux = <STM32_PINMUX('A', 6, AF4)>, /* SAI2_FS_B */
<STM32_PINMUX('A', 9, AF4)>, /* SAI2_SCK_B */
<STM32_PINMUX('A', 10, AF4)>; /* SAI2_SD_B */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
};
sai2b_sleep_pins_mx: sai2b_sleep_mx-0 {
pins {
pinmux = <STM32_PINMUX('A', 6, ANALOG)>, /* SAI2_FS_B */
<STM32_PINMUX('A', 9, ANALOG)>, /* SAI2_SCK_B */
<STM32_PINMUX('A', 10, ANALOG)>; /* SAI2_SD_B */
};
};
};
};
fragment@1 {
target = <&sai2>;
__overlay__ {
status = "okay";
};
};
fragment@2 {
target = <&sai2a>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&sai2a_pins_mx>;
dmas = <&hpdma 75 0x43 0x12>;
dma-names = "rx";
/*st,fifo-threshold = <1>;*/
/*st,sync = <&sai2b 2>;*/ /* Internal sync to SAI2B (clocks receiver) */
st,sync-ext;
/* 3 channels of 16-bit slots; enable slots 0..2 */
st,slots = <3>;
st,slot-width = <16>;
st,slot-mask = <0x7>;
#sound-dai-cells = <0>;
status = "okay";
};
};
fragment@3 {
target = <&sai2b>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&sai2b_pins_mx>;
/* Make sure B exposes playback */
dmas = <&hpdma 76 0x43 0x21>; /* <-- TX request for SAI2B (example) */
dma-names = "tx";
st,sync-ext;
/* 3 channels of 16-bit slots; enable slots 0..2 */
st,slots = <3>;
st,slot-width = <16>;
st,slot-mask = <0x7>;
/*st,fifo-threshold = <1>;*/
/* Let B provide MCLK if others need it */
#sound-dai-cells = <0>;
status = "okay";
};
};
/* Dummy codec for CPLD endpoint */
fragment@4 {
target-path = "/";
__overlay__ {
/* TX-side dummy (works well as a sink) */
dummy_codec_tx: dummy-codec-tx {
compatible = "linux,spdif-dit";
/*compatible = "simple-audio-card,dummy";*/
#sound-dai-cells = <0>;
};
/* RX-side dummy (bi-directional simple stub) */
dummy_codec_rx: dummy-codec-rx {
/*compatible = "linux,bt-sco";*/
/*compatible = "simple-audio-card,dummy";*/
compatible = "linux,spdif-dir";
#sound-dai-cells = <0>;
};
};
};
/* Playback card: CPU = sai2b (TX), codec = dummy_tx, external is clock master */
/* Define sound card for CPLD connection */
fragment@5 {
target-path = "/";
__overlay__ {
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "SAI2B Playback (slave)";
simple-audio-card,format = "dsp_a"; /* PCM/TDM mode -> previously i2s */
/* external codec/master drives clocks */
/*simple-audio-card,bitclock-master = <&play_codec>;
simple-audio-card,frame-master = <&play_codec>;*/
/*simple-audio-card,frame-inversion;
simple-audio-card,bitclock-inversion;*/
/* TX: sai2b */
simple-audio-card,cpu {
sound-dai = <&sai2b>;
dai-tdm-slot-num = <3>;
dai-tdm-slot-width = <16>;
dai-tdm-slot-tx-mask = <0x7>; /* 3 active slots (bits 0,1,2) */
};
/* RX: sai2a */
play_codec: simple-audio-card,codec {
sound-dai = <&dummy_codec_tx>;
};
};
};
};
/* Capture card: CPU = sai2a (RX), codec = dummy_rx, external is clock master */
fragment@6 {
target-path = "/";
__overlay__ {
sound-capture {
compatible = "simple-audio-card";
simple-audio-card,name = "SAI2A Capture (slave)";
simple-audio-card,format = "dsp_a"; /* PCM/TDM mode -> previously i2s */
/*simple-audio-card,bitclock-master = <&cap_codec>;
simple-audio-card,frame-master = <&cap_codec>;*/
/*simple-audio-card,frame-inversion;
simple-audio-card,bitclock-inversion;*/
simple-audio-card,cpu {
sound-dai = <&sai2a>;
/* add TDM params here too if needed */
dai-tdm-slot-num = <3>;
dai-tdm-slot-width = <16>;
dai-tdm-slot-rx-mask = <0x7>; /* slots 0,1,2 active */
};
cap_codec: simple-audio-card,codec {
sound-dai = <&dummy_codec_rx>;
};
};
};
};
/* Disable default SAI4 sound card */
fragment@7 {
target = <&sai4>;
__overlay__ {
status = "disabled";
};
};
fragment@8 {
target = <&sai4a>;
__overlay__ {
status = "disabled";
};
};
fragment@9 {
target = <&sai4b>;
__overlay__ {
status = "disabled";
};
};
fragment@10 {
target = <&adc_12>;
__overlay__ {
status = "disabled";
};
};
};
Alsa recognises the soundcards
root@ccmp25-dvk:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 1: Playbackslave [SAI2B Playback (slave)], device 0: 402a0024.audio-controller-dit-hifi dit-hifi-0 [402a0024.audio-controller-dit-hifi dit-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
root@ccmp25-dvk:~# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Captureslave [SAI2A Capture (slave)], device 0: 402a0004.audio-controller-dir-hifi dir-hifi-0 [402a0004.audio-controller-dir-hifi dir-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
I'm able to play an audio using aplay and I see signals in my scope. But arecord gives me the error
root@ccmp25-dvk:~# arecord -D hw:0,0 -f S16_LE -r 96000 -c 3 -d 5 test.wav
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 96000 Hz, Channels 3
arecord: pcm_read:2272: read error: Input/output error
root@ccmp25-dvk:~# arecord -D hw:0,0 --dump-hw-params
Warning: Some sources (like microphones) may produce inaudible results
with 8-bit sampling. Use '-f' argument to increase resolution
e.g. '-f S16_LE'.
HW Params of device "hw:0,0":
--------------------
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S16_LE S32_LE
SUBFORMAT: STD
SAMPLE_BITS: [16 32]
FRAME_BITS: [16 512]
CHANNELS: [1 16]
RATE: [8000 192000]
PERIOD_TIME: (83 256000]
PERIOD_SIZE: [16 2048]
PERIOD_BYTES: [1024 4096]
PERIODS: [2 8]
BUFFER_TIME: (166 2048000]
BUFFER_SIZE: [32 16384]
BUFFER_BYTES: [1024 32768]
TICK_TIME: ALL
--------------------
arecord: set_params:1387: Sample format non available
Available formats:
- S16_LE
- S32_LE
root@ccmp25-dvk:~# cat /sys/kernel/debug/clk/clk_summary | grep sai2
ck_icn_p_sai2 0 2 0 200000000 0 0 50000 Y 402a0000.sai pclk
ck_ker_sai2 1 1 0 12288000 0 0 50000 Y audio-controller@402a0024 no_connection_id
Where am I going wrong?