TLV320aic32x4 audio codec is not detecting for tx2i

Hi,
We are trying to run the plaback script and probe the I2S lines. We are getting following error s while running playback.sh.

aplay: main:788: audio open error: Device or resource busy

Please find attached the log file. play.txt (3.9 KB)

Regards,
Parashuram

Hello!

Yes that can be normal is something else like pulseaudio is using the device. Can you try using the plughw as follows …

amixer -c tegrasndt186ref cset name='z LO DAC Playback Switch' 1
amixer -c tegrasndt186ref cset name='z LOL Output Mixer L_DAC Switch' 1
amixer -c tegrasndt186ref cset name='z LOR Output Mixer R_DAC Switch' 1
speaker-test -D plughw:tegrasndt186ref,0 -c 2 -r 48000 -F S16_LE -t sine -f 500

Jon

Hi,

Please find the attached output results.

ubuntu@ubuntu-desktop:~$ amixer -c tegrasndt186ref cset name='z LO DAC Playback Switch' 1
numid=879,iface=MIXER,name='z LO DAC Playback Switch'
  ; type=BOOLEAN,access=rw------,values=2
  : values=on,on
ubuntu@ubuntu-desktop:~$ amixer -c tegrasndt186ref cset name='z LOL Output Mixer L_DAC Switch' 1
numid=1118,iface=MIXER,name='z LOL Output Mixer L_DAC Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on
ubuntu@ubuntu-desktop:~$ amixer -c tegrasndt186ref cset name='z LOR Output Mixer R_DAC Switch' 1
numid=1121,iface=MIXER,name='z LOR Output Mixer R_DAC Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on

Speakar log speakar_test.txt (100.6 KB)

Regards,
Parashuram

Hello!

Do you hear anything? If not do you see any activity of the I2S signals? Do you have an oscilloscope to probe the I2S signals?

Regards,
Jon

Hi,

we are able to see a transaction in the pin of aud_mclk, lrck and sclk data transaction is happening but there is no data transaction for SDATA_IN and SDATA_OUT pins.

These are my Pinmux configuration changes could you please let me know the Pinmux changes are proper.

pinmux.0x02431040 = 0x00000400; # dap1_sclk_pj0: i2s1, tristate-disable, input-disable, lpdr-disable
pinmux.0x02431038 = 0x00000400; # dap1_dout_pj1: i2s1, tristate-disable, input-disable, lpdr-disable
pinmux.0x02431030 = 0x00000458; # dap1_din_pj2: i2s1, pull-up, tristate-enable, input-enable, lpdr-disable
pinmux.0x02431028 = 0x00000400; # dap1_fs_pj3: i2s1, tristate-disable, input-disable, lpdr-disable
pinmux.0x02431020 = 0x00000400; # aud_mclk_pj4: aud, tristate-disable, input-disable, lpdr-disable

Regards,
Parashuram

Hello!

The pin settings look fine. What are the frequencies of the MCLK, SCLK and LRCK? The MCLK should be 12MHz, the LRCK should be the sample rate (eg. 44.1KHz, 48KHz, etc depending on the PCM sample rate) and the SCLK should be fsnum-channelsbits-per-channel.

Regards,
Jon

Hi Jon,
Below is the status of each pin :
MCLK : 12MHz
SCLK: 12MHz
LRCK: 93.7kHz
SDIN: No transaction.
SDOUT: No transaction.
Do we need to change anything tlvai320aicc32x4.c file so that transaction on SDIN and SDOUT gets enabled.

Regards
Parshuram

Hello!

What sample-rate are you using? If you are running the following command then the sample-rate should be 48kHz …

speaker-test -D plughw:tegrasndt186ref,0 -c 2 -r 48000 -F S16_LE -t sine -f 500

In this case I would expect the LRCK to be 48kHz and not ~94kHz. Furthermore, I would expect the SCLK to be 2 * 16 * 48000 = 1.536MHz and not 12MHz. So the clock frequencies here do not look correct. When you run the above command can you …

speaker-test -D plughw:tegrasndt186ref,0 -c 2 -r 48000 -F S16_LE -t sine -f 500 &
sudo grep "aud_mclk\|i2s1" /sys/kernel/debug/clk/clk_summary
sudo cat /sys/kernel/debug/regmap/tegra210-i2s.0/registers

There is nothing that needs to be changed in the codec driver as far as I know. At least the DOUT from Tegra should be just driven by Tegra for playback.

Are you probing the I2S pins on the 40-pin of the TX2i board? If so what pins are you probing?

Regards,
Jon

Hello,

Please find the attached sample rate output result speakar-TEST_11_01.txt (34.6 KB) .
speakar-TEST_500.txt (5.3 KB) aud_mclk.txt (572 Bytes) regmap.txt (670 Bytes)

We have a custom TX2i carrier board we are probing SDIN, SDOUT, LRCK,SCLK and MCLK on the PCB pads.

Regards,
Parashuram

Hello!

OK I can see a problem …

In the above I see the the codec is the bit clock and frame master. I believe originally, you had this configured as slave. Looking at Igal’s configuration he used slave and not master. If you want the codec to be the bit clock and frame master, then you need to enable the ‘input-enable’ for the dap1_fs_pj3 pin. Right now you have this disabled and so Tegra will not see the frame clock …

pinmux.0x02431028 = 0x00000400; # dap1_fs_pj3: i2s1, tristate-disable, input-disable, lpdr-disable

I am a bit concerned why the codec is generating the wrong frequencies for the SCLK and LRCK and so maybe there is something else you need to configure on the codec side. You would need to review the codec documentation to figure this out. Otherwise, you could make Tegra the bit clock and frame master instead because we know that Igal had this working.

Jon

Hi Jon,
I can hear the Line out audio after making bit-clock and frame in “slave” mode. Thanks a lot for your support !! I greatly appreciate it.

I am not able to see any output on the Headphone lines? Do i need to enable it in tegra186-quill-common.dtsi file?if yes, how do i enable it?
I could see transaction on DOUT and DIN pins only after playing the play.sh script. Without running this script, i couldn’t see any transaction even if i was playing some audio file. Any idea, why is that so?

Regards
Parshuram

Hello!

That is great to hear!

The reason you need to run the play.sh to hear the audio, is because this script is configuring the codec. I am also wondering if running just the following commands also work …

amixer -c tegrasndt186ref cset name='z LO DAC Playback Switch' 1
amixer -c tegrasndt186ref cset name='z LOL Output Mixer L_DAC Switch' 1
amixer -c tegrasndt186ref cset name='z LOR Output Mixer R_DAC Switch' 1
speaker-test -D plughw:tegrasndt186ref,0 -c 2 -r 48000 -F S16_LE -t sine -f 500

This is a common problem I see people struggle when integrating a new codec, is that by default the audio paths in the codec are not configured and so you need to figure out the mixer controls you need to set for the codec. Every codec is a bit different and so every codec has different mixer controls that need to be set. Hence, it is not easy for us to tell you how to configure the codec, especially when it is not a codec we test.

For the headphone you also need to add these to the route …

nvidia,audio-routing =
                "z Headphone", "z LOL",
            	"z Headphone", "z LOR",
                "z Headphone", "z HPL",
            	"z Headphone", "z HPR",
                "z Left DAC", "z Playback",
                "z Right DAC", "z Playback",
            	"z IN1_L", "z Mic",
            	"z IN1_R", "z Mic",
                "z Capture", "z Left ADC",
                "z Capture", "z Right ADC";

And you will need to enable the headphone output in the codec …

amixer -c tegrasndt186ref cset name='z HPL Output Mixer L_DAC Switch' 1
amixer -c tegrasndt186ref cset name='z HPR Output Mixer R_DAC Switch' 1

Regards,
Jon

Hello Jon,
Thanks for your reply. I tried above for enabling Headphone output. I can see the transaction on DOUT, MCLK,LRCK and SRCLK but there is no signal on HPL and HPR pins. When we enable Line out as suggested, we can see analog signals on LOL & LOR pins and we can hear the sound as well.
Are we missing something to enable Headphone out?
We also need to enable 1-Line IN and one MICIN. I added following but it is not working too.
nvidia,audio-routing =

            "z Headphone", "z LOL",
            "z Headphone", "z LOR",
            "z Headphone", "z HPL",
            "z Headphone", "z HPR",
            "z Left DAC", "z Playback",
            "z Right DAC", "z Playback",
            "z IN1_L", "z Mic",
            "z IN1_R", "z Mic",
            "z IN2_L", "z Mic",
            "z IN2_R", "z Mic",
            "z IN3_L", "z Mic",
            "z IN3_R", "z Mic",
            "z Capture", "z Left ADC",
            "z Capture", "z Right ADC";

Do we need to set the mixer controls for LINEIN and MICIN as well?
Regards
Parshuram

Hello Jon,

could you please update, I’m waiting for your reply. Any help will be greatly appreciated.

Regards,
Parashuram

Hello,

For assistance with configuring the codec itself, I recommend that you ask the codec vendor and/or review the codec documentation to understand if the codec is configured correctly. Please let us know if you are able to get this working.

Regards
Jon

Hello Jon,

Thanks for your support. codec is up and working fine.
Is there any way to convert mono input recorded from Mic IN to Stereo output for Playback?

Regards,
Parashuram

Hello!

Thanks. That is great news. If you have a moment to share all the changes and configuration for the codec, that would be great.

With regard to converting mono to stereo, this is possible by setting the following mixer control and playing the mono file …

amixer -c tegrasndt186ref cset name="I2S1 Playback mono to stereo conv" COPY'
aplay -D hw:tegrasndt186ref,0 <mono-wav-file>

Regards,
Jon

Hello Jon,

Here Is a complete breakdown of the changes I have made to get TLV320AIC32X4 working with the TX2i. Hopefully, this helps some other new to audio codec figure things out.
Anyone can use these modifications hoping that NVidia will find the time to embed these modifications or others to support future uses who intend to use audio CODECs like the TLV320AIC32x4.
Environment:-
Jetpack 4.3 with The target Jetson TX2i is programmed with L4T 32.4*

Here is the Device tree changes:
File Path: /home/parashuram/Linux_for_Tegra/sources/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi

 diff --git a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
old mode 100644
new mode 100755
index 9416a21..2fb56f5
--- a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
+++ b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
@@ -166,6 +166,18 @@
 				rom-val = /bits/ 8 <0x05>;
 			};
 		};
+ 	aic32x4: tlv320aic32x4.1-0018@18 {
+                        compatible = "ti,tlv320aic32x4";
+                        status = "okay";
+                        reg = <0x18>;
+                        clocks = <&tegra_car TEGRA186_CLK_AUD_MCLK>;
+                        clock-names = "mclk";
+			micbias-resistor-k-ohms = <2>;
+			micbias-voltage-m-volts = <3000>;
+                        dv-supply = <&battery_reg>;
+                        av-supply = <&battery_reg>;
+                        iov-supply = <&battery_reg>;
+                };	
 	};
 
 	i2c@c240000 {
@@ -668,7 +680,8 @@
 #endif
 	ahub {
 		/* I2S6 */
-		i2s@2901500 {
+		i2s@2901100 {
+			status = "okay";
 			bclk-ratio = <4>;
 		};
 
@@ -695,60 +708,53 @@
 	tegra_sound: sound {
 		compatible = "nvidia,tegra-audio-t186ref-mobile-rt565x";
 		nvidia,model = "tegra-snd-t186ref-mobile-rt565x";
-		nvidia,num-codec-link = <12>;
-		clocks = <&tegra_car TEGRA186_CLK_PLLA>,
-			 <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
-			 <&tegra_car TEGRA186_CLK_AUD_MCLK>;
-		clock-names = "pll_a", "pll_a_out0", "extern1";
-		assigned-clocks = <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
-				  <&tegra_car TEGRA186_CLK_AUD_MCLK>;
-		assigned-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>,
-					 <&tegra_car TEGRA186_CLK_PLL_A_OUT0>;
-		resets = <&tegra_car TEGRA186_RESET_AUD_MCLK>;
+		nvidia,num-codec-link = <13>;
+		 clocks = <&tegra_car TEGRA186_CLK_PLLA>,
+                        <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
+                        <&tegra_car TEGRA186_CLK_AHUB>,
+                        <&tegra_car TEGRA186_CLK_AUD_MCLK>;
+                clock-names = "pll_a", "pll_a_out0", "ahub", "extern1";
+                
+		/*assigned-clocks = <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
+                                  <&tegra_car TEGRA186_CLK_AHUB>,
+                                  <&tegra_car TEGRA186_CLK_AUD_MCLK>;
+                assigned-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>,
+                                         <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
+                                        <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
+                                        <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
+               assigned-clock-rates = <0>, <0>, <12000000>;*/
+		assigned-clocks = <&tegra_car TEGRA186_CLK_PLL_A_OUT0>, <&tegra_car TEGRA186_CLK_AUD_MCLK>;
+                assigned-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>, <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
+                assigned-clock-rates = <0>, <12000000>;
+
+                resets = <&tegra_car TEGRA186_RESET_AUD_MCLK>;
 		reset-names = "extern1_rst";
 
 		status = "okay";
 		nvidia,audio-routing =
-			"x Headphone",		"x OUT",
-			"x IN",			"x Mic",
-			"y Headphone",		"y OUT",
-			"y IN",			"y Mic",
-			"z Headphone",		"z OUT",
-			"z IN",			"z Mic",
-			"m Headphone",		"m OUT",
-			"m IN",			"m Mic",
-			"n Headphone",		"n OUT",
-			"n IN",			"n Mic",
-			"o Headphone",		"o OUT",
-			"o IN",			"o Mic",
-			"a IN",			"a Mic",
-			"b IN",			"b Mic",
-			"c IN",			"c Mic",
-			"d IN",			"d Mic",
-			"d1 Headphone",		"d1 OUT",
-			"d3 Headphone",		"d3 OUT";
 
+		"z Headphone", "z LOL",
+                "z Headphone", "z LOR",
+            	"z Headphone", "z HPL",
+            	"z Headphone", "z HPR",
+            	"z Left DAC", "z Playback",
+            	"z Right DAC", "z Playback",
+            	"z IN1_L", "z Mic",
+            	"z IN1_R", "z Mic",
+            	"z IN2_L", "z Mic",
+            	"z IN2_R", "z Mic",
+            	"z IN3_L", "z Mic",
+            	"z IN3_R", "z Mic",
+            	"z Capture", "z Left ADC",
+            	"z Capture", "z Right ADC";
+		 
 		nvidia,xbar = <&tegra_axbar>;
-		mclk-fs = <256>;
+		//mclk-fs = <256>;
 
 		rt565x_dai_link: nvidia,dai-link-1 {
 			link-name = "spdif-dit-0";
-			cpu-dai = <&tegra_i2s1>;
-			codec-dai = <&spdif_dit0>;
-			cpu-dai-name = "I2S1";
-			codec-dai-name = "dit-hifi";
-			format = "i2s";
-			bit-format = "s16_le";
-			srate = <48000>;
-			num-channel = <2>;
-			ignore_suspend;
-			name-prefix = "x";
-			status = "okay";
-		};
-		nvidia,dai-link-2 {
-			link-name = "spdif-dit-1";
 			cpu-dai = <&tegra_i2s2>;
-			codec-dai = <&spdif_dit1>;
+			codec-dai = <&spdif_dit0>;
 			cpu-dai-name = "I2S2";
 			codec-dai-name = "dit-hifi";
 			format = "i2s";
@@ -756,7 +762,7 @@
 			srate = <48000>;
 			num-channel = <2>;
 			ignore_suspend;
-			name-prefix = "y";
+			name-prefix = "x";
 			status = "okay";
 		};
 		nvidia,dai-link-3 {
@@ -770,8 +776,8 @@
 			srate = <48000>;
 			num-channel = <2>;
 			ignore_suspend;
-			name-prefix = "z";
-			status = "okay";
+			name-prefix = "a";
+			status = "disabled";
 		};
 		nvidia,dai-link-4 {
 			link-name = "spdif-dit-3";
@@ -785,7 +791,7 @@
 			num-channel = <2>;
 			ignore_suspend;
 			name-prefix = "m";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-5 {
 			link-name = "spdif-dit-4";
@@ -799,7 +805,7 @@
 			num-channel = <2>;
 			ignore_suspend;
 			name-prefix = "n";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-6 {
 			link-name = "spdif-dit-6";
@@ -816,7 +822,7 @@
 			num-channel = <1>;
 			ignore_suspend;
 			name-prefix = "o";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-7 {
 			link-name = "spdif-dit-7";
@@ -830,7 +836,7 @@
 			ignore_suspend;
 			num-channel = <2>;
 			name-prefix = "a";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-8 {
 			link-name = "spdif-dit-8";
@@ -844,7 +850,7 @@
 			ignore_suspend;
 			num-channel = <2>;
 			name-prefix = "b";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-9 {
 			link-name = "spdif-dit-9";
@@ -858,7 +864,7 @@
 			ignore_suspend;
 			num-channel = <2>;
 			name-prefix = "c";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-10 {
 			link-name = "spdif-dit-10";
@@ -872,7 +878,7 @@
 			ignore_suspend;
 			num-channel = <2>;
 			name-prefix = "d";
-			status = "okay";
+			status = "disabled";
 		};
 		nvidia,dai-link-11 {
 			link-name = "dspk1-playback";
@@ -886,7 +892,7 @@
 			num-channel = <2>;
 			ignore_suspend;
 			name-prefix = "d3";
-			status = "okay";
+			status = "disabled";
 		};
 		dspk_1_dai_link: nvidia,dai-link-12 {
 			link-name = "dspk-playback-l";
@@ -914,10 +920,31 @@
 			num-channel = <2>;
 			ignore_suspend;
 			name-prefix = "d2";
-			status = "okay";
-                };
-	};
+			status = "disabled";
+		};
 
+		nvidia,dai-link-2 {
+            		link-name = "ti-capture";
+            		cpu-dai = <&tegra_i2s1>;
+            		codec-dai = <&aic32x4>;
+            		cpu-dai-name = "I2S1";
+            		codec-dai-name = "tlv320aic32x4-hifi";
+         		tx-mask = <0xFF>;
+          		rx-mask = <0xFF>;            
+            		format = "i2s";
+            		bitclock-slave;
+		        frame-slave; 
+            		bitclock-noninversion;
+            		frame-noninversion;
+           		bit-format = "s16_le";
+            		bclk_ratio = <1>;
+            		srate = <44100>;
+            		num-channel = <2>;
+            		ignore_suspend;
+            		name-prefix = "z";
+			status = "okay"; 
+		};
+	};
 	backlight {
 		status = "okay";
 		panel-s-wuxga-8-0-bl {

Here is the mobile driver file changes: tegra_machine_driver_mobile.c
File path : /home/parashuram/Linux_for_Tegra/sources/kernel/nvidia/sound/soc/tegra-alt/machine_drivers//home/parashuram/Linux_for_Tegra/sources/kernel/nvidia/sound/soc/tegra-alt/machine_drivers

diff --git a/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c b/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
index fbca4699d..67b563cac 100644
--- a/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
+++ b/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
@@ -30,6 +30,7 @@
 #include <dt-bindings/sound/tas2552.h>
 #include "rt5659.h"
 #include "sgtl5000.h"
+#include "tlv320aic32x4.h"
 #include "tegra_asoc_machine_alt.h"
 #include "tegra210_xbar_alt.h"
 
@@ -282,10 +283,11 @@ static int tegra_machine_set_params(struct snd_soc_card *card,
 }
 
 static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
-				  unsigned int rate, unsigned int channels,
-				  u64 formats)
+				  int rate, unsigned int channels,
+				  u64 formats, bool is_palyback)
 {
 	struct snd_soc_card *card = runtime->card;
+	//struct snd_soc_card *card = rtd->card;
 	struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
 	struct snd_soc_pcm_stream *dai_params;
 	unsigned int aud_mclk, srate;
@@ -310,7 +312,6 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
 	err = tegra_machine_set_params(card, machine, rate, channels, formats);
 	if (err < 0)
 		return err;
-
 	rtd = snd_soc_get_pcm_runtime(card, "rt565x-playback");
 	if (rtd) {
 		dai_params =
@@ -327,6 +328,20 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
 			return err;
 		}
 	}
+//Added TLV320AIC32X4
+	rtd = snd_soc_get_pcm_runtime(card, "ti-capture");
+        if (rtd) {
+                dai_params =
+                (struct snd_soc_pcm_stream *)rtd->dai_link->params;
+                dai_params->rate_min = srate;
+		 dai_params->channels_min = channels;
+        	dai_params->formats = formats;
+                if (err < 0) {
+                        dev_err(card->dev, "codec_dai clock not parashuram set\n");
+                        return err;
+                }
+        }
+//Ended
 
 	rtd = snd_soc_get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
 	if (rtd) {
@@ -440,10 +455,17 @@ static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_card *card = rtd->card;
 	int err;
+	bool is_playback;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		is_playback = true;
+	else
+		is_playback = false;
 
 	err = tegra_machine_dai_init(rtd, params_rate(params),
 				     params_channels(params),
-				     1ULL << params_format(params));
+				     (1ULL << (params_format(params))),
+			is_playback);
 	if (err < 0) {
 		dev_err(card->dev, "Failed dai init\n");
 		return err;
@@ -593,7 +615,22 @@ static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
 
 	return 0;
 }
+//Added tlv320aic32x4
+static int tegra_machine_aic32x4_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct device *dev = rtd->card->dev;
+   	int err;
+
+	err = snd_soc_dai_set_sysclk(rtd->codec_dai, AIC32X4_FREQ_12000000, 12000000,
+                        SND_SOC_CLOCK_IN);
+    if (err) {
+        dev_err(dev, "failed to set aic32x4 sysclk!\n");
+        return err;
+    }
 
+    return 0;
+}
+//Ended
 static int codec_init(struct tegra_machine *machine)
 {
 	struct snd_soc_dai_link *dai_links = machine->asoc->dai_links;
@@ -611,6 +648,8 @@ static int codec_init(struct tegra_machine *machine)
 			dai_links[i].init = tegra_machine_rt565x_init;
 		else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
 			dai_links[i].init = tegra_machine_fepi_init;
+		 else if (strstr(dai_links[i].name, "ti-capture"))
+                        dai_links[i].init = tegra_machine_aic32x4_init;
 	}
 
 	return 0;

Here is the changes for audio codec tlv320aic32x4.c
File path: /home/parashuram/Linux_for_Tegra/sources/kernel/kernel-4.9/sound/soc/codecs/tlv320aic32x4.c

diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
old mode 100644
new mode 100755
index 28fdfc5ec544..644114743520
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -30,6 +30,7 @@
 #include <linux/pm.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/i2c.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
@@ -159,10 +160,7 @@ static const struct aic32x4_rate_divs aic32x4_divs[] = {
 	/* 48k rate */
 	{AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
 	{AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
-	{AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
-
-	/* 96k rate */
-	{AIC32X4_FREQ_25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
+	{AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}
 };
 
 static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
@@ -183,72 +181,44 @@ static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
 	SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0),
 };
 
-static const char * const resistor_text[] = {
-	"Off", "10 kOhm", "20 kOhm", "40 kOhm",
+static const struct snd_kcontrol_new left_input_mixer_controls[] = {
+	SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0),
+	SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0),
+	SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0),
 };
 
-/* Left mixer pins */
-static SOC_ENUM_SINGLE_DECL(in1l_lpga_p_enum, AIC32X4_LMICPGAPIN, 6, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in1r_lpga_p_enum, AIC32X4_LMICPGAPIN, 0, resistor_text);
-
-static SOC_ENUM_SINGLE_DECL(cml_lpga_n_enum, AIC32X4_LMICPGANIN, 6, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in2r_lpga_n_enum, AIC32X4_LMICPGANIN, 4, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in3r_lpga_n_enum, AIC32X4_LMICPGANIN, 2, resistor_text);
-
-static const struct snd_kcontrol_new in1l_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN1_L L+ Switch", in1l_lpga_p_enum),
-};
-static const struct snd_kcontrol_new in2l_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN2_L L+ Switch", in2l_lpga_p_enum),
-};
-static const struct snd_kcontrol_new in3l_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN3_L L+ Switch", in3l_lpga_p_enum),
-};
-static const struct snd_kcontrol_new in1r_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN1_R L+ Switch", in1r_lpga_p_enum),
-};
-static const struct snd_kcontrol_new cml_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("CM_L L- Switch", cml_lpga_n_enum),
-};
-static const struct snd_kcontrol_new in2r_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN2_R L- Switch", in2r_lpga_n_enum),
-};
-static const struct snd_kcontrol_new in3r_to_lmixer_controls[] = {
-	SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
+static const struct snd_kcontrol_new right_input_mixer_controls[] = {
+	SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0),
+	SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0),
+	SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0),
 };
+ 
 
-/*  Right mixer pins */
-static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in2l_rpga_p_enum, AIC32X4_RMICPGAPIN, 0, resistor_text);
-static SOC_ENUM_SINGLE_DECL(cmr_rpga_n_enum, AIC32X4_RMICPGANIN, 6, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in1l_rpga_n_enum, AIC32X4_RMICPGANIN, 4, resistor_text);
-static SOC_ENUM_SINGLE_DECL(in3l_rpga_n_enum, AIC32X4_RMICPGANIN, 2, resistor_text);
-
-static const struct snd_kcontrol_new in1r_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN1_R R+ Switch", in1r_rpga_p_enum),
-};
-static const struct snd_kcontrol_new in2r_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN2_R R+ Switch", in2r_rpga_p_enum),
-};
-static const struct snd_kcontrol_new in3r_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN3_R R+ Switch", in3r_rpga_p_enum),
-};
-static const struct snd_kcontrol_new in2l_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN2_L R+ Switch", in2l_rpga_p_enum),
-};
-static const struct snd_kcontrol_new cmr_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("CM_R R- Switch", cmr_rpga_n_enum),
-};
-static const struct snd_kcontrol_new in1l_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN1_L R- Switch", in1l_rpga_n_enum),
-};
-static const struct snd_kcontrol_new in3l_to_rmixer_controls[] = {
-	SOC_DAPM_ENUM("IN3_L R- Switch", in3l_rpga_n_enum),
-};
+static int mic_bias_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_component *component =
+snd_soc_dapm_to_component(w->dapm);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               /* Change Mic Bias Registor */
+               snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
+                               AIC32x4_MICBIAS_MASK,
+                               AIC32X4_MICBIAS_LDOIN |
+                               AIC32X4_MICBIAS_2075V);
+               printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
+                               AIC32x4_MICBIAS_MASK, 0);
+               printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
+                               __func__);
+               break;
+       }
+
+       return 0;
+}
 
 static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
 	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", AIC32X4_DACSETUP, 7, 0),
@@ -271,40 +241,17 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
 			   &lor_output_mixer_controls[0],
 			   ARRAY_SIZE(lor_output_mixer_controls)),
 	SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0),
-
-	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0),
-	SND_SOC_DAPM_MUX("IN1_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in1r_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("IN2_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in2r_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("IN3_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in3r_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("IN2_L to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in2l_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("CM_R to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			cmr_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("IN1_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			in1l_to_rmixer_controls),
-	SND_SOC_DAPM_MUX("IN3_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			in3l_to_rmixer_controls),
-
-	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0),
-	SND_SOC_DAPM_MUX("IN1_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in1l_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("IN2_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in2l_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("IN3_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in3l_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("IN1_R to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
-			in1r_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("CM_L to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			cml_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("IN2_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			in2r_to_lmixer_controls),
-	SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-			in3r_to_lmixer_controls),
-
-	SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
+	SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
+			   &left_input_mixer_controls[0],
+			   ARRAY_SIZE(left_input_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
+			   &right_input_mixer_controls[0],
+			   ARRAY_SIZE(right_input_mixer_controls)),
+	SND_SOC_DAPM_ADC(	"Left ADC", "Capture",			AIC32X4_ADCSETUP, 7, 0), // Jon 20.03.2018
+	SND_SOC_DAPM_ADC(	"Right ADC", "Capture",			AIC32X4_ADCSETUP, 6, 0), // Jon 20.03.2018
+	//SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), 
+	SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
+                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 	SND_SOC_DAPM_OUTPUT("HPL"),
 	SND_SOC_DAPM_OUTPUT("HPR"),
@@ -343,77 +290,19 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
 	{"LOR Power", NULL, "LOR Output Mixer"},
 	{"LOR", NULL, "LOR Power"},
 
+	/* Left input */
+	{"Left Input Mixer", "IN1_L P Switch", "IN1_L"},
+	{"Left Input Mixer", "IN2_L P Switch", "IN2_L"},
+	{"Left Input Mixer", "IN3_L P Switch", "IN3_L"},
+
+	{"Left ADC", NULL, "Left Input Mixer"},
+
 	/* Right Input */
-	{"Right ADC", NULL, "IN1_R to Right Mixer Positive Resistor"},
-	{"IN1_R to Right Mixer Positive Resistor", "10 kOhm", "IN1_R"},
-	{"IN1_R to Right Mixer Positive Resistor", "20 kOhm", "IN1_R"},
-	{"IN1_R to Right Mixer Positive Resistor", "40 kOhm", "IN1_R"},
-
-	{"Right ADC", NULL, "IN2_R to Right Mixer Positive Resistor"},
-	{"IN2_R to Right Mixer Positive Resistor", "10 kOhm", "IN2_R"},
-	{"IN2_R to Right Mixer Positive Resistor", "20 kOhm", "IN2_R"},
-	{"IN2_R to Right Mixer Positive Resistor", "40 kOhm", "IN2_R"},
-
-	{"Right ADC", NULL, "IN3_R to Right Mixer Positive Resistor"},
-	{"IN3_R to Right Mixer Positive Resistor", "10 kOhm", "IN3_R"},
-	{"IN3_R to Right Mixer Positive Resistor", "20 kOhm", "IN3_R"},
-	{"IN3_R to Right Mixer Positive Resistor", "40 kOhm", "IN3_R"},
-
-	{"Right ADC", NULL, "IN2_L to Right Mixer Positive Resistor"},
-	{"IN2_L to Right Mixer Positive Resistor", "10 kOhm", "IN2_L"},
-	{"IN2_L to Right Mixer Positive Resistor", "20 kOhm", "IN2_L"},
-	{"IN2_L to Right Mixer Positive Resistor", "40 kOhm", "IN2_L"},
-
-	{"Right ADC", NULL, "CM_R to Right Mixer Negative Resistor"},
-	{"CM_R to Right Mixer Negative Resistor", "10 kOhm", "CM_R"},
-	{"CM_R to Right Mixer Negative Resistor", "20 kOhm", "CM_R"},
-	{"CM_R to Right Mixer Negative Resistor", "40 kOhm", "CM_R"},
-
-	{"Right ADC", NULL, "IN1_L to Right Mixer Negative Resistor"},
-	{"IN1_L to Right Mixer Negative Resistor", "10 kOhm", "IN1_L"},
-	{"IN1_L to Right Mixer Negative Resistor", "20 kOhm", "IN1_L"},
-	{"IN1_L to Right Mixer Negative Resistor", "40 kOhm", "IN1_L"},
-
-	{"Right ADC", NULL, "IN3_L to Right Mixer Negative Resistor"},
-	{"IN3_L to Right Mixer Negative Resistor", "10 kOhm", "IN3_L"},
-	{"IN3_L to Right Mixer Negative Resistor", "20 kOhm", "IN3_L"},
-	{"IN3_L to Right Mixer Negative Resistor", "40 kOhm", "IN3_L"},
-
-	/* Left Input */
-	{"Left ADC", NULL, "IN1_L to Left Mixer Positive Resistor"},
-	{"IN1_L to Left Mixer Positive Resistor", "10 kOhm", "IN1_L"},
-	{"IN1_L to Left Mixer Positive Resistor", "20 kOhm", "IN1_L"},
-	{"IN1_L to Left Mixer Positive Resistor", "40 kOhm", "IN1_L"},
-
-	{"Left ADC", NULL, "IN2_L to Left Mixer Positive Resistor"},
-	{"IN2_L to Left Mixer Positive Resistor", "10 kOhm", "IN2_L"},
-	{"IN2_L to Left Mixer Positive Resistor", "20 kOhm", "IN2_L"},
-	{"IN2_L to Left Mixer Positive Resistor", "40 kOhm", "IN2_L"},
-
-	{"Left ADC", NULL, "IN3_L to Left Mixer Positive Resistor"},
-	{"IN3_L to Left Mixer Positive Resistor", "10 kOhm", "IN3_L"},
-	{"IN3_L to Left Mixer Positive Resistor", "20 kOhm", "IN3_L"},
-	{"IN3_L to Left Mixer Positive Resistor", "40 kOhm", "IN3_L"},
-
-	{"Left ADC", NULL, "IN1_R to Left Mixer Positive Resistor"},
-	{"IN1_R to Left Mixer Positive Resistor", "10 kOhm", "IN1_R"},
-	{"IN1_R to Left Mixer Positive Resistor", "20 kOhm", "IN1_R"},
-	{"IN1_R to Left Mixer Positive Resistor", "40 kOhm", "IN1_R"},
-
-	{"Left ADC", NULL, "CM_L to Left Mixer Negative Resistor"},
-	{"CM_L to Left Mixer Negative Resistor", "10 kOhm", "CM_L"},
-	{"CM_L to Left Mixer Negative Resistor", "20 kOhm", "CM_L"},
-	{"CM_L to Left Mixer Negative Resistor", "40 kOhm", "CM_L"},
-
-	{"Left ADC", NULL, "IN2_R to Left Mixer Negative Resistor"},
-	{"IN2_R to Left Mixer Negative Resistor", "10 kOhm", "IN2_R"},
-	{"IN2_R to Left Mixer Negative Resistor", "20 kOhm", "IN2_R"},
-	{"IN2_R to Left Mixer Negative Resistor", "40 kOhm", "IN2_R"},
-
-	{"Left ADC", NULL, "IN3_R to Left Mixer Negative Resistor"},
-	{"IN3_R to Left Mixer Negative Resistor", "10 kOhm", "IN3_R"},
-	{"IN3_R to Left Mixer Negative Resistor", "20 kOhm", "IN3_R"},
-	{"IN3_R to Left Mixer Negative Resistor", "40 kOhm", "IN3_R"},
+	{"Right Input Mixer", "IN1_R P Switch", "IN1_R"},
+	{"Right Input Mixer", "IN2_R P Switch", "IN2_R"},
+	{"Right Input Mixer", "IN3_R P Switch", "IN3_R"},
+
+	{"Right ADC", NULL, "Right Input Mixer"},
 };
 
 static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
@@ -423,12 +312,14 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
 		.window_start = 0,
 		.window_len = 128,
 		.range_min = 0,
-		.range_max = AIC32X4_RMICPGAVOL,
+		.range_max = 0xFB, //AIC32X4_RMICPGAVOL,
 	},
 };
 
 const struct regmap_config aic32x4_regmap_config = {
-	.max_register = AIC32X4_RMICPGAVOL,
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register =  0xFB, //AIC32X4_RMICPGAVOL,
 	.ranges = aic32x4_regmap_pages,
 	.num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
 };
@@ -464,7 +355,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
 	return -EINVAL;
 }
-
 static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
@@ -536,7 +426,7 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
 		printk(KERN_ERR "aic32x4: sampling rate not supported\n");
 		return i;
 	}
-
+#if 0
 	/* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */
 	snd_soc_write(codec, AIC32X4_CLKMUX, AIC32X4_PLLCLKIN);
 	snd_soc_write(codec, AIC32X4_IFACE3, AIC32X4_DACMOD2BCLK);
@@ -602,7 +492,7 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 	snd_soc_write(codec, AIC32X4_IFACE1, data);
-
+#endif
 	if (params_channels(params) == 1) {
 		data = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
 	} else {

Here are the changes for Pinmux

File Path: /home/parashuram/Linux_for_Tegra/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3489-1000-a00.cfg

    pinmux.0x02431040 = 0x00000400; # dap1_sclk_pj0: i2s1, tristate-disable, input-disable, lpdr-disable
    pinmux.0x02431038 = 0x00000400; # dap1_dout_pj1: i2s1, tristate-disable, input-disable, lpdr-disable
    pinmux.0x02431030 = 0x00000458; # dap1_din_pj2: i2s1, pull-up, tristate-enable, input-enable, lpdr-disable
    pinmux.0x02431028 = 0x00000440; # dap1_fs_pj3: i2s1, tristate-disable, input-enable, lpdr-disable
    pinmux.0x02431020 = 0x00000400; # aud_mclk_pj4: aud, tristate-disable, input-disable, lpdr-disable

To Activate the mixers run the attached script Record.sh (1.7 KB)

Regards,
Parashuram

1 Like

Thank you for sharing! Jon