xref: /openbmc/linux/include/sound/memalloc.h (revision 1fe7f397)
11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
3c1017a4cSJaroslav Kysela  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
41da177e4SLinus Torvalds  *                   Takashi Iwai <tiwai@suse.de>
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *  Generic memory allocators
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #ifndef __SOUND_MEMALLOC_H
101da177e4SLinus Torvalds #define __SOUND_MEMALLOC_H
111da177e4SLinus Torvalds 
12345a9ca3STakashi Iwai #include <asm/page.h>
13345a9ca3STakashi Iwai 
141da177e4SLinus Torvalds struct device;
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /*
171da177e4SLinus Torvalds  * buffer device info
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds struct snd_dma_device {
201da177e4SLinus Torvalds 	int type;			/* SNDRV_DMA_TYPE_XXX */
211da177e4SLinus Torvalds 	struct device *dev;		/* generic device */
221da177e4SLinus Torvalds };
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #define snd_dma_pci_data(pci)	(&(pci)->dev)
25019d80dbSAntonio Ospite #define snd_dma_continuous_data(x)	((struct device *)(__force unsigned long)(x))
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds  * buffer types
301da177e4SLinus Torvalds  */
311da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_UNKNOWN		0	/* not defined */
321da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_CONTINUOUS	1	/* continuous no-DMA memory */
331da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_DEV		2	/* generic device continuous */
3442e748a0STakashi Iwai #define SNDRV_DMA_TYPE_DEV_UC		5	/* continuous non-cahced */
35cc6a8acdSTakashi Iwai #ifdef CONFIG_SND_DMA_SGBUF
361da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_DEV_SG		3	/* generic device SG-buffer */
3742e748a0STakashi Iwai #define SNDRV_DMA_TYPE_DEV_UC_SG	6	/* SG non-cached */
38cc6a8acdSTakashi Iwai #else
39cc6a8acdSTakashi Iwai #define SNDRV_DMA_TYPE_DEV_SG	SNDRV_DMA_TYPE_DEV /* no SG-buf support */
4042e748a0STakashi Iwai #define SNDRV_DMA_TYPE_DEV_UC_SG	SNDRV_DMA_TYPE_DEV_UC
41cc6a8acdSTakashi Iwai #endif
42a5606f85STakashi Iwai #ifdef CONFIG_GENERIC_ALLOCATOR
4305503214SNicolin Chen #define SNDRV_DMA_TYPE_DEV_IRAM		4	/* generic device iram-buffer */
44a5606f85STakashi Iwai #else
45a5606f85STakashi Iwai #define SNDRV_DMA_TYPE_DEV_IRAM	SNDRV_DMA_TYPE_DEV
46a5606f85STakashi Iwai #endif
471fe7f397STakashi Iwai #define SNDRV_DMA_TYPE_VMALLOC		7	/* vmalloc'ed buffer */
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds /*
501da177e4SLinus Torvalds  * info for buffer allocation
511da177e4SLinus Torvalds  */
521da177e4SLinus Torvalds struct snd_dma_buffer {
531da177e4SLinus Torvalds 	struct snd_dma_device dev;	/* device type */
541da177e4SLinus Torvalds 	unsigned char *area;	/* virtual pointer */
551da177e4SLinus Torvalds 	dma_addr_t addr;	/* physical address */
561da177e4SLinus Torvalds 	size_t bytes;		/* buffer size in bytes */
571da177e4SLinus Torvalds 	void *private_data;	/* private for allocator; don't touch */
581da177e4SLinus Torvalds };
591da177e4SLinus Torvalds 
604cae99d9SPierre-Louis Bossart /*
614cae99d9SPierre-Louis Bossart  * return the pages matching with the given byte size
624cae99d9SPierre-Louis Bossart  */
634cae99d9SPierre-Louis Bossart static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
644cae99d9SPierre-Louis Bossart {
654cae99d9SPierre-Louis Bossart 	return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
664cae99d9SPierre-Louis Bossart }
674cae99d9SPierre-Louis Bossart 
68cc6a8acdSTakashi Iwai #ifdef CONFIG_SND_DMA_SGBUF
691da177e4SLinus Torvalds /*
701da177e4SLinus Torvalds  * Scatter-Gather generic device pages
711da177e4SLinus Torvalds  */
7277a23f26STakashi Iwai void *snd_malloc_sgbuf_pages(struct device *device,
7377a23f26STakashi Iwai 			     size_t size, struct snd_dma_buffer *dmab,
7477a23f26STakashi Iwai 			     size_t *res_size);
7577a23f26STakashi Iwai int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
7677a23f26STakashi Iwai 
771da177e4SLinus Torvalds struct snd_sg_page {
781da177e4SLinus Torvalds 	void *buf;
791da177e4SLinus Torvalds 	dma_addr_t addr;
801da177e4SLinus Torvalds };
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds struct snd_sg_buf {
831da177e4SLinus Torvalds 	int size;	/* allocated byte size */
841da177e4SLinus Torvalds 	int pages;	/* allocated pages */
851da177e4SLinus Torvalds 	int tblsize;	/* allocated table size */
861da177e4SLinus Torvalds 	struct snd_sg_page *table;	/* address table */
871da177e4SLinus Torvalds 	struct page **page_table;	/* page table (for vmap/vunmap) */
881da177e4SLinus Torvalds 	struct device *dev;
891da177e4SLinus Torvalds };
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds /*
921da177e4SLinus Torvalds  * return the physical address at the corresponding offset
931da177e4SLinus Torvalds  */
949d069dc0STakashi Iwai static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
959d069dc0STakashi Iwai 					   size_t offset)
961da177e4SLinus Torvalds {
979d069dc0STakashi Iwai 	struct snd_sg_buf *sgbuf = dmab->private_data;
9851e9f2e6STakashi Iwai 	dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
99932e9decSStefano Panella 	addr &= ~((dma_addr_t)PAGE_SIZE - 1);
10051e9f2e6STakashi Iwai 	return addr + offset % PAGE_SIZE;
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
10377a23f26STakashi Iwai /*
10477a23f26STakashi Iwai  * return the virtual address at the corresponding offset
10577a23f26STakashi Iwai  */
1069d069dc0STakashi Iwai static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
1079d069dc0STakashi Iwai 				     size_t offset)
10877a23f26STakashi Iwai {
1099d069dc0STakashi Iwai 	struct snd_sg_buf *sgbuf = dmab->private_data;
11077a23f26STakashi Iwai 	return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
11177a23f26STakashi Iwai }
1129d069dc0STakashi Iwai 
1139d069dc0STakashi Iwai unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
1149d069dc0STakashi Iwai 				      unsigned int ofs, unsigned int size);
1159d069dc0STakashi Iwai #else
1169d069dc0STakashi Iwai /* non-SG versions */
1179d069dc0STakashi Iwai static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
1189d069dc0STakashi Iwai 					    size_t offset)
1199d069dc0STakashi Iwai {
1209d069dc0STakashi Iwai 	return dmab->addr + offset;
1219d069dc0STakashi Iwai }
1229d069dc0STakashi Iwai 
1239d069dc0STakashi Iwai static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
1249d069dc0STakashi Iwai 				      size_t offset)
1259d069dc0STakashi Iwai {
1269d069dc0STakashi Iwai 	return dmab->area + offset;
1279d069dc0STakashi Iwai }
1289d069dc0STakashi Iwai 
1299d069dc0STakashi Iwai #define snd_sgbuf_get_chunk_size(dmab, ofs, size)	(size)
1309d069dc0STakashi Iwai 
131cc6a8acdSTakashi Iwai #endif /* CONFIG_SND_DMA_SGBUF */
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds /* allocate/release a buffer */
1341da177e4SLinus Torvalds int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
1351da177e4SLinus Torvalds 			struct snd_dma_buffer *dmab);
1361da177e4SLinus Torvalds int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
1371da177e4SLinus Torvalds                                  struct snd_dma_buffer *dmab);
1381da177e4SLinus Torvalds void snd_dma_free_pages(struct snd_dma_buffer *dmab);
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds #endif /* __SOUND_MEMALLOC_H */
1411da177e4SLinus Torvalds 
142