Nano Compatible I2S soundcard

I purchased a raspiaudio mix+ sound card which uses I2S, but have been unable to get it to work, it’s based on the NXP1334A chip. Does anyone know how to accomplish this? Has anyone found a compaible card that supports audio playback and recording?

Find out which driver the RPi uses for this. From there you can build a kernel module and copy it in place…then it should work. Most embedded systems don’t include the full range of drivers a PC includes. I’m sure RPi would have included this because the card is made for the RPi.

The PI uses the googlevoicehat-souncard kernel module. The NVIDIA kernel file does not include this an option. How do I build this? Or can I just copy the kernel object file.

It’s a dtbo file which probably won’t work.

I have a similar issue, trying to get this Pi I2S WM8960 Audio HAT working…
https://www.waveshare.com/wm8960-audio-hat.htm

It has Rasp Pi driver code available on Github…
https://github.com/waveshare/WM8960-Audio-HAT
… which I tried to modify (rebuilt dtbo on nano, compiled driver code on nano, and modified the install script). It all seemed to build ok, but the resultant wm8960-soundcard.service shows up as ‘failed’ using systemctl after it’s started.

I’m fairly new to linux, and I’m a bit out of my depth with this, so any pointers would be helpful.

@sms: How does the RPi get the driver? If this is the 64-bit (arm64/aarch64/ARMv8-a) RPi, then you should be able to build the module for the Jetson, or if lucky, simply copy the binary file into the correct module directory location. If this works on an RPi, then someone must have released the driver (and likely in source form).

@WillCUK: I’m not sure on the audio setup either, someone else may know though how to debug the sound card.

This is a device-tree file, which I’m guessing has to be built and flashed, but I haven’t done this.

Device trees are easy to work with on a Nano since it seems to use the old method of a file in “/boot”. The trick is that a device tree is usually tied to a driver. So if you don’t have the driver as well, then the device tree won’t do anything. I am guessing the kernel for the particular RPi ships with that driver, but the Jetson very likely does not. More advice can be given on the device tree if you can verify the driver itself is available.

See my post about enabling I2S audio.

Tks, yes that was really useful in getting the GPIO pins switched to I2S mode, and I have flashed the dtb to do this and it looks like it has worked…

$ sudo grep "Name:\|J:\|BB:" /sys/kernel/debug/tegra_gpio                                                                                                                                                                
Name:Bank:Port CNF OE OUT IN INT_STA INT_ENB INT_LVL
 J: 2:1 00 00 00 00 00 00 000000
BB: 6:3 00 00 00 00 00 00 000000

(I think that’s correct?)

However the WM8960 board I have is not detected/functioning, and I assumed this is because a driver is required.

Tried that, didn’t work, all it succeeded in doing was to kill the edimax network card. Here’s what I’ve tried so far:

  1. Replace dtb file in \boot\dtb with the one suggested by @jas-mx, failed.
  2. Built a new sdk with the SDK manager. Saw no way to enable any other audio or load drivers, just succeeded in wiping out my SD card and not letting me boot on that machine with a stock image on another card.

So if some would take the time to say STEP by STEP what needs to be done, that would be great. I appreciate the guidance, but I’m not a novice, but I’m also not someone working for NVIDIA. The Jetson Nano guides are all self-referential, and do NOT explan how the Nano uses the device-tree, how to build kernel modules for new devices etc. One line answers are great, but I’m guessing the majority of people reading this have less experience than the authors.

The WM8960 requires the I2C interface configured for the driver to be activated. Unfortunately it is very difficult to provide the level of support you require as configuring any sound card requires some knowledge of the ALSA kernel interface to understand what needs to be configured and how to debug if thing aren’t working. For example for the WM8960 I have had to review parts of the datasheet to understand that I2C needs to be configured in the kernel to make this work.

Hello!

Just for completeness, it appears that the same question was posted and answered here …

https://devtalk.nvidia.com/default/topic/1051993/rasperry-pi-compatible-i2s-sound-card/

Regads,
Jon

Hello!

So the raspberrypi device-tree overlay will not work on Jetson directly and will need to be ported. Basically, we need to ensure that the correct I2C and I2S interfaces and power-supplies are referenced in the device-tree which will vary from board to board. Furthermore, this raspberrypi audio HAT is using the simple-card audio machine driver and currently we do not support this for Jetson.

So what I think you would need to do is …

  1. Add support for the wm8960 to the Nano device-tree. It could be possible to create an overlay but given that currently there is no simple way to apply it, you are better off just modifying the base device-tree …
diff --git a/kernel-dts/porg-platforms/tegra210-porg-super-module-e2614.dtsi b/kernel-dts/porg-platforms/tegra210-porg-super-module-e2614.dtsi
index 99a36b989459..ed847fa55790 100644
--- a/kernel-dts/porg-platforms/tegra210-porg-super-module-e2614.dtsi
+++ b/kernel-dts/porg-platforms/tegra210-porg-super-module-e2614.dtsi
@@ -28,7 +28,7 @@
                                >;
                        label = "I2S4_LRCLK", "I2S4_SDIN", "I2S4_SDOUT",
                                "I2S4_CLK", "AUDIO_MCLK", "AUD_RST";
-                       status = "disabled";
+                       status = "okay";
                };
        };
diff --git a/kernel-dts/tegra210-porg-p3448-common.dtsi b/kernel-dts/tegra210-porg-p3448-common.dtsi
index 7cf5f76909bf..7509f13c52e8 100644
--- a/kernel-dts/tegra210-porg-p3448-common.dtsi
+++ b/kernel-dts/tegra210-porg-p3448-common.dtsi
@@ -345,7 +345,7 @@
        sound_card: sound {
                status = "okay";
                compatible = "nvidia,tegra-audio-t210ref-mobile-rt565x";
-               nvidia,model = "tegra-snd-t210ref-mobile-rt565x";
+               nvidia,model = "jetson-nano-wm8960";
 
                clocks = <&tegra_car TEGRA210_CLK_PLL_P_OUT1>,
                        <&tegra_car TEGRA210_CLK_PLL_A>,
@@ -365,8 +365,14 @@
                nvidia,num-codec-link = <4>;
 
                nvidia,audio-routing =
-                       "x Headphone",  "x OUT",
-                       "x IN",         "x Mic",
+                       "x Headphone", "HP_L",
+                       "x Headphone", "HP_R",  
+                       "x Int Spk", "SPK_LP",  
+                       "x Int Spkr", "SPK_LN",  
+                       "LINPUT1", "x Mic",  
+                       "LINPUT3", "x Mic",
+                       "RINPUT1", "x Mic",
+                       "RINPUT2", "x Mic",
                        "y Headphone",  "y OUT",
                        "y IN",         "y Mic",
                        "a IN",         "a Mic",
@@ -375,11 +381,13 @@
                nvidia,xbar = <&tegra_axbar>;
 
                i2s_dai_link1: nvidia,dai-link-1 {
-                       link-name = "spdif-dit-0";
+                       link-name = "wm8960";
                        cpu-dai = <&tegra_i2s4>;
-                       codec-dai = <&spdif_dit0>;
+                       codec-dai = <&wm8960>;
                        cpu-dai-name = "I2S4";
-                       codec-dai-name = "dit-hifi";
+                       codec-dai-name = "wm8960";
+                       bitclock-master;
+                       frame-master;
                        format = "i2s";
                        bit-format = "s16_le";
                        bclk_ratio = <1>;
@@ -681,6 +689,16 @@
                        status = "disabled";
                };
        };
+
+       i2c@7000c400 {
+               wm8960: wm8960{
+                       compatible = "wlf,wm8960";
+                       reg = <0x1a>;
+                       AVDD-supply = <&p3449_vdd_5v0_sys>;
+                       DVDD-supply = <&p3448_vdd_3v3_sys>;
+               };
+       };
+  
        clock@70110000 {
                status = "okay";
                vdd-cpu-supply = <&cpu_ovr_reg>;
@@ -787,6 +805,14 @@
                 pwm-regulator = <&cpu_ovr_reg>;
                 status = "okay";
         };
+
+       clocks {
+                wm8960_mclk: wm8960_mclk {
+                        compatible = "fixed-clock";
+                        #clock-cells = <0>;
+                        clock-frequency = <12288000>;
+                };
+       };
 };
 
 #if LINUX_VERSION >= 414
  1. Enable the WM8960 driver and update the Tegra audio machine driver …
diff --git a/sound/soc/tegra-alt/Kconfig b/sound/soc/tegra-alt/Kconfig
index dd460ad5c431..8cfe72824714 100644
--- a/sound/soc/tegra-alt/Kconfig
+++ b/sound/soc/tegra-alt/Kconfig
@@ -180,6 +180,7 @@ config SND_SOC_TEGRA_T210REF_MOBILE_ALT
        select SND_SOC_RT5640
        select SND_SOC_RT5659
        select SND_SOC_SGTL5000
+       select SND_SOC_WM8960
        select SND_SOC_TEGRA_ASOC_MACHINE_ALT
        help
          Say Y or M here.
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 cbe8c5ff3c6a..82a40b00342e 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
@@ -33,6 +33,7 @@
 #include <dt-bindings/sound/tas2552.h>
 #include "rt5659.h"
 #include "sgtl5000.h"
+#include "wm8960.h"  
 #include "tegra_asoc_utils_alt.h"  
 #include "tegra_asoc_machine_alt.h"  
 #include "tegra210_xbar_alt.h"  
@@ -651,6 +652,16 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
                dai_params->formats = formats;
        }
 
+       rtd = snd_soc_get_pcm_runtime(card, "wm8960");
+       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;
 }
@@ -808,6 +819,21 @@ static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
+static int tegra_machine_wm8960_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct device *dev = rtd->card->dev;
+       int err;
+
+       err = snd_soc_dai_set_sysclk(rtd->codec_dai, WM8960_SYSCLK_MCLK, 12288000,
+                                    SND_SOC_CLOCK_IN);
+       if (err) {
+               dev_err(dev, "failed to set wm8960 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;
@@ -922,6 +948,10 @@ static void dai_link_setup(struct platform_device *pdev)
                                "fe-pi-audio-z-v2")) {
                                tegra_machine_codec_links[i].init =
                                        tegra_machine_fepi_init;
+                       } else if (strstr(tegra_machine_codec_links[i].name,
+                               "wm8960")) {
+                               tegra_machine_codec_links[i].init =
+                                       tegra_machine_wm8960_init;
                        }
                }
        }
  1. Re-flash the new kernel Image and device-tree.

Obviously, this is completely untested because I don’t have this audio HAT. If you are looking for an audio HAT that has been tested then I can recommend the following …

https://fe-pi.com/products/fe-pi-audio-z-v2

Regards,
Jon

1 Like

Thanks Jon. I’ll give that a try.

Cheers,
Will

Hi Will,

I have updated the DT code snippet above so hopefully, you do not need jas-mx changes in addition to the DT changes above.

Regards,
Jon

Do you think this solution would work for the aiy voice V1 hat? Given the 40pin compatibility and all. I figure it be useful to have.

Hello!

In theory it could work, however, looking at the AIY Voice V1 it would also be necessary to add the googlevoicehat-codec.c driver [0] to the L4T kernel. It should not be necessary to add the googlevoicehat-soundcard.c driver, but rather include the relevant parts in the Tegra sound driver. Basically we would just need to add the code from snd_rpi_googlevoicehat_soundcard_hw_params() to tegra_machine_dai_init() as far as I can tell.

I am not sure if there are any other drivers that are needed, but if that is it, then it would seem possible.

Regards,
Jon

[0] https://aiyprojects.readthedocs.io/en/latest/voice.html#voice-hat-voice-kit-v1

I was thinking the same solution . node red has an even easier solution.

https://discourse.nodered.org/t/using-gpio-via-node-red-on-the-jetson-nano/16629/3

Tried it out last night and success. Between this and node-red. I was able to get it to work. But I get better quality out of my webcam mic and monitor sound.