ALSA: Make snd_sgbuf_get_{ptr|addr}() available for non-SG cases

Passing struct snd_dma_buffer pointer instead, so that they work no
matter whether real SG buffer is used or not.

This is a preliminary work for the HD-audio DSP loader code.

Signed-off-by: Ian Minett <ian_minett@creativelabs.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2012-09-20 20:29:12 -07:00
parent 3d98c21d06
commit 9d069dc00b
4 changed files with 66 additions and 53 deletions

View file

@ -98,8 +98,10 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
/* /*
* return the physical address at the corresponding offset * return the physical address at the corresponding offset
*/ */
static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset) static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{ {
struct snd_sg_buf *sgbuf = dmab->private_data;
dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
addr &= PAGE_MASK; addr &= PAGE_MASK;
return addr + offset % PAGE_SIZE; return addr + offset % PAGE_SIZE;
@ -108,10 +110,31 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t off
/* /*
* return the virtual address at the corresponding offset * return the virtual address at the corresponding offset
*/ */
static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset) static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
size_t offset)
{ {
struct snd_sg_buf *sgbuf = dmab->private_data;
return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
} }
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size);
#else
/* non-SG versions */
static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{
return dmab->addr + offset;
}
static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
size_t offset)
{
return dmab->area + offset;
}
#define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size)
#endif /* CONFIG_SND_DMA_SGBUF */ #endif /* CONFIG_SND_DMA_SGBUF */
/* allocate/release a buffer */ /* allocate/release a buffer */

View file

@ -983,53 +983,42 @@ static int snd_pcm_lib_alloc_vmalloc_32_buffer
_snd_pcm_lib_alloc_vmalloc_buffer \ _snd_pcm_lib_alloc_vmalloc_buffer \
(subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO)
#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p)
#ifdef CONFIG_SND_DMA_SGBUF #ifdef CONFIG_SND_DMA_SGBUF
/* /*
* SG-buffer handling * SG-buffer handling
*/ */
#define snd_pcm_substream_sgbuf(substream) \ #define snd_pcm_substream_sgbuf(substream) \
((substream)->runtime->dma_buffer_p->private_data) snd_pcm_get_dma_buf(substream)->private_data
static inline dma_addr_t
snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
{
struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
return snd_sgbuf_get_addr(sg, ofs);
}
static inline void *
snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
{
struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
return snd_sgbuf_get_ptr(sg, ofs);
}
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
unsigned long offset); unsigned long offset);
unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
unsigned int ofs, unsigned int size);
#else /* !SND_DMA_SGBUF */ #else /* !SND_DMA_SGBUF */
/* /*
* fake using a continuous buffer * fake using a continuous buffer
*/ */
#define snd_pcm_sgbuf_ops_page NULL
#endif /* SND_DMA_SGBUF */
static inline dma_addr_t static inline dma_addr_t
snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
{ {
return substream->runtime->dma_addr + ofs; return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs);
} }
static inline void * static inline void *
snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
{ {
return substream->runtime->dma_area + ofs; return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs);
} }
#define snd_pcm_sgbuf_ops_page NULL static inline unsigned int
snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) unsigned int ofs, unsigned int size)
{
#endif /* SND_DMA_SGBUF */ return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size);
}
/* handle mmap counter - PCM mmap callback should handle this counter properly */ /* handle mmap counter - PCM mmap callback should handle this counter properly */
static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)

View file

@ -327,32 +327,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
} }
EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
/*
* compute the max chunk size with continuous pages on sg-buffer
*/
unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
unsigned int ofs, unsigned int size)
{
struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
unsigned int start, end, pg;
start = ofs >> PAGE_SHIFT;
end = (ofs + size - 1) >> PAGE_SHIFT;
/* check page continuity */
pg = sg->table[start].addr >> PAGE_SHIFT;
for (;;) {
start++;
if (start > end)
break;
pg++;
if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
return (start << PAGE_SHIFT) - ofs;
}
/* ok, all on continuous pages */
return size;
}
EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
#endif /* CONFIG_SND_DMA_SGBUF */ #endif /* CONFIG_SND_DMA_SGBUF */
/** /**

View file

@ -22,6 +22,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/export.h>
#include <sound/memalloc.h> #include <sound/memalloc.h>
@ -136,3 +137,29 @@ void *snd_malloc_sgbuf_pages(struct device *device,
snd_free_sgbuf_pages(dmab); /* free the table */ snd_free_sgbuf_pages(dmab); /* free the table */
return NULL; return NULL;
} }
/*
* compute the max chunk size with continuous pages on sg-buffer
*/
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size)
{
struct snd_sg_buf *sg = dmab->private_data;
unsigned int start, end, pg;
start = ofs >> PAGE_SHIFT;
end = (ofs + size - 1) >> PAGE_SHIFT;
/* check page continuity */
pg = sg->table[start].addr >> PAGE_SHIFT;
for (;;) {
start++;
if (start > end)
break;
pg++;
if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
return (start << PAGE_SHIFT) - ofs;
}
/* ok, all on continuous pages */
return size;
}
EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);