Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+66 -53
+25 -2
include/sound/memalloc.h
··· 98 98 /* 99 99 * return the physical address at the corresponding offset 100 100 */ 101 - static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset) 101 + static 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 105 dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; 104 106 addr &= PAGE_MASK; 105 107 return addr + offset % PAGE_SIZE; ··· 110 108 /* 111 109 * return the virtual address at the corresponding offset 112 110 */ 113 - static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset) 111 + static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, 112 + size_t offset) 114 113 { 114 + struct snd_sg_buf *sgbuf = dmab->private_data; 115 115 return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; 116 116 } 117 + 118 + unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, 119 + unsigned int ofs, unsigned int size); 120 + #else 121 + /* non-SG versions */ 122 + static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, 123 + size_t offset) 124 + { 125 + return dmab->addr + offset; 126 + } 127 + 128 + static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, 129 + size_t offset) 130 + { 131 + return dmab->area + offset; 132 + } 133 + 134 + #define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size) 135 + 117 136 #endif /* CONFIG_SND_DMA_SGBUF */ 118 137 119 138 /* allocate/release a buffer */
+14 -25
include/sound/pcm.h
··· 983 983 _snd_pcm_lib_alloc_vmalloc_buffer \ 984 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 988 #ifdef CONFIG_SND_DMA_SGBUF 987 989 /* 988 990 * SG-buffer handling 989 991 */ 990 992 #define snd_pcm_substream_sgbuf(substream) \ 991 - ((substream)->runtime->dma_buffer_p->private_data) 992 - 993 - static inline dma_addr_t 994 - snd_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 - 1000 - static inline void * 1001 - snd_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 - } 993 + snd_pcm_get_dma_buf(substream)->private_data 1006 994 1007 995 struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, 1008 996 unsigned long offset); 1009 - unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, 1010 - unsigned int ofs, unsigned int size); 1011 - 1012 997 #else /* !SND_DMA_SGBUF */ 1013 998 /* 1014 999 * fake using a continuous buffer 1015 1000 */ 1001 + #define snd_pcm_sgbuf_ops_page NULL 1002 + #endif /* SND_DMA_SGBUF */ 1003 + 1016 1004 static inline dma_addr_t 1017 1005 snd_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 1022 1010 static inline void * 1023 1011 snd_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 1029 - 1030 - #define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) 1031 - 1032 - #endif /* SND_DMA_SGBUF */ 1016 + static inline unsigned int 1017 + snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, 1018 + unsigned int ofs, unsigned int size) 1019 + { 1020 + return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size); 1021 + } 1033 1022 1034 1023 /* handle mmap counter - PCM mmap callback should handle this counter properly */ 1035 1024 static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
-26
sound/core/pcm_memory.c
··· 327 327 } 328 328 329 329 EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); 330 - 331 - /* 332 - * compute the max chunk size with continuous pages on sg-buffer 333 - */ 334 - unsigned 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 - } 355 - EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); 356 330 #endif /* CONFIG_SND_DMA_SGBUF */ 357 331 358 332 /**
+27
sound/core/sgbuf.c
··· 22 22 #include <linux/slab.h> 23 23 #include <linux/mm.h> 24 24 #include <linux/vmalloc.h> 25 + #include <linux/export.h> 25 26 #include <sound/memalloc.h> 26 27 27 28 ··· 137 136 snd_free_sgbuf_pages(dmab); /* free the table */ 138 137 return NULL; 139 138 } 139 + 140 + /* 141 + * compute the max chunk size with continuous pages on sg-buffer 142 + */ 143 + unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, 144 + unsigned int ofs, unsigned int size) 145 + { 146 + struct snd_sg_buf *sg = dmab->private_data; 147 + unsigned int start, end, pg; 148 + 149 + start = ofs >> PAGE_SHIFT; 150 + end = (ofs + size - 1) >> PAGE_SHIFT; 151 + /* check page continuity */ 152 + pg = sg->table[start].addr >> PAGE_SHIFT; 153 + for (;;) { 154 + start++; 155 + if (start > end) 156 + break; 157 + pg++; 158 + if ((sg->table[start].addr >> PAGE_SHIFT) != pg) 159 + return (start << PAGE_SHIFT) - ofs; 160 + } 161 + /* ok, all on continuous pages */ 162 + return size; 163 + } 164 + EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);