How can I use Freescale‘s sgtl5000 on TX2?

hello everyone,
I am trying to enable a sound card soc(sgtl5000)on jetson TX2.
now my L4T version is R32.1.
In the kernel sources menuconfig,I saw the SND_SOC_TEGRA_SGTL5000 and SND_SOC_SGTL5000.I build them into the kernel,and
I added sound_ref node and sgtl5000 node in the device-tree accoring to its source code.
I changed the kernel and device tree. but it’s not work.
In the dmesg about sgtl5000 as follows:

tegra-snd-sgtl5000 sound_ref : SoC unknow to Tegra ASoC utils
tegra-snd-sgtl5000: probe of sound_ref failed with error -22

I found the error is from tegra_asoc_utils_init().
In the function have of_machine_is_compatible(),but it’s no “nvidia,tegra186”.Does this mean that sgtl5000 does not fit tx2 in the current version?

How can I enable the sgtl500 soc in the jetson TX2?

Looking forward to your reply!

Hello!

I have validated that the SGTL5000 codec works with the various Jetson boards using the FE-PI Audio Z V2 board [0]. The SND_SOC_TEGRA_SGTL5000 machine driver is not supported for TX2 and so I recommend that you do not use this. To enable support for this codec …

  1. Enable the codec under the machine driver used for Jetson TX2 (SND_SOC_TEGRA_T186REF_MOBILE_ALT)
diff --git a/sound/soc/tegra-alt/Kconfig b/sound/soc/tegra-alt/Kconfig
index 2d559708ce2e..0bd8c1248672 100644
--- a/sound/soc/tegra-alt/Kconfig
+++ b/sound/soc/tegra-alt/Kconfig
@@ -247,6 +248,7 @@ config SND_SOC_TEGRA_T186REF_MOBILE_ALT
        tristate "SoC Audio support for T186Ref Mobile"
        depends on SND_SOC_TEGRA_T186REF_ALT
        select SND_SOC_RT5659
+       select SND_SOC_SGTL5000
        help
          Say Y or M here.
  1. Add the codec node to Jetson TX2 DT file. Please note that in the case of the FE-PI module, the SGTL5000 is clocked by an on-board 12.288MHz fixed rate clock and so a dummy clock is added to DT. This may need to change depending on what is providing the codec mclk. Furthermore, the FE-PI module is connected to the 40-pin header on TX2 and so uses I2C controller ‘i2c@c240000’. If you uses a different I2C interface then this will also need to change.
diff --git a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
index 449be9586489..5131f69544b5 100644
--- a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
+++ b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
@@ -167,8 +167,30 @@
                };
        };
 
+       clocks {
+               sgtl5000_mclk: sgtl5000_mclk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <12288000>;
+                       clock-output-names = "sgtl5000-mclk";
+                       status = "okay";
+               };
+       };
+
        i2c@c240000 {
                status = "okay";
+
+               sgtl5000: sgtl5000@0a {
+                       compatible = "fsl,sgtl5000";
+                       reg = <0x0a>;
+                       clocks = <&sgtl5000_mclk>;
+                       micbias-resistor-k-ohms = <2>;
+                       micbias-voltage-m-volts = <3000>;
+                       VDDA-supply = <&vdd_3v3>;
+                       VDDIO-supply = <&vdd_3v3>;
+                       status = "okay";
+               };
+
                lp8556_backlight: lp8556-backlight-s-wqxga-10-1@2c {
                        status = "disabled";
                        disable-on-kernel-charging;
  1. Update the Jetson TX2 sound DT node. Please note that because the sgtl5000 is clocked by a fixed rate clock on the FE-PI board, I have configured the codec as the bitclock and frame master. If the mclk is provided by Tegra then the codec should be the bitclock and frame slave.
diff --git a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
index 449be9586489..c6c46bd6d7bb 100644
--- a/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
+++ b/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi
@@ -900,8 +922,8 @@
 
                status = "okay";
                nvidia,audio-routing =
-                       "x Headphone",          "x OUT",
-                       "x IN",                 "x Mic",
+                       "x Headphone",          "x HP_OUT",
+                       "x MIC_IN",             "x Mic";
                        "y Headphone",          "y OUT",
                        "y IN",                 "y Mic",
                        "z Headphone",          "z OUT",
@@ -922,14 +944,14 @@
                nvidia,xbar = <&tegra_axbar>;
 
                rt565x_dai_link: nvidia,dai-link-1 {
-                       link-name = "rt565x-playback";
+                       link-name = "fe-pi-audio-z-v2";
                        cpu-dai = <&tegra_i2s1>;
-                       codec-dai = <&spdif_dit0>;
+                       codec-dai = <&&sgtl5000>;
                        cpu-dai-name = "I2S1";
-                       codec-dai-name = "dit-hifi";
+                       codec-dai-name = "sgtl5000";
                        format = "i2s";
-                       bitclock-slave;
-                       frame-slave;
+                       bitclock-master;
+                       frame-master;
                        bitclock-noninversion;
                        frame-noninversion;
                        bit-format = "s16_le";
  1. Update the Jetson TX2 machine driver. Again because the sgtl5000 on the FE-PI module uses a fixed rate clock I need to tell the sgtl5000 driver this by calling snd_soc_dai_set_sysclk() for the codec. Finally, I also need to update the DAI params passed to the codec whenever playback/capture starts so that the codec is using the codec sample-rate, channels, etc.
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 e3428a6650af..46ce2bfda5c8 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
@@ -32,6 +32,7 @@
 #include <sound/soc.h>
 #include <dt-bindings/sound/tas2552.h>
 #include "rt5659.h"
+#include "sgtl5000.h"
 #include "tegra_asoc_utils_alt.h"
 #include "tegra_asoc_machine_alt.h"
 #include "tegra210_xbar_alt.h"
@@ -640,6 +641,16 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
                }
        }
 
+       rtd = snd_soc_get_pcm_runtime(card, "fe-pi-audio-z-v2");
+       if (rtd) {
+               dai_params =
+               (struct snd_soc_pcm_stream *)rtd->dai_link->params;
+
+               dai_params->rate_min = clk_rate;
+               dai_params->channels_min = channels;
+               dai_params->formats = formats;
+       }
+
        return 0;
 }
 
@@ -782,6 +793,21 @@ static int tegra_machine_compr_set_params(struct snd_compr_stream *cstream)
 }
 #endif
 
+static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct device *dev = rtd->card->dev;
+       int err;
+
+       err = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK, 12288000,
+                                    SND_SOC_CLOCK_IN);
+       if (err) {
+               dev_err(dev, "failed to set sgtl5000 sysclk!\n");
+               return err;
+       }
+
+       return 0;
+}
+
 static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_card *card = rtd->card;
@@ -885,13 +911,18 @@ static void dai_link_setup(struct platform_device *pdev)
                                                tegra_machine_rt565x_init;
                                }
                        } else if (strstr(tegra_machine_codec_links[i].name,
-                               "dspk-playback-r"))
+                               "dspk-playback-r")) {
                                tegra_machine_codec_links[i].init =
                                        tegra_machine_dspk_init;
-                       else if (strstr(tegra_machine_codec_links[i].name,
-                               "dspk-playback-l"))
+                       } else if (strstr(tegra_machine_codec_links[i].name,
+                               "dspk-playback-l")) {
                                tegra_machine_codec_links[i].init =
                                        tegra_machine_dspk_init;
+                       } else if (strstr(tegra_machine_codec_links[i].name,
+                               "fe-pi-audio-z-v2")) {
+                               tegra_machine_codec_links[i].init =
+                                       tegra_machine_fepi_init;
+                       }
                }
        }
  1. Finally, you need to ensure that pins for the I2S are configured for I2S. I am using the I2S controller exposes by 40-pin header. Please refer to the ‘Jetson TX2 Adaptation Guide’ [1] on how to reconfigure the pins on Jetson TX2.

Regards,
Jon

[0] https://fe-pi.com/products/fe-pi-audio-z-v2
[1] https://developer.nvidia.com/embedded/dlc/l4t-driver-package-tx2-adaptation-guide

@jonathanh
Thank you very much.
According to your suggestion,I enabled the codec under the machine driver used for Jetson TX2 ,and add the codec node to Jetson TX2 DT file.the codec mclk is providing by AUDIO_MCLK(F1),I changed the clocks. I also uses I2C controller ‘i2c@c240000’.
Because my mclk is provided by Tegra then the codec use the bitclock and frame slave mode.
In the update the Jetson TX2 machine driver,I didn’t change it。
I rebuild the kernel and dtb file.finally I from the dmesg get it:

[    4.590507] sgtl5000 1-000a: sgtl5000 revision 0x11
[    4.591084] sgtl5000 1-000a: Using internal LDO instead of VDDD: check ER1
[   20.646414] sgtl5000 1-000a: PLL not supported in slave mode
[   20.652142] sgtl5000 1-000a: 278 ratio is not supported. SYS_MCLK needs to be 256, 384 or 512 * fs
[   20.661604] sgtl5000 1-000a: ASoC: can't set sgtl5000 hw params: -22

My VDDD and VDDIO is provided by 1.8V circuit.

I also set bitclock and frame master mode? and what should I change the tegra_machine_fepi_init.

best regards!

Hello!

Yes you need to update the machine driver to configure the sgtl5000 sysclk. Can you trying something like the following, but update the DAI link name to match what you have in your DT for the ‘link-name’ property? In other words, replace ‘fe-pi-audio-z-v2’ with the whatever you have for the link-name ini DT.

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 d44a7449e0e8..beda784fcc7e 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
@@ -641,6 +641,23 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
                }
        }
 
+       rtd = snd_soc_get_pcm_runtime(card, "fe-pi-audio-z-v2");
+       if (rtd) {
+               dai_params =
+               (struct snd_soc_pcm_stream *)rtd->dai_link->params;
+
+               dai_params->rate_min = clk_rate;
+               dai_params->channels_min = channels;
+               dai_params->formats = formats;
+
+               err = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK,
+                                            clk_out_rate, SND_SOC_CLOCK_IN);
+               if (err) {
+                       dev_err(dev, "failed to set sgtl5000 sysclk!\n");
+                       return err;
+               }
+       }
+
        return 0;
 }

Regards
Jon

hi,
According to your help, I have successfully adapted to the R32.1 version.

But on the R32.3.1 version, I found that the device does not work normally according to the previous changes.

Mainly in two aspects:

  1. the dmesg about sgtl5000 is :sgtl5000 1_000a: sgtl50000_pcm_hw_params: set sysclk first!

in the node of pinmux@2430000 I add the node of aud_mclk_pj4 .
and set the sgtl5000 node the clocks = <&tegra_car TEGRA186_CLK_AUD_MCLK>

  1. I checked the i2s information:

sudo cat /sys/kernel/debug/tegra_pinctrl_reg | grep dap1

Bank:0 Reg: 0x02431028 Val : 0x00000055 → dap1_fs_pj3
Bank:0 Reg: 0x02431030 Val : 0x00000055 → dap1_fs_pj2
Bank:0 Reg: 0x02431038 Val : 0x00000055 → dap1_fs_pj1
Bank:0 Reg: 0x02431040 Val : 0x00000055 → dap1_fs_pj0

in the devicetree I add the node about i2s1 in pinmux mode follow the R32.1 version.

The above information has not changed.

the error about dmesg same as before.

Hello!

This would indicate that the function snd_soc_dai_set_sysclk() is not being called in the Tegra audio machine driver. Can you check if this is being called as expected?

Regards,
Jon

hello!

if(!strcmp(rtd->codec_dai->name, “sgtl5000”)){
err = snd_soc_dai_set_sysclk(rtd->codec_dai,
SGTL5000_SYSCLK, aud_mclk,
SND_SOC_CLOCK_IN);
printk(KERN_INFO"SGTL5000_AUD_MCLK_IS_SET");
if(err < 0 ){
dev_err(card->dev,“codev_dai clock not set\n”);
return err;
}

in the dmesg have the kern_info.

but the error about sgtl5000 is same.

Hello!

Do you see the error message …

dev_err(card->dev,“codev_dai clock not set\n”);

In the dmesg? This may indicate that the setting of the clock failed. Also what is happening first? Do you see the ‘sgtl50000_pcm_hw_params: set sysclk first!’ in dmesg before your print or your print first?

Regards,
Jon

In the dmesg information, I did not see codev_dai related information.

The printk information I added is printed out first, followed by the sysclk information.