Disable Bluetooth Power Saving with Pipewire

Hi there,

I’ve recently started using a Bluetooth speaker with my system and have noticed that, while the speaker stays connected, whenever audio is resumed after a pause in audio playback there is a short delay until audio starts playing. It is reminding me of the power saving feature in Pipewire that was causing the same issue with analog audio until I commented out suspend-node in /etc/pipewire/media-session.d. While that fixed the issues with my analog audio, it did not fix the issue for Bluetooth. Does anyone know of a way to disable the power saving for Bluetooth?

Thanks

My inxi -Fz:

System:
  Kernel: 5.14.21-2-MANJARO x86_64 bits: 64 Desktop: KDE Plasma 5.24.0
    Distro: Manjaro Linux
Machine:
  Type: Desktop Mobo: MSI model: B150 GAMING M3 (MS-7978) v: 2.0
    serial: <superuser required> UEFI: American Megatrends v: B.C0
    date: 07/05/2018
CPU:
  Info: quad core model: Intel Core i7-6700K bits: 64 type: MT MCP cache:
    L2: 1024 KiB
  Speed (MHz): avg: 4000 min/max: 800/4200 cores: 1: 4000 2: 4000 3: 4000
    4: 4000 5: 4000 6: 4000 7: 4000 8: 4000
Graphics:
  Device-1: NVIDIA GP102 [GeForce GTX 1080 Ti] driver: nvidia v: 510.47.03
  Device-2: Logitech C920 HD Pro Webcam type: USB
    driver: snd-usb-audio,uvcvideo
  Display: x11 server: X.Org 1.21.1.3 driver: loaded: nvidia resolution:
    1: 1920x1080~60Hz 2: 1920x1080
  OpenGL: renderer: NVIDIA GeForce GTX 1080 Ti/PCIe/SSE2
    v: 4.6.0 NVIDIA 510.47.03
Audio:
  Device-1: NVIDIA GP102 HDMI Audio driver: N/A
  Device-2: Logitech C920 HD Pro Webcam type: USB
    driver: snd-usb-audio,uvcvideo
  Device-3: ASUSTek Xonar SoundCard type: USB
    driver: hid-generic,snd-usb-audio,usbhid
  Sound Server-1: ALSA v: k5.14.21-2-MANJARO running: yes
  Sound Server-2: PipeWire v: 0.3.45 running: yes
Network:
  Device-1: Qualcomm Atheros Killer E2400 Gigabit Ethernet driver: alx
  IF: enp6s0 state: up speed: 1000 Mbps duplex: full mac: <filter>
Bluetooth:
  Device-1: Broadcom BCM20702A0 Bluetooth 4.0 type: USB driver: btusb
  Report: rfkill ID: hci0 state: up address: see --recommends
Drives:
  Local Storage: total: 4.19 TiB used: 2.78 TiB (66.2%)
  ID-1: /dev/sda vendor: Western Digital model: WD40EFRX-68N32N0
    size: 3.64 TiB
  ID-2: /dev/sdb vendor: Kingston model: SV300S37A240G size: 223.57 GiB
  ID-3: /dev/sdc vendor: SanDisk model: SDSSDX120GG25 size: 111.79 GiB
  ID-4: /dev/sdd vendor: Western Digital model: WD2500AAJS-65B4A0
    size: 232.89 GiB
Partition:
  ID-1: / size: 71.72 GiB used: 59.96 GiB (83.6%) fs: ext4 dev: /dev/sdb5
  ID-2: /boot/efi size: 187.1 MiB used: 258 KiB (0.1%) fs: vfat
    dev: /dev/sdb1
  ID-3: /home size: 109.37 GiB used: 58.28 GiB (53.3%) fs: ext4
    dev: /dev/sdb6
Swap:
  ID-1: swap-1 type: file size: 8 GiB used: 2 MiB (0.0%) file: /swapfile
Sensors:
  System Temperatures: cpu: 29.8 C pch: 50.0 C mobo: 27.8 C gpu: nvidia
    temp: 61 C
  Fan Speeds (RPM): N/A gpu: nvidia fan: 0%
Info:
  Processes: 349 Uptime: 34m Memory: 15.58 GiB used: 6.9 GiB (44.3%)
  Shell: Bash inxi: 3.3.12

My media-session.conf:

# Media session config file for PipeWire version "0.3.26" #

context.properties = {
    # Properties to configure the session and some
    # modules.
    #mem.mlock-all = false
    #support.dbus  = true
    #log.level     = 2
    #alsa.seq.name  = Midi-Bridge
}

context.spa-libs = {
    # Mapping from factory name to library.
    api.bluez5.*    = bluez5/libspa-bluez5
    api.alsa.*      = alsa/libspa-alsa
    api.v4l2.*      = v4l2/libspa-v4l2
    api.libcamera.* = libcamera/libspa-libcamera
}

context.modules = [
    #{   name = <module-name>
    #    [ args = { <key> = <value> ... } ]
    #    [ flags = [ [ ifexists ] [ nofail ] ]
    #}
    #
    # Loads a module with the given parameters.
    # If ifexists is given, the module is ignored when it is not found.
    # If nofail is given, module initialization failures are ignored.
    #
    # Uses RTKit to boost the data thread priority.
    {   name = libpipewire-module-rtkit
        args = {
            #nice.level   = -11
            #rt.prio      = 88
            #rt.time.soft = 200000
            #rt.time.hard = 200000
        }
        flags = [ ifexists nofail ]
    }

    # The native communication protocol.
    {   name = libpipewire-module-protocol-native }

    # Allows creating nodes that run in the context of the
    # client. Is used by all clients that want to provide
    # data to PipeWire.
    {   name = libpipewire-module-client-node }

    # Allows creating devices that run in the context of the
    # client. Is used by the session manager.
    {   name = libpipewire-module-client-device }

    # Makes a factory for wrapping nodes in an adapter with a
    # converter and resampler.
    {   name = libpipewire-module-adapter }

    # Allows applications to create metadata objects. It creates
    # a factory for Metadata objects.
    {   name = libpipewire-module-metadata }

    # Provides factories to make session manager objects.
    {   name = libpipewire-module-session-manager }
]

session.modules = {
    # These are the modules that are enabled when a file with
    # the key name is found in the media-session.d config directory.
    # the default bundle is always enabled.

    default = [
        flatpak                 # manages flatpak access
        portal                  # manage portal permissions
        v4l2                    # video for linux udev detection
        #libcamera              # libcamera udev detection
        #suspend-node            # suspend inactive nodes
        policy-node             # configure and link nodes
        #metadata               # export metadata API
        #default-nodes          # restore default nodes
        #default-profile        # restore default profiles
        #default-routes         # restore default route
        #streams-follow-default # move streams when default changes
        #alsa-seq               # alsa seq midi support
        #alsa-monitor           # alsa udev detection
        bluez5                 # bluetooth support
	#bluez5-autoswitch
        #restore-stream         # restore stream settings
        #logind                 # systemd-logind seat support
    ]
    with-audio = [
        metadata
        default-nodes
        default-profile
        default-routes
        alsa-seq
        alsa-monitor
    ]
    with-alsa = [
        with-audio
    ]
    with-jack = [
        with-audio
    ]
    with-pulseaudio = [
        with-audio
        bluez5
        logind
        restore-stream
        streams-follow-default
    ]
}

tlp has a lot a bluetooth power saving options. Try playing with those in /etc/tlp.conf:

# Exclude bluetooth devices from USB autosuspend:
# Radio devices to disable on startup: bluetooth, nfc, wifi, wwan.
#DEVICES_TO_DISABLE_ON_STARTUP="bluetooth nfc wifi wwan"
# Radio devices to enable on startup: bluetooth, nfc, wifi, wwan.
# Radio devices to disable on shutdown: bluetooth, nfc, wifi, wwan.
#DEVICES_TO_DISABLE_ON_SHUTDOWN="bluetooth nfc wifi wwan"
# Radio devices to enable on shutdown: bluetooth, nfc, wifi, wwan.
# Radio devices to enable on AC: bluetooth, nfc, wifi, wwan.
#DEVICES_TO_ENABLE_ON_AC="bluetooth nfc wifi wwan"
# Radio devices to disable on battery: bluetooth, nfc, wifi, wwan.
#DEVICES_TO_DISABLE_ON_BAT="bluetooth nfc wifi wwan"
#   bluetooth, nfc, wifi, wwan.
#DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE="bluetooth nfc wifi wwan"
# Possible devices: bluetooth, wifi, wwan.

Thanks for your reply. Sorry I forgot to mention I don’t have tlp on this system.

Try adding btusb.enable_autosuspend=n in GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub as root and run sudo update-grub. Reboot for changes to take effect.

further down in the same media-session.conf you get session modules for;

       #bluez5                 # bluetooth support
       #bluez5-autoswitch      # automatic bluetooth HSP/HFP profile switch

that are commented out, try playing with them and restarting pipwire-session service to reflect changes.

I attempted this but unfortunately it didn’t fix the issue.

I also gave this a shot but found that bluez5 was already enabled. Commenting it out didn’t change anything.