Sound on Raspberry Pi 4

Has anyone had success in getting sound to work RPi4 devices? What I’ve tried so far:

  • Adding dtparam=audio=on to boot.loader.raspberryPi.firmwareConfig and rebuilding the SD image
  • Manually adding the aforementioned boot option to the config.txt file in the boot partition
  • Enabling ALSA and Pulseaudio

Nothing has helped by get a running system where aplay -L yields more than the null card. Is there anything I’m missing here?

I’m not positive, but I think you might have to use linuxPackages_rpi4.

EDIT: It doesn’t look like the PWM audio driver was ever mainlined, so this is probably the case.

I had success having sound on the RPi4 jack output using this config.
All of it may not be necessary since I tried a lot of things.

{ pkgs, lib, flakeInputs, ... }:
{
  imports = [
    # ...
    flakeInputs.nixos-hardware.nixosModules.raspberry-pi-4
  ];


  boot = {
    extraModprobeConfig = ''
      options snd_bcm2835 enable_headphones=1
    '';
  };

  hardware.raspberry-pi."4" = {
    fkms-3d.enable = true;
    audio.enable = true;
    dwc2.enable = true;
  };

  hardware.pulseaudio = {
    enable = true;
    package = pkgs.pulseaudioFull;
  };
}

I also manually added

dtparam=audio=on

in the config.txt file. But I am not sure that it is needed.

I’m pretty sure the important part of that is nixos-hardware using the kernel that I mentioned, but I could be wrong.

Thanks for your answers! I copied @nurelin’s config and something in there seemed to do the trick :wink:

hi @nurelin or @yrd , could you provide your full nix configuration file? I would love to get my sound to work properly on my machine :slight_smile: thanks

Hey, this is the current state of my config (although I’m not actually using it at the moment, so I don’t know if it still works):

{config, pkgs, ...}: {
  boot = {
    loader.raspberryPi.firmwareConfig = ''
      dtparam=audio=on
    '';
    extraModprobeConfig = ''
      options snd_bcm2835 enable_headphones=1
    '';
  };

  hardware.raspberry-pi."4" = {
    fkms-3d.enable = true;
    audio.enable = true;
    dwc2.enable = true;
  };

  sound.enable = true;

  systemd.services.snapclient = {
    description = "Snapcast client";
    wantedBy = ["multi-user.target"];
    wants = ["network-online.target"];
    after = ["network-online.target"];

    serviceConfig = {
      Type = "forking";
      ExecStart = "${pkgs.snapcast}/bin/snapclient --daemon --hostID ${config.networking.hostName} -h audio.daheim.link --player alsa -s Headphones";
      PIDFile = "/run/snapclient/pid";
      Restart = "on-failure";
      RestartSec = "5s";
      DynamicUser = true;
      SupplementaryGroups = "audio";
      RuntimeDirectory = "snapclient";
    };
  };
}

Does anyone have this working in modern kernels? I’ve tried a bunch of things including the boot loader config above, but no audio. alsamixer shows just one default audio device, which I think is just a placeholder for Pipewire. pw-cli ls Node shows no sound devices.

In my case, it’s a headless Raspberry Pi 4 (no GUI) and I’m trying to use the headphone jack.

Finally got this working. In case it helps others, it’s as simple as:

  # Enable audio devices
  boot.kernelParams = [ "snd_bcm2835.enable_hdmi=1" "snd_bcm2835.enable_headphones=1" ];
  boot.loader.raspberryPi.firmwareConfig = ''
    dtparam=audio=on
  '';

You can also add hdmi_ignore_edid_audio=1 under dtparam=audio=on if you’re running headless and want to force use of the headphones jack instead of HDMI. Although I’m not sure it’s strictly needed.

I learned a few hard lessons that made this much harder to troubleshoot than I expected. Some of these can be attributed to running headless, though.

  1. The wiki instructions were outdated and made the situation worse. In particular, the hardware channel device tree tweaks aren’t necessary and actually broke my rebuilds. I have updated the wiki.
  2. Pipewire/WirePlumber might not start in time if you rely on socket activation. In my case mplayer would not play audio on the first attempt after a reboot, but would be fine on subsequent attempts. I was able to fix this by starting WirePlumber manually: systemctl --user start wireplumber.service
  3. Even if you manually start Pipewire/WirePlumber, audio doesn’t work if you logged in via SSH. Only interactive keyboard sessions work for me. I haven’t solved this one yet. Any advice?

In case it helps others, I solved #2 and #3 using config like this:

  # Socket activation too slow for headless; start at boot instead.
  services.pipewire.socketActivation = false; 
  # Start WirePlumber (with PipeWire) at boot.
  systemd.user.services.wireplumber.wantedBy = [ "default.target" ];
  users.users.<name>.linger = true; # keep user services running
  users.users.<name>.extraGroups = [ ... "audio" ];

Added to the wiki as well. Now I’m pretty happy with my headless Pi 4 setup. :slight_smile:

Can you share your full config? Adding these options didn’t work for me, I think I’m doing something else wrong. When I try to run aplay -l, it tells me there are no sound cards available and aplay -L just shows the null card.

I have also tried enabling pipewire, but that didn’t seem to help.

EDIT: /proc/asound/cards actually shows the headphone output, maybe the issue is that I’m trying to run the aplay commands over SSH, I’ve read that some people are having issues with that.

Ok, turns out it was just a permissions issue, I added the user to audio group and now everything works fine.

I have noticed there’s still a race condition that prevents audio from working if I start playing media immediately after login (e.g. via an SSH command). I worked around this by adding a small delay (sleep 5) before invoking the media player. There’s probably a better way, but I’m tired of fighting with it. :sweat_smile:

Here’s my full config if it helps: aquaria (Raspberry Pi 4).