Hello,
I have a i.MX8QM with a PCM3168A audio codec, Linux 6.1. I'm trying to use both audio playback and capture at the same time, but it seems that I can only use one at a time. If I make the device tree so that the playback dai-link master is the cpu, I can play audio. But I can't capture audio with this configuration. If I then change the device tree so that the capture dai-link master is the codec, I can record audio but I can't playback audio.
I added "fsl,sai-asynchronous" to the sai0 node, but that didn't seem to allow both to work at the same time. If I probe the ADC lines, I never see a BCLK or LRCLK signals when the cpu is the master, but I do see signals when the codec is the master.
What am I doing wrong? Here's my device tree below:
Playback working, Capture not working:
sound_card: sound-card {
compatible = "simple-audio-card";
simple-audio-card,name = "PCM3168A";
simple-audio-card,aux-devs = <&>;
simple-audio-card,widgets =
"Speaker", "Channel1out",
"Speaker", "Channel2out",
"Speaker", "Channel3out",
"Speaker", "Channel4out",
"Speaker", "Channel5out",
"Speaker", "Channel6out",
"Speaker", "Channel7out",
"Speaker", "Channel8out",
"Microphone", "Channel1in",
"Microphone", "Channel2in",
"Line", "Channel3in",
"Line", "Channel4in",
"Microphone", "Channel5in",
"Microphone", "Channel6in";
simple-audio-card,routing =
"Channel1out", "AOUT1L",
"Channel2out", "AOUT1R",
"Channel3out", "AOUT2L",
"Channel4out", "AOUT2R",
"Channel5out", "AOUT3L",
"Channel6out", "AOUT3R",
"Channel7out", "AOUT4L",
"Channel8out", "AOUT4R",
"Channel1in", "AIN1L",
"Channel2in", "AIN1R",
"Channel3in", "AIN2L",
"Channel4in", "AIN2R",
"Channel5in", "AIN3L",
"Channel6in", "AIN3R";
simple-audio-card,dai-link@0 {
format = "left_j";
bitclock-master = <&snd_cpu>;
frame-master = <&snd_cpu>;
mclk-fs = <512>;
snd_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_dac: codec {
sound-dai = <&pcm3168a 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
simple-audio-card,dai-link@1 {
format = "left_j";
bitclock-master = <&mic_cpu>;
frame-master = <&mic_cpu>;
mclk-fs = <512>;
mic_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_adc: codec {
sound-dai = <&pcm3168a 1>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
};
Capture Working, Playback not working:
simple-audio-card,dai-link@0 {
format = "left_j";
bitclock-master = <&snd_cpu>;
frame-master = <&snd_cpu>;
mclk-fs = <512>;
snd_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_dac: codec {
sound-dai = <&pcm3168a 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
simple-audio-card,dai-link@1 {
format = "left_j";
bitclock-master = <&pcm3168_adc>;
frame-master = <&pcm3168_adc>;
mclk-fs = <512>;
mic_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_adc: codec {
sound-dai = <&pcm3168a 1>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
SAI0 Node:
&sai0 {
#sound-dai-cells = <0>;
assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
<&sai0_lpcg 0>;
assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai0>;
fsl,sai-asynchronous;
status = "okay";
};
pinctrl_sai0: sai0grp {
fsl,pins = <
IMX8QM_SPI0_CS1_AUD_SAI0_TXC 0x0600004c // BCKDA
IMX8QM_SPI2_CS1_AUD_SAI0_TXFS 0x0600004c // LRCKDA
IMX8QM_SPI0_SDI_AUD_SAI0_RXD 0x0600004c // DOUT1
IMX8QM_SPI0_SDO_AUD_SAI0_TXD 0x0600006c // DIN1
IMX8QM_SPI0_SCK_AUD_SAI0_RXC 0x0600004c // BCKAD
IMX8QM_SPI0_CS0_AUD_SAI0_RXFS 0x0600004c // LRCKAD
>;
};
I2C Node:
// Audio Codec (8-channel output, 6-channel input)
pcm3168a: audio-codec@44 {
compatible = "ti,pcm3168a";
reg = <0x44>;
reset-gpios = <&lsio_gpio4 24 GPIO_ACTIVE_LOW>;
clocks = <&mclkout0_lpcg 0>;
clock-names = "scki";
clock-frequency = <24576000>;
assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
<&mclkout0_lpcg 0>;
assigned-clock-rates = <786432000>, <49152000>, <24576000>, <49152000>;
#sound-dai-cells = <1>;
VDD1-supply = <®_3v3>;
VDD2-supply = <®_3v3>;
VCCAD1-supply = <®_5v0>;
VCCAD2-supply = <®_5v0>;
VCCDA1-supply = <®_5v0>;
VCCDA2-supply = <®_5v0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_codec_clk &pinctrl_audio_reset>;
};
Solved! Go to Solution.
I figured it out. I noticed the SAI6 and SAI7 nodes had this flag set: fsl,txm-rxs;, which I think means TX=master, RX=slave. After setting this in the SAI0 node, and then making the following changes below, I can now capture and playback audio at the same time.
sound_card: sound-card {
compatible = "simple-audio-card";
simple-audio-card,name = "PCM3168A";
simple-audio-card,aux-devs = <&>;
simple-audio-card,widgets =
"Speaker", "Channel1out",
"Speaker", "Channel2out",
"Speaker", "Channel3out",
"Speaker", "Channel4out",
"Speaker", "Channel5out",
"Speaker", "Channel6out",
"Speaker", "Channel7out",
"Speaker", "Channel8out",
"Microphone", "Channel1in",
"Microphone", "Channel2in",
"Line", "Channel3in",
"Line", "Channel4in",
"Microphone", "Channel5in",
"Microphone", "Channel6in";
simple-audio-card,routing =
"Channel1out", "AOUT1L",
"Channel2out", "AOUT1R",
"Channel3out", "AOUT2L",
"Channel4out", "AOUT2R",
"Channel5out", "AOUT3L",
"Channel6out", "AOUT3R",
"Channel7out", "AOUT4L",
"Channel8out", "AOUT4R",
"Channel1in", "AIN1L",
"Channel2in", "AIN1R",
"Channel3in", "AIN2L",
"Channel4in", "AIN2R",
"Channel5in", "AIN3L",
"Channel6in", "AIN3R";
simple-audio-card,dai-link@0 {
format = "left_j";
bitclock-master = <&snd_cpu>;
frame-master = <&snd_cpu>;
mclk-fs = <512>;
snd_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_dac: codec {
sound-dai = <&pcm3168a 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
simple-audio-card,dai-link@1 {
format = "left_j";
bitclock-master = <&pcm3168_adc>;
frame-master = <&pcm3168_adc>;
mclk-fs = <512>;
mic_cpu: cpu {
sound-dai = <&sai0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_adc: codec {
sound-dai = <&pcm3168a 1>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
};
I figured it out. I noticed the SAI6 and SAI7 nodes had this flag set: fsl,txm-rxs;, which I think means TX=master, RX=slave. After setting this in the SAI0 node, and then making the following changes below, I can now capture and playback audio at the same time.
sound_card: sound-card {
compatible = "simple-audio-card";
simple-audio-card,name = "PCM3168A";
simple-audio-card,aux-devs = <&>;
simple-audio-card,widgets =
"Speaker", "Channel1out",
"Speaker", "Channel2out",
"Speaker", "Channel3out",
"Speaker", "Channel4out",
"Speaker", "Channel5out",
"Speaker", "Channel6out",
"Speaker", "Channel7out",
"Speaker", "Channel8out",
"Microphone", "Channel1in",
"Microphone", "Channel2in",
"Line", "Channel3in",
"Line", "Channel4in",
"Microphone", "Channel5in",
"Microphone", "Channel6in";
simple-audio-card,routing =
"Channel1out", "AOUT1L",
"Channel2out", "AOUT1R",
"Channel3out", "AOUT2L",
"Channel4out", "AOUT2R",
"Channel5out", "AOUT3L",
"Channel6out", "AOUT3R",
"Channel7out", "AOUT4L",
"Channel8out", "AOUT4R",
"Channel1in", "AIN1L",
"Channel2in", "AIN1R",
"Channel3in", "AIN2L",
"Channel4in", "AIN2R",
"Channel5in", "AIN3L",
"Channel6in", "AIN3R";
simple-audio-card,dai-link@0 {
format = "left_j";
bitclock-master = <&snd_cpu>;
frame-master = <&snd_cpu>;
mclk-fs = <512>;
snd_cpu: cpu {
sound-dai = <&sai0>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_dac: codec {
sound-dai = <&pcm3168a 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
simple-audio-card,dai-link@1 {
format = "left_j";
bitclock-master = <&pcm3168_adc>;
frame-master = <&pcm3168_adc>;
mclk-fs = <512>;
mic_cpu: cpu {
sound-dai = <&sai0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
pcm3168_adc: codec {
sound-dai = <&pcm3168a 1>;
clocks = <&mclkout0_lpcg 0>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
};
};
};