I would like to generate a constant 24.576 Mhz audio master clock output from the Orin AGX 40 pin header. I have set up the pin configuration using the opt/nvidia/jetson-io/jetson-io.py tool, but pin 7 (aud_mclk) is listed as unused, despite enabling I2S / TDM capability.
As a sanity check, I am able to send / receive TDM data on the rest of the signals on the 40 pin header (FS, BCLK, DOUT, DIN, looked at using an oscilloscope and logic analyzer, so I can confirm that the I2S/TDM peripheral is working). The audio master clock signal is not present (the signal is constant high).
I have, but its not totally clear to me how to set up this clock. I assume for someone with more experience than I in properly updating the nodes in the device tree, its trivial, but I’m a tad overwhelmed with all the things I need to know to piece it together right now.
I see there is an extperiph4_clk in the jetson-io.py tool that I can also enable. However, its not clear to me how to configure that clock.
What is required to switch the I2S2 block to be sourced (properly) from the pllp_out0 so that the master clock and the I2S2 block can both be synchronized?
There is no support to use pllp_out0 for audio IO operations. Alternatively you can try following options:
Not sure the audio codec or board you are using over 40-pin header. But is it possible that codec can derive the MCLK from external source? Typically few codecs can generate the system clock from onboard oscillator. Please check if this applies to your case.
Can your audio codec generate system clock based on the incoming I2S bit clock? If yes this can be used. In this case, Tegra I2S will be producer and the codec will be in consumer mode.
If above options don’t work, then you can try first by using PLLP_OUT0 for MCLK and see if you see clock sync problems.
If none of the options work, then you can hack a bit to update clock parent for I2S and MCLK in device tree. However you need to make sure if there is some other client which requests a different rate for PLLP. In that case you may not get a desired result at runtime.
@spujar Thank you for the information. I would be perfectly happy to do # 2, however, the bitclock stops whenever playback or recording completes. Is there is method to enable the bitclock and keep it running even when playback or recording stops?
The answers to your questions are below:
We are using multiple ADAU1787 Codecs, and yes, they can derive their own master clock / sysclk from a crystal connected to them. However, this would require a change to the hardware and I would prefer to explore options that do not require board re-spins if its possible.
Yes, the Codec supports getting a sysclk from the bit clock (and we actually use that currently with other hardware). The main need is for the bitclock to stay active after playback / recording stops so that the PLL can stay syncrhonized. We dont change the I2S/TDM format and keep everything constant from startup to shutdown. So, if there is a way to start the bitclock and keep it running, that would be perfectly acceptable too!
Currently the PLLP_OUT0 is set to a 24.000 Mhz clock and we need a 24.576 Mhz clock. Its not (yet) clear to me how to configure the PLLP_OUT0 for this frequency, but as you probably guess, that might break other peripherals that rely on the 24 Mhz PLLP setting
I would love to know how to modify the clock parent for the I2S system (however, I am missing some information on what to do and where in the device tree), and understand that there may be multiple consumers of the PLLP that might have different clocking needs that are in conflict.
Was I mistaken (or is the documentation in error) that pin 7 of the 40 pin GPIO header is intended to be the I2S master clock?
Thank you for answering my questions and making suggestions! The help is greatly appreciated.
The boards which have onboard codec the MCLK is routed there. In this case, on AGX Orin, the MCLK clock is routed to onboard RT5640 audio codec. So 40-pin does not have a dedicated MCLK here.
Hello @spujar, Thanks for the reply. I tried to enable the clock via debugfs and setting the “state” from 0 to 1. However, the clock seems to be gated by something else and did not show up on the pin. I confirmed that the bitclock was set and running by using ALSA to play / record and observed the 24.576 Mhz clock present on the bitclock pin and watched that all that changed in the debugfs was the state changing from 0 to 1. Attempting to enable it manually afterward did not turn the clock on.
Looks strange as to why debugfs is not working. Can you confirm if the parent state of I2S bit clock is 1 as well? You can check state of plla_out0 and pll_a clocks.
If above still does not work, then you may have to hack the driver. Just do an additional clk_prepare_enable() call in the I2S driver. This should keep the clock enabled always.
Hello @spujar
I’m also very much interested in this and I’m experiencing the same issues.
Directly acting on the debugfs entries is not working as @chriskeeser also confirmed. Even when all the I2S2 parents are enabled and the I2S2 clock itself is set to 1 I get no clock output on the pin header.
I also tried to add a clk_prepare_enable at probe time in the I2S driver but I still see no output from the pin header, even though on reboot the clk_tree output clearly marks the I2S2 clock (and all its parents) as enabled.
So my assumption is that something is gating the I2S2 clock output.
If the I2S2 clock is in output from the I2S controller, maybe the controller itself is powered down gating the clock?
Hello @spujar,
part of the problem was solved on my side by assigning the audio power domain TEGRA234_POWER_DOMAIN_AUD to an always-on governor. That allows to have the I2S2 clock always active (and controllable by debugfs) after something has been already played out by the I2S controller.
The problem I’m currently facing is that to have the I2S2 clock active I must play something out, otherwise the clock is still gated. After it is ungated, then I can control it.
Do you have any documentation or datasheet about the I2S controller can I can use to debug this problem?
Hi @DRAMESH ,
I have a couple of questions regarding you patch:
In the r35.4.1 release (jetson_35.4.1 tag) there is no tegra_machine_driver_mobile.c file in the kernel sources. What release and tag are you using for these changes?
Any reason why you are using the tegra-alt version on the I2S driver and not the one shipped in the kernel-5.10 sources (the regular sound/soc/tegra/tegra210_i2s.c)?
If you are using the tegra-alt version of the driver I am assuming you are not currently compiling the kernel using the tegra_defconfig configuration file?
BTW, I think we are interested in the Jetson Orin Developer Kit.
Hi chriskeeser,
The earlier patchset I provided is intended to generate BCLK and RLCK. I apologize for any confusion. In our case, only BCLK needs to be enabled, which requires only I2S in Master mode , that will set BCLK as it set with clk_tree.
Could you please ensure the I2S controller is in master mode?
Note: By default I2S controller is in Slave mode, probably that may be the reason when on reboot the clk_tree output marks the I2S2 clock (and all its parents) as enabled but clock is not seen on pads.
I2S_CTRL_0 Offset: 0xa0
(Bit 10 should be enabled for Tegra to be in Master Mode)