evankrall
Posts: 10
Joined: Tue Mar 23, 2021 3:21 am

Device tree overlay applies cleanly, but enable pin not pulled high and no device files in /dev/snd

Tue Mar 23, 2021 4:25 am

I've got the following device tree overlay for a soundcard built around the tlv320aic3104:

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";
    fragment@0 {
        target = <&gpio>;
        __overlay__ {
            aic3104_reset: aic3104_reset {
                brcm,pins = <17 27>;
                brcm,function = <1 1>;
                brcm,pull = <1 1>;
            };
        };
    };

    fragment@1 {
        target-path = "/";
        __overlay__ {

            vcc30: fixedregulator@1 {
                compatible = "regulator-fixed";
                regulator-name = "soundcard30";
                regulator-min-microvolt = <3000000>;
                regulator-max-microvolt = <3000000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };
            vcc18: fixedregulator@2 {
                compatible = "regulator-fixed";
                regulator-name = "soundcard18";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };

            amp: analog-amplifier {
                compatible = "simple-audio-amplifier";
                enable-gpios = <&gpio 17 0>;
                VCC-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@2 {
        target = <&i2c1>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;

            tlv320aic3104: tlv320aic3104@18 {
                // #address-cells = <1>;
                // #size-cells = <0>;
                #sound-dai-cells = <0>;
                compatible = "ti,tlv320aic3104";
                reg = <0x18>;

                reset-gpios = <&gpio 27 0>;

                AVDD-supply = <&vcc30>;
                DRVDD-supply = <&vcc30>;
                DVDD-supply = <&vcc18>;
                IOVDD-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@3 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };

    fragment@4 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s_controller = <&i2s>;
            status = "okay";
            simple-audio-card,name = "pipad";
            simple-audio-card,format = "i2s";

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

            simple-audio-card,widgets =
                "Microphone", "Microphone Jack",
                "Microphone", "Internal Microphone",
                "Headphone", "Headphone Jack",
                "Line", "Line Out",
                "Speaker", "Internal Speaker";
            simple-audio-card,routing =
                "Line Out", "HPLCOM",
                "Line Out", "HPRCOM",
                "Headphone Jack", "HPLOUT",
                "Headphone Jack", "HPROUT",
                "Microphone Jack", "MIC2L",
                "Internal Microphone", "MIC1L",
                "Internal Speaker", "LLOUT",
                "Internal Speaker", "RLOUT";
            simple-audio-card,aux-devs = <&amp>;
            dailink0_master: simple-audio-card,cpu {
                sound-dai = <&i2s>;
            };
            simple-audio-card,codec {
                sound-dai = <&tlv320aic3104>;
                system-clock-frequency = <12288000>;
            };
        };
    };
};
This seems to compile relatively cleanly:

Code: Select all

pi@raspberrypi:~ $ dtc -@ -Hepapr -I dts -O dtb -o pipad.dtbo pipad-i2s-soundcard-overlay.dts
pipad.dtbo: Warning (unit_address_vs_reg): /fragment@1/__overlay__/fixedregulator@1: node has a unit name, but no reg property
pipad.dtbo: Warning (unit_address_vs_reg): /fragment@1/__overlay__/fixedregulator@2: node has a unit name, but no reg property
It also seems to apply cleanly, both with the dtoverlay command at runtime, and the dtoverlay= parameter in /boot/config.txt.
I can't see any obvious errors in `dmesg`, `vcdbg log msg`, or `udevadm monitor` while loading the overlay with the `dtoverlay` command.

dmesg while loading overlay with the dtoverlay command:

Code: Select all

[  518.622783] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/i2s@7e203000/status
[  518.622822] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/compatible
[  518.622853] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/i2s_controller
[  518.622883] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/status
[  518.622910] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,name
[  518.622949] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,format
[  518.622976] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,bitclock-master
[  518.623003] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,frame-master
[  518.623030] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,widgets
[  518.623057] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,routing
[  518.623083] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/sound/simple-audio-card,aux-devs
[  518.639465] soundcard30: supplied by 3v3
[  518.640676] reg-fixed-voltage fixedregulator@2: nonexclusive access to GPIO for fixedregulator@2
[  518.640941] soundcard18: supplied by 3v3
`udevadm monitor` while loading overlay with the dtoverlay command:

Code: Select all

KERNEL[518.634788] add      /devices/platform/fixedregulator@1 (platform)
KERNEL[518.634965] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@1 (devlink)
KERNEL[518.639119] add      /devices/platform/fixedregulator@1/regulator/regulator.5 (regulator)
KERNEL[518.639290] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@1 (devlink)
KERNEL[518.639556] bind     /devices/platform/fixedregulator@1 (platform)
KERNEL[518.639752] add      /devices/platform/fixedregulator@2 (platform)
KERNEL[518.639879] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@2 (devlink)
KERNEL[518.640170] add      /devices/platform/fixedregulator@2/regulator/regulator.6 (regulator)
KERNEL[518.640334] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@2 (devlink)
KERNEL[518.640528] bind     /devices/platform/fixedregulator@2 (platform)
KERNEL[518.640718] add      /devices/platform/analog-amplifier (platform)
KERNEL[518.640845] add      /devices/virtual/devlink/platform:fe200000.gpio--platform:analog-amplifier (devlink)
KERNEL[518.640961] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:analog-amplifier (devlink)
KERNEL[518.641139] add      /devices/platform/soc/fe804000.i2c/i2c-1/1-0018 (i2c)
KERNEL[518.641267] add      /devices/virtual/devlink/platform:fe200000.gpio--i2c:1-0018 (devlink)
KERNEL[518.641386] add      /devices/virtual/devlink/platform:fixedregulator@1--i2c:1-0018 (devlink)
KERNEL[518.641500] add      /devices/virtual/devlink/platform:fixedregulator@2--i2c:1-0018 (devlink)
KERNEL[518.641644] add      /devices/virtual/devlink/platform:fixedregulator_3v3--i2c:1-0018 (devlink)
KERNEL[518.641837] add      /devices/platform/soc/fe203000.i2s (platform)
KERNEL[518.641965] add      /devices/virtual/devlink/platform:fe101000.cprman--platform:fe203000.i2s (devlink)
KERNEL[518.642085] add      /devices/virtual/devlink/platform:fe007000.dma--platform:fe203000.i2s (devlink)
KERNEL[518.642200] add      /devices/virtual/devlink/platform:fe200000.gpio--platform:fe203000.i2s (devlink)
KERNEL[518.642442] add      /devices/platform/soc/soc:sound (platform)
UDEV  [518.648779] add      /devices/platform/fixedregulator@1 (platform)
UDEV  [518.650315] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@1 (devlink)
UDEV  [518.652625] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@1 (devlink)
UDEV  [518.653939] add      /devices/platform/fixedregulator@1/regulator/regulator.5 (regulator)
UDEV  [518.656185] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@2 (devlink)
UDEV  [518.657140] add      /devices/platform/fixedregulator@2 (platform)
UDEV  [518.658151] bind     /devices/platform/fixedregulator@1 (platform)
UDEV  [518.659177] add      /devices/platform/fixedregulator@2/regulator/regulator.6 (regulator)
UDEV  [518.659547] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--platform:fixedregulator@2 (devlink)
UDEV  [518.661227] add      /devices/platform/analog-amplifier (platform)
UDEV  [518.662126] bind     /devices/platform/fixedregulator@2 (platform)
UDEV  [518.664106] add      /devices/virtual/devlink/platform:fixedregulator_3v3--platform:analog-amplifier (devlink)
UDEV  [518.665451] add      /devices/virtual/devlink/platform:fe200000.gpio--i2c:1-0018 (devlink)
UDEV  [518.665829] add      /devices/virtual/devlink/platform:fe200000.gpio--platform:analog-amplifier (devlink)
UDEV  [518.666844] add      /devices/virtual/devlink/platform:fixedregulator@1--i2c:1-0018 (devlink)
UDEV  [518.667318] add      /devices/virtual/devlink/platform:fixedregulator_3v3--i2c:1-0018 (devlink)
UDEV  [518.669355] add      /devices/virtual/devlink/platform:fe200000.gpio--platform:fe203000.i2s (devlink)
UDEV  [518.669874] add      /devices/virtual/devlink/platform:fe101000.cprman--platform:fe203000.i2s (devlink)
UDEV  [518.671101] add      /devices/virtual/devlink/platform:fixedregulator@2--i2c:1-0018 (devlink)
UDEV  [518.672091] add      /devices/virtual/devlink/platform:fe007000.dma--platform:fe203000.i2s (devlink)
KERNEL[518.674590] remove   /devices/virtual/devlink/platform:fe101000.cprman--platform:fe203000.i2s (devlink)
KERNEL[518.674860] remove   /devices/virtual/devlink/platform:fe007000.dma--platform:fe203000.i2s (devlink)
KERNEL[518.674924] remove   /devices/virtual/devlink/platform:fe200000.gpio--platform:fe203000.i2s (devlink)
KERNEL[518.675012] bind     /devices/platform/soc/fe203000.i2s (platform)
KERNEL[518.675072] add      /bus/platform/drivers/bcm2835-i2s (drivers)
UDEV  [518.675156] add      /devices/platform/soc/fe203000.i2s (platform)
KERNEL[518.675215] add      /module/snd_soc_bcm2835_i2s (module)
UDEV  [518.675309] remove   /devices/virtual/devlink/platform:fe200000.gpio--platform:fe203000.i2s (devlink)
UDEV  [518.675374] remove   /devices/virtual/devlink/platform:fe101000.cprman--platform:fe203000.i2s (devlink)
UDEV  [518.675844] remove   /devices/virtual/devlink/platform:fe007000.dma--platform:fe203000.i2s (devlink)
UDEV  [518.677535] add      /bus/platform/drivers/bcm2835-i2s (drivers)
KERNEL[518.678182] add      /module/snd_soc_simple_card_utils (module)
UDEV  [518.679143] add      /module/snd_soc_bcm2835_i2s (module)
UDEV  [518.679709] add      /module/snd_soc_simple_card_utils (module)
UDEV  [518.680141] bind     /devices/platform/soc/fe203000.i2s (platform)
KERNEL[518.681176] add      /bus/platform/drivers/asoc-simple-card (drivers)
KERNEL[518.681253] add      /module/snd_soc_simple_card (module)
UDEV  [518.681343] add      /devices/platform/soc/soc:sound (platform)
UDEV  [518.683187] add      /bus/platform/drivers/asoc-simple-card (drivers)
UDEV  [518.684111] add      /module/snd_soc_simple_card (module)
KERNEL[518.724976] add      /module/regmap_i2c (module)
UDEV  [518.726008] add      /module/regmap_i2c (module)
KERNEL[518.730607] add      /devices/virtual/devlink/regulator:regulator.1--i2c:1-0018 (devlink)
KERNEL[518.730683] add      /devices/virtual/devlink/regulator:regulator.6--i2c:1-0018 (devlink)
KERNEL[518.730733] add      /devices/virtual/devlink/regulator:regulator.5--i2c:1-0018 (devlink)
KERNEL[518.730986] remove   /devices/virtual/devlink/platform:fe200000.gpio--i2c:1-0018 (devlink)
KERNEL[518.731047] remove   /devices/virtual/devlink/platform:fixedregulator@1--i2c:1-0018 (devlink)
KERNEL[518.731097] remove   /devices/virtual/devlink/platform:fixedregulator@2--i2c:1-0018 (devlink)
KERNEL[518.731145] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--i2c:1-0018 (devlink)
KERNEL[518.731743] bind     /devices/platform/soc/fe804000.i2c/i2c-1/1-0018 (i2c)
KERNEL[518.731824] add      /bus/i2c/drivers/tlv320aic3x-codec (drivers)
KERNEL[518.731876] add      /module/snd_soc_tlv320aic3x (module)
UDEV  [518.732910] add      /devices/virtual/devlink/regulator:regulator.5--i2c:1-0018 (devlink)
UDEV  [518.732999] add      /devices/virtual/devlink/regulator:regulator.1--i2c:1-0018 (devlink)
UDEV  [518.733058] remove   /devices/virtual/devlink/platform:fixedregulator@2--i2c:1-0018 (devlink)
UDEV  [518.733338] remove   /devices/virtual/devlink/platform:fixedregulator@1--i2c:1-0018 (devlink)
UDEV  [518.733407] remove   /devices/virtual/devlink/platform:fe200000.gpio--i2c:1-0018 (devlink)
UDEV  [518.733616] add      /devices/virtual/devlink/regulator:regulator.6--i2c:1-0018 (devlink)
UDEV  [518.734264] remove   /devices/virtual/devlink/platform:fixedregulator_3v3--i2c:1-0018 (devlink)
UDEV  [518.735096] add      /devices/platform/soc/fe804000.i2c/i2c-1/1-0018 (i2c)
UDEV  [518.735525] add      /bus/i2c/drivers/tlv320aic3x-codec (drivers)
UDEV  [518.736442] add      /module/snd_soc_tlv320aic3x (module)
UDEV  [518.770283] bind     /devices/platform/soc/fe804000.i2c/i2c-1/1-0018 (i2c)
As you can see from the udevadm output, it's loading the proper modules. I can confirm with `raspi-gpio get` that GPIO 22 and 27 are both set as outputs, but they have level=0. (GPIO 17, for some reason, is still an input, but that shouldn't prevent the codec from working.)

It doesn't seem to be usable via ALSA:

Code: Select all

pi@raspberrypi:~ $ aplay -l
aplay: device_list:272: no soundcards found...
pi@raspberrypi:~ $ ls /dev/snd/
seq  timer
What am I missing? How do I debug this further?

Thanks in advance!

evankrall
Posts: 10
Joined: Tue Mar 23, 2021 3:21 am

Re: Device tree overlay applies cleanly, but enable pin not pulled high and no device files in /dev/snd

Sun Mar 28, 2021 5:56 am

I made progress on this - I now get alsa sound devices when I apply this DT overlay, and I can generate noise. (It sounds terrible, but recognizable.)

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";
    fragment@0 {
        target = <&gpio>;
        __overlay__ {
            amp_enable: amp_enable {
                brcm,pins = <17>;
                brcm,function = <1>;
                brcm,pull = <1>;
            };
        };
    };

    fragment@1 {
        target-path = "/";
        __overlay__ {

            vcc30: fixedregulator@1 {
                regulator-boot-on;
                compatible = "regulator-fixed";
                regulator-name = "soundcard30";
                regulator-min-microvolt = <3000000>;
                regulator-max-microvolt = <3000000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };
            vcc18: fixedregulator@2 {
                regulator-boot-on;
                compatible = "regulator-fixed";
                regulator-name = "soundcard18";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };

            amp: analog-amplifier {
                compatible = "simple-audio-amplifier";
                enable-gpios = <&gpio 17 0>;
                VCC-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@2 {
        target = <&i2c1>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;

            tlv320aic3104: tlv320aic3104@24 {
                // #address-cells = <1>;
                // #size-cells = <0>;
                status = "okay";
                #sound-dai-cells = <0>;
                compatible = "ti,tlv320aic3104";
                reg = <0x18>;

                reset-gpios = <&gpio 27 0>;
                ai3x-ocmv = <0>;
                // AVDD-supply = <&vcc30>;
                // DRVDD-supply = <&vcc30>;
                // DVDD-supply = <&vcc18>;
                // IOVDD-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@3 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };

    fragment@4 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s_controller = <&i2s>;
            status = "okay";
            simple-audio-card,name = "pipad";
            simple-audio-card,format = "i2s";

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

            simple-audio-card,widgets =
                "Microphone", "Microphone Jack",
                "Microphone", "Internal Microphone",
                "Headphone", "Headphone Jack",
                "Line", "Line Out",
                "Speaker", "Internal Speaker";
            simple-audio-card,routing =
                "Line Out", "HPLCOM",
                "Line Out", "HPRCOM",
                "Headphone Jack", "HPLOUT",
                "Headphone Jack", "HPROUT",
                "Microphone Jack", "MIC2L",
                "Internal Microphone", "LINE1L",
                "Internal Speaker", "LLOUT",
                "Internal Speaker", "RLOUT";

            simple-audio-card,aux-devs = <&amp>;
            dailink0_master: simple-audio-card,cpu {
                sound-dai = <&i2s>;
            };
            simple-audio-card,codec {
                sound-dai = <&tlv320aic3104>;
                system-clock-frequency = <12288000>;
            };
        };
    };
};
What I found helpful was the kernel's dynamic_debug functionality: https://www.kernel.org/doc/html/v4.15/a ... howto.html

Specifically, I added this to my /boot/cmdline.txt:

Code: Select all

dyndbg="func bus_add_driver +pflm" dyndbg="func really_probe +pflm" dyndbg="module tlv320aic3x +pflm" dyndbg="file simple-card.c +pflm"
I also added this to a new file in /etc/modprobe.d/:

Code: Select all

options tlv320aic3x dyndbg=+pflm
options snd_soc_tlv320aic3x dyndbg=+pflm
options snd_soc_simple_card dyndbg=+pflm
options snd_soc_simple_card_utils dyndbg=+pflm
options snd_soc_bcm2835_i2s dyndbg=+pflm
(I'm not sure that first line actually did anything since that isn't the correct module name.)

This makes the various debug messages from these modules/kernel source files actually show up in dmesg.

evankrall
Posts: 10
Joined: Tue Mar 23, 2021 3:21 am

Re: Device tree overlay applies cleanly, but enable pin not pulled high and no device files in /dev/snd

Sat Sep 18, 2021 7:32 am

Since I have built a second version of my soundcard, with a different codec, I had to adjust my device tree overlay. I ran into this same problem
with the device not showing up in `aplay -l` again. I feel like I should explain exactly how I figured it out this time:

Code: Select all

pi@cm4:~ $ sudo -i

# These modules need to be loaded before the `trace-cmd record` command later.
root@cm4:~# for mod in  snd-soc-tlv320aic32x4-i2c snd-soc-tlv320aic32x4 snd-soc-simple-card snd-soc-simple-card-utils; do modprobe $mod; done

# Run `dtoverlay pipad-i2s-soundcard` but record a function call graph for everything the kernel does.
root@cm4:~# trace-cmd record -p function_graph -F dtoverlay pipad-i2s-soundcard
  plugin 'function_graph'
CPU0 data recorded at offset=0x572000
    0 bytes in size
CPU1 data recorded at offset=0x572000
    18300928 bytes in size
CPU2 data recorded at offset=0x16e6000
    0 bytes in size
CPU3 data recorded at offset=0x16e6000
    0 bytes in size
    
# No obvious errors in dmesg:
root@cm4:~# dmesg
...
[   75.558853] soundcard18: supplied by 3v3
[   75.761239] snd_soc_simple_card:simple_get_dais_count:569: asoc-simple-card soc:sound: link 1, dais 2, ccnf 0
[   75.762502] snd_soc_simple_card:simple_dai_link_of:276: asoc-simple-card soc:sound: link_of (/soc/sound)

# But listing the audio devices doesn't show my "pipad" soundcard.
root@cm4:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: vc4hdmi0 [vc4-hdmi-0], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: vc4hdmi1 [vc4-hdmi-1], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

# Turn the binary file recorded by `trace-cmd record` above into text output:
root@cm4:~# trace-cmd report > ~pi/report
# Strip off everything up to the first pipe character. This prefix tells you the process name/pid that the line belongs to, but we know it's from dtoverlay. Stripping it makes it easier to deal with.
root@cm4:~# grep dtoverlay- ~pi/report | cut -f2 -d'|' > ~pi/report_filtered 
This report_filtered file will be a few hundred thousand lines. Since I know the code that's misbehaving is in simple-card.c, and the entrypoint to that module is asoc_simple_probe, I searched for that in report_filtered.

Using the "collapse" functionality of my text editor, I collapsed things so that I can only see the first level of calls from asoc_simple_probe, which looks like:

Code: Select all

asoc_simple_probe() {
  devm_kmalloc() {
    ...
  }
  simple_for_each_link() {
    ...
  }
  dev_driver_string();
  dev_printk_emit() {
    ...
  }
  asoc_simple_init_priv() {
    ...
  }
  of_device_is_available() {
    ...
  }
  asoc_simple_parse_widgets() {
    ...
  }
  asoc_simple_parse_routing() {
    ...
  }
  asoc_simple_parse_pin_switches() {
    ...
  }
  simple_for_each_link() {
    ...
  }
  simple_for_each_link() {
    ...
  }
  asoc_simple_parse_card_name() {
    ...
  }
  snd_soc_of_parse_aux_devs() {
    ...
  }
  devm_snd_soc_register_card() {
    ...
  }
  asoc_simple_clean_reference() {
    ...
  }
}
asoc_simple_clean_reference only seems to be called after an error happens, so let's look into the previous function call, devm_snd_soc_register_card:

Code: Select all

asoc_simple_probe() {
  ...
  devm_snd_soc_register_card() {
    devres_alloc_node() {
      __kmalloc_track_caller() {
        kmalloc_slab();
        should_failslab();
      }
    }
    snd_soc_register_card() {
      __mutex_init();
      __mutex_init();
      __mutex_init();
      snd_soc_bind_card() {
        mutex_lock();
        mutex_lock();
        snd_soc_dapm_init();
        soc_find_component() {
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
          snd_soc_is_matching_component();
        }
        soc_cleanup_card_resources() {
          snd_soc_dapm_shutdown() {
            soc_dapm_shutdown_dapm() {
              mutex_lock();
              mutex_unlock();
            }
          }
          snd_soc_dapm_free() {
            debugfs_remove();
          }
          debugfs_remove();
          snd_soc_card_remove();
        }
        mutex_unlock();
        mutex_unlock();
      }
    }
    devres_free() {
      kfree();
    }
  }
  asoc_simple_clean_reference() {
    ...
  }
}
Again it looks like within snd_soc_bind_card, soc_cleanup_card_resources is called after an error. Let's look at the function call before that: soc_find_component.

One thing to keep in mind about these ftrace recordings is that certain types of function calls are invisible to ftrace -- in particular, anything that's defined as an inline function won't show up on these traces. Some other functions are invisible as well- I think maybe if a static function is only called in one place, it can get inlined and won't show up in the traces.

I don't see snd_soc_bind_card actually calling soc_find_component directly, but it does get called from soc_bind_aux_dev, which is called soon after snd_soc_dapm_init.

Essentially, from this call graph, I can see that soc_bind_aux_dev is failing. This hints that this line in my device tree overlay is wrong:

Code: Select all

            simple-audio-card,aux-devs = <&amp>;
By commenting this line out, recompiling the overlay, and retrying, I get an alsa device now:

Code: Select all

pi@cm4:~ $ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: vc4hdmi0 [vc4-hdmi-0], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: vc4hdmi1 [vc4-hdmi-1], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: pipad [pipad], device 0: bcm2835-i2s-tlv320aic32x4-hifi tlv320aic32x4-hifi-0 [bcm2835-i2s-tlv320aic32x4-hifi tlv320aic32x4-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
My dts file at this point for posterity (though there are almost certainly more problems in it):

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";
    fragment@0 {
        target = <&gpio>;
        __overlay__ {
            amp_enable: amp_enable {
                brcm,pins = <17>;
                brcm,function = <1>;
                brcm,pull = <1>;
            };
        };
    };

    fragment@1 {
        target-path = "/";
        __overlay__ {

            vcc30: fixedregulator@1 {
                regulator-boot-on;
                compatible = "regulator-fixed";
                regulator-name = "soundcard30";
                regulator-min-microvolt = <3000000>;
                regulator-max-microvolt = <3000000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };
            vcc18: fixedregulator@2 {
                regulator-boot-on;
                compatible = "regulator-fixed";
                regulator-name = "soundcard18";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                gpio = <&gpio 22 0>;
                startup-delay-us = <70000>;
                enable-active-high;
                vin-supply = <&vdd_3v3_reg>;
            };

            amp: analog-amplifier {
                compatible = "simple-audio-amplifier";
                enable-gpios = <&gpio 17 0>;
                VCC-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@2 {
        target = <&i2c1>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;

            tlv320aic3104: tlv320aic3104@24 {
                // #address-cells = <1>;
                // #size-cells = <0>;
                status = "okay";
                #sound-dai-cells = <0>;
                compatible = "ti,tlv320aic3104";
                reg = <0x18>;

                reset-gpios = <&gpio 27 0>;
                ai3x-ocmv = <0>;
                // AVDD-supply = <&vcc30>;
                // DRVDD-supply = <&vcc30>;
                // DVDD-supply = <&vcc18>;
                // IOVDD-supply = <&vdd_3v3_reg>;
            };
        };
    };

    fragment@3 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };

    fragment@4 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s_controller = <&i2s>;
            status = "okay";
            simple-audio-card,name = "pipad";
            simple-audio-card,format = "i2s";

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

            simple-audio-card,widgets =
                "Microphone", "Microphone Jack",
                "Microphone", "Internal Microphone",
                "Headphone", "Headphone Jack",
                "Line", "Line Out",
                "Speaker", "Internal Speaker";
            simple-audio-card,routing =
                "Line Out", "HPLCOM",
                "Line Out", "HPRCOM",
                "Headphone Jack", "HPLOUT",
                "Headphone Jack", "HPROUT",
                "Microphone Jack", "MIC2L",
                "Internal Microphone", "LINE1L",
                "Internal Speaker", "LLOUT",
                "Internal Speaker", "RLOUT";

            // simple-audio-card,aux-devs = <&amp>;
            dailink0_master: simple-audio-card,cpu {
                sound-dai = <&i2s>;
            };
            simple-audio-card,codec {
                sound-dai = <&tlv320aic3104>;
                system-clock-frequency = <12288000>;
            };
        };
    };
};

aBUGSworstnightmare
Posts: 3610
Joined: Tue Jun 30, 2015 1:35 pm

Re: Device tree overlay applies cleanly, but enable pin not pulled high and no device files in /dev/snd

Sun Sep 19, 2021 5:09 am

tlv320aic3104: tlv320aic3104@24 {
// #address-cells = <1>;
// #size-cells = <0>;
status = "okay";
#sound-dai-cells = <0>;
compatible = "ti,tlv320aic3104";
reg = <0x18>;
what is your I2C device address, 0x24 (tlv320aic3104@24) or 0x18 (reg = <0x18>)?

Which overlay did you start with, or is all this from scratch?

Return to “Interfacing (DSI, CSI, I2C, etc.)”