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 mmap.
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 "straightforwardly".
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 two-periods.
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?
Yes.
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.
Takashi