[alsa-devel] Problems with safe API and snd-cs46xx

Raymond Yau superquad.vortex2 at gmail.com
Wed Sep 9 04:18:58 CEST 2009


2009/9/8 Takashi Iwai <tiwai at suse.de>

> At Tue, 8 Sep 2009 15:38:25 +0200,
> Lennart Poettering wrote:
> >
> > 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
>

it's rather common
e.g  HDA also have

    snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
    snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
                   128);
    snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
                   128);




> > > > 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's not about what unit you use.  It's the fact that three units
> exist in the hw_params space parallel and they have to be aligned with
> each other.  See ens1371 example below.
>
>
> > > > 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...
>
> Might be.
>


The front device of ice1712 has a route plugin

you may need to use hw:0,0 if you are using mmap_begin, .... and read/write
10 and 12 channels like jackd

Actually the front device of emu10k1 has two IFACE_PCM controls , most
likely you will need to modify EMU10K1.conf so that capture do not hook
those controls


>
> > > 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>
>
> I think yes.  But needs more testing of course :)
>
>
> > > > 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.
>
> Then the problem is likely the sample rate setup.  ens1371 can't give
> you always the integer sample rate.  Now the problem of multiple units
> appears here like a ghost.  Almost every parameter is associated with
> other parameters in the end due to the constraints below:
>  buffer_time = buffer_size / sample_rate
>  buffer_size = buffer_bytes / (channels * format_width)
>
> When you get a non-integer rate value, even buffer_size can be
> affected, rounded down to the next integer value.
>
> All for one, one for all -- what a perfect world.
>
>
> thanks,
>
> Takashi
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>


More information about the Alsa-devel mailing list