If your hardware supports the page table as in emu10k1 or the
buffer descriptors as in via82xx, you can use the scatter-gather
(SG) DMA. ALSA provides an interface for handling SG-buffers.
The API is provided in <sound/pcm.h>
.
For creating the SG-buffer handler, call
snd_pcm_lib_preallocate_pages()
or
snd_pcm_lib_preallocate_pages_for_all()
with SNDRV_DMA_TYPE_DEV_SG
in the PCM constructor like other PCI pre-allocator.
You need to pass snd_dma_pci_data(pci)
,
where pci is the struct pci_dev pointer
of the chip as well.
The struct snd_sg_buf instance is created as
substream->dma_private. You can cast
the pointer like:
struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
Then call snd_pcm_lib_malloc_pages()
in the hw_params
callback
as well as in the case of normal PCI buffer.
The SG-buffer handler will allocate the non-contiguous kernel
pages of the given size and map them onto the virtually contiguous
memory. The virtual pointer is addressed in runtime->dma_area.
The physical address (runtime->dma_addr) is set to zero,
because the buffer is physically non-contiguous.
The physical address table is set up in sgbuf->table.
You can get the physical address at a certain offset via
snd_pcm_sgbuf_get_addr()
.
When a SG-handler is used, you need to set
snd_pcm_sgbuf_ops_page
as
the page
callback.
(See
page callback section.)
To release the data, call
snd_pcm_lib_free_pages()
in the
hw_free
callback as usual.