IMX6 SSI Clock Slave

Hi community

We want to connected a Colibri IMX6DL 512MB Module to a Audio DSP ADAU1467, so we can play and record audio to/from this Audio DSP.

Our Goal is to use the TDM Signals like described in this Blog, to transmit 8 Channels and receive 8 Channels from the Audio DSP. The DSP works as clock master, as there are many other ADC’s and DAC’s connected to it. So the DSP provides the Bitclock and Frameclock to the imx6


The existing audio codec on the colibri module (sgtl15000) should be deactivated and only the DSP connection should appear as a soundcard on linux.

So we deactivated the sgtl15000 and route the ssi2 to the AUD4 and use the simple-audio-card with a dummy codec. The Input clock is configured for 48kHz sampling rate and 8 Channels with Slot width 32 Bit. This leads to a frequency of 12288000Hz.

I used the device-tree from imx6dl-colibri-eval-v3.dts and added following changes:

&iomuxc {

	/* remove existing sgtl15000 pinctrl */
	/delete-node/ pinctrl_audmux;
	
	/* add pinctrl to use AUD4 */
	pinctrl_audmux: audmuxgrp {
		fsl,pins = <
			MX6QDL_PAD_DISP0_DAT18__AUD4_RXFS 0x130b0
			MX6QDL_PAD_DISP0_DAT19__AUD4_RXC  0x130b0
			MX6QDL_PAD_DISP0_DAT20__AUD4_TXC  0x130b0
			MX6QDL_PAD_DISP0_DAT21__AUD4_TXD  0x130b0
			MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS 0x130b0
			MX6QDL_PAD_DISP0_DAT23__AUD4_RXD  0x130b0
		>;
	};
};

#define AUD_PORT_2 1
#define AUD_PORT_4 3

&audmux {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_audmux>;
	status = "okay";


	/*
	 * SSI2 on AUDMUX Port 2
	 * PTCR1:
	 *  - TFS_DIR 1	// TXFS is an output
	 *  - TFSEL 3	// TSFS Source Port 4
	 *  - TCLKDIR 1	// TCLK is an output
	 *  - TCSEL 3	// TCLK Source Port 4
	 *  - RFS_DIR 1	// RXFS is an output
	 *  - RFSEL 3	// RXFS Source Port 4
	 *  - RCLKDIR 1	// RCLK is an output
	 *  - RCSEL	3	// RCLK Source Port 4
	 *  - SYN 1		// Synchronous mode (4-wire interface)
	 * PDCR1:
	 *  - RXDSEL 4
	 *  - TXRXEN 0
	 *  - MODE 0
	 *  - INMMASK 0
	 *
	 * AUD4 on AUDMUX Port 4
	 *  - TFS_DIR 0	// TXFS as input
	 *  - TFSEL 0 	// will be ignored when TFS_DIR = 0
	 *  - TCLKDIR 0	// TCLK as Input
	 *  - TCSEL 0	// will be ignored when TCLKDIR = 0
	 *  - RFS_DIR 0	// RFS as Input
	 *  - RFSEL 0   // will be ignored when RFS_DIR = 0
	 *  - RCLKDIR 0	// RCLK as Input
	 *  - RCSEL	0	// will be ignored when RCLKDIR = 0
	 *  - SYN 1		// Synchronous mode (4-wire interface)
	 *
	 * PDCR4: 0x0000 0000
	 *  - RXDSEL 0
	 *  - TXRXEN 0
	 *  - MODE 0
	 *  - INMMASK 0
	*/
	ssi2 {
		fsl,audmux-port = <AUD_PORT_1>;
		fsl,port-config = <
			(IMX_AUDMUX_V2_PTCR_TFSDIR | IMX_AUDMUX_V2_PTCR_TFSEL(AUD_PORT_4) | IMX_AUDMUX_V2_PTCR_TCLKDIR | IMX_AUDMUX_V2_PTCR_TCSEL(AUD_PORT_4) | IMX_AUDMUX_V2_PTCR_RFSDIR | IMX_AUDMUX_V2_PTCR_RFSEL(AUD_PORT_4) | IMX_AUDMUX_V2_PTCR_RCLKDIR | IMX_AUDMUX_V2_PTCR_RCSEL(AUD_PORT_4) | IMX_AUDMUX_V2_PTCR_SYN)
			(IMX_AUDMUX_V2_PDCR_RXDSEL(AUD_PORT_4))
		>;
	};
	aud4 {
		fsl,audmux-port = <AUD_PORT_4>;
		fsl,port-config = <
			(IMX_AUDMUX_V2_PTCR_SYN)
			(IMX_AUDMUX_V2_PDCR_RXDSEL(AUD_PORT_2))
		>;
	};
};

&i2c2 {
	/delete-node/ sgtl5000@a;
};

&ssi2 {
	status = "okay";
};

/{
	/delete-node/ sound;
	
	codec_test: codec_test {
		compatible = "linux,snd-soc-dummy";
		#sound-dai-cells = <0>;
		status = "okay";
	};	

	sound@2 {
		compatible = "simple-audio-card";
		model = "ssi-test";
		ssi-controller = <&ssi2>;
		simple-audio-card,name = "ssi-test";
		simple-audio-card,format="dsp_a";
		simple-audio-card,frame-master = <&codec_test>;
		simple-audio-card,bitclock-master = <&codec_test>;
		
		sound2_ssi: simple-audio-card,cpu {
			sound-dai = <&ssi2>;
			system-clock-frequency = <12288000>;
			dai-tdm-slot-num = <8>;
			dai-tdm-slot-width = <16>;
		};
		sound2codec: simple-audio-card,codec {
			sound-dai = <&codec_test>;
		};
	};
};

When play some sound through the ssi-test soundcard i can see some data on the aud4 TXD output pin with a logic analyzer. But the Data is not synced to the input clock instead it look’s like it is synced to another clock (maybe 44100 from the sgtl1500 driver?).

I have tried several different combinations with different data format (dsp_a, dsp_b, left_justified) and configure the ssi port for i2s-master or i2s-slave with the same result. As the dsp is quite flexible for the input format i just want to see some audio data synced to the input clock.

Do you have any suggestions, what i have missed or wrongly configured?

Best regards
Martin

Dear @mme, how are you?

Thanks for reaching us. Can you please share with us a bit more information about your issue?

  • Which exact image and version are you using? For example, BSP 5.6.0 - Reference Minimal Image
  • Did you check if the ADAU drivers are enabled? From what I understand, they are not enabled by default in our images:
$ zcat /proc/config.gz | grep -i adau
# CONFIG_SND_SOC_ADAU1701 is not set
# CONFIG_SND_SOC_ADAU1761_I2C is not set
# CONFIG_SND_SOC_ADAU1761_SPI is not set
# CONFIG_SND_SOC_ADAU7002 is not set
  • I suppose you’re using your own carrier board, right?

Best regards,

Hi @gclaudino.tx, thanks i’m fine and you?

Which exact image and version are you using? For example, BSP 5.6.0 - Reference Minimal Image

Thank you for the fast response.
Im not totally sure about, how to get the correct version, we are using a custom image based on Poky (Yocto Project Reference Distro)

DISTRO = "poky"
DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
DISTRO_VERSION = "3.1.17"
DISTRO_CODENAME = "dunfell"

Did you check if the ADAU drivers are enabled? From what I understand, they are not enabled by default in our images:

Yes you are right. They are deactivated by default. I will activate them. So should i use them instead of the simple-audio-card? As a sidenote: The ADAU1467 is configured via SPI, but this SPI ist not connected to the Colibri Module, instead it is configured by another independent controller. We would just use the Audio interface.

Dear @mme, thanks for the update.

We had a quick chat about it internally and as you’re using another interface to connect it to the module you wouldn’t need them at all. We’d like, however, to suggest one change on the following part of your device tree:

Could you please test using the following fields:

simple-audio-card,frame-master = <&sound2_ssi>;
simple-audio-card,bitclock-master = <&sound2_ssi>;

As your clock is defined on the simple-audio-card, CPU side referencing the codec as you were trying to do may be responsible for the syncing problem. Can you please give it a try?

In addition, which command are you using to build your image? How are you doing it?

Could you also please share with us the output of a dmesg command?

Best regards,

Dear @gclaudino.tx

I have tested to use &sound2_ssi as bitclock-master and frame-master with the same result.

Here you will find the dmesg output:
dmesg.txt (21.9 KB)

We have setup the build repository with kas. The image is build with bitbake bitbake <custom-image-name>. Kas does basicly the same.

For testing the device-tree modifications i did it like described here:

  1. Open Kerne dev shell bitbake virtual/kernel -c devshell
  2. Compile device-tree files make dtbs
  3. Modify device-tree source file custom.dts
  4. Compile custom device-tree file make custom.dtb
  5. Copy compiled device-tree file from $KBUILD_OUTPUT to /boot/ directory of target
  6. Reboot target

If i have a working version, i will then have to include it into my custom layer. But that’s the problem for tomorrow :wink:

Best regards

Dear @mme,

We had another look at your device tree and a few things came to our attention. As you said, you used the Evaluation Board Device Tree as a reference for your project. On it, you can see the following includes:

#include "imx6dl.dtsi"
#include "imx6qdl-colibri.dtsi"

If we take a closer look on the device-trees that have been included we have:

  • on the imx6dl.dtsi we have a include to imx6qdl.dtsi. This file on its time has the definition of the ssi2 interface:
                                ssi2: ssi@202c000 {
                                        #sound-dai-cells = <0>;
                                        compatible = "fsl,imx6q-ssi",
                                                        "fsl,imx51-ssi";
                                        reg = <0x0202c000 0x4000>;
                                        interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6QDL_CLK_SSI2_IPG>,
                                                 <&clks IMX6QDL_CLK_SSI2>;
                                        clock-names = "ipg", "baud";
                                        dmas = <&sdma 41 1 0>,
                                               <&sdma 42 1 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        status = "disabled";
                                };

Therefore, if you have the same includes of the evaluation board, you may run into a few problems while using your device tree.

The first thing that you can see is a label to ssi@202c000 (Device Tree Customization | Toradex Developer Center) where it sets the compatible drivers and a few more things. Therefore, when you use &ssi2, you point to this node. On your device tree, you create a new node named ssi2. With this, these configurations are not transferred to the original node. You should instead use &ssi2 as the node was already created and included.

Can you please have a look at it and check how this affects your issue?

In addition, looking at your dmesg, it seems that the ssi-test device is being loaded without any major errors. Can you see this interface when you run cat /proc/asound/cards?

Lastly, may I ask you why do you use kas? Are there any particular benefits from that approach that we usually don’t have on our base Yocto settings? You’re using our reference images as a base in any case, right? Do you have our meta-layers?

Best regards,
Guilherme

Hi @gclaudino.tx

So if i unserstood you correctly, i created a new label ssi2 inside the audmux which overrides the &ssi2 label from the imx6qdl.dtsi.

To fix it, i have renamed the ssi2 label inside the audmux to audmuxssi2 so the configuration should now apply to the ssi@202c000 node.

But with these change, the Data output is still out of sync with the provided clock.

Yes i can see the interface.

$ cat /proc/asound/cards
 0 [ssitest        ]: ssi-test - ssi-test
                      ssi-test

About kas:
Actually we started with your base Yocto settings using repo. We have brought in an external expert to setup the u-boot configuration for Firmware Updates and he recommendet us to switch over to kas. As he already setup the kas with the same layers and same configuration, we are quite happy with it so far. Main advantage, it inclused the build/conf/local.conf changes directly within the yaml and so can be checked in our source control.

Yes we have a custom image based on your reference images.
Your meta layers are included:

  meta-toradex-bsp-common:
    url : "https://git.toradex.com/meta-toradex-bsp-common.git"
    refspec : dunfell-5.x.y
  meta-toradex-bsp-distros:
    url : "https://git.toradex.com/meta-toradex-distro.git"
    refspec : dunfell-5.x.y
  meta-toradex-bsp-nxp:
    url : "https://git.toradex.com/meta-toradex-nxp.git"
    refspec : dunfell-5.x.y

Dear @mme,

Just to get it clear, are the fsl,audmux-port and the fsl,portconfig intended to be on a separate node? And just as a final check, you now have something like this: audmuxssi2: ssi2? If so, I’d suggest you to give another try and change it to something like: audmuxssi2: not_named_as_ssi2.

If the above doesn’t help you at all, what I’d suggest you right now would be to test it with one of our reference images without any customization.

You can find the recipes to build them under OpenEmbedded Layer Index - meta-toradex-demos.

This way we can try to remove any kernel modification/package modification as a possible problem source. Could you please give it a try using for instance: bitbake tdx-reference-multimedia-image?

Also, thanks for the explanation about kas!

Best regards,

Hi @gclaudino.tx

Sorry for the late reply. It took me some time to setup the environment and adapt all changes to test it.

Now i’m using the tdx-reference-minimal-image where i added
IMAGE_INSTALL += " alsa-utils"

and in the kernel menuconfig activate:

SND_SIMPLE_CARD=y
SND_SIMPLE_CARD_UTILS=y

But i still have the same issue, that the AUD4 Data is not in sync with the provided input clock.

Attached you will find the actual device-tree file and also the dmesg output.

imx6dl-colibri-custom-board.dts (7.0 KB)
dmesg.txt (18.8 KB)

One thing i found was the message:
[ 2.708275] debugfs: Directory '202c000.ssi' with parent 'ssi-test' already present!

I don’t know exactly what is the reason for this, but maybe it is a hint, that something is not correctly configured.

Best regards.

Dear @mme,

Thanks for the update. Just a small feedback, if you use the tdx-reference-multimedia-image you’d have alsa-utils by default and could also have a folder called sound on your root directory with some samples for you to test. There may be other modules or packages necessary for the sound to work properly.

Would you please also give this a try with the simple card configuration enabled with the tdx-reference-multimedia-image?


If you have a look on the imx6dl.dtsi file you can find that 202c000 is the register address for the SSI2 interface. I’ll check more information about this message.

Best regards,
Guilherme

Hi @gclaudino.tx

I have now used the tdx-reference-multimedia-image for testing with the same result.

If you are interested, here is the Picture of the Logic Analyzer, when playing sound or use the speaker-test command:

Where the Bitclock and LRClock (Frameclock) are generated from the DSP, the Output Signal SDO is far to slow and completly out of sync.

The Error debugfs: Directory '202c000.ssi' with parent 'ssi-test' already present! is still in the dmesg output. Do you have any news for that?
dmesg.txt (19.9 KB)

Best regards
Martin