ALSA: memalloc: Support for non-contiguous DMA allocation

This patch adds the support for allocation of non-contiguous DMA pages
in the common memalloc helper.  It's another SG-buffer type, but
unlike the existing one, this is directional and requires the explicit
sync / invalidation of dirty pages on non-coherent architectures.

For this enhancement, the following points are changed:
- snd_dma_device stores the DMA direction.
- A new variant, snd_dma_alloc_dir_pages() and *_all() are introduced;
  snd_dma_alloc_pages() and *_all() just wrap with DMA_BIDIRECTIONAL.
- A new helper snd_dma_buffer_sync() is introduced;
  this gets called in the appropriate places.
- A new allocation type, SNDRV_DMA_TYPE_NONCONTIG, is introduced.

The driver needs to call the allocation with the new type, and it
likely needs to add SNDRV_PCM_INFO_SYNC_APPLPTR and
SNDRV_PCM_INFO_NO_STATUS_MMAP to the PCM hardware.info for disabling
the mmap of control and status data.  Otherwise it'd miss explicit
sync in the mmap mode.

The explicit sync is performed in  the points before and after
read/write transfer as well as and applptr/hwptr syncptr ioctl.  In
the case of mmap mode, user-space is supposed to call the syncptr
ioctl with the hwptr flag to update and fetch the status at first.
This corresponds to CPU-sync.  Then user-space advances the applptr
via syncptr ioctl again with applptr flag, and this corresponds to the
device sync with flushing.

Other than the DMA direction and the explicit sync, the usage of this
buffer type is almost equivalent with the existing
SNDRV_DMA_TYPE_DEV_SG; you can get the page and the address via
snd_sgbuf_get_page() and snd_sgbuf_get_addr(), also calculate the
continuous pages via snd_sgbuf_get_chunk_size().

For those SG-handling, the non-contig type shares the same ops with
the vmalloc handler.  As we do always vmap the SG pages at first, the
actual address can be deduced from the vmapped address easily without
iterating the SG-list.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
6 files changed