We want to use I2S microphone on our customized breakout board for Toradex colibri VF61 that provides ESAI connectivity. I have created below device tree that suppose to activate ESAI and offer it as a sound card within Linux; however when I start recording no clock signal is detectable on either of ESAI's clock pins. (Note: I had to tweak some portions of the kernel to even get ESAI registry written and start recording, logs attached further.)
#include "vf610-colibri-eval-v3.dts"
&iomuxc {
vf610-colibri {
pinctrl_gpio_bl_on: gpio_bl_on {
fsl,pins = <
VF610_PAD_PTB19__GPIO_41 0x30
>;
};
// Pin/pad definitions are in vf610-pinfunc.h in the same dir. as this file
// Output only pins - not needed for our use case
// VF610_PAD_PTC2__ESAI_SDO0 0x30d2
// VF610_PAD_PTC3__ESAI_SDO1 0x30d2
esai_pins: esai_pins {
fsl,pins = <
VF610_PAD_PTC0__ESAI_SCKT 0x31C3
VF610_PAD_PTC1__ESAI_FST 0x31C3
VF610_PAD_PTC4__ESAI_SDO2 0x0041
VF610_PAD_PTC5__ESAI_SDO3 0x0041
VF610_PAD_PTC6__ESAI_SDI0 0x0041
VF610_PAD_PTC7__ESAI_SDI1 0x0041
>;
};
};
};
&clks {
clocks = <&sxosc>, <&fxosc>;
clock-names = "sxosc", "fxosc";
};
&aips0 {
esai: esai@40062000 {
compatible = "fsl,vf610-esai";
reg = <0x40062000 0x1000>; // Base address and size of ESAI registers
#sound-dai-cells = <0>;
interrupts = <88 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_ESAI>, <&clks VF610_CLK_ESAI>, <&clks VF610_CLK_ESAI>;
clock-names = "core", "extal", "fsys";
assigned-clocks = <&clks VF610_CLK_PLL4>, <&clks VF610_CLK_PLL4_MAIN_DIV>, <&clks VF610_CLK_ESAI_SEL>, <&clks VF610_CLK_ESAI_DIV>, <&clks VF610_CLK_ESAI>;
assigned-clock-parents = <&clks VF610_CLK_PLL4_BYPASS_SRC>, <&clks VF610_CLK_PLL4_AUDIO>, <&clks VF610_CLK_PLL4_MAIN_DIV>, <&clks VF610_CLK_ESAI_EN>, <&clks VF610_CLK_ESAI_DIV>;
assigned-clock-rates = <768000000>, <48000000>, <0>, <12000000>, <0>;
dmas = <&edma0 0 30>, <&edma0 0 31>;
dma-names = "rx", "tx";
fsl,fifo-depth = <128>;
fsl,esai-rx-channels = <4>;
fsl,esai-tx-channels = <2>;
// fsl,esai-synchronous;
pinctrl-names = "default";
pinctrl-0 = <&esai_pins>;
status = "okay";
};
};
/ {
sph0645: mic-codec {
compatible = "linux,snd-soc-dummy";
#sound-dai-cells = <0>;
status = "okay";
};
pure-digital-sound {
compatible = "simple-audio-card";
simple-audio-card,name = "ESAI-Multi-Channel";
status = "okay";
simple-audio-card,dai-link@0 {
format = "i2s";
bitclock-master = <&esai>;
frame-master = <&esai>;
// This is pristine hacking. 48 kHz * 1024 = audio_ext_clk.clock-frequency.
// Really just a hack to trigger the code that registers sound card for input.
mclk-fs = <128>;
cpu {
sound-dai = <&esai>;
system-clock-frequency = <6000000>;
dai-tdm-slot-num = <2>; // Number of slots
dai-tdm-slot-width = <32>; // Width in bits per slot
//dai-tdm-slot-rx-mask = <1 1 1 1 0 0>;
};
codec {
sound-dai = <&sph0645>;
};
};
};
};
and when i start recording using
arecord -v -D hw:1,0 -c 2 -f S24_LE -r 46875 -d 5 test.wav
The result (incl. my kernel debug output) is a failure and osciloscope doesn't show any clock signal on either of ESAI clock pins (e.g. at UART pin osciloscope shows data signal correctly).
arecord -v -D hw:1,0 -c 2 -f S24_LE -r 46875 -d 5 test.wav
[ 1713.779730] fsl-esai-dai 40062000.esai: Startup: syncx=0
Recording WAVE 't[ 1713.786470] fsl-esai-dai 40062000.esai: SYSCLK clk_id=2 freq=6000000 dir=1
est.wav' : Signed[ 1713.794171] fsl-esai-dai 40062000.esai: HWP slot_width=32 params_rate=46875 slots=2
24 bit Little En[ 1713.803342] fsl-esai-dai 40062000.esai: BCLK ratio=2 hck_rate=6000000 freq=3000000 tx=0
dian, Rate 46875 [ 1713.812834] fsl-esai-dai 40062000.esai: HWP[ub] REG_ESAI_xCR(tx)=220 channels=2
Hz, Stereo
[ 1713.821634] fsl-esai-dai 40062000.esai: HWP[ub] REG_ESAI_xFCR(tx)=24
[ 1713.829056] fsl-esai-dai 40062000.esai: HWP[ub] mask=7ff3e val=27f04
[ 1713.835458] fsl-esai-dai 40062000.esai: HWP[ub] REG_ESAI_xCR(tx)=220 mask=7c00 val=7c00
[ 1713.843499] fsl-esai-dai 40062000.esai: HWP[ub] REG_ESAI_PRRC
[ 1713.849311] fsl-esai-dai 40062000.esai: HWP[ub] REG_ESAI_PCRC
[ 1713.855197] fsl-esai-dai 40062000.esai: HWP return
Hardware PCM card[ 1713.881667] fsl-esai-dai 40062000.esai: Trigger: tx=0 channels=2 pins=1 cmd=1
[ 1713.889006] fsl-esai-dai 40062000.esai: Trigger[START]: REG_ESAI_xFCR(tx)=24 REG_ESAI_xCR(tx)=220 ESAI_xCR_TE(pins)=1 ESAI_xCR_RE(pins)=1
1 'ESAI-Multi-Channel' device 0 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : S24_LE
subformat : STD
channels : 2
rate : 46875
exact rate : 46875 (46875/1)
msbits : 32
buffer_size : 29295
period_size : 5859
period_time : 124992
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 5859
period_event : 0
start_threshold : 1
stop_threshold : 29295
silence_threshold: 0
silence_size : 0
boundary : 1919877120
appl_ptr : 0
hw_ptr : 0
arecord: pcm_read[ 1723.895948] fsl-esai-dai 40062000.esai: Trigger: tx=0 channels=2 pins=1 cmd=0
:2096: read error: Input/output error
I am pretty new to dealing with HW via Linux's device tree. Before I used to wrote registries directly in microcontrollers' programs.
So what do I miss in the device tree to make the ESAI module being I2S clock master and actually send out the clock signal to ESAI clock pins? Of course recording the samples is my overall goal so DMA configuration might lack something as well.
Thanks for any little hints.
Martin
Hello,
First, I suggest you check with manufacturer BSP if is able to support that microphone and confirm that additional drivers are not needed.
cat /sys/kernel/debug/clk/clk_summary -n
Once you confirmed this, please check that ESAI clocks are correctly configured and enabled, you can see them with the next command:
Look for ESAI and its parent clocks to confirm they are enabled and running at expected frequencies.
Did you try with fsl,esai-synchronous; uncommented?
Best regards.
The content of clk_summary is as below (shortened for easier readability) so Linux is accepting my settings. Regardless of suppport of mentioned microphone, the clock signal shall appear even if the data are not accepted by driver.
Regarding the manufacturer advice I have raised question in Toradex's forum but no reply so far.
clock enable_cnt prepare_cnt rate accuracy phase ---------------------------------------------------------------------------------------- ... sxosc 0 0 32768 0 0 ftm3_fix_sel 0 0 32768 0 0 ftm2_fix_sel 0 0 32768 0 0 ftm1_fix_sel 0 0 32768 0 0 ftm0_fix_sel 0 0 32768 0 0 fxosc 1 1 24000000 0 0 fast_clk_sel 6 6 24000000 0 0 pll7_bypass_src 1 1 24000000 0 0 pll7 1 1 480000000 0 0 pll7_bypass 1 1 480000000 0 0 pll7_usb_host 1 1 480000000 0 0 usbphy1 1 1 480000000 0 0 ... pll4_bypass_src 1 1 24000000 0 0 pll4 1 1 768000000 0 0 pll4_bypass 1 1 768000000 0 0 pll4_audio 1 1 768000000 0 0 pll4_audio_div 1 2 48000000 0 0 esai_sel 0 1 48000000 0 0 esai_en 0 1 48000000 0 0 esai_div 0 1 12000000 0 0 esai 0 1 12000000 0 0 sai2_sel 0 0 48000000 0 0 sai2_en 0 0 48000000 0 0 sai2_div 0 0 48000000 0 0 sai0_sel 1 1 48000000 0 0 sai0_en 1 1 48000000 0 0 sai0_div 1 1 48000000 0 0 ...