Re: (re)use and (re)definition of snd_pcm_hw_params->fifo_size for 'jumpy DMA'

Jaroslav Kysela
2026-04-02T12:01:51Z

On 3/31/26 16:09, Péter Ujfalusi wrote:
>
>
> On 31/03/2026 15:00, Jaroslav Kysela wrote:
>> On 3/31/26 12:56, Péter Ujfalusi wrote:
>>
>>> Pipewire uses the minimum period size internally for headroom
>>> calculation:
>>> https://gitlab.freedesktop.org/pipewire/pipewire/-/
>>> commit/9c42c06af00818038be494fd41632cb2d50a0df5
>>>
>>> This works more or less, but things started to get out of control soon.
>>
>> It's conditional, so it's not a general rule. Pipewire just tries to
>> push the drivers to limits with hard-coded assumptions.
>>
>>> To get the most power saving benefit, you would want quite big
>>> DeepBuffer, let's say 100ms but for video/voice calls you don't want
>>> this big buffer, around 40ms should be OK, some other use case might
>>> need something in between.
>>> If you run tinyplay on the DeepBuffer PCM w/o  specifying period size,
>>> it will fail to find the minimum and outright fails unless we lower the
>>> DB to around 20ms.
>>> With 20ms you don't have much power savings in case of audio playback.
>>> So, you spam out several PCM devices with different DeepBuffer to
>>> accommodate use cases, this is really not something that makes sense.
>>>
>>> This is the reason why I have reversed the rules and adjusted the
>>> DeepBuffer size based on the period size.
>>> In this case we still need to limit how large the DB can be, so it is
>>> not true that the DeepBuffer equals to the period size, it is caped.
>>
>> It seems that the discussion somewhere else:
>>
>> 1) applications don't know what they are want, thus driver will enforce
>> a configuration (e.g. a forced deep buffer)
>>
>> 2) ALSA PCM period mapping to the hardware which allows "deep buffering"
>
> With SOF we don't advertise the use of the DeepBuffer enabled PCM, it is only used on consumer devices where the audio HAL knows how to use it.
> The static-DB and the dynamic-DB both works fine with applications, like mplayer, mpv, vlc, the only issue is with pipewire (which is not aware of it).
> What I want is to achieve at the end is to advertise this via UCM's low-power-hifi, but due to the bursts, Pipewire can get xrun.
>
>> At the moment, nothing prevents ALSA applications to use the bigger
>> period sizes when there are known beforehand like "play background
>> music". In other words - power efficiency can be controlled from the
>> app.
>
> But with a static-DB and locking t he period size to the DB size would prevent bigger period size use and even with bigger period size, if the DB size is 'small' then the power efficiency is out of the window.
> But, if we increase the static-DB size then we limit the minimum period size to scale down.

It's safe to allow bigger periods from the driver which are multiple of the DB
size.

>> The applications can also update PCM buffer at any time, so new
>> data (we are speaking about playback) can be feed at any time to make
>> the time window for the underrun occurrence shorter when the driver
>> transfers data to the hardware.
>
> Yes, pipewire does this, it does not care about the period size while media players do. I guess most application which uses NO_PERIOD_WAKEUP does this, they don't care about period boundaries.
> They look at avail (hw_ptr, sw_ptr, delay) and work on manage the data in buffer as close to hw_ptr as possible.

But apps should be aware about the information which area (e.g. period) is
current so they should avoid to work in this area, if system task scheduling
is probably going to interrupt this realtime data feed.

Basically, originally we took the periods as the base transfer block in API
design. The period size and the filled count of periods (playback) gave the
latency (of course without additional FIFO in hw path - just for the CPU <->
HW path).

>> We may have those configurations (* = future when driver tells the
>> initial count of queued periods):
>>
>
>> period | period count | init_periods | minimal data latency |
>> --------+--------------+---------------+----------------------+---------
>> 4ms | 4 | unsettled (1) | 4ms | realtime
>> *4ms | 200 | 25 | 100ms | semi-realtime
>> 1000ms | 2 | 1 | 1000ms | pwr efficient
>
> SOF specific, but we limit the period size to be min 8ms to unbrake pipewire to avoid xzrun on start and xrun handling and to hint application what is safe.

And it's the whole problem. You are trying to solve a problem caused with the
situation that applications do not know about those constraints.

>> IMHO, the period size describes the expected minimal latency and
>> applications can put more samples to the PCM buffer. So the whole
>> question is to give suggestions which data threshold is safe for the
>> standard operation.
>
> Yes, it is and not. PW allocates big period sizes and manages really low latencies when it comes to audio.
> And yes, the question is the 'headroom' that is safe to use by applications when dealing with something which is jumpy

But current PW behaviour is based on "assumption" that the data are processed
in small chunks from the PCM buffer. And this assumption is not true for SOF
while it worked perfectly for legacy HDA and all simple PCI (even ISA :-))
sound hardware. Also the initial transfer at the stream start is different.
And I think that USB / FireWire serial buses are in similar situation. I saw
workaround (special settings) in PW for those cases, too.

>> The timer based queuing should just help to feed data more frequently,
>> but it does not mean that applications should not set the period size
>> based on the requirements. Ideally, everything should be coordinated -
>> period sizes with proper sample feed timing from the application side.
>
> Right, but, but, in normal PCM of SOF, the ShallowBuffer is 4ms, we cannot set constraint for the period size to be min and max 4ms, that would xrun right away.

The xrun happens just because application do not push data to the next period
in time, right?

> And this would just bring in the issue of the static DB that we have, if it is big, then applications would break if they want smaller periods.

We need definitely a handshake (app<->kernel) for this, but the question is,
if just going back to honor the period sizes properly from the user space
applications is a right way to go or not. IMHO it may be just a clarification
for the current mechanism.

In any case we need those extensions:

Kernel -> user space:

- give the initial transfer chunk size to user space
- give the next (step) transfer chunk size to user space

The minimal requirement for the playback data at start would be:

'init_chunk + (2 * step_chunk)'

Note that init_chunk may be zero (legacy PCI HW).

In my proposal, step_chunk == period_size and init_chunk will be provided
using additional value in hw_params (as count of initial periods).

User space -> kernel:

- notification that the code honors period sizes + initial periods and uses
period size to ask kernel for requested latency (keeping the current behavior
for older binaries; and to allow drivers to do optimal setup)
- request for low hw_ptr granularity (to use e.g. deep buffers) - basically
okay, we don't care, the "BATCH" transfer mode with whole periods is okay

Example (with the "honor period size" handshake activated):

20ms latency goal, 4ms hw transfers, 12ms initial hw buffer

-> set period size to 10ms or less
# 2 periods must be filled to avoid an initial xrun
-> set buffer size to 30ms or more
<- get 8 periods x 4ms
<- 3 initial periods (3*4ms = 12ms)

suggested initial fill = 12ms + 2 * 4ms ; 20ms total

The driver (constraints setup) should take account the initial periods in this
case.

> BTW, should we still keep the dynamic DeepBuffer as a way from the kernel to do things automatically? It will allow unaware ALSA applications to gain this for free, but it needs information to be given to clever ones (like PW) on how to deal with the jumps.

It's difficult to suggest something for this problem when the specific
application does not give any hint to the kernel space about future API calls
and expected use (if they will do rewind for example in future). We need
properly document everything related to the transfers and let applications to
choose between "expect data change soon" and "buffering" behaviour IMHO.

And definitely, we should not do optimizations related to single app - choose
specific period size just because pipewire does not work correctly (speaking
about the clarified API) - in the drivers.

Jaroslav

--
Jaroslav Kysela <perex@perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.