[alsa-devel] Audio DMA buffer layout

Takashi Iwai tiwai at suse.de
Thu May 10 17:58:36 CEST 2007

At Thu, 10 May 2007 12:52:20 +0200,
Markus Korber wrote:
> Thus spake Takashi Iwai:
> First of all, thanks for your answer.  However, 
> > At Tue, 08 May 2007 13:47:47 +0200,
> > Markus Korber wrote:
> >>
> >>
> >>      IRQ1 +----------------+
> >>           | page_3 (right) |\
> >>           +----------------+ > double buffer 1
> >>           | page_2 (left)  |/
> >>      IRQ0 +----------------+
> >>           | page_1 (right) |\
> >>           +----------------+ > double buffer 0
> >>           | page_0 (left)  |/
> >>           +----------------+
> >
> > If I understand correctly, the samples for a channel (e.g. left) is
> > practically split to two regions, page 0 and page 2 in the above?
> Correct.
> > If yes, this h/w design is hard to implement mmap mode
> > straightforwardly because the alsa-lib (and apps) assume "linear"
> > buffers.  For normal read/write without mmap, this shouldn't be that
> > hard as you guess, though.
> Are there any drawbacks if I use the R/W mode without mmap, regarding
> applications (mplayer), dmix, etc.?

Exactly.  mplayer shouldn't be a problem, but dmix won't work without

> Furthermore, in mmap mode, I think I could use an intermediate buffer
> (with the layout as above), where I copy the data from the (linear)
> mmap'd buffer to, could I?  Maybe using helpers from struct
> pcm-indirect.h?  But this is not very beautiful.

Yeah, it's possible but not sexy.  That's what I meant

However, if the dmix is the main reason to support mmap, it would end
up with the intermediate buffer because dmix doesn't work well with

Thus the following might be not worth to consider.  Anyhow...

> > A workaround would be to use SG-buffer (if possible).  The constraint
> > is thta both double buffers above have to be aligned in PAGE_SIZE
> > (depending on architecture, 4KB mostly).
> It's a custom chip with an ARM core and an AMBA-AHB bus.  PAGE_SIZE
> alignment wouldn't be a problem, although then buffer_size would be
> fixed to multiples of PAGE_SIZE, i guess?


> I'm not quite sure how to implement this:
> chip_pcm_new
>         - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
>                 snd_dma_continuous_data(GFP_KERNEL), PAGE_SIZE, PAGE_SIZE)
> chip_hw_params
>         - snd_pcm_lib_malloc_pages(substream,
>                                    params_buffer_bytes(hw_params))
>         - map sg-pages with snd_pcm_sgbuf_get_addr()
>         Why/How?
> I mean, my hardware DMA layout is fixed (apart from the double buffer
> page sizes, which should be a multiple of PAGE_SIZE).  
> So do I have to call snd_pcm_lib_malloc_pages() and/or do I need to call
> dma_map_sg() with a scatterlist?  Or how do I tell ALSA about my DMA
> layout?  And how is the application informed about this?

Does the hardware support the "real" SG buffers?  That is, you can
compose a buffer from the different memory chunks, or do you need a
linear buffer but split to two inside?

In the latter case, I'd do like the following:
- preallocate the buffer as TYPE_CONTINUOUS
- Use snd_pcm_lib_malloc_pages() in hw_params callback as if it's a
  normal linear buffer.
- Then linearize the virtual buffer via vmap() in hw_params.
  (It has to be vfree'd in the corresponding hw_free or succeeding
   call of hw_params.)
- Implement page PCM ops for mmap, too, so that it can map correctly.
  Or implement mmap PCM ops, especially for ARM, and co.  In this
  case, map two regions by dma_mmap_cohernt() call.
- This would require a constraint to align period_bytes PAGE_SIZE.
  snd_pcm_hw_constraint_step() can be used for this purpose.


More information about the Alsa-devel mailing list