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

Péter Ujfalusi
2026-03-31T10:56:09Z

On 31/03/2026 12:29, Jaroslav Kysela wrote:
> On 3/31/26 08:36, Takashi Iwai wrote:
>
>>>> if a device allows a different queue size, it should be configurable
>>>> via hw_params.
>>>
>>> I'm not sure if I follow this statement. the fifo_size is a driver to
>>> user space information, driver fills it and user space ignores it ;) - I
>>> cannot find any evidence of it's use.
>>
>> If a chip has a similar constraint but the init and step sizes are
>> adjustable, they should be configurable via hw_params procedure --
>> that's my point.
>>
>>> The init_chunk, step_chunk would be similar, the driver sets it and user
>>> space would use it.
>>>
>>> In SOF this will be dynamic and it will depend on the period size:
>>> https://github.com/thesofproject/linux/pull/5673/
>>> commits/18f3ba5e42212d77019d79ec09b7057a7703d361
>>
>> Well, so even in your case, the driver can implement the hw_constraint
>> for coupling those numbers, too.  Then application may choose the
>> init_chunk or step_chunk, which restricts the period size
>> automatically.  If application doesn't choose those, the hw_params
>> engine will choose depending on the period size, and application can
>> see the values after hw_params call.
>
> I was more thinking about this problem and it seems that the root of
> this cause is that application (pipewire) is trying to bypass the period
> based mechanism for which we already have the handshake. It's no issue
> to ask for smaller periods from the app side to maintain the expected
> latency. It is also understandable that we need to fill at least two
> periods at start and keep this buffer timing (also with counting the
> system scheduling latencies).
>
> So, perhaps, the only flag may be added notifying that the (first)
> minimal period is processed immediately after start. It's also common
> situation for other drivers with double buffering in the driver like
> USB, maybe FireWire, right ? Note that this flag won't be the BATCH
> flag. Or we can just add a field notifying how many minimal periods are
> queued at start to be more universal (apparently SOF requires this,
> because the initial chunk of queued samples is bigger then the later
> chunks - so the first transfer will go over more periods).
>
> We may discuss if small periods are efficient. We have already mechanism
> to disable period events (SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP) and
> drivers don't do usually deep buffering, so they program DMA transfers
> with smaller (or equal) chunks than period size.
>
> It seems to me that we are trying to design another layer on top of the
> current just to satisfy the improper current PCM API use.
>
> And saying this, it appears that the kernel drivers (yes SOF) are trying
> the bypass the period constraints make it freely customized [1] instead
> to apply constraints based on the hardware limits including the internal
> maintenance (CPU <-> DSP buffering). So the issue is on both sides and
> the things are failing because the standard period handshake is not
> honored.

The dynamic DeepBuffer support is not upstream for SOF, yet. Currently
we have static DeepBuffer where the topology defines the size of the hos
facing buffer to be used in the DSP.
This is entirely SW concept.
For this static DeepBuffer the kernel will place a constraint on the
minimum period size to not allow it smaller (plus some headroom) than
the DeepBuffer set by the topology file.
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.
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.

With the reversed rule we cannot constrain the period size obviously.

Still, with the constrained period size in current static DeepBuffer, PW
is free to do whatever it wants and thus we needed to enforce that the
it is not safe to be closer to the hw_ptr than the minimum period size.

We don't want to allow DeepBuffer on the normal PCM, we still want this
to be available on a special PCM device, use case:
audio plays on DeepBuffer which allows power saving and notifications
are played through normal PCMs - they are mixed in DSP and as soon as
normal PCM is closed we can immediately benefit from the power savings.

Probably a user configurable DeepBuffer can work, but then the kernel
should limit the maximum period size?

Strictly locking the DeepBuffer with period size creates another
obstacle for audio applications, audio servers like PW don't care about
periods, they work on the buffer with timer based updates and rewriting
samples in buffer ahead of the hw_ptr.

>
>                     Jaroslav
>
> [1] https://github.com/thesofproject/linux/pull/5673/changes#diff-
> d8bbc05d879b6eee2041d6fc0ee06f050be097ac05b12cfec9b35d89f66d3a84R79-R89
>
> /*
>  * When the host DMA buffer size is larger than 8ms, the firmware
> switches from
>  * a constant fill mode to burst mode, keeping a 4ms threshold to
> trigger
>  * transfer of approximately host DMA buffer size - 4ms after the
> initial burst
>  * to fill the entire buffer.
>  * To simplify the logic, above 20ms ALSA period size use the same size
> for host
>  * DMA buffer, while if the ALSA period size is smaller than 20ms, then
> use a
>  * headroom between host DMA buffer and ALSA period size.
>  */
>

--
Péter