I2S got wrong frame & bit clock

We set dts like below:

 tegra_sound: sound {
		status = "okay";
		compatible = "nvidia,tegra-audio-t210ref-mobile-rt565x";
		nvidia,model = "tegra-snd-t210ref-mobile-rt565x";

		clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
			 <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
			 <&tegra_car TEGRA210_CLK_D_AUDIO>,
			 <&tegra_car TEGRA210_CLK_EXTERN1>;
		clock-names = "pll_a", "pll_a_out0", "ahub", "extern1";
		assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>,
				  <&tegra_car TEGRA210_CLK_EXTERN1>;
		assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
					 <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
		nvidia,num-codec-link = <1>;

		nvidia,audio-routing =
			"x Int Spk", "x SPKOUTP", 
			"x Int Spk", "x SPKOUTN", 
			"x MICP", "x Int Mic",
			"x MICN", "x Int Mic";

		nvidia,xbar = <&tegra_axbar>;
		mclk-fs = <256>;

		i2s_dai_link1: nvidia,dai-link-1 {
			link-name = "nau8810-codec";
			cpu-dai = <&tegra_i2s4>;
			codec-dai = <&nau8810>;
			cpu-dai-name = "I2S4";
			codec-dai-name = "nau8810-hifi";
			format = "i2s";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			srate = <48000>;
			num-channel = <1>;
			ignore_suspend;
			name-prefix = "x";
			status = "okay";
		};
	};

And play wav file

Playing WAVE ‘african.wav’ : Signed 16 b[ 46.596817] nau8810 2-001a: nau8810_mclk_clkdiv 44100
it Little Endian, Rate 44100 Hz, Stereo

But the frame clock is 5.5K shown in oscilloscope, and with 32 bit format , bit clock frequency is 352k.The mclk is correct :11.28M (44100*256).


The frame frequency should be 44.1k, looks like it divided by 8, but why?

Thank for your help!!

Same issue with I2S capture.

Hello!

That does look odd indeed. If you run audio playback or capture what does the following show …

$ sudo grep "clock\|extern1\|i2s3\|pll_a_out" /sys/kernel/debug/clk/clk_summary
   clock                                           enable_cnt  prepare_cnt        rate    req_rate   accuracy   phase
 i2s3_sync                                                  0            0    24576000    24576000          0 0  
          pll_a_out0_div                                    1            1    45158334    61440000          0 0  
             pll_a_out0                                     3            3    45158334    45158400          0 0  
                i2s3                                        1            1     1411198     1411200          0 0  
                extern1                                     3            3    11289584    11289600          0 0  
          pll_a_out_adsp                                    0            0   338687500           0          0 0  
          pll_a_out0_out_adsp                               0            0   338687500           0          0 0  

The I2S clock is set by this function …

And the clock rate is calculated here …

Regards,
Jon

Thanks for your help!

We make it right by comment lines

if (i2s->codec_bit_format) {
....
}

and

if (i2s->sample_rate_via_control)

In tegra210_i2s_alt.c.

We wonder which configuration set sample_rate_via_control to 1920?

Hello!

Thanks for the feedback. The values of these controls are set by userspace …

$ amixer -c tegrasndt210ref sget "I2S4 codec bit format"
$ amixer -c tegrasndt210ref sget "I2S4 Sample Rate"

It would be interesting what they default to. However, they should be set as follows by default …

$ amixer -c tegrasndt210ref sset "I2S4 codec bit format" None
$ amixer -c tegrasndt210ref sset "I2S4 Sample Rate" 0

Regards,
Jon

We never set them.

In our case, I2S4 codec bit format is 32, I2S4 Sample Rate is 1920 (weired value).
Where are their default value defined in?
We don’t want to modify official code if not neccessary.

Thanks for your help!

Hello!

I have to say that this is strange. We have never had this problem before, so it is unclear to me why the default values are not the values we expect.

That said, once you set the mixer controls to the expected value …

$ amixer -c tegrasndt210ref sset "I2S4 codec bit format" None
$ amixer -c tegrasndt210ref sset "I2S4 Sample Rate" 0

And reboot, the alsa save-restore service will ensure that these settings are saved and restored on every boot.

Now for any default mixer settings that we what to ensure are set initially after flashing, these are handled by the also postinit script in the file /usr/share/alsa/init/postinit/00-tegra.conf. This script is executed on the first boot after flashing because the alsa file where the settings are stored by the save-restore service (/var/lib/alsa/asound.state) does not exist yet. Also if you are to execute the following command, this will also trigger the settings in the 00-tegra.conf to be applied …

$ alsactl init

If you look at the file 00-tegra.conf you will see that the above mixer controls are not set by this file and this is simply because we have not needed to. It would be interesting to see if you reflash the system, if the issue persists or not.

Regards
Jon

The system is early version, We reflash it with V32.4.3 sample rootfs.
Then got right default value for “I2S4 codec bit format” & “I2S4 Sample Rate”.
BUT, The main clock is gone.
We using same dtb with old version, and decompile it be sure the gpio configure appropriate.

  	aud_mclk_pbb0 {
  		nvidia,pins = "aud_mclk_pbb0"; 
  		nvidia,function = "aud";
  		nvidia,pull = <TEGRA_PIN_PULL_UP>;
  		nvidia,tristate = <TEGRA_PIN_DISABLE>; 
  		nvidia,enable-input = <TEGRA_PIN_DISABLE>; 
  	};

Kernel Debug info list below

root@h-desktop:/sys/kernel/debug# cat /sys/kernel/debug/tegra_gpio
Name:Bank:Port CNF OE OUT IN INT_STA INT_ENB INT_LVL
A: 0:0 64 40 40 04 00 00 000000
B: 0:1 f0 00 00 70 00 00 000000
C: 0:2 1f 00 00 00 00 00 000000
D: 0:3 00 00 00 00 00 00 000000
E: 1:0 48 00 00 48 00 08 080800
F: 1:1 00 00 00 00 00 00 000000
G: 1:2 0c 00 00 08 00 00 000000
H: 1:3 fd 99 00 60 00 00 000000
I: 2:0 07 07 02 02 00 00 000000
J: 2:1 f0 00 00 00 00 00 000000
K: 2:2 00 00 00 00 00 00 000000
L: 2:3 00 00 00 00 00 00 000000
M: 3:0 00 00 00 00 00 00 000000
N: 3:1 00 00 00 00 00 00 000000
O: 3:2 00 00 00 00 00 00 000000
P: 3:3 00 00 00 00 00 00 000000
Q: 4:0 00 00 00 00 00 00 000000
R: 4:1 00 00 00 00 00 00 000000
S: 4:2 a0 80 00 20 00 00 000000
T: 4:3 01 01 00 00 00 00 000000
U: 5:0 00 00 00 00 00 00 000000
V: 5:1 03 00 00 03 00 00 000000
W: 5:2 00 00 00 00 00 00 000000
X: 5:3 78 08 08 70 00 60 606000
Y: 6:0 06 00 00 02 00 00 000000
Z: 6:1 0f 08 00 07 00 04 000400
AA: 6:2 00 00 00 00 00 00 000000
BB: 6:3 01 00 00 00 00 00 000000
CC: 7:0 92 80 80 10 00 12 121200
DD: 7:1 01 00 00 00 00 00 000000
EE: 7:2 00 00 00 00 00 00 000000
FF: 7:3 00 00 00 00 00 00 000000
root@h-desktop:/sys/kernel/debug# cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins | grep -i pb
pin 8 (DAP1_FS PB0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 9 (DAP1_DIN PB1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 10 (DAP1_DOUT PB2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 11 (DAP1_SCLK PB3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 12 (SPI2_MOSI PB4): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function rsvd2 group spi2_mosi_pb4
pin 13 (SPI2_MISO PB5): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function rsvd2 group spi2_miso_pb5
pin 14 (SPI2_SCK PB6): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function rsvd2 group spi2_sck_pb6
pin 15 (SPI2_CS0 PB7): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function rsvd2 group spi2_cs0_pb7
pin 216 (AUD_MCLK PBB0): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function aud group aud_mclk_pbb0
pin 217 (DVFS_PWM PBB1): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function cldvfs group dvfs_pwm_pbb1
pin 218 (DVFS_CLK PBB2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 219 (GPIO_X1_AUD PBB3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 220 (GPIO_X3_AUD PBB4): (MUX UNCLAIMED) (GPIO UNCLAIMED)

Thank you!!

Hello!

By default in the more recent L4T releases, the pins on the 40-pin header are enabled as GPIO (apart from the I2C pins) and so yes it is expected that the AUD_MCLK and I2S signals are not enabled. With R32.4.3 there is a tool called ‘Jetson-IO’ [0] that can be used to configure the pins as follows …

$ sudo /opt/nvidia/jetson-io/config-by-function.py -o dtb aud_mclk i2s4
$ sudo reboot

Regards,
Jon

[0] https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide%2Fhw_setup_jetson_io.html%23

The AUD_MCLK disabled even pinmux register set to aud ?

pin 216 (AUD_MCLK PBB0): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function aud group aud_mclk_pbb0

Hello!

The function ‘aud’ is correct for the AUD_MCLK.

Regards,
Jon

But there is no clock output on pin216.
Why pinmux set to sf function but gpio config remain “GPIO”?

We just modify pinmux part in dts then things done before reflash to 32.4.3.
How can we change the GPIO CNF ?

Thanks for your help!

We can’t find the way to change CNF bit in GPIO register, which list in kernel debug tegra_gpio.
Expect your help. thanks a lot!

Hello!

After flashing r32.4.3 you should see the following by default …

$ sudo cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins | grep AUD_MCLK
pin 216 (AUD_MCLK PBB0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
$ sudo grep BB /sys/kernel/debug/tegra_gpio 
BB: 6:3 00 00 00 00 00 00 000000

This indicates that the pin is not used and actually for Tegra210, the pins on the 40-pin header do not default to GPIO, but just inputs (outputs are disabled).

Then if you run …

$ sudo /opt/nvidia/jetson-io/config-by-function.py -o dtb aud_mclk i2s4
$ sudo reboot

Then you should see …

$ sudo cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins | grep AUD_MCLK
pin 216 (AUD_MCLK PBB0): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function aud group aud_mclk_pbb0
$ sudo grep BB /sys/kernel/debug/tegra_gpio                                                                                                                                                    
BB: 6:3 00 00 00 00 00 00 000000
$ sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled
The following functions are enabled on the 40-pin header:
 1. aud_mclk
 2. i2s4

And …

sudo cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinconf-groups
...
107 (aud_mclk_pbb0): 
        pull=0
        tristate=0
        enable-input=0
        open-drain=0
        lock=0
        schmitt=0
        pull-down-strength=16
        pull-up-strength=16
        lpdr=0
        pbias-buf=0
        preemp=0
        rfu-in=0
        special-function=0
        func=aud

Regards,
Jon

Hello!

Have you made any changes to device-tree to HOG the GPIO for aud_mclk? If so you should remove this. By default with r32.4.3, the bit in the GPIO CNF register should not be set for the AUD_MCLK.

If you have not made changes to the HOG the GPIO in device-tree, but make sure you are using the latest u-boot bootloader from r32.4.3, because earlier versions would also set the GPIO CNF register.

Jon

We realized that issue related with emmc(002) version.
We flash same rootfs (V32.4.3) to sdcard & emmc.

For sdcard

$ sudo grep BB /sys/kernel/debug/tegra_gpio
BB: 6:3 00 00 00 00 00 00 000000

For emmc

$ sudo grep BB /sys/kernel/debug/tegra_gpio
BB: 6:3 01 00 00 00 00 00 000000

And we have no idea how to change the CNF bit.

Thank you!!

Hello!

I see. Yes the Nano modules with integrated eMMC is not supported by Jetson-IO currently. The purpose of Jetson-IO was to simplify the configuration of the IOs on the 40-pin of the devkit (which by default includes the SD card Nano module).

For changing the pinmux configuration on the Nano module with the eMMC, please follow the below instructions …

https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide%2Fadaptation_and_bringup_nano.html%23wwpID0E06P0HA

Regards,
Jon

The reason is DTB in partition has higher priority than FDT assigned in rootfs.
Both DTBs have effect, But the DTB in rootfs could not overwrite SOME register.
It’s weired.