This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TAS2110: TAS2110/TAS2562 device tree for imx8m mini

Part Number: TAS2110
Other Parts Discussed in Thread: TAS2562, TAS2563

Hello,

we have designed a custom board with the NXP iMX8M Mini processor and the TAS2110 audio amp. We are using YOCTO to build the Linux Kernel.

From this thread I learned that the TAS2562 driver can be used for TAS2110.

The driver repo contains information on how the device tree node for I2C needs to look like:

tas2562:tas2562@4c {
	#sound-dai-cells = <0>;
	compatible = "ti,tas2562";
	reg = <0x4c>;
	ti,left-channel = <0x4c>;
	ti,right-channel = <0x4d>;
	ti,channels = <2>; /* channel number */
	ti,reset-gpio = <&gpio1 17 0>;
	ti,reset-gpio2 = <&gpio1 16 0>;
	ti,irq-gpio = <&gpio1 15 0>;
	ti,irq-gpio2 = <&gpio1 14 0>;
	status = "ok";
};

This is fairly straight forward. However, it seems like the device tree is missing essential parts.

We still need to connect the I2S interface (of TAS2110) to the SAI interface (of iMX) as well as expose that to the Linux Kernel (some sort of sound device).

Iwould have assumed something along the lines of:

/* ??? */
sound-tas2562 { compatible = "???"; audio-cpu = <&sai5>; audio-codec = <&tas2562>; }; &sai5 { #sound-dai-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai5>; fsl,mode = "i2s-master"; status = "okay"; }; &iomuxc { /* ... */ pinctrl_sai5: sai5grp { fsl,pins = < MX8MM_IOMUXC_SAI5_RXD1_SAI5_TX_SYNC 0xd6 /* FSYNC */ MX8MM_IOMUXC_SAI5_RXD2_SAI5_TX_BCLK 0xd6 /* SBLCK */ MX8MM_IOMUXC_SAI5_RXD3_SAI5_TX_DATA0 0xd6 /* SDIN */ >; }; }; &i2c1 { status = "okay"; clock-frequency = <400000>; /* using mono example from dts.readme in TI driver repo */ tas2562:tas2562@4c { #sound-dai-cells = <0>; compatible = "ti,tas2562"; reg = <0x4c>; ti,left-channel = <0x4c>; ti,channels = <1>; /* channel number */ ti,reset-gpio = <&gpio1 15 0>; status = "ok"; ti,iv-width = <16>; /* IV sense by default is set to 16 bit, in case of power Limiter it should be 12*/ ti,vbat-mon = <0>; /* By default Vbat should be 0, in case os power limiter it should be 1*/ }; };

The driver repo also contains dai_link.readme:

example for connecting CPU DAI

#elif defined(CONFIG_TAS2562_CODEC)    
    {
        .name = LPASS_BE_PRI_MI2S_RX,
        .stream_name = "Primary MI2S Hostless Playback",
        .cpu_dai_name = "msm-dai-q6-mi2s.0",
        .platform_name = "msm-pcm-routing",
        .codec_name     = "tas2562.3-004e",
        .codec_dai_name = "tas2562 ASI1",
        .no_pcm = 1,
        .be_id = MSM_BACKEND_DAI_PRI_MI2S_RX,
        .be_hw_params_fixup = msm_be_prim_mi2s_hw_params_fixup,
        .ops = &XXXX_prim_mi2s_be_ops,
    },
    {
        .name = LPASS_BE_PRI_MI2S_TX,
        .stream_name = "Primary MI2S Hostless Capture",
        .cpu_dai_name = "msm-dai-q6-mi2s.0",
        .platform_name = "msm-pcm-routing",
        .codec_name     = "tas2562.3-004e",
        .codec_dai_name = "tas2562 ASI1",
        .no_pcm = 1,
        .be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
        .be_hw_params_fixup = msm_be_prim_mi2s_hw_params_fixup,
        .ops = &XXXX_prim_mi2s_be_ops,
    },    
#endif    

I assume this has to do with what I am looking for, however, I don't really know what to do with it.

TL;DR:

We got TAS2110 (or TAS2562 for all purposes regarding the driver) connected to

  1. I2C -> I2C1
  2. I2S -> SAI5

What should the complete device tree look like? How to make the audio device available in Linux?

Thanks for your help.

  • Hi, Philip,

    Welcome to E2E and thank you for your interest in our products!

    Our team will take a look at this and will answer as soon as possible.

    Best regards,
    Luis Fernando Rodríguez S.

  • Hi Philipp,

    I'll have to get in touch with our software team on this, please allow 2 or 3 days to get feedback on this.

    Best regards,
    -Ivan Salazar
    Audio Applications Engineer - Low Power Audio & Actuators

  • Hi Philipp,

    Feedback form our team is below, please let me know if you have any questions:

    You may as well consult your platform (iMX) vendor about this.

    The attachment is the dts file including tas2563 chip configs from a Amba Linux platform,
    tas256x is connected with i2s0.
    Pay more attention to following config in dts:

                                               codec {
                                                              sound-dai = <&tas2563>;
                                               };

    In fact, we only add tas2563 part into dts file, other configs is helped by Amba.
    Hope the above can help this case

    Best regards,
    -Ivan Salazar
    Audio Applications Engineer - Low Power Audio & Actuators

  • Hey Ivan,

    thank you for your reply.

    You mention an "attachment" but I can't see any. Did you forget to add it to you post?

    Regards,

    Philipp

  • Hi Philipp,

    Let me try to re-attach the file, if not working then I'll reach out through private message.

    Best regards,
    -Ivan Salazar
    Audio Applications Engineer - Low Power Audio & Actuators

    dts.txt
    /*
     * Copyright (C) 2013 Ambarella,Inc. - http://www.ambarella.com/
     * Author: Cao Rongrong <rrcao@ambarella.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    /dts-v1/;
    
    /include/ "ambarella-cv25.dtsi"
    #include "cv25_hazelnut_private.dtsi"
    #include "config.h"
    #include "bsp.h"
    
    / {
    	model = "Ambarella CV25 Hazelnut Board";
    	compatible = "ambarella,cv25_hazelnut", "ambarella,cv25";
    
    	chosen {
    #if defined(CONFIG_AMBARELLA_ROOTFS_CPIO)
    		bootargs = "console=ttyS0";
    #else
    		bootargs = "console=ttyS0 ubi.mtd=lnx root=ubi0:rootfs rw rootfstype=ubifs init=/linuxrc";
    #endif
    	};
    
    	n_apb@e4000000 {
    		i2c0: i2c@e4008000 {
    			status = "ok";
    
    			tas2563: codec@4c {
    				compatible = "ti,tas2563";
    				#sound-dai-cells = <0>;
    				reg = <0x4c>;
    				ti,asi-format = <1>; /* 0, i2S; 1, DSP;  */
    				ti,reset-gpio = <&pca9539 16 0>;
    				ti,irq-gpio = <&pca9539 15 0>;
    				ti,left-slot = <0>; /* <left slot number> */
    				ti,right-slot = <1>; /* <right slot number> */
    				ti,imon-slot-no = <0>; /* <current sense slot number> */
    				ti,vmon-slot-no = <2>; /* <current voltage slot number> */
    				ti,i2s-bits = <16>;   /* support 16, 24, 32 */
    				ti,bypass-tmax = <0>;   /* 0, not bypass; 1, bypass */
    				status = "ok";
    			};
    
    		};
    
    		i2c1: i2c@e4009000 {
    			status = "ok";
    			pinctrl-0 = <&i2c1_pins_b>;
    		};
    		i2c2: i2c@e400a000 {
    			status = "ok";
    			pinctrl-0 = <&i2c2_pins_b>;
    			it66121@4c {
    				compatible = "it66121";
    				reg = <0x4c>;
    				rst_gpios = <&pca9539 3 0x0>;
    			};
    		};
    
    		i2c3: i2c@e400b000 {
    			status = "ok";
    
    			pca9539: pca9539@74 {
    				compatible = "nxp,pca9539";
    				reg = <0x74>;
    				gpio-controller;
    				interrupt-parent = <&gpio>;
    				interrupt-controller;
    				#gpio-cells = <2>;
    				interrupts = <9 0x0>;
    			};
    
    			isl12022: rtc@6f {
    				compatible = "isil,isl12022";
    				reg = <0x6f>;
    			};
    
    			ambvin1@01 {
    				compatible = "ambarella,ambvin";
    				reg = <0x01>;	/* fake address, will be overwritten in runtime */
    			};
    		};
    	};
    
    	n_ahb@e0000000 {
    #if defined(CONFIG_BOOT_MEDIA_STACK)
    		nand0: nand@e0002000 {
    			status = "disabled";
    		};
    #endif
    
    		sdmmc0: sdmmc0@e0004000 {
    			pwr-gpios = <&gpio 81 0x1>;
    			v18-gpios = <&gpio 105 0x1>;
    #if defined(CONFIG_BOOT_MEDIA_EMMC) || defined(CONFIG_BOOT_MEDIA_STACK)
    			amb,fixed-cd = <1>;
    #endif
    		};
    
    		sdmmc1: sdmmc1@e0005000 {
    			status = "disabled";
    		};
    
    		sdmmc2: sdmmc2@e0016000 {
    			status = "disabled";
    		};
    
    		mac0: ethernet@e000e000 {
    			pinctrl-0 = <&rgmii_pins &enet_2nd_ref_clk_pins_a>;
    			amb,ahb-12mhz-div = <5>;
    			amb,tx-clk-invert;
    			phy@0 {
    				reg = <0>;
    				rst-gpios = <&pca9539 11 0>;
    			};
    		};
    
    		spi0: spi@e0011000 {
    #if defined(CONFIG_BRIDGE_SERDES_B5) || defined(CONFIG_BRIDGE_SERDES_B6)
    			status = "ok";
    #else
    			status = "disabled";
    #endif
    
    #if defined(BUILD_GYRO)
    			cs-gpios = <&gpio 7 0>;
    			ambvin0@0 {
    				compatible = "ambarella,ambvin";
    				reg = <0>;
    				spi-max-frequency = <1000000>;
    				spi-cpha;
    				spi-cpol;
    			};
    #else
    			cs-gpios = <&gpio 7 0>, <&gpio 8 0>;
    
    			ambvin0@0 {
    				compatible = "ambarella,ambvin";
    				reg = <0>;
    				spi-max-frequency = <1000000>;
    				spi-cpha;
    				spi-cpol;
    			};
    
    			ambvin1@0 {
    				compatible = "ambarella,ambvin";
    				reg = <1>;
    				spi-max-frequency = <1000000>;
    				spi-cpha;
    				spi-cpol;
    			};
    #endif
    		};
    
    		spi1: spi@e0012000 {
    			status = "ok";
    			cs-gpios = <&gpio 78 0>;
    
    			gyro@0 {
    				compatible = "ambarella,gyro";
    				reg = <0>;
    				spi-max-frequency = <20000000>;
    				spi-cpha;
    				spi-cpol;
    				irq-gpio = <&gpio 8 0>;
    			};
    		};
    
    		i2s0: i2s@e001d000 {
    			amb,i2s-channels = <4>;
    		};
    
    		hdmi@e000b000 {
    			amb,i2c-adapter = <1>;
    		};
    
    		uart2: uart@e0018000 {
    			status = "ok";
    			/delete-property/ amb,msr-used;
    			/delete-property/ amb,txdma-used;
    			/delete-property/ amb,rxdma-used;
    		};
    
    	};
    
    	s_ahb@e8000000 { /* Secure AHB, but configurable */
    		rtc@e8001000 {
    			status = "disabled";
    		};
    	};
    
    	rct@ed080000 {
    		usbphy: usbphy@ed080050 {
    			/* high will trigger the ocp interrupt */
    			amb,ocp-polarity = <0>;
    			pinctrl-names = "default";
    			pinctrl-0 = <&usb_host0_pins_a>;
    			hub-gpios = <&pca9539 10 0>;
    		};
    	};
    
    	bogus_bus {
    		pwm_bl@0 {
    			compatible = "pwm-backlight";
    			reg = <0>;
    			pwms = <&pwm0 0 40000 0>;
    			pinctrl-names = "default";
    			pinctrl-0 = <&pwm0_pins_c>;
    			brightness-levels = <0 4 8 16 32 64 128 255>;
    			default-brightness-level = <7>;
    			status = "disabled";
    		};
    
    		dummycodec: codec@0 {
     			compatible = "ambarella,dummycodec";
     			reg = <0>;
    			#sound-dai-cells = <0>;
    		};
    	};
    
    	iav {
    		/* node for vin controller */
    		vinc0 {
    			vinrst-gpios = <&gpio 84 0>;
    			/* vinpwr-gpios = <>; */
    		};
    		vinc1 {
                            vinrst-gpios = <&gpio 19 0>;
                            /* vinpwr-gpios = <>; */
    		};
    
    		/* node for vin bridge */
    		vinbrg0 {
    			compatible = "ambarella,vinbrg";
    #if defined(CONFIG_BRIDGE_SERDES_B5) || defined(CONFIG_BRIDGE_SERDES_B6)
    			brgrst-gpios = <&pca9539 1 0>;
    #else
    			brgpwr-gpios = <&gpio 6 1>;
    			brgrst-gpios = <&gpio 4 0>, <&pca9539 1 0>;
    #endif
    			bus-addr = <0x00000>;
    		};
    
    		vinbrg1 {
    			compatible = "ambarella,vinbrg";
    #if defined(CONFIG_BRIDGE_SERDES_B5) || defined(CONFIG_BRIDGE_SERDES_B6)
    			brgrst-gpios = <&pca9539 0 0>;
    #else
    			brgpwr-gpios = <&gpio 6 1>;
    			brgrst-gpios = <&gpio 5 0>, <&pca9539 0 0>;
    #endif
    			bus-addr = <0x00001>;
    		};
    
    		/* node for lcd md092ml04 */
    		lcd_md092ml04 {
    			compatible = "ambarella,lcd_md092ml04";
    			pwr-gpios = <&pca9539 7 1>;
    			backlight-gpios = <&gpio 42 1>;
    		};
    
    		voutc0 {
    			pinctrl-names;
    			pinctrl-0;
    		};
    	};
    
    
    	sound {
    		compatible = "ambarella,audio-board";
    		simple-audio-card,name = "tas2563 @ AMBEVK";
    		simple-audio-card,mclk-fs = <256>;
    		simple-audio-card,widgets =
    		"Speaker", "Speaker",
    		 "Headphone", "HP Jack",
    		 "Line", "Line In",
    		"Line", "Line Out",
    		 "Microphone", "Mic Internal",
    		"Microphone", "Mic External";
    		simple-audio-card,routing =
    		 "LIN2", "Mic Bias",
    		 "RIN2", "Mic Bias",
    		 "Mic Bias", "Mic Internal",
    		"LIN3", "Line In",
    		 "RIN3", "Line In",
    		 "Line Out", "SPKLO",
    		 "HP Jack", "HPL",
    		 "HP Jack", "HPR",
    		 "Speaker", "SPKLO";
    
    		simple-audio-card,dai-link@0 {
    			format = "dsp_a";
    
    			cpu {
    				sound-dai = <&i2s0>;
    			};
    
    			codec {
    				sound-dai = <&tas2563>;
    			};
    		};
    
    		simple-audio-card,dai-link@1 {
    			format = "dsp_a";
    
    			cpu {
    				sound-dai = <&i2s0>;
    			};
    
    			codec {
    				sound-dai = <&dummycodec>;
    			};
    		};
    	};
    };

  • Hello Phillip

    Unfortunately the DTS example attached is not for the driver you backported from the 5.8 kernel.  The 5.8 upstream driver does not have these dt entries.

    Please take a look at the upstream DT documentation it has an example of the TAS2562 DT and as Ivan pointed out that for the ASI/I2S/I2C buses and sound card we respectfully ask you to ping NXP for their setup as their pinmux and sound cards are different from what TI implemented.  For my testing I just used a simple sound card dt entry.

  • Hello everyone,

    thank you Dan and Ivan for your input. After some trial-and-error I was finally able to get it to work.

    So here is our solution:

    1. Like Dan already mentioned, we backported the TAS2562 driver from mainline 5.8 to our linux-imx 5.4. This required two minor changes which don't affect the driver but were simply necessary to get it to compile.

    2. I got it to work with "simple-audio-card". The relevant device tree parts looks like this:

    // Sound device
    sound-tas2562 {
    	compatible = "simple-audio-card";
    	simple-audio-card,name = "tas2562";
    	simple-audio-card,format = "i2s";
    	simple-audio-card,bitclock-inversion;
    	simple-audio-card,frame-master = <&tas2562cpu>;
    	simple-audio-card,bitclock-master = <&tas2562cpu>;
    	
    	tas2562cpu: simple-audio-card,cpu {
    		sound-dai = <&sai5>;
    		dai-tdm-slot-num = <2>;
    		dai-tdm-slot-width = <16>;
    	};
    
    	simple-audio-card,codec {
    		sound-dai = <&audio_amp>;
    	};
    };
    
    
    // Audio Amp I2S
    &sai5 {
    	#sound-dai-cells = <0>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_sai5>;
    	assigned-clocks = <&clk IMX8MM_CLK_SAI5>;
    	assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
    	assigned-clock-rates = <24576000>;
    	status = "okay";
    };
    
    
    // Audio Amp I2C
    &i2c1 {
    	clock-frequency = <400000>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_i2c1>;
    	status = "okay";
    	
    	// Audio Amp
    	audio_amp: tas2562@4c {
    		#sound-dai-cells = <0>;
    		reg = <0x4c>;
            compatible = "ti,tas2562";
    		shutdown-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; // <-- this is strange
            ti,imon-slot-no = <0>;
            ti,vmon-slot-no = <1>;
    		status = "okay";
    	};
    };
    
    
    &iomuxc {
    
        // I2C1 Audio Amp
    	pinctrl_i2c1: i2c1grp {
    		fsl,pins = <
    			MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL			0x400001c3
    			MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA			0x400001c3
    		>;
    	};
    	
    	// I2S Audio Amp
    	pinctrl_sai5: sai5grp {
    		fsl,pins = <
    			MX8MM_IOMUXC_SAI5_RXD1_SAI5_TX_SYNC		0xd6 /* FSYNC */
    			MX8MM_IOMUXC_SAI5_RXD2_SAI5_TX_BCLK		        0xd6 /* SBLCK */
    			MX8MM_IOMUXC_SAI5_RXD3_SAI5_TX_DATA0		0xd6 /* SDIN */
    		>;
    	};
    };

    For some reason it only works when the shutdown pin (SDZ) is configured ACTIVE_HIGH instead of ACTIVE_LOW, because otherwise it is permanently held low and the amp shutdown the entire time.

    Most importantly, I can confirm that the TAS2562 driver works for the TAS2110 as well.

    I hope others find this helpful.

    Phil