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