Hi,
I'm working through an audio codec integration on an IMX8MP platform and have been having issues with configuration/development of the sound card driver for my board. This is a custom carrier board using the Boundary Devices Nitrogen8MP SOM. We've wired ECSPI2 to the CODEC and have options to route the CODEC's ADC Digital interface to either SAI2 or SAI5. I've populated some resistors to wire it to SAI5 at the moment. Only the ADC interfaces of the CODEC are connected -- to four on-board microphones.
I've now tried two approaches to the ASoC portion of this integration but have come up empty so far. I started by first attempting to write a custom soundcard driver, based on the imx-wm8960 driver and some tweaks to the AD193x codec to change the default register settings of the part. I've now also tried using the simple-audio-card driver and received a comparable result to my custom driver.
This part supports several different digital data offload schemes -- I2S Stereo, TDM, and ADC "Aux" mode. The I2S Stereo mode uses two data lanes to provide two stereo I2S streams, containing all four ADC inputs worth of data. The TDM mode uses one data lane to provide eight TDM slots at 32-bits each, and populates only the first four slots to contain the four ADC inputs worth of data. The AUX mode is a TDM variant, but does not support the higher sample rates offered by this CODEC, thus cannot be used for my implementation.
From the datasheet, the ADC TDM mode waveform looks like:
The I2S mode is very standard:
On our custom board, we have the CODEC MCLK being driven by a standalone 12.288 MHz crystal that is not connected to the imx.
At the moment, in both implementations I am trying to use the TDM mode to avoid using a second data lane. I have not been able to find any examples of using multiple data lanes on an SAI interface for a sound card driver. I have done quite a bit of messing around configuring the part for I2S stereo mode to obtain audio data, without much luck.
My DT-entries for the simple-audio-card implementation is shown below:
&iomuxc {
/* hsandlar - 12/17/20 - Define Pins for SAI5 (AD193x CODEC interface) */
pinctrl_sai5: sai5-codec-grp {
fsl,pins = <
MX8MP_IOMUXC_SAI5_RXC__AUDIOMIX_SAI5_RX_BCLK 0xd6 /* RXC - Bitclock */
MX8MP_IOMUXC_SAI5_RXFS__AUDIOMIX_SAI5_RX_SYNC 0xd6 /* RXFS - Frame Sync */
MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_SAI5_RX_DATA00 0xd6 /* RXD0 - Channel 0 */
MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI5_RX_DATA01 0xd6 /* RXD1 - Channel 1 */
MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI5_MCLK 0xd6
>;
};
pinctrl_sound_ad1938: ad1938grp {
};
};
&ecspi2 {
ad1938: audio-codec@0 {
compatible = "adi,ad193x";
reg = <0>;
spi-max-frequency = <1000000>;
clocks = <&codec_mclk 0>;
clock-names = "mclk";
#sound-dai-cells = <0>;
};
};
/ {
codec_mclk: oscillator {
compatible = "fixed-clock";
#clock-cells = <1>;
clock-frequency = <12288000>;
clock-output-names = "mclk";
};
sound {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sound_ad1938>;
simple-audio-card,name = "AD1938 Microphone SoundCard";
simple-audio-card,format = "i2s";
simple-audio-card,widgets = "Microphone", "Mic1",
"Microphone", "Mic2";
simple-audio-card,routing = "Mic1", "ADC1IN",
"Mic2", "ADC2IN";
simple-audio-card,bitclock-master = <&cpu_dai>;
simple-audio-card,frame-master = <&cpu_dai>;
cpu_dai: simple-audio-card,cpu {
sound-dai = <&sai5 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
dai-tdm-slot-tx-mask = <0 0 0 0 0 0 0 0>;
dai-tdm-slot-rx-mask = <1 1 1 1 0 0 0 0>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&ad1938>;
clocks = <&codec_mclk>;
};
};
};
&sai5 {
#sound-dai-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai5>;
assigned-clocks = <&clk IMX8MP_CLK_SAI5>;
assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
assigned-clock-rates = <49152000>;
clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI5_IPG>,
<&clk IMX8MP_CLK_DUMMY>,
<&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1>,
<&clk IMX8MP_CLK_DUMMY>,
<&clk IMX8MP_CLK_DUMMY>;
clock-names = "bus",
"mclk0",
"mclk1",
"mclk2",
"mclk3";
//fsl,sai-synchronous-rx;
fsl,sai-asynchronous;
status = "okay";
};
^ I have tried both fsl,sai-synchronous-rx and fsl,sai-asynchronous with no discernable difference in behavior.
I've added the appropriate of_match_table in the ad193x-spi driver so that the CODEC driver is recognized and loaded. Communicating with the CODEC appears to function as expected, and I can reconfigure the part to enable it's internal mic bias, enable the on-board mclk oscillator, specify the output data mode, etc..
My observations with this approach:
The imx generates the correct bitclock frequency (256*fs in this case) but the LRCLK is not a 50% duty cycle output. See this capture:
We can clearly see the microphone data in slots 0-3 of the TDM stream, though I haven't heard a recording output from arecord that sounds even close to correct yet.
The other strange observation is that no matter what rate I specify in my arecord command, the LRCLK is always 48kHz. I expect LRCLK to be the same frequency as the requested sample rate. The "ADC Control Register 0" of this part specifies the output sample rate ranges, and I understand that configuration of this section of this register is likely a primary concern for the custom soundcard driver. However, I don't expect the IMX to care about this register configuration -- if I request a 48kHz sample rate, I expect a 48kHz LRCLK; an 8kHz rate should generate 8kHz LRCLK; a 192kHz rate should generate 192kHz.. etc..
I've added some debug prints into fsl_sai.c fsl_sai_hw_params function and for some reason no matter what rate I request in arecord, it always states that params_rate(params) = 48kHz, thus leading to the 48kHz LRCLK. When I manually hack in a different rate, the IMX generates the correct LRCLK rate (though still with an incorrect LRCLK duty cycle).
Here are a couple examples of arecord commands (all of which produce 48kHz LRCLK):
The associated debug prints:
Can anyone point me in the right direction here? I get the sense that I'm missing a very subtle setting requirement for this ASoC subsystem, or that I'm up against a bug in the NXP SAI support.
Thanks,
Please note that the 8M Plus has not been publicly launched, consequently all information and documentation is NDA only. We cannot answer any 8M Plus questions in this public community. Public support will be available once the device launches, which is currently targeted at sometime in March 2021. Questions should be directed (privately) to the Module Partner who provided you with the pre-launch SOM/Board.
Hi,
We're in a very similar position with the imx8 and CODECs, did you get you issue resolved?
Thanks.