Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d069dc0 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarIan Minett <ian_minett@creativelabs.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 3d98c21d
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -98,8 +98,10 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
/*
 * 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;
	addr &= PAGE_MASK;
	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
 */
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;
}

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 */

/* allocate/release a buffer */
+14 −25
Original line number Diff line number Diff line
@@ -983,53 +983,42 @@ static int snd_pcm_lib_alloc_vmalloc_32_buffer
	_snd_pcm_lib_alloc_vmalloc_buffer \
			(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
/*
 * SG-buffer handling
 */
#define snd_pcm_substream_sgbuf(substream) \
	((substream)->runtime->dma_buffer_p->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);
}
	snd_pcm_get_dma_buf(substream)->private_data

struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
				    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 */
/*
 * fake using a continuous buffer
 */
#define snd_pcm_sgbuf_ops_page	NULL
#endif /* SND_DMA_SGBUF */

static inline dma_addr_t
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 *
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

#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size)	(size)

#endif /* SND_DMA_SGBUF */
static inline unsigned int
snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
			     unsigned int ofs, unsigned int size)
{
	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 */
static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+0 −26
Original line number Diff line number Diff line
@@ -327,32 +327,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
}

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 */

/**
+27 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/export.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 */
	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);