Issue regarding adding TLV320AIC3204 audio codecs on an i.MX7D with Latest Kernel Sources

I am currently working on bringing up two TLV320AIC3204 audio codecs on an i.MX7D running Linux kernel 6.1. Both codecs are physically present on the I2C bus and are detected via i2cdetect, however only one codec at a time is registering as a sound card in ALSA (aplay -l).

Both codecs are on different i2c buses but with same register address.

       
sound {
 			compatible = "simple-audio-card";
 			simple-audio-card,name = "tlv320aic32x4";
 			simple-audio-card,format = "i2s";
 			simple-audio-card,bitclock-master = <&dailink_master_cpu>;
 			simple-audio-card,frame-master = <&dailink_master_cpu>;
                         simple-audio-card,widgets =
 			"Microphone", "Mic Jack",
 			"Line", "Line In",
 			"Line", "Line Out",
 			"Headphone", "Headphone Jack";
 			simple-audio-card,routing =
 			"IN1_L", "Line In",
 			"IN1_R", "Line In",
 			"IN3_R", "Mic Jack",
 			"CM_L", "Mic Jack",
 			"CM_R", "Mic Jack",
 			"Line Out", "LOL",
 			"Line Out", "LOR",
 			"Headphone Jack", "HPL",
 			"Headphone Jack", "HPR";
 			dailink_master_cpu: simple-audio-card,cpu {
                                           sound-dai = <&sai3>;
 						//clocks = <&clks IMX7D_SAI3_ROOT_CLK>;						
                                          clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
                                         clock-names = "mclk";
                                              };
                          simple-audio-card,codec {
                                           sound-dai = <&codec_tlv>;
                                          system-clock-frequency= <12288000>;
 						//clocks = <&clks IMX7D_SAI3_ROOT_CLK>;					                                         
                                              };
                   };
	

		
sound1 {
		compatible = "simple-audio-card";
		simple-audio-card,name = "tlv320aic32x4_1";
		simple-audio-card,format = "i2s";
		simple-audio-card,bitclock-master = <&master_sai2>;
		simple-audio-card,frame-master = <&master_sai2>;
                     simple-audio-card,widgets =
		"Microphone", "Mic Jack",
		"Line", "Line In",
		"Line", "Line Out",
		"Headphone", "Headphone Jack";
		simple-audio-card,routing =
		"IN1_L", "Line In",
		"IN1_R", "Line In",
		"IN3_R", "Mic Jack",
		"CM_L", "Mic Jack",
		"CM_R", "Mic Jack",
		"Line Out", "LOL",
		"Line Out", "LOR",
		"Headphone Jack", "HPL",
		"Headphone Jack", "HPR";
		
		master_sai2: simple-audio-card,cpu {
                                       sound-dai = <&sai2>;
                                        clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
                                     clock-names = "mclk";
                                      
                                          };
                                          
                                            simple-audio-card,codec {
                                        sound-dai = <&codec_tlv2>;
                                       system-clock-frequency= <12288000>;
                                       //clocks = <&clks IMX7D_SAI2_ROOT_CLK>;
                                      
                                               };

&clks {
assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
assigned-clock-rates = <626688000>;

};

&sai3 {
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_sai3 &pinctrl_sai3_mclk>;
assigned-clocks = <&clks IMX7D_SAI3_ROOT_SRC>,
<&clks IMX7D_SAI3_ROOT_CLK>;
//<&clks IMX7D_PLL_AUDIO_POST_DIV>;
assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
assigned-clock-rates = <0>, <36864000>;
//assigned-clock-rates = <0>, <12288000>;
fsl,sai-mclk-direction-output;

status = "okay";

};

&sai2 {
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_sai2 &pinctrl_sai2_mclk>;
assigned-clocks = <&clks IMX7D_SAI2_ROOT_SRC>,
<&clks IMX7D_SAI2_ROOT_CLK>;
//<&clks IMX7D_PLL_AUDIO_POST_DIV>;
assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
assigned-clock-rates = <0>, <36864000>;
fsl,sai-mclk-direction-output;
//assigned-clock-rates = <0>, <12288000>;
status = “okay”;
};
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = “default”, “gpio”;
pinctrl-0 = <&pinctrl_i2c2>;
pinctrl-1 = <&pinctrl_i2c2_recovery>;
scl-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = “okay”;

    codec_tlv: tlv320aic32x4@18 {
	compatible = "ti,tlv320aic32x4";
	#sound-dai-cells = <0>;
	reg = <0x18>;
	//clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
	clocks = <&clks IMX7D_SAI3_ROOT_CLK>;
	clock-names = "mclk";
	//clock-names = "mclk";
	//pinctrl-names = "default";
	status = "okay";

	ldoin-supply = <&reg_module_3v3>;
	iov-supply = <&reg_module_3v3>;
         };

};

&i2c3 {
clock-frequency = <100000>;
pinctrl-names = “default”, “gpio”;
//pinctrl-0 = <&pinctrl_i2c4>;
//pinctrl-1 = <&pinctrl_i2c4_recovery>;
//scl-gpios = <&gpio7 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
//sda-gpios = <&gpio7 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_recovery>;
scl-gpios = <&gpio1 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio1 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = “okay”;

    codec_tlv2: tlv320aic32x4@18 {
	compatible = "ti,tlv320aic32x4";
	#sound-dai-cells = <0>;
	reg = <0x18>;
	//clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
	clocks = <&clks IMX7D_SAI2_ROOT_CLK>;
	clock-names = "mclk";
	//pinctrl-names = "default";
	status = "okay";
	
	 //avdd-supply  = <&reg_module_3v3>;
	 //   dvdd-supply  = <&reg_module_3v3>;
	    iov-supply   = <&reg_module_3v3>;
	    ldoin-supply = <&reg_module_3v3>;
		     };

};

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


I’d be glad to help! Could you let me know which OS and version you are using? This will help me provide the most accurate guidance for your dual TLV320AIC3204 codec setup on i.MX7D.

To get this information quickly, you can run the tdx-info command on your device. You can find more details about this command at tdx-info.

Understanding your specific platform configuration will allow me to provide targeted advice for your audio codec device tree configuration and ALSA setup.

Best regards,
Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Provided Which OS and Version below.

cat /etc/os-release
PRETTY_NAME=“Ubuntu 22.04.5 LTS”
NAME=“Ubuntu”
VERSION_ID=“22.04”
VERSION=“22.04.5 LTS (Jammy Jellyfish)”
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL=“https://www.ubuntu.com/

UBUNTU_CODENAME=jammy
medha@C2662:~/Desktop/YOCTO-NXP/oe-core/build$ uname -a
Linux C2662 6.8.0-90-generic #91~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 15:20:45 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
medha@C2662:~/Desktop/YOCTO-NXP/oe-core/build$ uname -r
6.8.0-90-generic
medha@C2662:~/Desktop/YOCTO-NXP/oe-core/build$

root@colibri-imx7-emmc-mcp:~# uname -a
Linux colibri-imx7-emmc-mcp 6.1.154-6.8.4-devel+git.7b34dc04e4ff #1 SMP Thu Jan 8 05:45:43 UTC 2026 armv7l armv7l armv7l GNU/Linux

I can see you’re working with a Colibri iMX7 module running a Linux kernel 6.1 with dual TLV320AIC3204 audio codecs. Your device tree configuration looks mostly correct, but there are some potential issues that could prevent both codecs from registering simultaneously in ALSA.

Common Issues with Multiple Audio Codecs

Based on your device tree configuration, here are the key areas to review:

1. Unique Sound Card Names

Your sound cards have different names (tlv320aic32x4 and tlv320aic32x4_1), which is correct (1).

2. Clock Configuration

Both codecs are using different SAI clocks, which is appropriate:

  • First codec uses IMX7D_SAI3_ROOT_CLK
  • Second codec uses IMX7D_SAI2_ROOT_CLK

3. Device Tree Structure Verification

To ensure your device tree modifications are properly applied, you can compile and deploy them following the process outlined in the documentation (1).

Troubleshooting Steps

Check Current Registration Status

First, verify which codec is currently active:

cat /proc/asound/cards
dmesg | grep -i tlv320

Verify I2C Detection

Since you mentioned both codecs are detected via i2cdetect, confirm they’re on different buses:

i2cdetect -y 2  # For codec on i2c2
i2cdetect -y 3  # For codec on i2c3

Review Device Tree Compilation

Ensure your custom device tree is properly compiled and deployed. The documentation provides guidance on compiling device trees with the DTC tool (1):

make DTC_FLAGS="-@" <device-tree>.dtb

Potential Solutions

  1. Check for conflicting driver instances - The kernel might be treating both codecs as the same device due to identical compatible strings and register addresses.

  2. Verify power supply configuration - I notice slight differences in your power supply configurations between the two codecs. Ensure both have consistent supply configurations.

  3. Review kernel logs for any error messages during codec initialization that might indicate why only one is registering.

The device tree structure you’ve provided follows the correct format for multiple audio devices as described in the Toradex documentation for device tree customization (1).

Best regards,
Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Device Tree Requirements for Recent Kernel Versions

For the Linux kernel 6.1 you’re using, there are some important considerations when adding audio codecs compared to older kernel versions:

Device Tree Binding Requirements

The device tree structure you’ve provided follows the correct format for device customization as described in the documentation (1). However, ensure you’re referencing the correct device tree bindings for your kernel version.

For your i.MX7D platform, the device tree files are typically located in the /arch/arm/boot/dts/nxp/ directory (2). The documentation shows that device trees follow a three-level structure:

  1. SoC level: Include files (*.dtsi) containing SoC-level definitions (1)
  2. SoM level: Include files (*.dtsi) containing specific SoM-level definitions (1)
  3. Board level: Files for board-level definitions (1)

Compilation Requirements

When compiling your device tree for recent kernel versions, use the DTC_FLAGS parameter as shown in the documentation (3):

make DTC_FLAGS="-@" <device-tree>.dtb

(3)

Key Properties to Verify

Ensure your device tree includes all standard properties for device nodes (1):

  • compatible: Define the specific programming model for the device (1)
  • status: Indicate operational status (“okay” or “disabled”) (1)
  • reg: Describe the address of device resources (1)
  • #sound-dai-cells: Required for audio devices (1)

Communicating with Toradex Community

You’re already communicating with the Toradex community effectively by:

  1. Using @ToradexAI: You can tag me using @ToradexAI for AI assistance
  2. Community Forum: You’re currently using the community forum platform
  3. Providing Details: Include your hardware setup, OS version, and device tree configuration as you’ve done

For additional community interaction, other community members will see your posts and may provide additional insights based on their experience.

Your device tree configuration appears to follow the correct structure for multiple audio codecs. The main areas to focus on for troubleshooting would be ensuring proper clock configuration and verifying that both codec drivers are loading correctly in the kernel logs.

Best regards,
Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Hello @RAKESH_BOINI ,
As discussed on call, the issue has been solved and I am closing this ticket