11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
3c1017a4cSJaroslav Kysela * Copyright (c) by Jaroslav Kysela <[email protected]>
41da177e4SLinus Torvalds * Takashi Iwai <[email protected]>
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
12a25684a9STakashi Iwai #include <linux/dma-direction.h>
1383fbcaedSTakashi Iwai #include <asm/page.h>
1483fbcaedSTakashi Iwai
151da177e4SLinus Torvalds struct device;
16a202bd1aSTakashi Iwai struct vm_area_struct;
17a25684a9STakashi Iwai struct sg_table;
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds /*
201da177e4SLinus Torvalds * buffer device info
211da177e4SLinus Torvalds */
221da177e4SLinus Torvalds struct snd_dma_device {
231da177e4SLinus Torvalds int type; /* SNDRV_DMA_TYPE_XXX */
24a25684a9STakashi Iwai enum dma_data_direction dir; /* DMA direction */
25a25684a9STakashi Iwai bool need_sync; /* explicit sync needed? */
261da177e4SLinus Torvalds struct device *dev; /* generic device */
271da177e4SLinus Torvalds };
281da177e4SLinus Torvalds
291da177e4SLinus Torvalds /*
301da177e4SLinus Torvalds * buffer types
311da177e4SLinus Torvalds */
321da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */
331da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */
341da177e4SLinus Torvalds #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */
3558a95dfaSTakashi Iwai #define SNDRV_DMA_TYPE_DEV_WC 5 /* continuous write-combined */
36a5606f85STakashi Iwai #ifdef CONFIG_GENERIC_ALLOCATOR
3705503214SNicolin Chen #define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */
38a5606f85STakashi Iwai #else
39a5606f85STakashi Iwai #define SNDRV_DMA_TYPE_DEV_IRAM SNDRV_DMA_TYPE_DEV
40a5606f85STakashi Iwai #endif
411fe7f397STakashi Iwai #define SNDRV_DMA_TYPE_VMALLOC 7 /* vmalloc'ed buffer */
42a25684a9STakashi Iwai #define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */
4373325f60STakashi Iwai #define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */
442c95b92eSTakashi Iwai #ifdef CONFIG_SND_DMA_SGBUF
45*e469e204STakashi Iwai #define SNDRV_DMA_TYPE_DEV_SG 3 /* S/G pages */
462c95b92eSTakashi Iwai #define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
472c95b92eSTakashi Iwai #else
482c95b92eSTakashi Iwai #define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
492c95b92eSTakashi Iwai #define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
502c95b92eSTakashi Iwai #endif
511da177e4SLinus Torvalds
521da177e4SLinus Torvalds /*
531da177e4SLinus Torvalds * info for buffer allocation
541da177e4SLinus Torvalds */
551da177e4SLinus Torvalds struct snd_dma_buffer {
561da177e4SLinus Torvalds struct snd_dma_device dev; /* device type */
571da177e4SLinus Torvalds unsigned char *area; /* virtual pointer */
581da177e4SLinus Torvalds dma_addr_t addr; /* physical address */
591da177e4SLinus Torvalds size_t bytes; /* buffer size in bytes */
601da177e4SLinus Torvalds void *private_data; /* private for allocator; don't touch */
611da177e4SLinus Torvalds };
621da177e4SLinus Torvalds
634cae99d9SPierre-Louis Bossart /*
644cae99d9SPierre-Louis Bossart * return the pages matching with the given byte size
654cae99d9SPierre-Louis Bossart */
snd_sgbuf_aligned_pages(size_t size)664cae99d9SPierre-Louis Bossart static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
674cae99d9SPierre-Louis Bossart {
684cae99d9SPierre-Louis Bossart return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
694cae99d9SPierre-Louis Bossart }
704cae99d9SPierre-Louis Bossart
711da177e4SLinus Torvalds /* allocate/release a buffer */
72a25684a9STakashi Iwai int snd_dma_alloc_dir_pages(int type, struct device *dev,
73a25684a9STakashi Iwai enum dma_data_direction dir, size_t size,
741da177e4SLinus Torvalds struct snd_dma_buffer *dmab);
75a25684a9STakashi Iwai
snd_dma_alloc_pages(int type,struct device * dev,size_t size,struct snd_dma_buffer * dmab)76a25684a9STakashi Iwai static inline int snd_dma_alloc_pages(int type, struct device *dev,
77a25684a9STakashi Iwai size_t size, struct snd_dma_buffer *dmab)
78a25684a9STakashi Iwai {
79a25684a9STakashi Iwai return snd_dma_alloc_dir_pages(type, dev, DMA_BIDIRECTIONAL, size, dmab);
80a25684a9STakashi Iwai }
81a25684a9STakashi Iwai
821da177e4SLinus Torvalds int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
831da177e4SLinus Torvalds struct snd_dma_buffer *dmab);
841da177e4SLinus Torvalds void snd_dma_free_pages(struct snd_dma_buffer *dmab);
85a202bd1aSTakashi Iwai int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab,
86a202bd1aSTakashi Iwai struct vm_area_struct *area);
871da177e4SLinus Torvalds
88a25684a9STakashi Iwai enum snd_dma_sync_mode { SNDRV_DMA_SYNC_CPU, SNDRV_DMA_SYNC_DEVICE };
89a25684a9STakashi Iwai #ifdef CONFIG_HAS_DMA
90a25684a9STakashi Iwai void snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
91a25684a9STakashi Iwai enum snd_dma_sync_mode mode);
92a25684a9STakashi Iwai #else
snd_dma_buffer_sync(struct snd_dma_buffer * dmab,enum snd_dma_sync_mode mode)93a25684a9STakashi Iwai static inline void snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
94a25684a9STakashi Iwai enum snd_dma_sync_mode mode) {}
95a25684a9STakashi Iwai #endif
96a25684a9STakashi Iwai
9737af81c5STakashi Iwai dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset);
9837af81c5STakashi Iwai struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
9937af81c5STakashi Iwai unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
10037af81c5STakashi Iwai unsigned int ofs, unsigned int size);
10137af81c5STakashi Iwai
102427ae268STakashi Iwai /* device-managed memory allocator */
103a25684a9STakashi Iwai struct snd_dma_buffer *snd_devm_alloc_dir_pages(struct device *dev, int type,
104a25684a9STakashi Iwai enum dma_data_direction dir,
105427ae268STakashi Iwai size_t size);
106427ae268STakashi Iwai
107a25684a9STakashi Iwai static inline struct snd_dma_buffer *
snd_devm_alloc_pages(struct device * dev,int type,size_t size)108a25684a9STakashi Iwai snd_devm_alloc_pages(struct device *dev, int type, size_t size)
109a25684a9STakashi Iwai {
110a25684a9STakashi Iwai return snd_devm_alloc_dir_pages(dev, type, DMA_BIDIRECTIONAL, size);
111a25684a9STakashi Iwai }
112a25684a9STakashi Iwai
113a25684a9STakashi Iwai static inline struct sg_table *
snd_dma_noncontig_sg_table(struct snd_dma_buffer * dmab)114a25684a9STakashi Iwai snd_dma_noncontig_sg_table(struct snd_dma_buffer *dmab)
115a25684a9STakashi Iwai {
116a25684a9STakashi Iwai return dmab->private_data;
117a25684a9STakashi Iwai }
118a25684a9STakashi Iwai
1191da177e4SLinus Torvalds #endif /* __SOUND_MEMALLOC_H */
1201da177e4SLinus Torvalds
121