Hello,
I am integrating a TLV320AIC3104 sound codec (I2S) into a custom BeagleY-AI hat we have built for a computer science embedded systems course I am teaching. I have made a custom device tree overlay but am unable to have Linux successfully detect the TLV320AIC3104 chip.
Problems:
- Linux won’t load the
tlv320aic3x
driver at boot: gives “platform sound1: deferred probe pending”. - Sound does not work (when tested with
speaker-test
)
What I have succeeded at:
- Create a device tree overlay and have it load at startup (included below). It shows up in /proc/device-tree/chosen/overlays/
- Compile the TLV320AIC3104 driver (not compiled in default BYAI image):
CONFIG_SND_SOC_TLV320AIC3X_I2C=m
in kernel config, buildssnd-soc-tlv320aic3x.ko
andsnd-soc-tlv320aic3x-i2c.ko
. Copied to/lib/modules/6.1.83-ti-arm64-r63/kernel/sound/soc/codecs/
and can be manually loaded withinsmod
. - Once manually loaded, the TLV320AIC3014 device specified by the device tree shows up as a device is
aplay -l
. See below.
I’m struggling to debug the overlay and sound driver configuration. Some specific issues I would like help with include:
1. Reset Line
Three unexpected behaviours with the reset line:
1. Reset line stays at ~0.8v during boot, even when trying to probe.
2. When I manually load the tlv320aic3x.ko driver (with insmod), it pulls the reset line low and holds it low.
3. gpioinfo
shows “active-high”, regardless of if I use GPIO_ACTIVE_LOW
or GPIO_ACTIVE_HIGH
in my device-tree overlay.
reset-gpios
in the device tree overlay (full code below):
&mcu_i2c0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
tlv320aic3104: tlv320aic3104@18 {
#sound-dai-cells = <0>;
compatible = "ti,tlv320aic3104";
reg = <0x18>;
status = "okay";
reset-gpios = <&main_gpio0 36 GPIO_ACTIVE_LOW>;
ai3x-micbias-vg = <2>; // set MICBIAS to 2.5v
AVDD-supply = <&vdd_3v3>;
IOVDD-supply = <&vdd_3v3>;
DRVDD-supply = <&vdd_3v3>;
DVDD-supply = <&vdd_audio_1v8>;
};
};
GPIO26 is the right pin: when its manually driven low, the codec reads X’s with i2cdump; when manually driven high, it reads seemingly valid values.
main_gpio0 36
seems correct: gpioinfo
shows:
line 36: "GPIO26" "tlv320aic3x reset" output active-high [used]
.
But, watching the physical pin with a multimeter, it has the above three unexpected behaviours.
2. Linux is unable to detect the codec
When configured to load the device-tree overlay in extlinux.conf, it seems to try to find the device, but it fails.
dmesg displays:
[ 26.592305] platform sound1: deferred probe pending
$ cat /sys/kernel/debug/devices_deferred
sound1 asoc-simple-card: parse error
When I manually hold the reset line high (externally wired with a pull-up resistor and changed .dts to not use the reset pin), it is still unable to find the device. Hence, it does not automatically load the tlv320aic3x
driver.
I have checked most of the syntax and structure of my overlay against the k3-am625-beaglemod-audio.dts
file and looked into as many differences as I could find but am stuck!
Any suggestions would be very helpful!
Brian.
System Information
BeagleY-AI board
$ uname -a
Linux BeagleBone 6.1.83-ti-arm64-r63 #1bookworm SMP PREEMPT_DYNAMIC Wed Jul 10 23:00:56 UTC 2024 aarch64 GNU/Linux
aplay listing of devices:
$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: HDMI [it66122 HDMI], device 0: davinci-mcasp.0-i2s-hifi i2s-hifi-0 [davinci-mcasp.0-i2s-hifi i2s-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Audio [ZenHat Audio], device 0: davinci-mcasp.0-tlv320aic3x-hifi tlv320aic3x-hifi-0 [davinci-mcasp.0-tlv320aic3x-hifi tlv320aic3x-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
Beagle-Version:
$ sudo beagle-version
eeprom:[BYAI202406002197]
model:[BeagleBoard.org_BeagleY-AI]
dogtag:[BeagleBoard.org Debian Bookworm Minimal Image 2024-09-06]
bootloader:[/dev/mmcblk1]:[/boot/firmware/tiboot3.bin]:[U-Boot SPL 2023.04-g93735daa (Aug 29 2024 - 22:05:30 +0000)]
bootloader:[/dev/mmcblk1]:[/boot/firmware/tispl.bin]:[U-Boot SPL 2023.04-g93735daa (Aug 29 2024 - 22:05:30 +0000)]
bootloader:[/dev/mmcblk1]:[/boot/firmware/u-boot.img]:[U-Boot 2023.04-g93735daa (Aug 29 2024 - 22:05:30 +0000)]
UBOOT: Booted Device-Tree:[k3-am67a-beagley-ai.dts]
UBOOT: Loaded Overlay:[k3-am67asbeaglemod-audio.kernel]
kernel:[6.1.83-ti-arm64-r63]
pkg check: to individually upgrade run: [sudo apt install --only-upgrade <pkg>]
pkg:[bb-u-boot-beagley-ai]:[2023.04.20240319.24-09.02.00.009-0~bookworm+20240829]
pkg:[bb-wl18xx-firmware]:[1.20240622.0-0~bookworm+20240622]
pkg:[bb-customizations]:[1.20240627.0-0~bookworm+20240627]
pkg:[bb-usb-gadgets]:[1.20240717.0-0~bookworm+20240717]
groups:[brian : brian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal input render netdev i2c bluetooth gpio admin tisdk weston-launch cloud9ide]
cmdline:[console=ttyS2,115200n8 root=/dev/mmcblk1p3 ro rootfstype=ext4 resume=/dev/mmcblk1p2 rootwait net.ifnames=0 quiet]
ti-sci:
optee:
wlcore:
wlcore: Wireless driver version 1.7.0.114
wlcore: Wireless firmware version 1.7.0.130
wlcore: Wireless PHY version 1.2.36.5.22.66
dmesg | grep remote
[ 7.095303] k3-dsp-rproc 7e000000.dsp: configured DSP for remoteproc mode
[ 7.095554] remoteproc remoteproc0: 7e000000.dsp is available
[ 7.096567] k3-dsp-rproc 7e000000.dsp: register pm nitifiers in remoteproc mode
[ 7.097715] k3-dsp-rproc 7e200000.dsp: configured DSP for remoteproc mode
[ 7.097958] remoteproc remoteproc1: 7e200000.dsp is available
[ 7.099965] remoteproc remoteproc1: Direct firmware load for j722s-c71_1-fw failed with error -2
[ 7.099965] remoteproc remoteproc0: Direct firmware load for j722s-c71_0-fw failed with error -2
[ 7.100001] remoteproc remoteproc1: powering up 7e200000.dsp
[ 7.100002] remoteproc remoteproc0: powering up 7e000000.dsp
[ 7.100057] remoteproc remoteproc1: Direct firmware load for j722s-c71_1-fw failed with error -2
[ 7.100058] remoteproc remoteproc0: Direct firmware load for j722s-c71_0-fw failed with error -2
[ 7.100067] remoteproc remoteproc0: request_firmware failed: -2
[ 7.100067] remoteproc remoteproc1: request_firmware failed: -2
[ 7.100449] k3-dsp-rproc 7e200000.dsp: register pm nitifiers in remoteproc mode
[ 7.376611] platform 79000000.r5f: configured R5F for remoteproc mode
[ 7.402231] remoteproc remoteproc2: 79000000.r5f is available
[ 7.402599] remoteproc remoteproc2: Direct firmware load for j722s-mcu-r5f0_0-fw failed with error -2
[ 7.402640] remoteproc remoteproc2: powering up 79000000.r5f
[ 7.402696] remoteproc remoteproc2: Direct firmware load for j722s-mcu-r5f0_0-fw failed with error -2
[ 7.402708] remoteproc remoteproc2: request_firmware failed: -2
[ 7.523563] remoteproc remoteproc3: 78000000.r5f is available
[ 7.523700] remoteproc remoteproc3: attaching to 78000000.r5f
[ 7.862551] remoteproc remoteproc3: remote processor 78000000.r5f is now attached
[ 7.883956] platform 78400000.r5f: configured R5F for remoteproc mode
[ 7.886809] remoteproc remoteproc4: 78400000.r5f is available
[ 7.887120] remoteproc remoteproc4: Direct firmware load for j722s-main-r5f0_0-fw failed with error -2
[ 7.887154] remoteproc remoteproc4: powering up 78400000.r5f
[ 7.887274] remoteproc remoteproc4: Direct firmware load for j722s-main-r5f0_0-fw failed with error -2
[ 7.887293] remoteproc remoteproc4: request_firmware failed: -2
[ 12.232427] Modules linked in: cc33xx mac80211 algif_aead rpmsg_ctrl rpmsg_char virtio_rpmsg_bus rpmsg_ns libarc4 crct10dif_ce snd_soc_simple_card snd_soc_simple_card_utils pvrsrvkm(O) cpufreq_dt cc33xx_sdio cfg80211 pwm_fan e5010_jpeg_enc at24 rti_wdt btti_uart bluetooth ti_k3_r5_remoteproc wave5 snd_soc_davinci_mcasp snd_soc_ti_udma snd_soc_ti_edma videobuf2_dma_contig v4l2_mem2mem snd_soc_hdmi_codec snd_soc_ti_sdma videobuf2_memops videobuf2_v4l2 snd_soc_core videobuf2_common snd_pcm_dmaengine ti_k3_dsp_remoteproc ti_k3_common snd_pcm videodev snd_timer mc snd uio_pdrv_genirq uio loop dm_mod efi_pstore
[ 12.233864] Modules linked in: cc33xx mac80211 algif_aead rpmsg_ctrl rpmsg_char virtio_rpmsg_bus rpmsg_ns libarc4 crct10dif_ce snd_soc_simple_card snd_soc_simple_card_utils pvrsrvkm(O) cpufreq_dt cc33xx_sdio cfg80211 pwm_fan e5010_jpeg_enc at24 rti_wdt btti_uart bluetooth ti_k3_r5_remoteproc wave5 snd_soc_davinci_mcasp snd_soc_ti_udma snd_soc_ti_edma videobuf2_dma_contig v4l2_mem2mem snd_soc_hdmi_codec snd_soc_ti_sdma videobuf2_memops videobuf2_v4l2 snd_soc_core videobuf2_common snd_pcm_dmaengine ti_k3_dsp_remoteproc ti_k3_common snd_pcm videodev snd_timer mc snd uio_pdrv_genirq uio loop dm_mod efi_pstore
dmesg | grep pru
dmesg | grep pinctrl-single
[ 1.111489] pinctrl-single 4084000.pinctrl: 34 pins, size 136
[ 1.112516] pinctrl-single f4000.pinctrl: 171 pins, size 684
dmesg | grep gpio-of-helper
lsusb
Bus 002 Device 002: ID 0451:8140 Texas Instruments, Inc. TUSB8041 4-Port Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 0451:8142 Texas Instruments, Inc. TUSB8041 4-Port Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
lspci
00:00.0 PCI bridge: Texas Instruments Device b010
END
extlinux.conf
...
label microSD (default)
kernel /Image
append console=ttyS2,115200n8 root=/dev/mmcblk1p3 ro rootfstype=ext4 resume=/dev/mmcblk1p2 rootwait net.ifnames=0 quiet
fdtdir /
fdt /ti/k3-am67a-beagley-ai.dtb
fdtoverlays /overlays/k3-am67a-beaglemod-audio.dtbo
#initrd /initrd.img
Device Tree Overlay
It is annotated with thoughts and questions from my debugging process.
It is built and installed natively on the target using the tree cloned from https://openbeagle.org/beagleboard/BeagleBoard-DeviceTrees.git
, on branch v6.1.x-Beagle
.
// Audio driver for TLV320AIC3104 for BeagleY-AI
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
* Modified by Brian Fraser
*/
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include "ti/k3-pinctrl.h"
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
&{/chosen} {
overlays {
k3-am67asbeaglemod-audio.kernel = __TIMESTAMP__;
};
};
&{/} {
tlv320aic3104_mclk: tlv320aic3104_mclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <12000000>;
};
// Question: Should this be "sound1" or the like to not conflict with the HDMI?
// (HDMI is "sound0")
// - When this is just 'sound', then it stops HDMI sound from loading, and
// generates no "deferred" messages when booting.
// - When this is 'sound1' or 'sound1', it generates a message in dmesg:
// [ 26.336146] platform sound1: deferred probe pending
// ==> Seems 'sound1' is a good answer.
sound1 {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "ZenHat Audio";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
status = "okay";
simple-audio-card,widgets =
"Headphone", "Headphone Jack",
"Line", "Line In";
simple-audio-card,routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"LINE1L", "Line In",
"LINE1R", "Line In";
// QUESTION: Should the "dailink0_master:" label be on the first or second struct?
// Is this defining which chip is in control of the clock? (referenced above)
// Observation from other .DTS:
// When running in i2s format, the CPU is setup with the label.
// See: src/arm64/overlays/k3-am625-beaglemod-audio.dts
// When running in dsp_b format, the codec has the label (ex k3-am62x-sk-common.dtsi)
dailink0_master: simple-audio-card,cpu {
sound-dai = <&mcasp0>;
system-clock-direction-out;
};
simple-audio-card,codec {
sound-dai = <&tlv320aic3104>;
// This line is not in k3-j722s-beagley-ai-evt, but is for k3-am62x-sk-common
clocks = <&tlv320aic3104_mclk>;
};
};
// Added to remove error on load:
// [ 39.214167] tlv320aic3x 1-0018: Invalid supply voltage(s) AVDD: 3300000, DVDD: -22
// (Unsure if this is the correct value: 1.8v?)
vdd_audio_1v8: regulator-audio {
compatible = "regulator-fixed";
regulator-name = "vdd_audio_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
vin-supply = <&vdd_3v3>;
regulator-always-on;
regulator-boot-on;
};
};
&main_pmx0 {
// I2S running on MCASP0 (MCASP1 is HDMI audio).
main_mcasp0_pins_default: main-mcasp0-codec-default-pins {
pinctrl-single,pins = <
J722S_IOPAD(0x01a4, PIN_INPUT, 0) /* BCLK on hat-12 (D25) MCASP0_ACLKX */
J722S_IOPAD(0x01a8, PIN_INPUT, 0) /* WCLK on hat-35 (C26) MCASP0_AFSX */
J722S_IOPAD(0x01a0, PIN_INPUT, 0) /* DIN on hat-38 (F24) MCASP0_AXR0 (may be F23, as per beagley_ai-pinmux.dts)*/
J722S_IOPAD(0x019c, PIN_OUTPUT, 0)/* DOUT on hat-40 (B25) MCASP0_AXR1 */
/*Question: Is this needed in use reset_gpios below?*/
J722S_IOPAD(0x0094, PIN_OUTPUT, 7) /* Reset on hat-37 (P26) GPMC0_BE1n.GPIO0_36 */
>;
};
// Question: Is this needed in use reset_gpios below?
// Have found it does not make a difference to the reset line.
// And I2C chip still fails to detect.
// mygpio1_pins_default: mygpio1-default-pins {
// pinctrl-single,pins = <
// >;
// };
};
&mcu_i2c0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
tlv320aic3104: tlv320aic3104@18 {
#sound-dai-cells = <0>;
compatible = "ti,tlv320aic3104";
reg = <0x18>; // I2C address 0x18, matches @18 of this section.
status = "okay";
// Reset pin (active low) is GPIO26 = "gpiochip1 36" to Linux user space
// From k3-am67a-beagly-ai.dts:
// &main_gpio0 {
// status = "okay";
// pinctrl-names = "default";
// gpio-line-names = "", "", "", "", "", /* 0-4 */
// "", "", "", "", "", /* 5-9 */
// "", "", "", "", "", /* 10-14 */
// "", "", "", "", "", /* 15-19 */
// "", "", "", "", "", /* 20-24 */
// "", "", "", "", "", /* 25-29 */
// "", "", "USB_RST", "GPIO27", "", /* 30-34 */
// "", "GPIO26", "", "GPIO4", "", /* 35-39 */
// "", "GPIO22", "GPIO25", "", ""; /* 40-44 */
// };
// Question: Could it be &main_gpio1? &mcu_gpio1?
// -> Likely not. Above comment seems pretty clear.
// -> Seems correct, because when driver loader:
// $ gpioset gpiochip1 36=1
// gpioset: error setting the GPIO line values: Device or resource busy
// Whereas `reset-gpios = <&mcu_gpio0 36 GPIO_ACTIVE_LOW>;` same gpioset succeeds.
// Also, when driver manually loaded it forces pin to 0, but holds it there.
// HOWEVER:
// Loading the DTS seems not affect the reset line (watched with a DMM)
// Before and after driver manually loaded, read X's from i2cdump, so in reset.
// Seems to have no effect for ACTIVE_LOW or ACTIVE_HIGH; Either way :
// During start up pin seems to be ~0.8v (floating? input?)
// When driver is loaded, pin gets pulled low
// Seems not to matter if pin is defined using J722S_IOPAD either.
//
// Using GPIO_ACTIVE_LOW gpioinfo shows "active high":
// line 36: "GPIO26" "tlv320aic3x reset" output active-high [used]
reset-gpios = <&main_gpio0 36 GPIO_ACTIVE_LOW>; // Suspected best one
// reset-gpios = <&main_gpio0 36 GPIO_ACTIVE_HIGH>; // Just testing to see if I can get the pin high.
ai3x-micbias-vg = <2>; // set MICBIAS to 2.5v
AVDD-supply = <&vdd_3v3>;
IOVDD-supply = <&vdd_3v3>;
DRVDD-supply = <&vdd_3v3>;
// Issue: If `DVDD-supply = <&vdd_3v3>;`, get error:
// [ 66.836344] tlv320aic3x 1-0018: Too high supply voltage(s) AVDD: 3300000, DVDD: 3300000
// DVDD-supply = <&vdd_3v3>;
DVDD-supply = <&vdd_audio_1v8>;
};
};
&mcasp0 {
// This section made on template of the mcasp1 from k3-am67a-beagley-ai.dts
status = "okay";
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&main_mcasp0_pins_default>;
auxclk-fs-ratio = <2177>; // No idea! It's in the mcasp1 definition.
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
2 1 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>;
/* Audio FIFO *threshold for transmit and receive */
// Question: What values are needed here?
tx-num-evt = <32>;
rx-num-evt = <32>;
// tx-num-evt = <1>;
// rx-num-evt = <1>;
};
Modinfo on drivers
$ modinfo /lib/modules/6.1.83-ti-arm64-r63/kernel/sound/soc/codecs/snd-soc-tlv320aic3x.ko
filename: /lib/modules/6.1.83-ti-arm64-r63/kernel/sound/soc/codecs/snd-soc-tlv320aic3x.ko
license: GPL
author: Vladimir Barinov
description: ASoC TLV320AIC3X codec driver
depends: snd-soc-core,snd-pcm
intree: Y
name: snd_soc_tlv320aic3x
vermagic: 6.1.83 SMP preempt mod_unload modversions aarch64
$ modinfo /lib/modules/6.1.83-ti-arm64-r63/kernel/sound/soc/codecs/snd-soc-tlv320aic3x-i2c.ko
filename: /lib/modules/6.1.83-ti-arm64-r63/kernel/sound/soc/codecs/snd-soc-tlv320aic3x-i2c.ko
license: GPL
author: Arun KS <arunks@mistralsolutions.com>
description: ASoC TLV320AIC3x codec driver I2C
alias: of:N*T*Cti,tlv320aic3106C*
alias: of:N*T*Cti,tlv320aic3106
alias: of:N*T*Cti,tlv320aic3104C*
alias: of:N*T*Cti,tlv320aic3104
alias: of:N*T*Cti,tlv320aic3007C*
alias: of:N*T*Cti,tlv320aic3007
alias: of:N*T*Cti,tlv320aic33C*
alias: of:N*T*Cti,tlv320aic33
alias: of:N*T*Cti,tlv320aic3xC*
alias: of:N*T*Cti,tlv320aic3x
alias: i2c:tlv320aic3106
alias: i2c:tlv320aic3104
alias: i2c:tlv320aic3007
alias: i2c:tlv320aic33
alias: i2c:tlv320aic3x
depends: snd-soc-tlv320aic3x
intree: Y
name: snd_soc_tlv320aic3x_i2c
vermagic: 6.1.83 SMP preempt mod_unload modversions aarch64