mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 23:27:06 +00:00
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:
parent
3d98c21d06
commit
9d069dc00b
4 changed files with 66 additions and 53 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue