Apalis iMX6 Support I2S Output to ADAU7002

I would like to interface a ADAU7002 PDM-to-I2S conversions IC to the Apalis iMX6. My initial thought was that this would be possible using the digital audio interface via AUD5 on the X5 connector of the Apalis Evaluation Board if I removed the associated jumpers on X6 to access MXM3_200, MXM3_202, and MXM3_204.

I modified the kernel config to include the ADAU7002 driver:

diff .config .config.new 
3197c3197
< # CONFIG_SND_SOC_ADAU7002 is not set
---
> CONFIG_SND_SOC_ADAU7002=y

And I made the following device tree modifications.

diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
index cfaaa571c158..2400355e1f9d 100644
--- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
@@ -206,6 +206,17 @@
                mux-ext-port = <4>;
        };
 
+       sound_adau7002: sound-adau7002 {
+               compatible = "adi,adau7002";
+               model = "imx6q-apalis-adau7002";
+               cpu-dai = <&ssi2>;
+               audio-codec = <&adau7002>;
+               audio-routing =
+                       "PDM_DAT", "Digital Mics";
+               mux-int-port = <2>;
+               mux-ext-port = <5>;
+       };
+
        sound_hdmi: sound-hdmi {
                compatible = "fsl,imx6q-audio-hdmi",
                             "fsl,imx-audio-hdmi";
@@ -439,6 +450,12 @@
                VDDD-supply =<&reg_1p8v>;
        };
 
+       adau7002: pdm-to-i2s {
+               compatible = "adi,adau7002";
+               // Commenting this out indicates supply pin is hardwired always on.
+               //IOVDD-supply = <&reg_3p3v>;
+       };
+
        /* STMPE811 touch screen controller */
        stmpe811@41 {
                compatible = "st,stmpe811";
@@ -665,6 +682,10 @@
        status = "okay";
 };
 
+&ssi2 {
+       status = "okay";
+};
+
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1_dte &pinctrl_uart1_ctrl>;
@@ -813,6 +834,11 @@
                        MX6QDL_PAD_DISP0_DAT23__AUD4_RXD        PAD_CTRL_HYS_PD
                        /* SGTL5000 sys_mclk */
                        MX6QDL_PAD_GPIO_5__CCM_CLKO1            PAD_CTRL_HYS_PD
+
+                       /* AUD5 for ADAU7002. */
+                       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD        PAD_CTRL_HYS_PD
+                       MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS       PAD_CTRL_HYS_PD
+                       MX6QDL_PAD_DISP0_DAT16__AUD5_TXC        PAD_CTRL_HYS_PD
                >;
        };

With these changes, I see the following error in the boot console output:

i2c i2c-2: of_i2c: invalid reg on /soc/aips-bus@02100000/i2c@021a4000/pdm-to-i2s
i2c i2c-2: Failed to create I2C device for /soc/aips-bus@02100000/i2c@021a4000/pdm-to-i2s

However, I didn’t think that an I2C device needed to be associated with the adau7002. Here is the device tree doc for that driver from the kernel:

cat Documentation/devicetree/bindings/sound/adi,adau7002.txt 
Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter

Required properties:

 - compatible: Must be "adi,adau7002"

Optional properties:

 - IOVDD-supply: Phandle and specifier for the power supply providing the IOVDD
        supply as covered in Documentation/devicetree/bindings/regulator/regulator.txt

        If this property is not present it is assumed that the supply pin is
        hardwired to always on.

Example:
        adau7002: pdm-to-i2s {
                compatible = "adi,adau7002";
                IOVDD-supply = <&supply>;
        };

Do you know why I am getting this I2C error?
Is my approach correct (and possible) with the Apalis iMX6?

Thanks.

I believe your approach has currently several misconceptions:

  1. As you add such device on the carrier board level you should not be messing with the module level device tree.
  2. As your device does not seem to feature any out-of-band I2C control interface, you should not add it as a I2C bus sub device device tree node but rather an independent one.
  3. Adding a low-level audio device in Linux always requires multiple device tree nodes. One for the CPU side of things also taking care of the pin muxing. And one for the codec side of things in your case that AUD thingy. On the top level it requires an audio routing entry linking those former two which in your case may be as simple as a simple card device.

http://git.toradex.com/cgit/linux-toradex.git/tree/Documentation/devicetree/bindings/sound/simple-card.txt?h=toradex_4.9-2.3.x-imx

Thanks for being willing to give this high level course correction. I knew that I’d want to move my changes out of the module level device tree once I got things working, but pointing out this use of the simple card device really clarified things for me, and the i2c bus sub device was a poor oversight on my part as I’m coming up to speed on all this. I also see that arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi is doing this with simple card device as you suggest so I’ll dig into that as a reference.

You are very welcome.

Perfect that it works. Thanks for your Input.

For what it’s worth, I did recently get back to this task and following your guidance I was successful in getting the ADAU7002 working using the simple-card device. I had to enable the drivers in the kernel config and then the following device tree patch worked and I captured good sounding recordings. I know this isn’t the proper place for the change in the device tree hierarchy and I plan to go back and rework how I’m managing that along with some other changes I have at the module level device tree, but I figured I’d share the working changes at this point anyway. Thanks for the guidance!

diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
index cfaaa571c158..d15bcade92dc 100644
--- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
@@ -42,6 +42,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
 
 / {
 	model = "Toradex Apalis iMX6Q/D Module";
@@ -206,6 +207,44 @@
 		mux-ext-port = <4>;
 	};
 
+	sound_adau7002: sound-adau7002 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "DigitalMics";
+
+		simple-audio-card,format = "i2s";
+
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack";
+
+		// Maybe adde widget: PDM
+		simple-audio-card,routing =
+		 	"PDM_DAT", "Digital Mics";
+
+		// The SSI2 is the I2S master.
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+
+		status = "okay";
+
+		dailink_master: simple-audio-card,cpu {
+			sound-dai = <&ssi2>;
+    	        	system-clock-frequency = <883200>;
+		};
+
+		dailink_slave: simple-audio-card,codec {
+			sound-dai = <&adau7002>;
+		};
+	};
+
+	adau7002: pdm-to-i2s {
+		#sound-dai-cells = <0>;
+		#address-cells = <0>;
+               	#size-cells = <0>;
+		compatible = "adi,adau7002";
+		status = "okay";
+		//IOVDD-supply = <&reg_3p3v>;
+	};
+
 	sound_hdmi: sound-hdmi {
 		compatible = "fsl,imx6q-audio-hdmi",
 			     "fsl,imx-audio-hdmi";
@@ -243,6 +282,25 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_audmux>;
 	status = "okay";
+
+	ssi2 {
+		fsl,audmux-port = <MX31_AUDMUX_PORT2_SSI1>;
+     		fsl,port-config = <
+		 	0x00000000
+         		IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5)
+		 >;
+	};
+
+	aud5 {
+		fsl,audmux-port = <MX31_AUDMUX_PORT5_SSI_PINS_5>;
+      	fsl,port-config = <
+		  (IMX_AUDMUX_V2_PTCR_TFSDIR |
+          IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT2_SSI1) |
+          IMX_AUDMUX_V2_PTCR_TCLKDIR |
+          IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT2_SSI1))
+          IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT2_SSI1)
+		  >;
+	};
 };
 
 &can1 {
@@ -665,6 +723,14 @@
 	status = "okay";
 };
 
+&ssi2 {
+      	fsl,mode = "i2s-master";
+      	assigned-clocks = <&clks IMX6QDL_CLK_SSI2_SEL>, <&clks IMX6QDL_CLK_SSI2>;
+      	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+      	assigned-clock-rates = <0>, <49152000>; // 48kHz on SSI1 clock
+      	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1_dte &pinctrl_uart1_ctrl>;
@@ -813,6 +879,12 @@
 			MX6QDL_PAD_DISP0_DAT23__AUD4_RXD	PAD_CTRL_HYS_PD
 			/* SGTL5000 sys_mclk */
 			MX6QDL_PAD_GPIO_5__CCM_CLKO1		PAD_CTRL_HYS_PD
+
+			/* AUD5 for ADAU7002. */
+			MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 	PAD_CTRL_HYS_PD
+			MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 	PAD_CTRL_HYS_PD
+			MX6QDL_PAD_DISP0_DAT16__AUD5_TXC  	PAD_CTRL_HYS_PD
+			MX6QDL_PAD_DISP0_DAT17__AUD5_TXD  	PAD_CTRL_HYS_PD
 		>;
 	};