At Tue, 08 May 2007 13:47:47 +0200, Markus Korber wrote:
Hi,
I'm working with a custom sound chip with its own DMA hardware. The figure shows how the I2S DMA expects data to be prepared:
IRQ1 +----------------+ | page_3 (right) |\ +----------------+ > double buffer 1 | page_2 (left) |/ IRQ0 +----------------+ | page_1 (right) |\ +----------------+ > double buffer 0 | page_0 (left) |/ +----------------+
The hardware has 2 double buffers, each containing left and right sample regions, i.e. it alternately transmits samples from page_0 and page_1, i.e. double buffer 0, then generates an interrupt and starts transmitting page_2 and page_3. After that another interrupt is generated and the process begins again with double buffer 0.
So my question is, how to tell ALSA about this memory layout? Is it possible to operate in MMAP mode with SNDRV_PCM_INFO_NONINTERLEAVED? But then, how to tell the application that it should either fill double buffer 0 or 1? Or should I use RW mode and copy samples manually to another buffer? Or something else? SG-DMA? page()-callback?
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? 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.
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). For implementing a SG buffer, you can use either mmap or page pcm_ops. The mmap is to do the whole mmap operation, so you can do all what you'd like. The page is a callback used by the default ALSA mmap handler and you can return the page pointer corresponding to the given buffer offset.
Takashi