PCM3168A SAI Audio In/Out not working at same time

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PCM3168A SAI Audio In/Out not working at same time

Jump to solution
577 Views
jsmith8831
Contributor III

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 = <&amp>;
	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 = <&reg_3v3>;
	VDD2-supply = <&reg_3v3>;
	VCCAD1-supply = <&reg_5v0>;
	VCCAD2-supply = <&reg_5v0>;
	VCCDA1-supply = <&reg_5v0>;
	VCCDA2-supply = <&reg_5v0>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_codec_clk &pinctrl_audio_reset>;
};

 

Tags (2)
0 Kudos
Reply
1 Solution
563 Views
jsmith8831
Contributor III

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 = <&amp>;
	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>;
			};
	};
};

 

View solution in original post

0 Kudos
Reply
1 Reply
564 Views
jsmith8831
Contributor III

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 = <&amp>;
	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>;
			};
	};
};

 

0 Kudos
Reply