Commit graph

1315 commits

Author SHA1 Message Date
Daniel Nouri
1951e7d2b4 Merge branch 'fix-iec958-unmute-on-activation' into 'master'
Fix HDMI/DisplayPort Audio by Enabling IEC958 Switches

Closes #3261

See merge request pipewire/pipewire!2556
2026-01-27 13:28:20 +00:00
Arun Raghavan
04793138b5 alsa-card-profiles: Add config for a couple of JBL gaming headsets
Similar to the existing SteelSeries and Logitech ones, but the order of
the playback endpoints is reversed, and only mono input is supported.
2026-01-22 15:35:05 +00:00
Pauli Virtanen
e91a79dab7 spa: alsa: actually set the channel map when use-chmap=true
When using channel maps, the active map should be set using
snd_pcm_set_chmap(). This has to be called when stream is in prepared
state.

Track which of the maps the selected format has set, and set it in
do_prepare().
2026-01-05 15:37:05 +00:00
Arun Raghavan
e2262617aa spa: alsa: Fix off-by-one check in ELD channel position parsing 2025-12-17 11:08:44 -08:00
Arun Raghavan
ee42b18226 spa: alsa: Guard against mismatched LPCM channel count in ELD parsing
With wonky EDID states, we want to make sure we don't overflow the
available positions.
2025-12-15 12:47:49 -08:00
Wim Taymans
4f39329ca9 alsa: use graph rate for rate latency
When we recalculate the headroom we also update the latency in frames.
We should express this latency in the graph rate. This is usually the
rate that is suggested in the target_rate but when we are forcing our
own rate (mostly when using IRQ or when in DSD/IEC mode) we should
ignore that value and use our own rate that we will force instead.

Fixes #4977
2025-12-01 14:20:12 +01:00
Wim Taymans
4152c5d292 alsa: add firewire latency before we scale with rate
We first add all the latency in the rate of the pcm device and then
convert it to the rate of the graph.

See #4977
2025-12-01 12:52:37 +01:00
Daniel Nouri
9fa0de16e9 revert: Remove mixer path IEC958 fix
Reverts alsa-mixer.c changes from 32a3ffc74. The comprehensive ACP
layer fix (bdb82be4e) handles all scenarios including pro-audio
profiles that bypass mixer paths, making this approach redundant.
2025-10-31 08:22:44 +00:00
Daniel Nouri
f030e1dc03 alsa: Enable IEC958 switches on device activation
IEC958 (S/PDIF, HDMI, DisplayPort) switches default to muted in ALSA
drivers, causing no audio output on digital devices.

While UCM configurations and mixer paths can handle IEC958 unmuting,
several scenarios lack coverage:
- Pro-audio profiles (bypass UCM and mixer paths by design)
- Devices without UCM configurations
- Devices with incomplete mixer path definitions
- Cards with multiple HDMI/DP outputs (indexed switches)

This ensures IEC958 switches are enabled during device activation and
port changes. The implementation uses the device mixer when available,
falls back to the card mixer for pro-audio profiles, and enables all
IEC958 switches regardless of index.

Safe for all configurations: the operation is idempotent and provides
defense-in-depth even when UCM or mixer paths handle it correctly.

Tested on AMD Rembrandt GPU with 3 HDMI outputs in pro-audio mode.
2025-10-31 08:22:44 +00:00
Daniel Nouri
88f8eda1e9 refactor: Remove test-alsa-path-select tool
Not run by meson test and requires specific ALSA hardware.
Fix verification already completed manually.
2025-10-31 08:22:44 +00:00
Daniel Nouri
9ad6219db3 refactor: Remove redundant ret assignments in test-alsa-path-select
The variable ret is initialized to 2 at function entry. Error paths that
want this default value can simply goto cleanup without reassigning it.
2025-10-31 08:22:44 +00:00
Daniel Nouri
e29d851d2c alsa: Fix IEC958 digital output not unmuted on path activation
When selecting an HDMI/DisplayPort (IEC958) output path, the hardware
mute switch remains in kernel default state (muted), causing no audio
output despite correct software routing.

Root cause: pa_alsa_path_select() only sets mute switches when
mute_during_activation is enabled. No mixer paths enable this setting,
making the switch configuration code unreachable for IEC958 paths.

Solution: Always set mute switches to match device mute status after
path activation, regardless of mute_during_activation setting.

Testing: Added test-alsa-path-select tool to verify the fix.
- Loads mixer path and calls pa_alsa_path_select()
- Verifies switch states match expected values
- Tested on AMD Radeon HDMI and Realtek ALC257 analog

Manual verification:
- Before: IEC958 switch OFF, no audio
- After: IEC958 switch set correctly, audio works

This bug was inherited from PulseAudio's ALSA mixer path code where
HDMI path configurations lack IEC958 unmute sections.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3261
See-Also: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/562
See-Also: 33be660e4b
See-Also: https://bugs.launchpad.net/hundredpapercuts/+bug/681996
2025-10-31 08:22:44 +00:00
Pauli Virtanen
3febf09b85 alsa: fix typoed braces in condition + assign 2025-10-26 14:12:19 +00:00
Wim Taymans
88c65932d8 acp: use global max channels if defined 2025-10-24 17:16:03 +02:00
Wim Taymans
c8d4de5e77 acp: bump max channels to 128 2025-10-24 17:00:42 +02:00
Wim Taymans
c4244a6cf3 string: use spa_strbuf instead of snprintf magic 2025-10-24 17:00:11 +02:00
Wim Taymans
11f1298f53 spa: make a function to make a channel short name
Make a function that can generate and parse a short name for
the positions that are not in the type list, like the AUX channels.
2025-10-22 13:04:53 +02:00
Wim Taymans
6465a63bf6 spa: parse the audio.position completetly
Parse the audio.position spec completely so that we have the right
number of channels but only store the first max_position channels.

Also rename some field to make it clear that this is about the max
number of channel positions.
2025-10-22 12:47:00 +02:00
Wim Taymans
8bbca3b8f3 spa: add spa_audio_parse_position_n
Add a function that accepts the size of the position array when reading
the audio positions. This makes it possible to decouple the position
array size from SPA_AUDIO_MAX_CHANNELS.

Also use SPA_N_ELEMENTS to pass the number of array elements to
functions instead of a fixed constant. This makes it easier to change
the array size later to a different constant without having to patch up
all the places where the size is used.
2025-10-21 09:59:13 +02:00
Wim Taymans
13b8c23767 Don't use SPA_AUDIO_MAX_CHANNELS directly
Make a MAX_CHANNELS define and use that one in code. This makes it
easier to change the constant later.
2025-10-21 09:43:06 +02:00
Pauli Virtanen
da2cecf074 alsa: acp: don't disable dB if negative max unless range is small
Disabling dB volumes for max_dB < 0 was added in Pulseaudio in 2021,
based on a device which had -128..-127.07 range. However, negative
max_dB is valid value for USB devices, and there are devices that have
it.

Eg. Microsoft LifeChat LX-3000 has

numid=6,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=151,step=0
  : values=150,150
  | dBminmax-min=-28.37dB,max=-0.06dB

and the dB range seems to be OK. Web search for "The decibel volume
range for element" also gives other hits with seemingly OK looking
ranges.

Don't disable dB volume unless both the max is negative and the range is
suspiciously small. This should still disable it for the device this
check was originally added for.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/447
Link: 10ac01a206
2025-10-15 21:37:06 +03:00
Pauli Virtanen
c89acd3e1c alsa: acp: fix volume rounding down causing mute
Some ALSA devices have minimum HW volume value that is muted.  ALSA
indicates it with SND_CTL_TLV_DB_GAIN_MUTE = -9999999 dB/100 volume dB.
When rounding down to HW volume, we may get this muted value.

When determining splitting of volumes to mixers and soft volume, we
don't want HW mixers to set volume to muted, unless the target volume is
actually muted.

Fix by adding element_ask_unmuted_dB_vol() that rounds up if the asked
rounding mode resulted to mute.

This fixes mic getting muted at low volume despite ALSA reporting the dB
values correctly.

Fixes #4890
2025-10-14 08:02:23 +00:00
Arun Raghavan
154ab33607 spa: alsa: Add option to use ELD-detected channels 2025-10-10 09:34:43 +00:00
Arun Raghavan
91e2f184e2 spa: alsa: Read and expose channel count and position from ELD
The next step will be to propagate this to the correct node.
2025-10-10 09:34:43 +00:00
Peter Ujfalusi
9c42c06af0 alsa: Use the minimum period size as headroom for SOF cards
Configure the headroom to be equal of the minimum allowed period size for
the configuration.

This is desirable when the ALSA driver's hw_ptr is 'jumpy' due to
underplaying hardware architecture, like SOF.
In case of SOF the DSP firmware will burst read at stream start to fill
it's host facing buffer and later settles to a constant pace. The minimal
period size is constrained by the driver to cover the initial burst and
settling time of the hw_ptr.

Guard this mode of working with a new boolean flag, which is only enabled
for SOF cards, kept it disabled for other cards to avoid any unforeseen
side effects.

Even if the use-period-size-min-as-headroom is set to true, the manual
headroom configuration will take precedence to allow experimentation.

Link: https://github.com/thesofproject/linux/issues/5284
Link: https://github.com/thesofproject/sof/issues/9695#issuecomment-2569033847
Link: https://github.com/thesofproject/sof/issues/10172
Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4489
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
2025-09-25 16:30:08 +03:00
Wim Taymans
f8389cbdb7 alsa: improve force_rate handling
Replace force_rate with force_quantum. We use force_rate when we need
to play an IEC958 or a DSD format but it does not make sense to just
force the rate without also forcing the duration.

This is also what happens when doing IRQ based scheduling, we then force
both the duration and rate of the graph so we can reuse this logic.

Also when forcing a quantum, take into account the suggested duration
and rate of the graph and scale that with the currently configured rate
for the period size. This gives a quantum that will match the requested
rate better. This is important for the DSD, where rate are very high and
we want the period size to be something reasonable relative to the
selected graph rate.

For batch devices (and when using a timer) we also configure a period
size that is half the duration of the quantum, to make sure we get some
headroom. We however need to force the full duration as the quantum, so
keep track of this scaling and apply when calculating the duration.
2025-09-25 12:29:05 +02:00
Pauli Virtanen
2e2f7c9f79 alsa: don't fail if 3 periods_min fails
Some drivers (emu10k1) appear to not necessarily support more than 2
periods.

Don't fail start if snd_pcm_hw_params_set_periods_min() fails, then we
just set nearest possible periods and buffer sizes.
2025-09-23 07:21:29 +00:00
Pauli Virtanen
bf783ab08f alsa: report extra latency for FireWire drivers
Based on testing, ALSA FireWire drivers introduce additional latency
determined by the buffer size.

Report that latency.

Pass device.bus to the node, so it can recognize firewire.
2025-09-07 18:23:31 +00:00
Pauli Virtanen
916896c1cc alsa: force IRQ scheduling for firewire in pro-audio profile
FireWire ALSA driver latency is determined by the buffer size and not the
period. Timer-based scheduling is then not really useful on these devices as
the latency is fixed.

In pro-audio profile, enable IRQ scheduling unconditionally for these
devices, so that controlling the latency works properly.

See #4785
2025-09-07 18:23:31 +00:00
Pauli Virtanen
64aaf8a832 alsa: set minimum period count before automatic period size
Some devices (FireWire) fail to produce audio if period count is < 3,
and also have small buffer size. When quantum is too large, we might
then get too few periods and broken sound.

Set minimum for the period count in ALSA, to determine the maximum
period size we can use. If smaller than what we were going to use, round
down to power-of-2.

See #4785
2025-09-07 18:23:31 +00:00
Wim Taymans
0f6aae914f alsa: don't add MAX_LATENCY when using IRQ scheduling
The Max latency property only works for timer based scheduling so that
we don't select a quantum larger than we can handle in our buffer.

With IRQ based scheduling this does not make sense because we will
reconfigure the buffer completely when we change quantums and so the
currently selected buffer size does not limit the latency in any way.

Fixes #4877
2025-09-02 18:52:38 +02:00
Wim Taymans
9606b37776 alsa: use 3 periods in IRQ mode by default
3 seems to work better as a default for Firewire. It does not actually
add latency because we only keep 1 period filled with data at all times.
2025-09-02 17:29:26 +02:00
Wim Taymans
0095d79ef8 alsa: use 2 (or 3 for batch) periods in IRQ mode
Some drivers (Firewire) have a latency depending on the ALSA buffer size
instead of the period size.

In IRQ mode, we can safely use 2 (or 3 for batch devices) periods
because we always need to reconfigure the hardware when we want to
change the period and so we don't need to keep some headroom like we do
for timer based scheduling.

See #4785
2025-09-02 14:13:19 +02:00
alexdlm
b0b6b1fcc5 Map Razer BlackShark v3 ACP 2025-08-27 15:55:02 +00:00
Wim Taymans
e35a8554f8 control: improve UMP to Midi conversiom
Improve the spa_ump_to_midi function so that it can consume multiple UMP
messages and produce multiple midi messages.

Some UMP messages (like program changes) need to be translated into up
to 3 midi messages. Do this byt adding a state to the function and by
making it consume the input bytes, just like the spa_ump_from_midi
function.

Adapt code to this new world. This is a little API break..
2025-08-19 18:33:59 +02:00
Wim Taymans
f562394596 alsa-seq: improve debug
Make it easier to change the event debug. Also add some more context
to the event debug.
2025-08-19 18:33:58 +02:00
Pauli Virtanen
618d60a1f2 alsa: show correct value in api.alsa.period-num 2025-08-09 12:53:41 +03:00
Wim Taymans
c9c7552fed alsa: clear port before adding to free list
If we clear the port after adding, we will destroy the links into the
list and cause crashes later.
2025-08-04 11:02:02 +02:00
Wim Taymans
4715e36a5c spa: don't free the mix_list ports
We can't move the mix_list ports to the free_list like that because the
elements in the list use a different list to link together. Also, we
don't need to free those ports at all because they will be freed when we
move the port_list to the free_list.
2025-07-31 10:20:59 +02:00
Wim Taymans
a3da53f66e alsa: fix seq compilation 2025-07-30 18:54:16 +02:00
Wim Taymans
7f7b4be82d alsa: use the safer pod parser for control events 2025-07-30 18:43:34 +02:00
Wim Taymans
6d07eaea1f seq: rework port handling
Dynamically allocate ports as we need them.
Use port lists to iterate active ports.
2025-07-30 17:32:02 +02:00
Wim Taymans
685aed1de2 alsa: update resampler requested size before reading
spa_alsa_read is called from the source process function when we are a
follower and no buffer is ready yet.

Part of the rate correction was performed by the ALSA driver when it
woke up but now, the resampler has updated the requested size and we
need to requery it before we can start reading samples.

Otherwise, we end up with requested samples from before the rate update
and we might not give enough samples to the resampler. In that case, the
adapter will call us again and we will again try to produce a buffer
worth of the requested samples, which will xrun.
2025-07-22 16:48:43 +02:00
Karl Relton
9189b1d8b7 Add ACP for Logitech 407 USB PC Speaker set 2025-07-21 12:25:26 +00:00
Karl Relton
eac495f0e7 Option of analog or iec958 stereo output, both merging volume switches 2025-07-21 12:19:13 +00:00
Karl Relton
47e8984450 Upload New File 2025-07-21 12:17:40 +00:00
Wim Taymans
f2fb0b0aa5 alsa: update resample state in all cases
We need to manually recheck the resample state when the matching state
got updated.
2025-07-18 19:20:00 +02:00
Wim Taymans
ce2989891d alsa: init the bw_max value
Otherwise, rate matching doesn't work when it's left to 0.0.
2025-07-18 18:21:18 +02:00
Carlos Rafael Giani
c504851dca alsa-compress-offload-sink: Improve write_queued_output_buffers comments 2025-07-18 10:53:59 +02:00
Carlos Rafael Giani
48716a72b1 alsa-compress-offload-sink: Remove unused variable 2025-07-18 10:53:52 +02:00