xref: /OK3568_Linux_fs/kernel/include/sound/memalloc.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4*4882a593Smuzhiyun  *                   Takashi Iwai <tiwai@suse.de>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *  Generic memory allocators
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #ifndef __SOUND_MEMALLOC_H
10*4882a593Smuzhiyun #define __SOUND_MEMALLOC_H
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <asm/page.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun struct device;
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun /*
17*4882a593Smuzhiyun  * buffer device info
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun struct snd_dma_device {
20*4882a593Smuzhiyun 	int type;			/* SNDRV_DMA_TYPE_XXX */
21*4882a593Smuzhiyun 	struct device *dev;		/* generic device */
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define snd_dma_continuous_data(x)	((struct device *)(__force unsigned long)(x))
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun  * buffer types
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_UNKNOWN		0	/* not defined */
31*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_CONTINUOUS	1	/* continuous no-DMA memory */
32*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV		2	/* generic device continuous */
33*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_UC		5	/* continuous non-cahced */
34*4882a593Smuzhiyun #ifdef CONFIG_SND_DMA_SGBUF
35*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_SG		3	/* generic device SG-buffer */
36*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_UC_SG	6	/* SG non-cached */
37*4882a593Smuzhiyun #else
38*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_SG	SNDRV_DMA_TYPE_DEV /* no SG-buf support */
39*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_UC_SG	SNDRV_DMA_TYPE_DEV_UC
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun #ifdef CONFIG_GENERIC_ALLOCATOR
42*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_IRAM		4	/* generic device iram-buffer */
43*4882a593Smuzhiyun #else
44*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_DEV_IRAM	SNDRV_DMA_TYPE_DEV
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun #define SNDRV_DMA_TYPE_VMALLOC		7	/* vmalloc'ed buffer */
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun  * info for buffer allocation
50*4882a593Smuzhiyun  */
51*4882a593Smuzhiyun struct snd_dma_buffer {
52*4882a593Smuzhiyun 	struct snd_dma_device dev;	/* device type */
53*4882a593Smuzhiyun 	unsigned char *area;	/* virtual pointer */
54*4882a593Smuzhiyun 	dma_addr_t addr;	/* physical address */
55*4882a593Smuzhiyun 	size_t bytes;		/* buffer size in bytes */
56*4882a593Smuzhiyun 	void *private_data;	/* private for allocator; don't touch */
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun  * return the pages matching with the given byte size
61*4882a593Smuzhiyun  */
snd_sgbuf_aligned_pages(size_t size)62*4882a593Smuzhiyun static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #ifdef CONFIG_SND_DMA_SGBUF
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun  * Scatter-Gather generic device pages
70*4882a593Smuzhiyun  */
71*4882a593Smuzhiyun void *snd_malloc_sgbuf_pages(struct device *device,
72*4882a593Smuzhiyun 			     size_t size, struct snd_dma_buffer *dmab,
73*4882a593Smuzhiyun 			     size_t *res_size);
74*4882a593Smuzhiyun int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun struct snd_sg_page {
77*4882a593Smuzhiyun 	void *buf;
78*4882a593Smuzhiyun 	dma_addr_t addr;
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun struct snd_sg_buf {
82*4882a593Smuzhiyun 	int size;	/* allocated byte size */
83*4882a593Smuzhiyun 	int pages;	/* allocated pages */
84*4882a593Smuzhiyun 	int tblsize;	/* allocated table size */
85*4882a593Smuzhiyun 	struct snd_sg_page *table;	/* address table */
86*4882a593Smuzhiyun 	struct page **page_table;	/* page table (for vmap/vunmap) */
87*4882a593Smuzhiyun 	struct device *dev;
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * return the physical address at the corresponding offset
92*4882a593Smuzhiyun  */
snd_sgbuf_get_addr(struct snd_dma_buffer * dmab,size_t offset)93*4882a593Smuzhiyun static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
94*4882a593Smuzhiyun 					   size_t offset)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct snd_sg_buf *sgbuf = dmab->private_data;
97*4882a593Smuzhiyun 	dma_addr_t addr;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	if (!sgbuf)
100*4882a593Smuzhiyun 		return dmab->addr + offset;
101*4882a593Smuzhiyun 	addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
102*4882a593Smuzhiyun 	addr &= ~((dma_addr_t)PAGE_SIZE - 1);
103*4882a593Smuzhiyun 	return addr + offset % PAGE_SIZE;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun  * return the virtual address at the corresponding offset
108*4882a593Smuzhiyun  */
snd_sgbuf_get_ptr(struct snd_dma_buffer * dmab,size_t offset)109*4882a593Smuzhiyun static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
110*4882a593Smuzhiyun 				     size_t offset)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	struct snd_sg_buf *sgbuf = dmab->private_data;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (!sgbuf)
115*4882a593Smuzhiyun 		return dmab->area + offset;
116*4882a593Smuzhiyun 	return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
120*4882a593Smuzhiyun 				      unsigned int ofs, unsigned int size);
121*4882a593Smuzhiyun #else
122*4882a593Smuzhiyun /* non-SG versions */
snd_sgbuf_get_addr(struct snd_dma_buffer * dmab,size_t offset)123*4882a593Smuzhiyun static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
124*4882a593Smuzhiyun 					    size_t offset)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	return dmab->addr + offset;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
snd_sgbuf_get_ptr(struct snd_dma_buffer * dmab,size_t offset)129*4882a593Smuzhiyun static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
130*4882a593Smuzhiyun 				      size_t offset)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	return dmab->area + offset;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #define snd_sgbuf_get_chunk_size(dmab, ofs, size)	(size)
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun #endif /* CONFIG_SND_DMA_SGBUF */
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun /* allocate/release a buffer */
140*4882a593Smuzhiyun int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
141*4882a593Smuzhiyun 			struct snd_dma_buffer *dmab);
142*4882a593Smuzhiyun int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
143*4882a593Smuzhiyun                                  struct snd_dma_buffer *dmab);
144*4882a593Smuzhiyun void snd_dma_free_pages(struct snd_dma_buffer *dmab);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun #endif /* __SOUND_MEMALLOC_H */
147*4882a593Smuzhiyun 
148