162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
462306a36Sopenharmony_ci *                   Takashi Iwai <tiwai@suse.de>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Generic memory allocators
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __SOUND_MEMALLOC_H
1062306a36Sopenharmony_ci#define __SOUND_MEMALLOC_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/dma-direction.h>
1362306a36Sopenharmony_ci#include <asm/page.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct device;
1662306a36Sopenharmony_cistruct vm_area_struct;
1762306a36Sopenharmony_cistruct sg_table;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * buffer device info
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_cistruct snd_dma_device {
2362306a36Sopenharmony_ci	int type;			/* SNDRV_DMA_TYPE_XXX */
2462306a36Sopenharmony_ci	enum dma_data_direction dir;	/* DMA direction */
2562306a36Sopenharmony_ci	bool need_sync;			/* explicit sync needed? */
2662306a36Sopenharmony_ci	struct device *dev;		/* generic device */
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * buffer types
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_UNKNOWN		0	/* not defined */
3362306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_CONTINUOUS	1	/* continuous no-DMA memory */
3462306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV		2	/* generic device continuous */
3562306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_WC		5	/* continuous write-combined */
3662306a36Sopenharmony_ci#ifdef CONFIG_GENERIC_ALLOCATOR
3762306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_IRAM		4	/* generic device iram-buffer */
3862306a36Sopenharmony_ci#else
3962306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_IRAM	SNDRV_DMA_TYPE_DEV
4062306a36Sopenharmony_ci#endif
4162306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_VMALLOC		7	/* vmalloc'ed buffer */
4262306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_NONCONTIG	8	/* non-coherent SG buffer */
4362306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_NONCOHERENT	9	/* non-coherent buffer */
4462306a36Sopenharmony_ci#ifdef CONFIG_SND_DMA_SGBUF
4562306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_SG		SNDRV_DMA_TYPE_NONCONTIG
4662306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_WC_SG	6	/* SG write-combined */
4762306a36Sopenharmony_ci#else
4862306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_SG	SNDRV_DMA_TYPE_DEV /* no SG-buf support */
4962306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_WC_SG	SNDRV_DMA_TYPE_DEV_WC
5062306a36Sopenharmony_ci#endif
5162306a36Sopenharmony_ci/* fallback types, don't use those directly */
5262306a36Sopenharmony_ci#ifdef CONFIG_SND_DMA_SGBUF
5362306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK		10
5462306a36Sopenharmony_ci#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK	11
5562306a36Sopenharmony_ci#endif
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * info for buffer allocation
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_cistruct snd_dma_buffer {
6162306a36Sopenharmony_ci	struct snd_dma_device dev;	/* device type */
6262306a36Sopenharmony_ci	unsigned char *area;	/* virtual pointer */
6362306a36Sopenharmony_ci	dma_addr_t addr;	/* physical address */
6462306a36Sopenharmony_ci	size_t bytes;		/* buffer size in bytes */
6562306a36Sopenharmony_ci	void *private_data;	/* private for allocator; don't touch */
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * return the pages matching with the given byte size
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_cistatic inline unsigned int snd_sgbuf_aligned_pages(size_t size)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/* allocate/release a buffer */
7762306a36Sopenharmony_ciint snd_dma_alloc_dir_pages(int type, struct device *dev,
7862306a36Sopenharmony_ci			    enum dma_data_direction dir, size_t size,
7962306a36Sopenharmony_ci			    struct snd_dma_buffer *dmab);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic inline int snd_dma_alloc_pages(int type, struct device *dev,
8262306a36Sopenharmony_ci				      size_t size, struct snd_dma_buffer *dmab)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	return snd_dma_alloc_dir_pages(type, dev, DMA_BIDIRECTIONAL, size, dmab);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciint snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
8862306a36Sopenharmony_ci                                 struct snd_dma_buffer *dmab);
8962306a36Sopenharmony_civoid snd_dma_free_pages(struct snd_dma_buffer *dmab);
9062306a36Sopenharmony_ciint snd_dma_buffer_mmap(struct snd_dma_buffer *dmab,
9162306a36Sopenharmony_ci			struct vm_area_struct *area);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cienum snd_dma_sync_mode { SNDRV_DMA_SYNC_CPU, SNDRV_DMA_SYNC_DEVICE };
9462306a36Sopenharmony_ci#ifdef CONFIG_HAS_DMA
9562306a36Sopenharmony_civoid snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
9662306a36Sopenharmony_ci			 enum snd_dma_sync_mode mode);
9762306a36Sopenharmony_ci#else
9862306a36Sopenharmony_cistatic inline void snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
9962306a36Sopenharmony_ci				       enum snd_dma_sync_mode mode) {}
10062306a36Sopenharmony_ci#endif
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cidma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset);
10362306a36Sopenharmony_cistruct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
10462306a36Sopenharmony_ciunsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
10562306a36Sopenharmony_ci				      unsigned int ofs, unsigned int size);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/* device-managed memory allocator */
10862306a36Sopenharmony_cistruct snd_dma_buffer *snd_devm_alloc_dir_pages(struct device *dev, int type,
10962306a36Sopenharmony_ci						enum dma_data_direction dir,
11062306a36Sopenharmony_ci						size_t size);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic inline struct snd_dma_buffer *
11362306a36Sopenharmony_cisnd_devm_alloc_pages(struct device *dev, int type, size_t size)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	return snd_devm_alloc_dir_pages(dev, type, DMA_BIDIRECTIONAL, size);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic inline struct sg_table *
11962306a36Sopenharmony_cisnd_dma_noncontig_sg_table(struct snd_dma_buffer *dmab)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return dmab->private_data;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#endif /* __SOUND_MEMALLOC_H */
12562306a36Sopenharmony_ci
126