How to integrate the TLV320AIC32X4 codec to Jetson systems

From RidgeRun Developer Connection
Jump to: navigation, search

Introduction

This wiki page shows the steps necessary to integrate the TLV320AIC32X4 to Jetson systems. This guide is for a Jetson TX2 but it can be adapted to other Jetson platforms. This guide also assumes that the kernel used is L4T 32.4 or above.

Device tree

The following changes need to be done in the top level device tree.

1. Add the codec to the I2C bus it is attached to, in this example the I2C bus address is 3160000:

i2c@3160000 {
	aic32x4_2: 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>;
		reset-gpios = <&tegra_main_gpio TEGRA_MAIN_GPIO(J, 6) GPIO_ACTIVE_HIGH>;
	};
};

2. Set up the clocks:

  • The clock definition in the device tree was added to make TEGRA186_CLK_PLLP_OUT0 (408 MHz) the parent clock of TEGRA186_CLK_AUD_MCLK (12 MHz). The property mclk-fs was deleted to prevent any undesired escalation to TEGRA186_CLK_AUD_MCLK.
sound {
	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-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>,
				 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
	assigned-clock-rates = <0>, <12000000>;

	/delete-property/mclk-fs;
.
.
.
}

3. Add the audio routing:

  • The DAPM widgets need to be manually routed in the device tree. This is done by looking at the machine driver defined widgets and the codec's driver defined widgets and pairing them. This routing depends on the functionality one wants out of the codec.
  • For the TX2, the locations of these are the following inside the sources directory:

- Machine driver: kernel/nvidia/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c

- Driver: kernel/kernel-4.9/sound/soc/codecs/tlv320aic32x4.c

  • Note that the prefix used in this example is z.
sound {
.
.
.
	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";
.
.
.
}

4. Configure one of the dai-link nodes in the device tree with the I2S interface to use:

Important: There should only be one link per I2S interface.

  • All other links not in used are changed to disable.
  • In this example the I2S interface in use is I2S1 and it is attached to dai-link-2.
sound {
.
.
.
	nvidia,dai-link-1 {
		cpu-dai = <&tegra_i2s2>;
		cpu-dai-name = "I2S2";
		status = "disabled";
	};
	nvidia,dai-link-2 {
		link-name = "ti-capture";
		cpu-dai = <&tegra_i2s1>;
		codec-dai = <&aic32x4_2>;
		cpu-dai-name = "I2S1";
		codec-dai-name = "tlv320aic32x4-hifi";
		tx-mask = <0xFF>;
		rx-mask = <0xFF>;
		bitclock-slave;
		frame-slave;
		bitclock-noninversion;
		frame-noninversion;
		bclk_ratio = <1>;
		srate = <44100>;
		name-prefix = "z";
		status = "okay";
	};
	nvidia,dai-link-3 {
		name-prefix = "d3";
		status = "disabled";
	};
	nvidia,dai-link-4 {
		status = "disabled";
	};
	nvidia,dai-link-5 {
		status = "disabled";
	};
	nvidia,dai-link-6 {
		status = "disabled";
	};
	nvidia,dai-link-7 {
		status = "disabled";
	};
	nvidia,dai-link-8 {
		status = "disabled";
	};
	nvidia,dai-link-9 {
		status = "disabled";
	};
	nvidia,dai-link-10 {
		status = "disabled";
	};
	nvidia,dai-link-11 {
		status = "disabled";
	};
	nvidia,dai-link-12 {
		status = "disabled";
	};
	nvidia,dai-link-13 {
		status = "disabled";
	};
};
  • The final sound node is as follows:
sound {
	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-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>,
				 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
	assigned-clock-rates = <0>, <12000000>;

	/delete-property/mclk-fs;

	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";

	nvidia,dai-link-1 {
		cpu-dai = <&tegra_i2s2>;
		cpu-dai-name = "I2S2";
		status = "disabled";
	};
	nvidia,dai-link-2 {
		link-name = "ti-capture";
		cpu-dai = <&tegra_i2s1>;
		codec-dai = <&aic32x4_2>;
		cpu-dai-name = "I2S1";
		codec-dai-name = "tlv320aic32x4-hifi";
		tx-mask = <0xFF>;
		rx-mask = <0xFF>;
		bitclock-slave;
		frame-slave;
		bitclock-noninversion;
		frame-noninversion;
		bclk_ratio = <1>;
		srate = <44100>;
		name-prefix = "z";
		status = "okay";
	};
	nvidia,dai-link-3 {
		name-prefix = "d3";
		status = "disabled";
	};
	nvidia,dai-link-4 {
		status = "disabled";
	};
	nvidia,dai-link-5 {
		status = "disabled";
	};
	nvidia,dai-link-6 {
		status = "disabled";
	};
	nvidia,dai-link-7 {
		status = "disabled";
	};
	nvidia,dai-link-8 {
		status = "disabled";
	};
	nvidia,dai-link-9 {
		status = "disabled";
	};
	nvidia,dai-link-10 {
		status = "disabled";
	};
	nvidia,dai-link-11 {
		status = "disabled";
	};
	nvidia,dai-link-12 {
		status = "disabled";
	};
	nvidia,dai-link-13 {
		status = "disabled";
	};
};

Machine driver

To support a custom audio card, it is needed to update the machine driver. There are three main changes that need to be included:

  • Initialization Function for the Codec
  • Registering the Initialization Function
  • Support for Runtime Configuration of Codec Parameters

- More details at Update the Machine Driver to Support a Custom Audio Card.

The final patch in the machine driver for this example is the following:

diff --git a/kernel/nvidia/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c b/kernel/nvidia/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
index b2e8fa2..37f0a73 100644
--- a/kernel/nvidia/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
+++ b/kernel/nvidia/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"
 
@@ -358,6 +359,16 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
 		}
 	}
 
+	/* Set TLV320AIC32X4 runtime parameters */
+	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;
+    }
+
 	rtd = snd_soc_get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
 	if (rtd) {
 		dai_params =
@@ -583,6 +594,22 @@ static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+/* Add TLV320AIC32X4 initialization function */
+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;
+}
+
 static int codec_init(struct tegra_machine *machine)
 {
 	struct snd_soc_dai_link *dai_links = machine->asoc->dai_links;
@@ -602,6 +629,8 @@ static int codec_init(struct tegra_machine *machine)
 			dai_links[i].init = tegra_machine_fepi_init;
 		else if (strstr(dai_links[i].name, "respeaker-4-mic-array"))
 			dai_links[i].init = tegra_machine_respeaker_init;
+		else if (strstr(dai_links[i].name, "ti-capture"))  /* Register TLV320AIC32X4 initialization function */
+			dai_links[i].init = tegra_machine_aic32x4_init;
 	}
 
 	return 0;
-- 
2.17.1

Driver patch

The following patch is applied to the codec driver:

diff --git a//kernel/kernel-4.9/sound/soc/codecs/tlv320aic32x4.c b//kernel/kernel-4.9/sound/soc/codecs/tlv320aic32x4.c
index c27e347..39ca663 100644
--- a/kernel/kernel-4.9/sound/soc/codecs/tlv320aic32x4.c
+++ b/kernel/kernel-4.9/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>
@@ -131,6 +132,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
                        0, 0x1F, 0),
        SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7,
                        0, 0x0F, 0),
+       SOC_SINGLE("Mic Bias Switch", AIC32X4_MICBIAS, 6, 1, 0),
+       SOC_SINGLE("Mic Bias Voltage", AIC32X4_MICBIAS, 4, 3, 0),
 };
 
 static const struct aic32x4_rate_divs aic32x4_divs[] = {
@@ -159,10 +162,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,71 +183,16 @@ 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",
-};
-
-/* 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 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),
 };
 
-/*  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 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),
 };
 
 static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
@@ -271,40 +216,14 @@ 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),
+       SND_SOC_DAPM_ADC("Right ADC", "Capture", AIC32X4_ADCSETUP, 6, 0),
 
        SND_SOC_DAPM_OUTPUT("HPL"),
        SND_SOC_DAPM_OUTPUT("HPR"),
@@ -345,77 +264,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"},
-       {"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[] = {
@@ -425,12 +286,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,
+       .max_register =  0xFB, //AIC32X4_RMICPGAVOL,
        .ranges = aic32x4_regmap_pages,
        .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
 };
@@ -466,7 +329,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;
@@ -538,7 +400,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);
@@ -604,7 +466,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 {

Pinxmux changes

Important: This will change depending on the platform.

Pinmux changes are needed and they depend on the pins the codec is connected to. In this case, the pins are the DAP1 and AUD_MCLK. These changed need to be done in <top_Jetpack_dir>/Linux_for_Tegra/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg.

Important: In case the platform is not a TX2, the pins would have to be edited in the pinmux spreadsheet NVIDIA provides for each platform. The pins need to be edited appropriately for the I2S and AUD_MCLK functions.

The file was edited in this example is as follows:

diff --git a/Linux_for_Tegra_patches/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg b/Linux_for_Tegra_patches/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg
index c1df730..fa2cb03 100644
--- a/Linux_for_Tegra_patches/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg
+++ b/Linux_for_Tegra_patches/bootloader/t186ref/BCT/tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg
@@ -327,11 +327,11 @@ pinmux.0x02434058 = 0x00000000; # gpio_wan1_pb4: rsvd0, tristate-disable, input-
 pinmux.0x02434050 = 0x00000058; # gpio_wan2_pb5: rsvd0, pull-up, tristate-enable, input-enable, lpdr-disable
 pinmux.0x02434048 = 0x00000000; # gpio_wan3_pb6: rsvd0, tristate-disable, input-disable, lpdr-disable
 pinmux.0x02434040 = 0x00000058; # gpio_wan4_pc0: rsvd0, pull-up, tristate-enable, input-enable, lpdr-disable
-pinmux.0x02431040 = 0x00000055; # dap1_sclk_pj0: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
-pinmux.0x02431038 = 0x00000055; # dap1_dout_pj1: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
-pinmux.0x02431030 = 0x00000055; # dap1_din_pj2: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
-pinmux.0x02431028 = 0x00000055; # dap1_fs_pj3: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
-pinmux.0x02431020 = 0x00000059; # aud_mclk_pj4: rsvd1, pull-up, tristate-enable, input-enable, lpdr-disable
+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
 pinmux.0x02431018 = 0x00000054; # gpio_aud0_pj5: rsvd0, pull-down, tristate-enable, input-enable, lpdr-disable
 pinmux.0x02431010 = 0x00000058; # gpio_aud1_pj6: rsvd0, pull-up, tristate-enable, input-enable, lpdr-disable
 pinmux.0x02432028 = 0x0000405a; # dmic4_clk_pm5: rsvd2, pull-up, tristate-enable, input-enable

Once the board is flashed, run the following to verify the pinmux settings:

sudo grep "aud_mclk\|dap1" /sys/kernel/debug/tegra_pinctrl_reg

- The result should be the following for this example:

Bank: 0 Reg: 0x02431020 Val: 0x00000400 -> aud_mclk_pj4
Bank: 0 Reg: 0x02431028 Val: 0x00000440 -> dap1_fs_pj3
Bank: 0 Reg: 0x02431030 Val: 0x00000458 -> dap1_din_pj2
Bank: 0 Reg: 0x02431038 Val: 0x00000400 -> dap1_dout_pj1
Bank: 0 Reg: 0x02431040 Val: 0x00000400 -> dap1_sclk_pj0

References


RidgeRun Resources

Quick Start Client Engagement Process RidgeRun Blog Homepage
Technical and Sales Support RidgeRun Online Store RidgeRun Videos Contact Us

OOjs UI icon message-progressive.svg Contact Us

Visit our Main Website for the RidgeRun Products and Online Store. RidgeRun Engineering informations are available in RidgeRun Professional Services, RidgeRun Subscription Model and Client Engagement Process wiki pages. Please email to support@ridgerun.com for technical questions and contactus@ridgerun.com for other queries. Contact details for sponsoring the RidgeRun GStreamer projects are available in Sponsor Projects page. Ridgerun-logo.svg
RR Contact Us.png