[alsa-devel] Problems with safe API and snd-cs46xx
Lennart Poettering
mznyfn at 0pointer.de
Tue Sep 8 15:38:25 CEST 2009
On Tue, 08.09.09 08:29, Takashi Iwai (tiwai at suse.de) wrote:
> > This turned out to cause a couple of issues with some drivers (i think
> > CS46xx is one of them, ice1712 another, I lack the hw in question, so
> > i never tried to track this down further). Basically on those drivers
> > both _set_buffer_size_near() and _set_periods_near() would fail with
> > EINVAL for some reason and then causing snd_pcm_hw_params() to return
> > ENOENT. Removing the two calls and calling snd_pcm_hw_params() would
> > however work. Changing the order of the first two calls, i.e. doing
> > first _set_periods_near() and then _set_buffer_size_near() would make
> > both calls succeed and the snd_pcm_hw_params(), too.
>
> The general problem in the hw_params setup is that the multiple
> parameters depending with each other are allowed almost freely.
> And, yet another problematic constraint is like cs46xx's one, the
> power-of-two rule. This limits strongly the value range.
>
> Also, another issue is the presence of three units to specify the same
> thing. There are units, frame, bytes and time for period and buffer
> sizes. Especially the former two and the time units can be
> inconsistent due to the integer rounding.
I always use 'frames' as unit for the actual calls, even if I said
bytes.
> > It would be good if the ALSA docs would actually mention in which
> > order those functions need to be called, if the order matters, which
> > it apparently does.
>
> There is no golden rule, unfortunately, AFAIK. There can be pretty
> weird hardware, e.g. the buffer size depending on rate. But, as a
> rule of thumb:
> 1. set access, format, channels and rate first,
> 2. if you need larger buffers than shorter periods, set the buffer
> size first,
> 3. set the period size only when you must specify it
This breaks on ice1712 at least...
> But, this can also fail when a hardware has a strong dependency
> between period and buffer sizes together with a strong constraint
> in period size. In that case, you may need to try another way,
> set period and hw_params.
For me the large buffers matter most. And large periods are the second
most important thing. Would something like the following make sense?
<snip>
snd_pcm_hw_params_any(pcm, hw);
snd_pcm_hw_params_set_access(pcm, hw, ...);
snd_pcm_hw_params_set_format(pcm, hw, ...);
snd_pcm_hw_params_set_rate_near(pcm, hw, ...);
snd_pcm_hw_params_set_channels_near(pcm, hw, ...);
snd_pcm_hw_params_copy(hw2, hw);
/* We care more about buffer size than the period size, so try setting
things in this order first */
snd_pcm_hw_params_set_buffer_size_near(hw, ...);
snd_pcm_hw_params_set_periods_near(hw, ...);
if (snd_pcm_hw_params(pcm, hw) < 0) {
/* This order didn't work, so let's try it the other way round */
snd_pcm_hw_params_set_periods_near(hw2, ...);
snd_pcm_hw_params_set_buffer_size_near(hw2, ...);
if (snd_pcm_hw_params(pcm, hw2) < 0) {
/* fail fatally */
....
}
}
</snip>
> > ens1371 has some issues with the buffer size: if you ask it for 65536
> > bytes in the playback buffer it will only agree to 65532. If the next
> > time you ask for 65532 right-away it will only agree to 65528, and so on...)
>
> The byte size can depend on the sample format and channels.
> This might be the case. Otherwise I don't see any strong restriction
> of buffer/period size in ens1371 code. It has the restriction of
> sample rates, though.
I only actually manipulate samples here, not bytes. So the prob is
that if you ask for a buffer size of n samples it will only agree to
n-1 samples, for every possible n. Other drivers don't do that.
Lennart
--
Lennart Poettering Red Hat, Inc.
lennart [at] poettering [dot] net
http://0pointer.net/lennart/ GnuPG 0x1A015CC4
More information about the Alsa-devel
mailing list