Audio codec rt5631 on TX2

Dear all,

I wanna use I2S0 to connect with ALC5633 audio codec and I found out that rt5631 codec driver already inside kernel source code. When I tried to config kernel menu it was so hard to see which module should be selected to build as well as how to modify the device tree to load that module.

Any help would be appreciated.

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

Looking at the device-tree documentation for the rt5631 driver [0] it only lists the following devices as compatible …

- compatible : "realtek,alc5631" or "realtek,rt5631"

Typically, the device-tree would state what device variants that it supports, but there is no mention of support for the rt5633 codec. So I just wanted to check that the rt5633 device that you wish to use is supported by this driver. I am not familiar with this realtek codec, have you checked with realtek if this codec is supported by the above driver?

Regards,
Jon

[0] rt5631.txt « sound « bindings « devicetree « Documentation - kernel/git/torvalds/linux.git - Linux kernel source tree

Hi jonathanh,

Thank for your reply. I think there is not much difference between alc5631 and rt5633 codecs. So if I want to use “realtek,alc5631” codec on TX2, could you please let me know how to modify kernel configuration as well as device tree.

Best Regards,
Vu Nguyen

Hi Vu,

Thanks for the confirmation.

So to enable the driver, looking at the kernel source (from our rel28.x release) I see …

$ grep -r rt5631 sound/soc/codecs/Makefile | grep CONFIG
obj-$(CONFIG_SND_SOC_RT5631)    += snd-soc-rt5631.o

So the easiest way to enable this would be to add to the tegra18_defconfig …

diff --git a/arch/arm64/configs/tegra18_defconfig b/arch/arm64/configs/tegra18_defconfig
index 0b286e78c61f..1b0d3a8dfdca 100644
--- a/arch/arm64/configs/tegra18_defconfig
+++ b/arch/arm64/configs/tegra18_defconfig
@@ -474,6 +474,7 @@ CONFIG_SND_SOC_TEGRA_T186REF_ALT=y
 CONFIG_SND_SOC_TEGRA_T186REF_MOBILE_ALT=y
 CONFIG_SND_SOC_TEGRA_T186REF_P4573_ALT=y
 CONFIG_SND_SOC_TEGRA_T186REF_M3420_ALT=y
+CONFIG_SND_SOC_RT5631=y
 CONFIG_HIDRAW=y
 CONFIG_UHID=y
 CONFIG_HID_A4TECH=y

Once the driver is built, then you need to add this to device-tree. Assuming that it connects to I2C, you need to add the codec under the I2C device that you are connecting it to. For example, we use the rt5658 codec and it is connected to the I2C bus on the Jetson J21 header …


i2c@c240000 {


...
         i2cmux@70 {
             ...
             i2c@3 {
                 reg = <3>;
                 i2c-mux,deselect-on-exit;
                 #address-cells = <1>;
                 #size-cells = <0>;
                 e2614_rt5658_i2c3: rt5659.12-001a@1a {
                     compatible = "realtek,rt5658";
                     reg = <0x1a>;
                     status = "disabled";

                     /* gpio for jack detection */
                     gpios = <&tegra_main_gpio TEGRA_MAIN_GPIO(J , 5) GPIO_ACTIVE_HIGH>;
 
                     /* refer include/sound/rt5659.h for the values to be used */
                     realtek,jd-src = <1>; /* RT5659_JD3 */
                     realtek,dmic1-data-pin = <2>; /* RT5659_DMIC1_DATA_GPIO5 */
                 };
             };
         };

The above is from the file hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-super-module-e2614-p2597-1000-a00.dtsi and note that we have an i2c-mux between the i2c-controller and the codec. You probably will not have this and so you will not have the ‘i2cmux@70’ and ‘i2c@3’ nodes above and the codec node will be directly under the i2c-controller node.

So you need to figure out (using the rt5631 binding documenation) how to add the DT node for the rt5633 device under the i2c controller.

Once this is done and you have verified that the codec is detected and initialised correctly on boot, then you need to modify the ‘sound’ node in the DT file to add support for the codec as a playback/capture device.

diff --git a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
index 46de427f71f8..23a0616c8003 100644
--- a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
+++ b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
@@ -839,9 +839,9 @@
                rt565x_dai_link: nvidia,dai-link-1 {
                        link-name = "rt565x-playback";
                        cpu-dai = <&tegra_i2s1>;
-                       codec-dai = <&spdif_dit0>;
+                       codec-dai = <&rt5631_codec>;
                        cpu-dai-name = "I2S1";
-                       codec-dai-name = "dit-hifi";
+                       codec-dai-name = "rt5631-hifi";
                        format = "i2s";
                        bitclock-slave;
                        frame-slave;

Note that the ‘&rt5631_codec’ needs to match whatever phandle name you use when you add the rt5631 node, for example …

i2c@... {
        rt5631_codec: rt5631@... {
            ...
        };
    };

Finally, once that is done, we need to update the dapm routing for the ‘x’ prefixed codec in the following …

nvidia,audio-routing =
        "x Headphone",          "x OUT",
        "x IN",                 "x Mic",
        ...

By the way, I assume that you are connecting the audio mclk from Tegra (on J21 header) to the codec and Tegra is the bit clock and frame clock master?

Regards,
Jon

Hi jonathanh,

Really good instruction. By printing out some debug message I could confirm that “rt5631” module has been probed but I have faced reboot issue as below debug log

[    7.734257] [VuNguyen] : rt5631_probe 1579 !!!!!!!!!!!!!!!
[    7.734917] [VuNguyen] : rt5631_probe 1585 !!!!!!!!!!!!!!!
[    7.765206] mmc1: queuing unknown CIS tuple 0x80 (5 bytes)
[    7.817405] [VuNguyen] : rt5631_probe 1615 !!!!!!!!!!!!!!!
[    7.822311] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF1 <-> ADMAIF1 mapping ok
[    7.822401] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF2 <-> ADMAIF2 mapping ok
[    7.822473] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF3 <-> ADMAIF3 mapping ok
[    7.822559] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF4 <-> ADMAIF4 mapping ok
[    7.822641] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF5 <-> ADMAIF5 mapping ok
[    7.822716] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF6 <-> ADMAIF6 mapping ok
[    7.822802] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF7 <-> ADMAIF7 mapping ok
[    7.822867] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF8 <-> ADMAIF8 mapping ok
[    7.822934] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF9 <-> ADMAIF9 mapping ok
[    7.823007] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF10 <-> ADMAIF10 mapping ok
[    7.823090] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF11 <-> ADMAIF11 mapping ok
[    7.823157] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF12 <-> ADMAIF12 mapping ok
[    7.823226] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF13 <-> ADMAIF13 mapping ok
[    7.823292] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF14 <-> ADMAIF14 mapping ok
[    7.823357] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF15 <-> ADMAIF15 mapping ok
[    7.823448] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF16 <-> ADMAIF16 mapping ok
[    7.823517] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF17 <-> ADMAIF17 mapping ok
[    7.823585] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF18 <-> ADMAIF18 mapping ok
[    7.823654] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF19 <-> ADMAIF19 mapping ok
[    7.823723] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF20 <-> ADMAIF20 mapping ok
[    7.826860] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE1 <-> ADSP PCM1 mapping ok
[    7.826935] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE2 <-> ADSP PCM2 mapping ok
[    7.826958] compress asoc: ADSP-FE3 <-> ADSP COMPR1 mapping ok
[    7.826980] compress asoc: ADSP-FE4 <-> ADSP COMPR2 mapping ok
[    7.837793] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for x OUT
[    7.837796] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x OUT -> direct -> x Headphone
[    7.837829] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no sink widget found for x IN
[    7.837832] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x Mic -> direct -> x IN
[    7.854757] input: tegra-snd-t186ref-mobile-rt565x Headphone Jack as /devices/sound/sound/card1/input2
[    7.855144] tegra-snd-t186ref-mobile-rt565x sound: codec-dai "rt5631-hifi" registered
[    7.855151] ------------[ cut here ]------------
[    7.855152] WARNING: at ffffffc0000bb518 [verbose debug info unavailable]
[    7.855155] Modules linked in:
[    7.855155] 
[    7.855159] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 4.4.38 #5
[    7.855160] Hardware name: quill (DT)
[    7.855162] task: ffffffc1ece70000 ti: ffffffc1ece78000 task.ti: ffffffc1ece78000
[    7.855169] PC is at __queue_delayed_work+0x140/0x154
[    7.855171] LR is at queue_delayed_work_on+0x6c/0x74
[    7.855173] pc : [<ffffffc0000bb518>] lr : [<ffffffc0000bb598>] pstate: 200000c5
[    7.855174] sp : ffffffc1ece7bb00
[    7.855176] x29: ffffffc1ece7bb00 x28: ffffffc1e61ca818 
[    7.855179] x27: 0000000000000014 x26: ffffffc001368c40 
[    7.855181] x25: 0000000000000000 x24: ffffffc070387418 
[    7.855182] x23: ffffffc1e61e4018 x22: ffffffc001368868 
[    7.855184] x21: ffffffc1ecde4e00 x20: 0000000000000040

I still didn’t understand how to modify this part

Yes, correct.

Thanks and Best Regards,
Vu Nguyen

Hi jonathanh,

I kept device tree as original to test dummy codec.

rt565x_dai_link: nvidia,dai-link-1 {
			link-name = "rt565x-playback";
			cpu-dai = <&tegra_i2s1>;
			codec-dai = <&spdif_dit0>;
			/*codec-dai = <&rt5631_codec>;*/
			cpu-dai-name = "I2S1";
			codec-dai-name = "dit-hifi";
			/*codec-dai-name = "rt5631-hifi";*/
			format = "i2s";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			bclk_ratio = <0>;
			srate = <48000>;
			num-channel = <2>;
			ignore_suspend;
			name-prefix = "x";
			status = "okay";
		};

Played audio file with aplay utility (aplay -Dhw:1,0 audio.wav) then probed data on I2S0_SDOUT and I2S0_SDIN pins I could see any data output.

Thanks
Vu Nguyen

Hi Vu,

Can you include or attach the full crash log to see exactly where it is crashing?

Don’t worry about this bit for now we will sort that out later.

Regards,
Jon

Hi Vu,

Do you mean could NOT see any data or could see data?

If you cannot see any data can you …

$ alsactl store -f alsa-settings.txt

… and attach the file?

Are you using rel28.1 or rel28.2?

Regards,
Jon

Hi jonathanh,

Sorry my mistake, I could see data when running with dummy codec.

I found out that below function cause reboot issue

/* setup for jack detection only in non-dummy case */
rt5659_set_jack_detect(codec, &tegra_t186ref_hp_jack);

If I comment that function, system could boot properly and full console log would be

[    9.990101] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF1 <-> ADMAIF1 mapping ok
[    9.990173] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF2 <-> ADMAIF2 mapping ok
[    9.990241] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF3 <-> ADMAIF3 mapping ok
[    9.990309] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF4 <-> ADMAIF4 mapping ok
[    9.990379] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF5 <-> ADMAIF5 mapping ok
[    9.990451] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF6 <-> ADMAIF6 mapping ok
[    9.990525] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF7 <-> ADMAIF7 mapping ok
[    9.990590] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF8 <-> ADMAIF8 mapping ok
[    9.990660] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF9 <-> ADMAIF9 mapping ok
[    9.990728] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF10 <-> ADMAIF10 mapping ok
[    9.990797] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF11 <-> ADMAIF11 mapping ok
[    9.990866] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF12 <-> ADMAIF12 mapping ok
[    9.990933] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF13 <-> ADMAIF13 mapping ok
[    9.991005] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF14 <-> ADMAIF14 mapping ok
[    9.991073] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF15 <-> ADMAIF15 mapping ok
[    9.991142] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF16 <-> ADMAIF16 mapping ok
[    9.991215] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF17 <-> ADMAIF17 mapping ok
[    9.991284] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF18 <-> ADMAIF18 mapping ok
[    9.991353] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF19 <-> ADMAIF19 mapping ok
[    9.991422] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF20 <-> ADMAIF20 mapping ok
[    9.994461] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE1 <-> ADSP PCM1 mapping ok
[    9.994536] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE2 <-> ADSP PCM2 mapping ok
[    9.994560] compress asoc: ADSP-FE3 <-> ADSP COMPR1 mapping ok
[    9.994581] compress asoc: ADSP-FE4 <-> ADSP COMPR2 mapping ok
[   10.004149] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for x OUT
[   10.004152] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x OUT -> direct -> x Headphone
[   10.004189] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no sink widget found for x IN
[   10.004191] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x Mic -> direct -> x IN
[   10.021977] input: tegra-snd-t186ref-mobile-rt565x Headphone Jack as /devices/sound/sound/card1/input2
[   10.022372] [VuNguyen] : tegra_t186ref_driver_probe 1114 !!!!!!!!!!!!!!!
[   10.022378] tegra-snd-t186ref-mobile-rt565x sound: codec-dai "rt5631-hifi" registered

..............

[   24.551060] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.551062] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.551066] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.551166] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.551167] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.551170] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.551202] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.551204] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.551205] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.551232] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.551234] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.551235] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.551258] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.551259] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.551261] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.553896] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.553899] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.553902] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.553945] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.553947] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.553948] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.553979] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.553981] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.553982] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.554010] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.554011] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.554012] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.554036] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.554037] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.554038] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   24.556811] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   24.556813] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   24.556815] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

I strongly recommend that you upgrade to the rel28.2 release because I have fixed [0] the crash that you observed in this release, along with other issues.

So here is what I think you should do …

  1. In the DT file change the link name to be something different so we do not have any conflicts with the ‘rt565x-playback’ link.
nvidia,dai-link-1 {
                link-name = "rt5631-playback";
                ...
  1. In the following to tegra_t186ref_mobile_rt565x.c …
diff --git a/sound/soc/tegra-alt/tegra_t186ref_mobile_rt565x.c b/sound/soc/tegra-alt/tegra_t186ref_mobile_rt565x.c
index c5466cb7b037..422ccc703f48 100644
--- a/sound/soc/tegra-alt/tegra_t186ref_mobile_rt565x.c
+++ b/sound/soc/tegra-alt/tegra_t186ref_mobile_rt565x.c
@@ -318,6 +318,30 @@ static int tegra_t186ref_dai_init(struct snd_soc_pcm_runtime *rtd,
                }
        }
 
+       idx = tegra_machine_get_codec_dai_link_idx_t18x("rt5631-playback");
+       /* check if idx has valid number */
+       if (idx != -EINVAL) {
+               dai_params =
+               (struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
+
+               dai_params->rate_min = clk_rate;
+               dai_params->formats = formats;
+
+               err = snd_soc_dai_set_pll(card->rtd[idx].codec_dai, 0, 0, 0, 0);
+               if (err < 0) {
+                       dev_err(card->dev, "failed to configure pll!\n");
+                       return err;
+               }
+
+               err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai, 0,
+                                            clk_out_rate, SND_SOC_CLOCK_IN);
+               if (err < 0) {
+                       dev_err(card->dev, "failed to set codec clock to %d\n",
+                               clk_out_rate);
+                       return err;
+               }
+       }
+
        /* set clk rate for i2s3 dai link*/
        idx = tegra_machine_get_codec_dai_link_idx_t18x("spdif-dit-2");
        if (idx != -EINVAL) {
@@ -1115,6 +1139,9 @@ static void dai_link_setup(struct platform_device *pdev)
                                "rt565x-playback"))
                                tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
                        else if (strstr(tegra_t186ref_codec_links[i].name,
+                               "rt5631-playback"))
+                               tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
+                       else if (strstr(tegra_t186ref_codec_links[i].name,
                                "dspk-playback-r"))
                                tegra_t186ref_codec_links[i].init = tegra_t186ref_dspk_init;
                        else if (strstr(tegra_t186ref_codec_links[i].name,

Can you check if the codec is registered?

$ find /sys/devices/*.i2c/ -name name -exec cat {} ; | grep 5631

Regards,
Jon

[0] nv-tegra.nvidia Code Review - linux-4.4.git/commit

Hi jonathanh,

Please refer my current driver as well as dtb

/* check if idx has valid number */
	if (idx == -EINVAL)
		dev_warn(&pdev->dev, "codec link not defined - codec not part of sound card");
	else {
		codec = card->rtd[idx].codec;
		codec_dai_name = card->rtd[idx].dai_link->codec_dai_name;

		dev_info(&pdev->dev,
			"codec-dai \"%s\" registered\n", codec_dai_name);
		if (!strcmp("dit-hifi", codec_dai_name)) {
			dev_info(&pdev->dev, "This is a dummy codec\n");
			machine->is_codec_dummy = 1;
		}
		printk ("[VuNguyen] : %s %d !!!!!!!!!!!!!!!\r\n", __func__, __LINE__);
		if (!machine->is_codec_dummy) {
			/* setup for jack detection only in non-dummy case */
			rt5659_set_jack_detect(codec, &tegra_t186ref_hp_jack);
		}
	}
	printk ("[VuNguyen] : %s %d !!!!!!!!!!!!!!!\r\n", __func__, __LINE__);
rt565x_dai_link: nvidia,dai-link-1 {
			link-name = "rt565x-playback";
			cpu-dai = <&tegra_i2s1>;
			/*codec-dai = <&spdif_dit0>;*/
			codec-dai = <&rt5631_codec>;
			cpu-dai-name = "I2S1";
			/*codec-dai-name = "dit-hifi";*/
			codec-dai-name = "rt5631-hifi";
			format = "i2s";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			bclk_ratio = <0>;
			srate = <48000>;
			num-channel = <2>;
			ignore_suspend;
			name-prefix = "x";
			status = "okay";
		};

I have running on 28.2 release but still faced crash issue.

Yes, I could see rt5631 has been registered.

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

Per my comment in #10 above, I recommend that you change the ‘link-name’ as I have shown.

Regards,
Jon

Hi Jonathanh
According to your recommendation

DT

rt565x_dai_link: nvidia,dai-link-1 {
			/*link-name = "rt565x-playback";*/
			link-name = "rt5631-playback";
			cpu-dai = <&tegra_i2s1>;
			/*codec-dai = <&spdif_dit0>;*/
			codec-dai = <&rt5631_codec>;
			cpu-dai-name = "I2S1";
			/*codec-dai-name = "dit-hifi";*/
			codec-dai-name = "rt5631-hifi";
			format = "i2s";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			bclk_ratio = <0>;
			srate = <48000>;
			num-channel = <2>;
			ignore_suspend;
			name-prefix = "x";
			status = "okay";
		};

tegra_t186ref_mobile_rt565x.c

/*
 * tegra_t186ref_mobile_rt565x.c - Tegra t186ref Machine driver
 *
 * Copyright (c) 2015-2017 NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <soc/tegra/pmc.h>
#ifdef CONFIG_SWITCH
#include <linux/switch.h>
#endif
#include <linux/pm_runtime.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
#include <linux/platform_data/tegra_asoc_pdata.h>
#else
#include <mach/tegra_asoc_pdata.h>
#endif

#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "../codecs/rt5659.h"

#include "tegra_asoc_utils_alt.h"
#include "tegra_asoc_machine_alt.h"
#include "tegra_asoc_machine_alt_t18x.h"
#include "tegra210_xbar_alt.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
#include <dt-bindings/sound/tas2552.h>
#endif

#define DRV_NAME "tegra-snd-t186ref-mobile-rt565x"

#define GPIO_SPKR_EN    BIT(0)
#define GPIO_HP_MUTE    BIT(1)
#define GPIO_INT_MIC_EN BIT(2)
#define GPIO_EXT_MIC_EN BIT(3)
#define GPIO_HP_DET     BIT(4)

#define PARAMS(sformat, channels)			\
	{						\
		.formats = sformat,			\
		.rate_min = 48000,			\
		.rate_max = 48000,			\
		.channels_min = channels,		\
		.channels_max = channels,		\
	}

struct tegra_t186ref {
	struct tegra_asoc_platform_data *pdata;
	struct tegra_asoc_audio_clock_info audio_clock;
	unsigned int num_codec_links;
	int gpio_requested;
#ifdef CONFIG_SWITCH
	int jack_status;
#endif
	struct regulator *digital_reg;
	struct regulator *spk_reg;
	struct regulator *dmic_reg;
	struct snd_soc_card *pcard;
	int rate_via_kcontrol;
	int is_codec_dummy;
	int fmt_via_kcontrol;
};

static const int tegra_t186ref_srate_values[] = {
	0,
	8000,
	16000,
	44100,
	48000,
	11025,
	22050,
	24000,
	32000,
	88200,
	96000,
	176400,
	192000,
};

static struct snd_soc_jack tegra_t186ref_hp_jack;

#ifdef CONFIG_SWITCH
static struct switch_dev tegra_t186ref_headset_switch = {
        .name = "h2w",
};

static int tegra_t186ref_jack_notifier(struct notifier_block *self,
			      unsigned long action, void *dev)
{
	struct snd_soc_jack *jack = dev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
	struct snd_soc_codec *codec = jack->codec;
	struct snd_soc_card *card = codec->component.card;
#else
	struct snd_soc_card *card = jack->card;
#endif
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	enum headset_state state = BIT_NO_HEADSET;
	int idx = 0;
	static bool button_pressed = false;

	if (machine->is_codec_dummy)
		return NOTIFY_OK;

	idx = tegra_machine_get_codec_dai_link_idx_t18x("rt565x-playback");
	/* check if idx has valid number */
	if (idx == -EINVAL)
		return idx;

	dev_dbg(card->dev, "jack status = %d", jack->status);
	if (jack->status & (SND_JACK_BTN_0 | SND_JACK_BTN_1 |
		SND_JACK_BTN_2 | SND_JACK_BTN_3)) {
		button_pressed = true;
		return NOTIFY_OK;
	} else if ((jack->status & SND_JACK_HEADSET) && button_pressed) {
		button_pressed = false;
		return NOTIFY_OK;
	}

	switch (jack->status) {
	case SND_JACK_HEADPHONE:
		state = BIT_HEADSET_NO_MIC;
		break;
	case SND_JACK_HEADSET:
		state = BIT_HEADSET;
		break;
	case SND_JACK_MICROPHONE:
		/* mic: would not report */
	default:
		state = BIT_NO_HEADSET;
	}

	dev_dbg(card->dev, "switch state to %x\n", state);
	switch_set_state(&tegra_t186ref_headset_switch, state);
	return NOTIFY_OK;
}

static struct notifier_block tegra_t186ref_jack_detect_nb = {
	.notifier_call = tegra_t186ref_jack_notifier,
};
#else
static struct snd_soc_jack_pin tegra_t186ref_hp_jack_pins[] = {
	{
		.pin = "Headphone Jack",
		.mask = SND_JACK_HEADPHONE,
	},
};
#endif

static struct snd_soc_pcm_stream tegra_t186ref_asrc_link_params[] = {
	PARAMS(SNDRV_PCM_FMTBIT_S32_LE, 8),
	PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
	PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
	PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
	PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
	PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
};

static int tegra_t186ref_set_params(struct snd_soc_card *card,
				    struct tegra_t186ref *machine,
				    int rate,
				    int channels,
				    u64 formats)
{
	unsigned int tx_mask = (1 << channels) - 1;
	unsigned int rx_mask = (1 << channels) - 1;
	int idx, err = 0;
	u64 format_k;
	int num_of_dai_links = TEGRA186_XBAR_DAI_LINKS +
				machine->num_codec_links;

	format_k = (machine->fmt_via_kcontrol == 2) ?
				(1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;

	/* update dai link hw_params */
	for (idx = 0; idx < num_of_dai_links; idx++) {
		if (card->rtd[idx].dai_link->params) {
			struct snd_soc_pcm_stream *dai_params;

			dai_params =
			  (struct snd_soc_pcm_stream *)
			  card->rtd[idx].dai_link->params;

			dai_params->rate_min = rate;
			dai_params->channels_min = channels;
			dai_params->formats = format_k;

			if (idx >= TEGRA186_XBAR_DAI_LINKS) {
				unsigned int fmt;
				int bclk_ratio;

				err = 0;
				dai_params->formats = formats;

				fmt = card->rtd[idx].dai_link->dai_fmt;
				bclk_ratio =
					tegra_machine_get_bclk_ratio_t18x(
						&card->rtd[idx]);

				if (bclk_ratio >= 0) {
					err = snd_soc_dai_set_bclk_ratio(
							card->rtd[idx].cpu_dai,
							bclk_ratio);
				}

				if (err < 0) {
					dev_err(card->dev,
					"Failed to set cpu dai bclk ratio for %s\n",
					card->rtd[idx].dai_link->name);
				}

				/* set TDM slot mask */
				if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
							SND_SOC_DAIFMT_DSP_A) {
					err = snd_soc_dai_set_tdm_slot(
							card->rtd[idx].cpu_dai,
							tx_mask, rx_mask, 0, 0);
					if (err < 0) {
						dev_err(card->dev,
						"%s cpu DAI slot mask not set\n",
						card->rtd[idx].cpu_dai->name);
					}
				}
			}
		}
	}
	return 0;
}

static int tegra_t186ref_dai_init(struct snd_soc_pcm_runtime *rtd,
					int rate,
					int channels,
					u64 formats,
					bool is_playback)
{
	struct snd_soc_card *card = rtd->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct snd_soc_pcm_stream *dai_params;
	unsigned int idx, clk_out_rate;
	int err, codec_rate, clk_rate;

	codec_rate = tegra_t186ref_srate_values[machine->rate_via_kcontrol];
	clk_rate = (machine->rate_via_kcontrol) ? codec_rate : rate;

	err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, clk_rate,
						0, 0);
	if (err < 0) {
		dev_err(card->dev, "Can't configure clocks\n");
		return err;
	}

	clk_out_rate = machine->audio_clock.clk_out_rate;

	pr_debug("pll_a_out0 = %d Hz, aud_mclk = %d Hz, codec rate = %d Hz\n",
		machine->audio_clock.set_mclk, clk_out_rate, clk_rate);

	tegra_t186ref_set_params(card, machine, rate, channels, formats);

	idx = tegra_machine_get_codec_dai_link_idx_t18x("rt565x-playback");
	/* check if idx has valid number */
	if (idx != -EINVAL) {
		dai_params =
		(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		dai_params->rate_min = clk_rate;
		dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
                                (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;

		if (!machine->is_codec_dummy) {
			err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
			RT5659_SCLK_S_MCLK, clk_out_rate, SND_SOC_CLOCK_IN);
			if (err < 0) {
				dev_err(card->dev, "codec_dai clock not set\n");
				return err;
			}
		}
	}
	
	idx = tegra_machine_get_codec_dai_link_idx_t18x("rt5631-playback");
	/* check if idx has valid number */
	if (idx != -EINVAL) {
		dai_params = (struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		dai_params->rate_min = clk_rate;
		dai_params->formats = formats;

		err = snd_soc_dai_set_pll(card->rtd[idx].codec_dai, 0, 0, 0, 0);
		if (err < 0) {
			dev_err(card->dev, "failed to configure pll!\n");
			return err;
		}
	
		err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai, 0,
									clk_out_rate, SND_SOC_CLOCK_IN);
		if (err < 0) {
			dev_err(card->dev, "failed to set codec clock to %d\n",
					clk_out_rate);
				return err;
		}
	}

	/* set clk rate for i2s3 dai link*/
	idx = tegra_machine_get_codec_dai_link_idx_t18x("spdif-dit-2");
	if (idx != -EINVAL) {
		dai_params =
		(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		dai_params->rate_min = clk_rate;
	}

	idx = tegra_machine_get_codec_dai_link_idx_t18x("dspk-playback-r");
	if (idx != -EINVAL) {
		dai_params =
		(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		if (!machine->is_codec_dummy) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
			err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
				0, clk_out_rate, SND_SOC_CLOCK_IN);
#else
			err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
				TAS2552_PDM_CLK_IVCLKIN, clk_out_rate,
				SND_SOC_CLOCK_IN);
#endif
			if (err < 0) {
				dev_err(card->dev, "codec_dai clock not set\n");
				return err;
			}
		}
	}

	idx = tegra_machine_get_codec_dai_link_idx_t18x("dspk-playback-l");
	if (idx != -EINVAL) {
		dai_params =
		(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		if (!machine->is_codec_dummy) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
			err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
				0, clk_out_rate, SND_SOC_CLOCK_IN);
#else
			err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
				TAS2552_PDM_CLK_IVCLKIN, clk_out_rate,
				SND_SOC_CLOCK_IN);
#endif
			if (err < 0) {
				dev_err(card->dev, "codec_dai clock not set\n");
				return err;
			}
		}
	}

	idx = tegra_machine_get_codec_dai_link_idx_t18x("spdif-playback");
	if ((idx != -EINVAL) && (clk_rate >= 32000)) {
		dai_params =
		(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;

		if (is_playback) {
			err = snd_soc_dai_set_sysclk(card->rtd[idx].cpu_dai, 0,
						clk_rate, SND_SOC_CLOCK_OUT);
			if (err < 0) {
				dev_err(card->dev, "cpu_dai out clock not set\n");
				return err;
			}
		} else {
			err = snd_soc_dai_set_sysclk(card->rtd[idx].cpu_dai, 0,
						clk_rate, SND_SOC_CLOCK_IN);
			if (err < 0) {
				dev_err(card->dev, "cpu_dai in clock not set\n");
				return err;
			}
		}
	}

	return 0;
}

static int tegra_t186ref_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	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_t186ref_dai_init(rtd, params_rate(params),
			params_channels(params),
			(1ULL << (params_format(params))),
			is_playback);
	if (err < 0) {
		dev_err(card->dev, "Failed dai init\n");
		return err;
	}

	return 0;
}

static int tegra_t186ref_compr_startup(struct snd_compr_stream *cstream)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);

	return 0;
}

static void tegra_t186ref_compr_shutdown(struct snd_compr_stream *cstream)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);

	return;
}
static int tegra_t186ref_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(rtd->card);

	tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);

	return 0;
}

static void tegra_t186ref_shutdown(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(rtd->card);

	tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);

	return;
}

static int tegra_t186ref_dspk_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_dapm_context *dapm = &card->dapm;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	int err;

	err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
							"pll_a_out0");
	if (err < 0)
		dev_err(card->dev, "Failed to set extern clk parent\n");

	snd_soc_dapm_sync(dapm);
	return err;
}

static int tegra_t186ref_compr_set_params(struct snd_compr_stream *cstream)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_codec codec_params;
	int err;
	bool is_playback;

	if (platform->driver->compr_ops &&
		platform->driver->compr_ops->get_params) {
		err = platform->driver->compr_ops->get_params(cstream,
			&codec_params);
		if (err < 0) {
			dev_err(card->dev, "Failed to get compr params\n");
			return err;
		}
	} else {
		dev_err(card->dev, "compr ops not set\n");
		return -EINVAL;
	}

	if (cstream->direction == SND_COMPRESS_PLAYBACK)
		is_playback = true;
	else
		is_playback = false;

	err = tegra_t186ref_dai_init(rtd, codec_params.sample_rate,
			codec_params.ch_out, SNDRV_PCM_FMTBIT_S16_LE,
			is_playback);
	if (err < 0) {
		dev_err(card->dev, "Failed dai init\n");
		return err;
	}

	return 0;
}

static int tegra_t186ref_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_card *card = rtd->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	int err;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_codec *codec = codec_dai->codec;
#endif

	err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
							"pll_a_out0");
	if (err < 0) {
		dev_err(card->dev, "Failed to set extern clk parent\n");
		return err;
	}

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
		&tegra_t186ref_hp_jack);

#else
	err = snd_soc_card_jack_new(card, "Headphone Jack", SND_JACK_HEADPHONE,
				    &tegra_t186ref_hp_jack, NULL, 0);
	if (err) {
		dev_err(card->dev, "Headset Jack creation failed %d\n", err);
		return err;
	}
#endif

#ifndef CONFIG_SWITCH
	err = snd_soc_jack_add_pins(&tegra_t186ref_hp_jack,
				    ARRAY_SIZE(tegra_t186ref_hp_jack_pins),
				    tegra_t186ref_hp_jack_pins);
	if (err) {
		dev_err(card->dev, "snd_soc_jack_add_pins failed %d\n", err);
		return err;
	}
#else
	snd_soc_jack_notifier_register(&tegra_t186ref_hp_jack,
		&tegra_t186ref_jack_detect_nb);
#endif

	/* single button supporting play/pause */
	snd_jack_set_key(tegra_t186ref_hp_jack.jack,
		SND_JACK_BTN_0, KEY_MEDIA);

	/* multiple buttons supporting play/pause and volume up/down */
	snd_jack_set_key(tegra_t186ref_hp_jack.jack,
		SND_JACK_BTN_1, KEY_MEDIA);
	snd_jack_set_key(tegra_t186ref_hp_jack.jack,
		SND_JACK_BTN_2, KEY_VOLUMEUP);
	snd_jack_set_key(tegra_t186ref_hp_jack.jack,
		SND_JACK_BTN_3, KEY_VOLUMEDOWN);

	snd_soc_dapm_sync(&card->dapm);

	return 0;
}

static int tegra_t186ref_sfc_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	unsigned int in_srate, out_srate;
	int err;

	in_srate = 48000;
	out_srate = 8000;

	err = snd_soc_dai_set_sysclk(codec_dai, 0, out_srate,
					SND_SOC_CLOCK_OUT);
	err = snd_soc_dai_set_sysclk(codec_dai, 0, in_srate,
					SND_SOC_CLOCK_IN);

	return err;
}

static int tegra_rt565x_event_int_spk(struct snd_soc_dapm_widget *w,
					struct snd_kcontrol *k, int event)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_soc_card *card = dapm->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
	int err;

	if (machine->spk_reg) {
		if (SND_SOC_DAPM_EVENT_ON(event))
			err = regulator_enable(machine->spk_reg);
		else
			regulator_disable(machine->spk_reg);
	}

	if (!(machine->gpio_requested & GPIO_SPKR_EN))
		return 0;

	gpio_set_value_cansleep(pdata->gpio_spkr_en,
				!!SND_SOC_DAPM_EVENT_ON(event));

	return 0;
}

static int tegra_rt565x_event_hp(struct snd_soc_dapm_widget *w,
					struct snd_kcontrol *k, int event)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_soc_card *card = dapm->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;

	if (!(machine->gpio_requested & GPIO_HP_MUTE))
		return 0;

	gpio_set_value_cansleep(pdata->gpio_hp_mute,
				!SND_SOC_DAPM_EVENT_ON(event));
	return 0;
}

static int tegra_rt565x_event_int_mic(struct snd_soc_dapm_widget *w,
					struct snd_kcontrol *k, int event)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_soc_card *card = dapm->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
	int ret = 0;

	if (machine->dmic_reg) {
		if (SND_SOC_DAPM_EVENT_ON(event))
			ret = regulator_enable(machine->dmic_reg);
		else
			regulator_disable(machine->dmic_reg);
	}

	if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
		return 0;

	gpio_set_value_cansleep(pdata->gpio_int_mic_en,
				!!SND_SOC_DAPM_EVENT_ON(event));

	return 0;
}

static int tegra_rt565x_event_ext_mic(struct snd_soc_dapm_widget *w,
					struct snd_kcontrol *k, int event)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_soc_card *card = dapm->card;
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;

	if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
		return 0;

	gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
				!SND_SOC_DAPM_EVENT_ON(event));

	return 0;
}

static struct snd_soc_ops tegra_t186ref_ops = {
	.hw_params = tegra_t186ref_hw_params,
	.startup = tegra_t186ref_startup,
	.shutdown = tegra_t186ref_shutdown,
};

static struct snd_soc_compr_ops tegra_t186ref_compr_ops = {
	.set_params = tegra_t186ref_compr_set_params,
	.startup = tegra_t186ref_compr_startup,
	.shutdown = tegra_t186ref_compr_shutdown,
};

static const struct snd_soc_dapm_widget tegra_t186ref_dapm_widgets[] = {
	SND_SOC_DAPM_HP("x Headphone Jack", tegra_rt565x_event_hp),
	SND_SOC_DAPM_SPK("x Int Spk", tegra_rt565x_event_int_spk),
	SND_SOC_DAPM_MIC("x Int Mic", tegra_rt565x_event_int_mic),
	SND_SOC_DAPM_MIC("x Mic Jack", tegra_rt565x_event_ext_mic),
	SND_SOC_DAPM_MIC("Int Mic", NULL),
	SND_SOC_DAPM_HP("x Headphone", NULL),
	SND_SOC_DAPM_MIC("x Mic", NULL),
	SND_SOC_DAPM_HP("y Headphone", NULL),
	SND_SOC_DAPM_MIC("y Mic", NULL),
	SND_SOC_DAPM_HP("z Headphone", NULL),
	SND_SOC_DAPM_MIC("z Mic", NULL),
	SND_SOC_DAPM_HP("m Headphone", NULL),
	SND_SOC_DAPM_MIC("m Mic", NULL),
	SND_SOC_DAPM_HP("n Headphone", NULL),
	SND_SOC_DAPM_MIC("n Mic", NULL),
	SND_SOC_DAPM_HP("o Headphone", NULL),
	SND_SOC_DAPM_MIC("o Mic", NULL),
	SND_SOC_DAPM_MIC("a Mic", NULL),
	SND_SOC_DAPM_MIC("b Mic", NULL),
	SND_SOC_DAPM_MIC("c Mic", NULL),
	SND_SOC_DAPM_MIC("d Mic", NULL),
	SND_SOC_DAPM_HP("e Headphone", NULL),
	SND_SOC_DAPM_MIC("e Mic", NULL),
	SND_SOC_DAPM_SPK("d1 Headphone", NULL),
	SND_SOC_DAPM_SPK("d2 Headphone", NULL),
};

static int tegra_t186ref_suspend_pre(struct snd_soc_card *card)
{
	unsigned int idx;

	/* DAPM dai link stream work for non pcm links */
	for (idx = 0; idx < card->num_rtd; idx++) {
		if (card->rtd[idx].dai_link->params)
			INIT_DELAYED_WORK(&card->rtd[idx].delayed_work, NULL);
	}

	return 0;
}

static int tegra_t186ref_suspend_post(struct snd_soc_card *card)
{
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	if (machine->digital_reg)
		regulator_disable(machine->digital_reg);

	return 0;
}

static int tegra_t186ref_resume_pre(struct snd_soc_card *card)
{
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	int ret;

	if (machine->digital_reg)
		ret = regulator_enable(machine->digital_reg);

	return 0;
}

static int tegra_t186ref_remove(struct snd_soc_card *card)
{
	return 0;
}

static const char * const tegra_t186ref_srate_text[] = {
	"None",
	"8kHz",
	"16kHz",
	"44kHz",
	"48kHz",
	"11kHz",
	"22kHz",
	"24kHz",
	"32kHz",
	"88kHz",
	"96kHz",
	"176kHz",
	"192kHz",
};

static int tegra_t186ref_codec_get_rate(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	ucontrol->value.integer.value[0] = machine->rate_via_kcontrol;

	return 0;
}

static int tegra_t186ref_codec_put_rate(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	/* set the rate control flag */
	machine->rate_via_kcontrol = ucontrol->value.integer.value[0];

	return 0;
}

static const char * const tegra_t186ref_format_text[] = {
	"None",
	"16",
	"32",
};

static int tegra_t186ref_codec_get_format(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	ucontrol->value.integer.value[0] = machine->fmt_via_kcontrol;

	return 0;
}

static int tegra_t186ref_codec_put_format(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	/* set the format control flag */
	machine->fmt_via_kcontrol = ucontrol->value.integer.value[0];

	return 0;
}

static const char * const tegra_t186ref_jack_state_text[] = {
	"None",
	"HS",
	"HP",
};

static int tegra_t186ref_codec_get_jack_state(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	ucontrol->value.integer.value[0] = tegra_t186ref_headset_switch.state;
	return 0;
}

static int tegra_t186ref_codec_put_jack_state(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	if (ucontrol->value.integer.value[0] == 0)
		switch_set_state(&tegra_t186ref_headset_switch, BIT_NO_HEADSET);
	else if (ucontrol->value.integer.value[0] == 1)
		switch_set_state(&tegra_t186ref_headset_switch, BIT_HEADSET);
	else if (ucontrol->value.integer.value[0] == 2)
		switch_set_state(&tegra_t186ref_headset_switch,
			BIT_HEADSET_NO_MIC);
	return 0;
}

static const struct soc_enum tegra_t186ref_codec_rate =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_t186ref_srate_text),
		tegra_t186ref_srate_text);

static const struct soc_enum tegra_t186ref_codec_format =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_t186ref_format_text),
		tegra_t186ref_format_text);

static const struct soc_enum tegra_t186ref_jack_state =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_t186ref_jack_state_text),
		tegra_t186ref_jack_state_text);

static const struct snd_soc_dapm_route tegra_t186ref_audio_map[] = {
};

static const struct snd_kcontrol_new tegra_t186ref_controls[] = {
	SOC_DAPM_PIN_SWITCH("x Int Spk"),
	SOC_DAPM_PIN_SWITCH("x Headphone Jack"),
	SOC_DAPM_PIN_SWITCH("x Mic Jack"),
	SOC_DAPM_PIN_SWITCH("x Int Mic"),
	SOC_ENUM_EXT("codec-x rate", tegra_t186ref_codec_rate,
		tegra_t186ref_codec_get_rate, tegra_t186ref_codec_put_rate),
	SOC_ENUM_EXT("codec-x format", tegra_t186ref_codec_format,
		tegra_t186ref_codec_get_format, tegra_t186ref_codec_put_format),
	SOC_ENUM_EXT("Jack-state", tegra_t186ref_jack_state,
		tegra_t186ref_codec_get_jack_state,
		tegra_t186ref_codec_put_jack_state),
};

static struct snd_soc_card snd_soc_tegra_t186ref = {
	.name = "tegra-t186ref",
	.owner = THIS_MODULE,
	.remove = tegra_t186ref_remove,
	.suspend_post = tegra_t186ref_suspend_post,
	.suspend_pre = tegra_t186ref_suspend_pre,
	.resume_pre = tegra_t186ref_resume_pre,
	.controls = tegra_t186ref_controls,
	.num_controls = ARRAY_SIZE(tegra_t186ref_controls),
	.dapm_widgets = tegra_t186ref_dapm_widgets,
	.num_dapm_widgets = ARRAY_SIZE(tegra_t186ref_dapm_widgets),
	.fully_routed = true,
};

static void dai_link_setup(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
	struct snd_soc_codec_conf *tegra_machine_codec_conf = NULL;
	struct snd_soc_codec_conf *tegra_t186ref_codec_conf = NULL;
	struct snd_soc_dai_link *tegra_machine_dai_links = NULL;
	struct snd_soc_dai_link *tegra_t186ref_codec_links = NULL;
	int i;

	/* set new codec links and conf */
	tegra_t186ref_codec_links = tegra_machine_new_codec_links(pdev,
		tegra_t186ref_codec_links,
		&machine->num_codec_links);
	if (!tegra_t186ref_codec_links)
		goto err_alloc_dai_link;

	/* set codec init */
	for (i = 0; i < machine->num_codec_links; i++) {
		if (tegra_t186ref_codec_links[i].name) {
			if (strstr(tegra_t186ref_codec_links[i].name,
				"rt565x-playback"))
				tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
			else if (strstr(tegra_t186ref_codec_links[i].name,
				"rt5631-playback"))
				tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
			else if (strstr(tegra_t186ref_codec_links[i].name,
				"dspk-playback-r"))
				tegra_t186ref_codec_links[i].init = tegra_t186ref_dspk_init;
			else if (strstr(tegra_t186ref_codec_links[i].name,
				"dspk-playback-l"))
				tegra_t186ref_codec_links[i].init = tegra_t186ref_dspk_init;
		}
	}

	tegra_t186ref_codec_conf = tegra_machine_new_codec_conf(pdev,
		tegra_t186ref_codec_conf,
		&machine->num_codec_links);
	if (!tegra_t186ref_codec_conf)
		goto err_alloc_dai_link;

	/* get the xbar dai link/codec conf structure */
	tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
	if (!tegra_machine_dai_links)
		goto err_alloc_dai_link;

	tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
	if (!tegra_machine_codec_conf)
		goto err_alloc_dai_link;

	/* set ADMAIF dai_ops */
	for (i = TEGRA186_DAI_LINK_ADMAIF1;
		i <= TEGRA186_DAI_LINK_ADMAIF20; i++)
		tegra_machine_set_dai_ops(i, &tegra_t186ref_ops);

	/* set sfc dai_init */
	tegra_machine_set_dai_init(TEGRA186_DAI_LINK_SFC1_RX,
		&tegra_t186ref_sfc_init);
#if defined(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
	/* set ADSP PCM/COMPR */
	for (i = TEGRA186_DAI_LINK_ADSP_PCM1;
		i <= TEGRA186_DAI_LINK_ADSP_PCM2; i++) {
		tegra_machine_set_dai_ops(i, &tegra_t186ref_ops);
	}

	/* set ADSP COMPR */
	for (i = TEGRA186_DAI_LINK_ADSP_COMPR1;
		i <= TEGRA186_DAI_LINK_ADSP_COMPR2; i++) {
		tegra_machine_set_dai_compr_ops(i,
			&tegra_t186ref_compr_ops);
	}
#endif

	/* set ASRC params. The default is 2 channels */
	for (i = 0; i < 6; i++) {
		tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_TX1 + i,
			(struct snd_soc_pcm_stream *)
				&tegra_t186ref_asrc_link_params[i]);
		tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_RX1 + i,
			(struct snd_soc_pcm_stream *)
				&tegra_t186ref_asrc_link_params[i]);
	}

	/* append t186ref specific dai_links */
	card->num_links =
		tegra_machine_append_dai_link_t18x(tegra_t186ref_codec_links,
			2 * machine->num_codec_links);
	tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
	card->dai_link = tegra_machine_dai_links;

	/* append t186ref specific codec_conf */
	card->num_configs =
		tegra_machine_append_codec_conf_t18x(tegra_t186ref_codec_conf,
			machine->num_codec_links);
	tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
	card->codec_conf = tegra_machine_codec_conf;

	return;

err_alloc_dai_link:
	tegra_machine_remove_dai_link();
	tegra_machine_remove_codec_conf();
	return;
}

static int tegra_t186ref_driver_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct snd_soc_card *card = &snd_soc_tegra_t186ref;
	struct tegra_t186ref *machine;
	struct tegra_asoc_platform_data *pdata = NULL;
	struct snd_soc_codec *codec = NULL;
	int idx = 0;
	int ret = 0;
	const char *codec_dai_name;

	if (!np) {
		dev_err(&pdev->dev, "No device tree node for t186ref driver");
		return -ENODEV;
	}

	machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_t186ref),
			       GFP_KERNEL);
	if (!machine) {
		dev_err(&pdev->dev, "Can't allocate t186ref struct\n");
		ret = -ENOMEM;
		goto err;
	}

	card->dev = &pdev->dev;
	platform_set_drvdata(pdev, card);
	snd_soc_card_set_drvdata(card, machine);
	machine->is_codec_dummy = 0;
	machine->audio_clock.clk_cdev1_state = 0;
	machine->digital_reg = NULL;
	machine->spk_reg = NULL;
	machine->dmic_reg = NULL;
	card->dapm.idle_bias_off = true;

	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
	if (ret)
		goto err;

	ret = snd_soc_of_parse_audio_routing(card,
				"nvidia,audio-routing");
	if (ret)
		goto err;

	if (of_property_read_u32(np, "nvidia,num-clk",
			       &machine->audio_clock.num_clk) < 0) {
		dev_err(&pdev->dev,
			"Missing property nvidia,num-clk\n");
		ret = -ENODEV;
		goto err;
	}

	if (of_property_read_u32_array(np, "nvidia,clk-rates",
				(u32 *)&machine->audio_clock.clk_rates,
				machine->audio_clock.num_clk) < 0) {
		dev_err(&pdev->dev,
			"Missing property nvidia,clk-rates\n");
		ret = -ENODEV;
		goto err;
	}

	dai_link_setup(pdev);

#ifdef CONFIG_SWITCH
	/* Addd h2w swith class support */
	ret = tegra_alt_asoc_switch_register(&tegra_t186ref_headset_switch);
	if (ret < 0)
		goto err_alloc_dai_link;
#endif

	pdata = devm_kzalloc(&pdev->dev,
				sizeof(struct tegra_asoc_platform_data),
				GFP_KERNEL);
	if (!pdata) {
		dev_err(&pdev->dev,
			"Can't allocate tegra_asoc_platform_data struct\n");
		return -ENOMEM;
	}

	pdata->gpio_codec1 = pdata->gpio_codec2 = pdata->gpio_codec3 =
	pdata->gpio_spkr_en = pdata->gpio_hp_mute =
	pdata->gpio_int_mic_en = pdata->gpio_ext_mic_en = -1;

	machine->pdata = pdata;
	machine->pcard = card;

	ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
					&pdev->dev,
					card);
	if (ret)
		goto err_alloc_dai_link;

	ret = snd_soc_register_card(card);
	if (ret) {
		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
			ret);
		goto err_fini_utils;
	}

	idx = tegra_machine_get_codec_dai_link_idx_t18x("rt565x-playback");
	/* check if idx has valid number */
	if (idx == -EINVAL)
		dev_warn(&pdev->dev, "codec link not defined - codec not part of sound card");
	else {
		codec = card->rtd[idx].codec;
		codec_dai_name = card->rtd[idx].dai_link->codec_dai_name;

		dev_info(&pdev->dev,
			"codec-dai \"%s\" registered\n", codec_dai_name);
		if (!strcmp("dit-hifi", codec_dai_name)) {
			dev_info(&pdev->dev, "This is a dummy codec\n");
			machine->is_codec_dummy = 1;
		}
		printk ("[VuNguyen] : %s %d !!!!!!!!!!!!!!!\r\n", __func__, __LINE__);
		if (!machine->is_codec_dummy) {
			/* setup for jack detection only in non-dummy case */
			rt5659_set_jack_detect(codec, &tegra_t186ref_hp_jack);
		}
	}
	printk ("[VuNguyen] : %s %d !!!!!!!!!!!!!!!\r\n", __func__, __LINE__);

	return 0;

err_fini_utils:
	tegra_alt_asoc_utils_fini(&machine->audio_clock);
err_alloc_dai_link:
	tegra_machine_remove_dai_link();
	tegra_machine_remove_codec_conf();
err:

	return ret;
}

static int tegra_t186ref_driver_remove(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);

	snd_soc_unregister_card(card);

	tegra_machine_remove_dai_link();
	tegra_machine_remove_codec_conf();
	tegra_alt_asoc_utils_fini(&machine->audio_clock);

	return 0;
}

static const struct of_device_id tegra_t186ref_of_match[] = {
	{ .compatible = "nvidia,tegra-audio-t186ref-mobile-rt565x", },
	{},
};

static struct platform_driver tegra_t186ref_driver = {
	.driver = {
		.name = DRV_NAME,
		.owner = THIS_MODULE,
		.pm = &snd_soc_pm_ops,
		.of_match_table = tegra_t186ref_of_match,
	},
	.probe = tegra_t186ref_driver_probe,
	.remove = tegra_t186ref_driver_remove,
};
module_platform_driver(tegra_t186ref_driver);

MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
MODULE_DESCRIPTION("Tegra+t186ref machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_DEVICE_TABLE(of, tegra_t186ref_of_match);

And console result

[    9.766879] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF1 <-> ADMAIF1 mapping ok
[    9.766953] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF2 <-> ADMAIF2 mapping ok
[    9.767020] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF3 <-> ADMAIF3 mapping ok
[    9.767094] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF4 <-> ADMAIF4 mapping ok
[    9.767166] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF5 <-> ADMAIF5 mapping ok
[    9.767232] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF6 <-> ADMAIF6 mapping ok
[    9.767303] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF7 <-> ADMAIF7 mapping ok
[    9.767371] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF8 <-> ADMAIF8 mapping ok
[    9.767443] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF9 <-> ADMAIF9 mapping ok
[    9.767511] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF10 <-> ADMAIF10 mapping ok
[    9.767582] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF11 <-> ADMAIF11 mapping ok
[    9.767648] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF12 <-> ADMAIF12 mapping ok
[    9.767718] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF13 <-> ADMAIF13 mapping ok
[    9.767786] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF14 <-> ADMAIF14 mapping ok
[    9.767853] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF15 <-> ADMAIF15 mapping ok
[    9.767927] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF16 <-> ADMAIF16 mapping ok
[    9.767996] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF17 <-> ADMAIF17 mapping ok
[    9.768065] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF18 <-> ADMAIF18 mapping ok
[    9.768131] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF19 <-> ADMAIF19 mapping ok
[    9.768197] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF20 <-> ADMAIF20 mapping ok
[    9.771135] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE1 <-> ADSP PCM1 mapping ok
[    9.771211] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE2 <-> ADSP PCM2 mapping ok
[    9.771233] compress asoc: ADSP-FE3 <-> ADSP COMPR1 mapping ok
[    9.771253] compress asoc: ADSP-FE4 <-> ADSP COMPR2 mapping ok
[    9.781921] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for x OUT
[    9.781924] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x OUT -> direct -> x Headphone
[    9.781958] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no sink widget found for x IN
[    9.781960] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x Mic -> direct -> x IN
[    9.799606] input: tegra-snd-t186ref-mobile-rt565x Headphone Jack as /devices/sound/sound/card1/input2
[    9.800065] tegra-snd-t186ref-mobile-rt565x sound: codec link not defined - codec not part of sound card
[    9.800067] [VuNguyen] : tegra_t186ref_driver_probe 1123 !!!!!!!!!!!!!!!
...........................
...........................
...........................
[   18.096618] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   18.096619] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
[   18.096717] tegra-snd-t186ref-mobile-rt565x sound: codec_dai clock not set
[   18.096718] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init
[   18.096720] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 5 printk messages dropped ** [   18.099495] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 59 printk messages dropped ** [   18.110012] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 44 printk messages dropped ** [   18.114710] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 59 printk messages dropped ** [   18.120928] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 29 printk messages dropped ** [   18.129810] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 59 printk messages dropped ** [   18.135584] tegra-snd-t186ref-mobile-rt565x sound: ASoC: machine hw_params failed: -524
** 61 printk messages dropped ** [   18.169242] tegra-snd-t186ref-mobile-rt565x sound: Failed dai init

Thanks and Best Regards,
Vu Nguyen

Hi Jonathanh,

After I skip dspk_1_dai_link and dspk_2_dai_link in DT almost warning disappeared. Now I think we could focus on widget config

[   10.826938] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF1 <-> ADMAIF1 mapping ok
[   10.835510] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF2 <-> ADMAIF2 mapping ok
[   10.843971] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF3 <-> ADMAIF3 mapping ok
[   10.852398] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF4 <-> ADMAIF4 mapping ok
[   10.860808] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF5 <-> ADMAIF5 mapping ok
[   10.869173] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF6 <-> ADMAIF6 mapping ok
[   10.877535] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF7 <-> ADMAIF7 mapping ok
[   10.885833] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF8 <-> ADMAIF8 mapping ok
[   10.894234] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF9 <-> ADMAIF9 mapping ok
[   10.902385] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF10 <-> ADMAIF10 mapping ok
[   10.910598] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF11 <-> ADMAIF11 mapping ok
[   10.918855] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF12 <-> ADMAIF12 mapping ok
[   10.927024] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF13 <-> ADMAIF13 mapping ok
[   10.935224] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF14 <-> ADMAIF14 mapping ok
[   10.943360] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF15 <-> ADMAIF15 mapping ok
[   10.951480] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF16 <-> ADMAIF16 mapping ok
[   10.959652] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF17 <-> ADMAIF17 mapping ok
[   10.967747] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF18 <-> ADMAIF18 mapping ok
[   10.975873] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF19 <-> ADMAIF19 mapping ok
[   10.983933] tegra-snd-t186ref-mobile-rt565x sound: ADMAIF20 <-> ADMAIF20 mapping ok
[   10.996384] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE1 <-> ADSP PCM1 mapping ok
[   11.004672] tegra-snd-t186ref-mobile-rt565x sound: ADSP-FE2 <-> ADSP PCM2 mapping ok
[   11.012748] compress asoc: ADSP-FE3 <-> ADSP COMPR1 mapping ok
[   11.018964] compress asoc: ADSP-FE4 <-> ADSP COMPR2 mapping ok
[   11.044159] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for x OUT
[   11.052927] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x OUT -> direct -> x Headphone
[   11.063305] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no sink widget found for x IN
[   11.071562] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route x Mic -> direct -> x IN
[   11.081852] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for d1 OUT
[   11.091156] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route d1 OUT -> direct -> d1 Headphone
[   11.101957] tegra-snd-t186ref-mobile-rt565x sound: ASoC: no source widget found for d2 OUT
[   11.111156] tegra-snd-t186ref-mobile-rt565x sound: ASoC: Failed to add route d2 OUT -> direct -> d2 Headphone
[   11.145560] input: tegra-snd-t186ref-mobile-rt565x Headphone Jack as /devices/sound/sound/card1/input2
[   11.156749] tegra-snd-t186ref-mobile-rt565x sound: codec link not defined - codec not part of sound card
[   11.167500] [VuNguyen] : tegra_t186ref_driver_probe 1123 !!!!!!!!!!!!!!!

Thanks and Best Regards,
Vu Nguyen

Hi Janathanh,

According to NVIDIA Tegra Linux Driver Package document at System Configuration->Tegra ASoc Driver->Troubleshooting, I have facing Issue 1: No Sound Cards Found as below

• Identify the ASoC error that lead to no sound card detection with the dmesg [dmesg | grep ASoC] command. Output is similar to the following:
[4.874720] tegra-audio-t210ref tegra-audio-t210ref.0: ASoC: no source widget found for x OUT
[4.874724] tegra-audio-t210ref tegra-audio-t210ref.0: ASoC: Failed to add route x OUT-> direct-> Headphone-x
[4.874736] tegra-audio-t210ref tegra-audio-t210ref.0: ASoC: no sink widget found for x IN
[4.874739] tegra-audio-t210ref tegra-audio-t210ref.0: ASoC: Failed to add route LineIn-x-> direct-> x IN
In this case, x OUT and x IN are the widgets of the spdif-dit dummy codec. It might have not been instantiated in ASoC. Confirm that with the following command:
cat /sys/kernel/debug/asoc/codecs
if spdif-dit is instantiated. The spdif device must be instantiated using platform_register in the board-specific file.

But I didn’t understand how to instantiate spdif device by using platform_register in the board-specific file.

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

Can you try changing the routing as follows …

diff --git a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
index 46de427f71f8..a769b8ed5546 100644
--- a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
+++ b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
@@ -813,8 +813,10 @@
 
                status = "okay";
                nvidia,audio-routing =
-                       "x Headphone",          "x OUT",
-                       "x IN",                 "x Mic",
+                       "x Headphone",          "x Left DAC",
+                       "x Headphone",          "x Right DAC",
+                       "x IN",                 "x Left ADC",
+                       "x IN",                 "x Right ADC",
                        "y Headphone",          "y OUT",
                        "y IN",                 "y Mic",
                        "z Headphone",          "z OUT",

Regards
Jon

Hi jonathanh,

It look good. As the original DTB, when I played one .wav file (about 2-3mins) it will be terminated after 5 seconds and there was nothing on “I2S0_SDOUT” pin. If I modified as your recommendation, audio was playing about 2-3mins and there was data on “I2S0_SDOUT” pin. The last one is I could hear nothing from speaker.

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

Great. You may need to check your codec configuration to ensure it is setup correctly.

Regards,
Jon

Hi Jonathanh,

After checking configuration for audio codec I could hear sound on the speaker. However the volume is so low, may it related to Headphone configuration, should I change it to speaker instead?

+                       "x Headphone",          "x Left DAC",
+                       "x Headphone",          "x Right DAC",
+                       "x IN",                 "x Left ADC",
+                       "x IN",                 "x Right ADC",

Thanks and Best Regards,
Vu Nguyen

Hi Vu,

I see that the codec has various volume controls, have you tried adjusting these?

I think that if you …

$ amixer -c 1 | grep "x " | grep Volume

… you should see some Volume controls and something like “x HP Playback Volume”. Maybe you can try configuring this?

Regards,
Jon