aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-09-20 23:29:12 -0400
committerTakashi Iwai <tiwai@suse.de>2012-09-23 05:24:42 -0400
commit9d069dc00b02b886abe3cab5e369140f7cd78965 (patch)
treed2f29878332a7c36a6c30128b67b2780c4a44f41
parent3d98c21d064bfbb8c6fddc659471acb4950320fa (diff)
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>
-rw-r--r--include/sound/memalloc.h27
-rw-r--r--include/sound/pcm.h39
-rw-r--r--sound/core/pcm_memory.c26
-rw-r--r--sound/core/sgbuf.c27
4 files changed, 66 insertions, 53 deletions
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index c42506212649..844af65af626 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -98,8 +98,10 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
98/* 98/*
99 * return the physical address at the corresponding offset 99 * return the physical address at the corresponding offset
100 */ 100 */
101static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset) 101static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
102 size_t offset)
102{ 103{
104 struct snd_sg_buf *sgbuf = dmab->private_data;
103 dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; 105 dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
104 addr &= PAGE_MASK; 106 addr &= PAGE_MASK;
105 return addr + offset % PAGE_SIZE; 107 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
108/* 110/*
109 * return the virtual address at the corresponding offset 111 * return the virtual address at the corresponding offset
110 */ 112 */
111static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset) 113static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
114 size_t offset)
112{ 115{
116 struct snd_sg_buf *sgbuf = dmab->private_data;
113 return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; 117 return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
114} 118}
119
120unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
121 unsigned int ofs, unsigned int size);
122#else
123/* non-SG versions */
124static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
125 size_t offset)
126{
127 return dmab->addr + offset;
128}
129
130static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
131 size_t offset)
132{
133 return dmab->area + offset;
134}
135
136#define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size)
137
115#endif /* CONFIG_SND_DMA_SGBUF */ 138#endif /* CONFIG_SND_DMA_SGBUF */
116 139
117/* allocate/release a buffer */ 140/* allocate/release a buffer */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 669c85a7fb03..7e4e4e380106 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -983,53 +983,42 @@ static int snd_pcm_lib_alloc_vmalloc_32_buffer
983 _snd_pcm_lib_alloc_vmalloc_buffer \ 983 _snd_pcm_lib_alloc_vmalloc_buffer \
984 (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) 984 (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO)
985 985
986#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p)
987
986#ifdef CONFIG_SND_DMA_SGBUF 988#ifdef CONFIG_SND_DMA_SGBUF
987/* 989/*
988 * SG-buffer handling 990 * SG-buffer handling
989 */ 991 */
990#define snd_pcm_substream_sgbuf(substream) \ 992#define snd_pcm_substream_sgbuf(substream) \
991 ((substream)->runtime->dma_buffer_p->private_data) 993 snd_pcm_get_dma_buf(substream)->private_data
992
993static inline dma_addr_t
994snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
995{
996 struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
997 return snd_sgbuf_get_addr(sg, ofs);
998}
999
1000static inline void *
1001snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
1002{
1003 struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
1004 return snd_sgbuf_get_ptr(sg, ofs);
1005}
1006 994
1007struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, 995struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
1008 unsigned long offset); 996 unsigned long offset);
1009unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
1010 unsigned int ofs, unsigned int size);
1011
1012#else /* !SND_DMA_SGBUF */ 997#else /* !SND_DMA_SGBUF */
1013/* 998/*
1014 * fake using a continuous buffer 999 * fake using a continuous buffer
1015 */ 1000 */
1001#define snd_pcm_sgbuf_ops_page NULL
1002#endif /* SND_DMA_SGBUF */
1003
1016static inline dma_addr_t 1004static inline dma_addr_t
1017snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) 1005snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
1018{ 1006{
1019 return substream->runtime->dma_addr + ofs; 1007 return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs);
1020} 1008}
1021 1009
1022static inline void * 1010static inline void *
1023snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) 1011snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
1024{ 1012{
1025 return substream->runtime->dma_area + ofs; 1013 return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs);
1026} 1014}
1027 1015
1028#define snd_pcm_sgbuf_ops_page NULL 1016static inline unsigned int
1029 1017snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
1030#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) 1018 unsigned int ofs, unsigned int size)
1031 1019{
1032#endif /* SND_DMA_SGBUF */ 1020 return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size);
1021}
1033 1022
1034/* handle mmap counter - PCM mmap callback should handle this counter properly */ 1023/* handle mmap counter - PCM mmap callback should handle this counter properly */
1035static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) 1024static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 957131366dd9..69e01c4fc32d 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -327,32 +327,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
327} 327}
328 328
329EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); 329EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
330
331/*
332 * compute the max chunk size with continuous pages on sg-buffer
333 */
334unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
335 unsigned int ofs, unsigned int size)
336{
337 struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
338 unsigned int start, end, pg;
339
340 start = ofs >> PAGE_SHIFT;
341 end = (ofs + size - 1) >> PAGE_SHIFT;
342 /* check page continuity */
343 pg = sg->table[start].addr >> PAGE_SHIFT;
344 for (;;) {
345 start++;
346 if (start > end)
347 break;
348 pg++;
349 if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
350 return (start << PAGE_SHIFT) - ofs;
351 }
352 /* ok, all on continuous pages */
353 return size;
354}
355EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
356#endif /* CONFIG_SND_DMA_SGBUF */ 330#endif /* CONFIG_SND_DMA_SGBUF */
357 331
358/** 332/**
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index d0f00356fc11..0a418503ec41 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/export.h>
25#include <sound/memalloc.h> 26#include <sound/memalloc.h>
26 27
27 28
@@ -136,3 +137,29 @@ void *snd_malloc_sgbuf_pages(struct device *device,
136 snd_free_sgbuf_pages(dmab); /* free the table */ 137 snd_free_sgbuf_pages(dmab); /* free the table */
137 return NULL; 138 return NULL;
138} 139}
140
141/*
142 * compute the max chunk size with continuous pages on sg-buffer
143 */
144unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
145 unsigned int ofs, unsigned int size)
146{
147 struct snd_sg_buf *sg = dmab->private_data;
148 unsigned int start, end, pg;
149
150 start = ofs >> PAGE_SHIFT;
151 end = (ofs + size - 1) >> PAGE_SHIFT;
152 /* check page continuity */
153 pg = sg->table[start].addr >> PAGE_SHIFT;
154 for (;;) {
155 start++;
156 if (start > end)
157 break;
158 pg++;
159 if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
160 return (start << PAGE_SHIFT) - ofs;
161 }
162 /* ok, all on continuous pages */
163 return size;
164}
165EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);