[alsa-devel] mapping externally allocated Scatter Gather DMA buffers

Manu Abraham abraham.manu at gmail.com
Wed Nov 10 19:30:49 CET 2010

On Wed, Nov 10, 2010 at 11:35 PM, Jaroslav Kysela <perex at perex.cz> wrote:
> On Wed, 10 Nov 2010, Manu Abraham wrote:
>> On Wed, Nov 10, 2010 at 8:35 PM, Jaroslav Kysela <perex at perex.cz> wrote:
>>> On Wed, 10 Nov 2010, Manu Abraham wrote:
>>>>        /* enable stream */
>>>>        /* initializing 8 buffer with "pages" pages each .. */
>>>>        stream = saa7231_stream_init(saa7231, AUDIO_CAPTURE, ADAPTER_INT,
>>>> 0, pages);
>>>>        if (!stream) {
>>>>                dprintk(SAA7231_ERROR, 1, "ERROR: Registering stream");
>>>>                return -ENOMEM;
>>>>        }
>>>>        audio->stream = stream;
>>>>        buffer = stream->dmabuf;
>>>>        saa7231_add_irqevent(saa7231, 43, SAA7231_EDGE_RISING,
>>>> saa7231_audio_evhandler, "AS2D_AVIS");
>>>>        dprintk(SAA7231_DEBUG, 1, "Mapping %d buffers with %d pages
>>>> each",
>>>> XS2D_BUFFERS, pages);
>>> Unfortunately, I don't understand the role of XS2D_BUFFERS. The ALSA
>>> bufsize
>>> is the whole DMA area (you should use params_buffer_bytes() to get this
>>> value instead of calculating this using periods * period_size).
>>> It means: Just allocate number of pages required for buffer_bytes. Don't
>>> play with periods (except the interrupts).
>> There are 8 SG buffers for the hardware; the maximum size of each
>> buffer can be 512 pages,
>> the minimum can be a single page.
> Could you describe more the whole DMA layout, including IRQ acks?
> It seems to me:
> SG PAGE 1 points to 1 - 512 data pages (4096 bytes long)
> SG PAGE 2 .....
>    ....
> SG PAGE 8 .....

Yes, correct.

My initial thoughts and concepts were thus:
 - A particular buffer size is requested by ALSA
 - this buffer size is set for all the 8 SG buffers
 - A virtual area is created from these 8 SG buffers
 - This virtual area is mmap()'d
 - SG Buffer 0 gets filled
 - Interrupt occurs
 - Driver reads from offset 0 of virtual area
 - SG Buffer 1 gets filled
 - Interrupt occurs
 - Driver reads from offset "buffer size" of virtual area

and so on, the cycle repeats.

Little did I realize at that point of time that buffer size for ALSA
meant the total length of the

> How you can program interrupts? Only when the whole page is finished or the
> interrupt does not depend on the DMA buffer position, but a hw clock timer?

All 8 SG heads are placed on the MMU. The MMU can be programmed to
generate an IRQ
when "size" buffer is full. Suppose that an SG buffer which is 8 pages
long, but I did program
the MMU to generate an IRQ when eg: 192 bytes of data is filled into
SG buffer. Now, as data
is being digitized and grabbed, I get an interrupt when 192 bytes is
filled in the SG buffer.

When the interrupt occurs, the driver needs to check from hardware
registers, which of the
8 SG buffers has been filled upto say 192 bytes. Now, since I know
that SG buffer 'x' is filled,
I can ask the application to read from the buffer area. This length is
called "stride" by the chip.

Normally, I could say the interrupts would be following a certain
order, SGBUF1, SGBUF2,
but It is indeed necessary to read the buffer index first and then
deduce which SGBUF to read.

Putting it short, even though a whole page is setup for DMA, an
interrupt can be invoked,
depending on setting up the "stride" length, the maximum of which is
the buffer length setup
on the MMU.

There is no hardware clock timer involved in this process. but there
is a hardware feature
where the buffers can be time stamped for reason such as
synchronization with a video stream
for example.

> Could you limit how much data (samples) are fetched from the one data page
> or the hw operates with whole pages only?

You need to setup a whole PAGE on to the MMU, even if you need to
transfer only a byte.

Yes, you can set any number of bytes (stride) to be read from the
whole SG buffer. ie, even
if the SG buffer is 512 pages long, it could contain just contain 4
bytes of data alone
(depending on stride), If I set up the hardware to generate an
interrupt when 4 bytes is filled up.

> Note that the stream processing rate is usually independent from the DMA
> layout in most hw.

Yes. I need to set the number of bytes that will be filled up for a
buffer that causes an interrupt.


More information about the Alsa-devel mailing list