/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
 * Copyright (c) 2021 MediaTek Inc.
 */

#ifndef _AUDIO_LOOPBACK_DMA_H
#define _AUDIO_LOOPBACK_DMA_H

//------------------------------------------------------------------------------
//  Include Files
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Enumerate And Structure
//------------------------------------------------------------------------------
enum audio_loopback_dma_mode {
	AUDIO_LOOPBACK_AEC_DMA = 1,
	AUDIO_LOOPBACK_DSP_I2S_DMA,
	AUDIO_LOOPBACK_DSP_DIRECT_DMA,
	AUDIO_LOOPBACK_SW_WRITE_DMA,
	AUDIO_LOOPBACK_SW_READ_DMA,
	AUDIO_LOOPBACK_MERGED_DMA,
	AIDOP_LOOPBACK_UNKNOWN_DMA,
};

enum audio_loopback_dma_attr {
	AUDIO_LOOPBACK_DMA_ATTR_SOURCE = 1,
	AUDIO_LOOPBACK_DMA_ATTR_AEC_SINE_GEN,
	AUDIO_LOOPBACK_DMA_ATTR_SW_WRITE_TIMESTAMP_UPDATE,
	AUDIO_LOOPBACK_DMA_ATTR_DBG_LEVEL,
	AUDIO_LOOPBACK_DMA_ATTR_UNKNOWN,
};

enum audio_loopback_dma_source {
	AUDIO_LOOPBACK_DMA_SOURCE_SPK_DELAY_SE = 0,
	AUDIO_LOOPBACK_DMA_SOURCE_ADC2 = 1,
	AUDIO_LOOPBACK_DMA_SOURCE_ADC1 = 2,
	AUDIO_LOOPBACK_DMA_SOURCE_I2S_RX = 3,
	AUDIO_LOOPBACK_DMA_SOURCE_DBG_SINE_TONE = 4,
	AUDIO_LOOPBACK_DMA_SOURCE_I2S_RX_4ch = 5, //SD_0_1
	AUDIO_LOOPBACK_DMA_SOURCE_I2S_RX_8ch = 6, //SD_0_1_2_3
	AUDIO_LOOPBACK_DMA_SOURCE_DEC_SRC_OUT_8ch = 9,
	AUDIO_LOOPBACK_DMA_SOURCE_ENC_FRONT_END_8ch = 10,
	AUDIO_LOOPBACK_DMA_SOURCE_UNKNOWN,
};

struct mem_info {
	unsigned int miu;
	unsigned long bus_addr;
	unsigned long buffer_size;
	unsigned long memory_bus_base;
	unsigned long dma_dram_write_base;
};

/* Define a STR (Suspend To Ram) data structure */
struct mtk_str_mode_struct {
	ptrdiff_t physical_addr;
	ptrdiff_t bus_addr;
	ptrdiff_t virtual_addr;
};

/* Define a Ring Buffer data structure */
struct mtk_ring_buffer_struct {
	unsigned char *addr;
	unsigned int size;
	unsigned int high_threshold;
	unsigned int buffer_level;
	unsigned int sw_w_offset;
	unsigned char *w_ptr;
	unsigned char *r_ptr;
	unsigned char *buf_end;
	unsigned long long total_read_size;
	unsigned long long total_write_size;
	unsigned long update_jiffies;
};

/* Define a Ring Buffer data structure */
struct mtk_copy_buffer_struct {
	unsigned char *addr;
	unsigned int size;
	unsigned int avail_size;
	unsigned int copy_size;
	unsigned int remain_size;
};

/* Define a Loopback DMA structure */
struct audio_loopback_dma_struct {
	struct mtk_ring_buffer_struct r_buf;
	struct mtk_copy_buffer_struct c_buf;
	struct mtk_str_mode_struct str_mode_info;
	struct mem_info dma_mem_info;
	void (*interrupt_callback)(void *priv);
	void *interrupt_priv;
	unsigned int initialized_status;
	unsigned int channel_mode;
	unsigned int sample_rate;
	unsigned int sample_bits;
	unsigned int mode;
	unsigned int status;
};
//------------------------------------------------------------------------------
// Global Function
//------------------------------------------------------------------------------
int audio_loopback_dma_probe(void);
int audio_loopback_dma_destroy(void);
int audio_loopback_dma_get_attr(int attr);
int audio_loopback_dma_set_attr(int attr, int params);
int audio_loopback_dma_set(struct audio_loopback_dma_struct *dma_buf, unsigned int mode,
			unsigned int channel, unsigned int sample_rate, unsigned int bitwidth,
			struct mem_info mem_info, unsigned int dma_offset, unsigned int dma_size,
			unsigned char *copy_buffer, unsigned int copy_buffer_size);
int audio_loopback_dma_set_inturrupt_callback(struct audio_loopback_dma_struct *dma_buf,
			void *callback, void *priv);
int audio_loopback_dma_init(struct audio_loopback_dma_struct *dma_buf);
int audio_loopback_dma_start(struct audio_loopback_dma_struct *dma_buf);
int audio_loopback_dma_stop(struct audio_loopback_dma_struct *dma_buf);
int audio_loopback_dma_get_offset(struct audio_loopback_dma_struct *dma_buf);
unsigned int audio_loopback_dma_get_avail_size(struct audio_loopback_dma_struct *dma_buf);
unsigned int audio_loopback_dma_write(struct audio_loopback_dma_struct *dma_buf,
			void *buffer, unsigned int bytes);
unsigned int audio_loopback_dma_read(struct audio_loopback_dma_struct *dma_buf,
			void *buffer, unsigned int bytes);
int audio_loopback_dma_exit(struct audio_loopback_dma_struct *dma_buf);

#endif /* _AUDIO_LOOPBACK_DMA_H */
