/* Copyright (c) 2022, Canaan Bright Sight Co., Ltd
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef _DRIVER_I2S_H
#define _DRIVER_I2S_H

#include <stdint.h>
#include <stddef.h>
#include "platform.h"
#include "io.h"
#include "dmac.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef enum _i2s_device_number
{
    I2S_DEVICE_0 = 0,
    I2S_DEVICE_MAX
} i2s_device_number_t;
typedef enum _i2s_channel_num
{
    I2S_CHANNEL_0 = 0,
    I2S_CHANNEL_1 = 1,
    I2S_CHANNEL_2 = 2,
    I2S_CHANNEL_3 = 3
} i2s_channel_num_t;

typedef enum _i2s_transmit
{
    I2S_TRANSMITTER = 0,
    I2S_RECEIVER = 1
} i2s_transmit_t;

typedef enum _i2s_work_mode
{
    STANDARD_MODE = 1,
    RIGHT_JUSTIFYING_MODE = 2,
    LEFT_JUSTIFYING_MODE = 4
} i2s_work_mode_t;

typedef enum _sclk_gating_cycles
{
    /* Clock gating is diable */
    NO_CLOCK_GATING = 0x0,
    /* Gating after 12 sclk cycles */
    CLOCK_CYCLES_12 = 0x1,
    /* Gating after 16 sclk cycles */
    CLOCK_CYCLES_16 = 0x2,
    /* Gating after 20 sclk cycles */
    CLOCK_CYCLES_20 = 0x3,
    /* Gating after 24 sclk cycles */
    CLOCK_CYCLES_24 = 0x4
} i2s_sclk_gating_cycles_t;

typedef enum _word_select_cycles
{
    /* 16 sclk cycles */
    SCLK_CYCLES_16 = 0x0,
    /* 24 sclk cycles */
    SCLK_CYCLES_24 = 0x1,
    /* 32 sclk cycles */
    SCLK_CYCLES_32 = 0x2
} i2s_word_select_cycles_t;

typedef enum _word_length
{
    /* Ignore the word length */
    IGNORE_WORD_LENGTH = 0x0,
    /* 12-bit data resolution of the receiver */
    RESOLUTION_12_BIT = 0x1,
    /* 16-bit data resolution of the receiver */
    RESOLUTION_16_BIT = 0x2,
    /* 20-bit data resolution of the receiver */
    RESOLUTION_20_BIT = 0x3,
    /* 24-bit data resolution of the receiver */
    RESOLUTION_24_BIT = 0x4,
    /* 32-bit data resolution of the receiver */
    RESOLUTION_32_BIT = 0x5
} i2s_word_length_t;

typedef enum _fifo_threshold
{
    /* Interrupt trigger when FIFO level is 1 */
    TRIGGER_LEVEL_1 = 0x0,
    /* Interrupt trigger when FIFO level is 2 */
    TRIGGER_LEVEL_2 = 0x1,
    /* Interrupt trigger when FIFO level is 3 */
    TRIGGER_LEVEL_3 = 0x2,
    /* Interrupt trigger when FIFO level is 4 */
    TRIGGER_LEVEL_4 = 0x3,
    /* Interrupt trigger when FIFO level is 5 */
    TRIGGER_LEVEL_5 = 0x4,
    /* Interrupt trigger when FIFO level is 6 */
    TRIGGER_LEVEL_6 = 0x5,
    /* Interrupt trigger when FIFO level is 7 */
    TRIGGER_LEVEL_7 = 0x6,
    /* Interrupt trigger when FIFO level is 8 */
    TRIGGER_LEVEL_8 = 0x7,
    /* Interrupt trigger when FIFO level is 9 */
    TRIGGER_LEVEL_9 = 0x8,
    /* Interrupt trigger when FIFO level is 10 */
    TRIGGER_LEVEL_10 = 0x9,
    /* Interrupt trigger when FIFO level is 11 */
    TRIGGER_LEVEL_11 = 0xa,
    /* Interrupt trigger when FIFO level is 12 */
    TRIGGER_LEVEL_12 = 0xb,
    /* Interrupt trigger when FIFO level is 13 */
    TRIGGER_LEVEL_13 = 0xc,
    /* Interrupt trigger when FIFO level is 14 */
    TRIGGER_LEVEL_14 = 0xd,
    /* Interrupt trigger when FIFO level is 15 */
    TRIGGER_LEVEL_15 = 0xe,
    /* Interrupt trigger when FIFO level is 16 */
    TRIGGER_LEVEL_16 = 0xf
} i2s_fifo_threshold_t;


typedef struct _i2s_ier
{
    /* Bit 0 is ien, 0 for disable i2s and 1 for enable i2s */
    uint32_t ien : 1;
    /* Bits [31:1] is reserved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_ier_t;

typedef union _ier_u
{
    i2s_ier_t ier;
    uint32_t reg_data;
} ier_t;

typedef struct _i2s_irer
{
    /* Bit 0 is receiver block  enable,
     * 0 for receiver disable
     * 1 for receiver enable
     */
    uint32_t rxen : 1;
    /* Bits [31:1] is reserved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_irer_t;

typedef union _irer_u
{
    i2s_irer_t irer;
    uint32_t reg_data;
} irer_t;

typedef struct _i2s_iter
{
    uint32_t txen : 1;
    /* Bit 0 is transmitter block  enable,
     * 0 for transmitter disable
     * 1 for transmitter enable
     */
    uint32_t resv : 31;
    /* Bits [31:1] is reserved */
} __attribute__((packed, aligned(4))) i2s_iter_t;

typedef union _iter_u
{
    i2s_iter_t iter;
    uint32_t reg_data;
} iter_t;

typedef struct _i2s_cer
{
    uint32_t clken : 1;
    /* Bit 0 is clock generation enable/disable,
     * 0 for clock generation disable,
     * 1 for clock generation enable
     */
    uint32_t resv : 31;
    /* Bits [31:1] is reserved */
} __attribute__((packed, aligned(4))) i2s_cer_t;

typedef union _cer_u
{
    i2s_cer_t cer;
    uint32_t reg_data;
} cer_t;

typedef struct _i2s_ccr
{
    /* Bits [2:0] is used to program  the gating of sclk,
     * 0x0 for clock gating is diable,
     * 0x1 for gating after 12 sclk cycles
     * 0x2 for gating after 16 sclk cycles
     * 0x3 for gating after 20 sclk cycles
     * 0x4 for gating after 24 sclk cycles
     */
    uint32_t clk_gate : 3;
    /* Bits [4:3] used program  the number of sclk cycles for which the
     * word select line stayd in the left aligned or right aligned mode.
     * 0x0 for 16sclk cycles, 0x1 for 24 sclk cycles 0x2 for 32 sclk
     * cycles
     */
    uint32_t clk_word_size : 2;
    /* Bit[5:7] is alignment mode setting.
     * 0x1 for standard i2s format
     * 0x2 for right aligned format
     * 0x4 for left aligned format
     */
    uint32_t align_mode : 3;
    /* Bit[8] is DMA transmit enable control */
    uint32_t dma_tx_en : 1;
    /* Bit[9] is DMA receive enable control */
    uint32_t dma_rx_en : 1;
    uint32_t dma_divide_16 : 1;
    /* Bit[10] split 32bit data to two 16 bit data and filled in left
     * and right channel. Used with dma_tx_en or dma_rx_en
     */
    uint32_t sign_expand_en : 1;
    uint32_t resv : 20;
    /* Bits [31:11] is reseved */
} __attribute__((packed, aligned(4))) i2s_ccr_t;

typedef union _ccr_u
{
    i2s_ccr_t ccr;
    uint32_t reg_data;
} ccr_t;

typedef struct _i2s_rxffr
{
    uint32_t rxffr : 1;
    /* Bit 0 is receiver FIFO reset,
     * 0 for does not flush RX FIFO, 1 for flush RX FIFO
     */
    uint32_t resv : 31;
    /* Bits [31:1] is reserved */
} __attribute__((packed, aligned(4))) i2s_rxffr_t;

typedef union _rxffr_u
{
    i2s_rxffr_t rxffr;
    uint32_t reg_data;
} rxffr_t;

typedef struct _i2s_lrbrthr
{
    uint32_t fifo : 16;
    /* Bits [15:0] if used data receive or transmit */
    uint32_t resv : 16;
} i2s_lrbrthr_t;

typedef union _lrbthr_u
{
    i2s_lrbrthr_t buffer;
    uint32_t reg_data;
} lrbthr_t;

typedef struct _i2s_rthr
{
    /* Bits  [15:0] is right stereo data transmitted serially
     * from transmit channel input
     */
    uint32_t rthrx : 16;
    /* Bits [31:16] is reserved */
    uint32_t resv : 16;
} __attribute__((packed, aligned(4))) i2s_rthr_t;

typedef union _rthr_u
{
    i2s_rthr_t rthr;
    uint32_t reg_data;
} rthr_t;

typedef struct _i2s_rer
{
    /* Bit 0 is receive channel enable/disable, 0 for receive channel disable,
     *1 for receive channel enable
     */
    uint32_t rxchenx : 1;
    /* Bits [31:1] is reseved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_rer_t;

typedef union _rer_u
{
    i2s_rer_t rer;
    uint32_t reg_data;
} rer_t;

typedef struct _i2s_ter
{
    /* Bit 0 is transmit channel enable/disable, 0 for transmit channel disable,
     * 1 for transmit channel enable
     */
    uint32_t txchenx : 1;
    /* Bits [31:1] is reseved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_ter_t;

typedef union _ter_u
{
    i2s_ter_t ter;
    uint32_t reg_data;
} ter_t;

typedef struct _i2s_rcr_tcr
{
    /* Bits [2:0] is used to program desired data resolution of
     * receiver/transmitter,
     * 0x0 for ignore the word length
     * 0x1 for 12-bit data resolution of the receiver/transmitter,
     * 0x2 for 16-bit data resolution of the receiver/transmitter,
     * 0x3 for 20-bit data resolution of the receiver/transmitter,
     * 0x4 for 24-bit data resolution of the receiver/transmitter,
     * 0x5 for 32-bit data resolution of the receiver/transmitter
     */
    uint32_t wlen : 3;
    /* Bits [31:3] is reseved */
    uint32_t resv : 29;
} __attribute__((packed, aligned(4))) i2s_rcr_tcr_t;

typedef union _rcr_tcr_u {
    i2s_rcr_tcr_t rcr_tcr;
    uint32_t reg_data;
} rcr_tcr_t;

typedef struct _i2s_isr
{
    /* Bit 0 is status of receiver data avaliable interrupt
     * 0x0 for RX FIFO trigger level not reached
     * 0x1 for RX FIFO trigger level is reached
     */
    uint32_t rxda : 1;
    /* Bit 1 is status of data overrun interrupt for rx channel
     * 0x0 for RX FIFO write valid
     * 0x1 for RX FIFO write overrun
     */
    uint32_t rxfo : 1;
    /* Bits [3:2] is reserved */
    uint32_t resv1 : 2;
    /* Bit 4 is status of transmit empty triger interrupt
     * 0x0 for TX FIFO triiger level is reach
     * 0x1 for TX FIFO trigger level is not reached
     */
    uint32_t txfe : 1;
    /* BIt 5 is status of data overrun interrupt for the TX channel
     * 0x0 for TX FIFO write valid
     * 0x1 for TX FIFO write overrun
     */
    uint32_t txfo : 1;
    /* BIts [31:6] is reserved */
    uint32_t resv2 : 26;
} __attribute__((packed, aligned(4))) i2s_isr_t;

typedef union _isr_u
{
    i2s_isr_t isr;
    uint32_t reg_data;
} isr_t;

typedef struct _i2s_imr
{
    /* Bit 0 is mask RX FIFO data available interrupt
     * 0x0 for unmask RX FIFO data available interrupt
     * 0x1 for mask  RX FIFO data available interrupt
     */
    uint32_t rxdam : 1;
    /* Bit 1 is mask RX FIFO overrun interrupt
     * 0x0 for unmask RX FIFO overrun interrupt
     * 0x1 for mask RX FIFO  overrun interrupt
     */
    uint32_t rxfom : 1;
    /* Bits [3:2] is reserved */
    uint32_t resv1 : 2;
    /* Bit 4 is mask TX FIFO empty interrupt,
     * 0x0 for unmask TX FIFO empty interrupt,
     * 0x1 for mask TX FIFO empty interrupt
     */
    uint32_t txfem : 1;
    /* BIt 5 is mask TX FIFO overrun interrupt
     * 0x0 for mask TX FIFO overrun interrupt
     * 0x1 for unmash TX FIFO overrun interrupt
     */
    uint32_t txfom : 1;
    /* Bits [31:6] is reserved */
    uint32_t resv2 : 26;
} __attribute__((packed, aligned(4))) i2s_imr_t;

typedef union _imr_u
{
    i2s_imr_t imr;
    uint32_t reg_data;
} imr_t;

typedef struct _i2s_ror
{
    /* Bit 0 is read this bit to clear RX FIFO data overrun interrupt
     * 0x0 for RX FIFO write valid,
     *0x1 for RX FIFO write overrun
     */
    uint32_t rxcho : 1;
    /* Bits [31:1] is reserved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_ror_t;

typedef union _ror_u
{
    i2s_ror_t ror;
    uint32_t reg_data;
} ror_t;

typedef struct _i2s_tor
{
    /* Bit 0 is read this bit to clear TX FIFO data overrun interrupt
     * 0x0 for TX FIFO write valid,
     *0x1 for TX FIFO write overrun
     */
    uint32_t txcho : 1;
    /* Bits [31:1] is reserved */
    uint32_t resv : 31;
} __attribute__((packed, aligned(4))) i2s_tor_t;

typedef union _tor_u
{
    i2s_tor_t tor;
    uint32_t reg_data;
} tor_t;

typedef struct _i2s_rfcr
{
    /* Bits [3:0] is used program the trigger level in the RX FIFO at
     * which the receiver data available interrupt generate,
     * 0x0 for interrupt trigger when FIFO level is 1,
     * 0x2 for interrupt trigger when FIFO level is 2,
     * 0x3 for interrupt trigger when FIFO level is 4,
     * 0x4 for interrupt trigger when FIFO level is 5,
     * 0x5 for interrupt trigger when FIFO level is 6,
     * 0x6 for interrupt trigger when FIFO level is 7,
     * 0x7 for interrupt trigger when FIFO level is 8,
     * 0x8 for interrupt trigger when FIFO level is 9,
     * 0x9 for interrupt trigger when FIFO level is 10,
     * 0xa for interrupt trigger when FIFO level is 11,
     * 0xb for interrupt trigger when FIFO level is 12,
     * 0xc for interrupt trigger when FIFO level is 13,
     * 0xd for interrupt trigger when FIFO level is 14,
     * 0xe for interrupt trigger when FIFO level is 15,
     * 0xf for interrupt trigger when FIFO level is 16
     */
    uint32_t rxchdt : 4;
    /* Bits [31:4] is reserved */
    uint32_t rsvd_rfcrx : 28;
} __attribute__((packed, aligned(4))) i2s_rfcr_t;

typedef union _rfcr_u
{
    i2s_rfcr_t rfcr;
    uint32_t reg_data;
} rfcr_t;

typedef struct _i2s_tfcr
{
    /* Bits [3:0] is used program the trigger level in the TX FIFO at
     * which the receiver data available interrupt generate,
     * 0x0 for interrupt trigger when FIFO level is 1,
     * 0x2 for interrupt trigger when FIFO level is 2,
     * 0x3 for interrupt trigger when FIFO level is 4,
     * 0x4 for interrupt trigger when FIFO level is 5,
     * 0x5 for interrupt trigger when FIFO level is 6,
     * 0x6 for interrupt trigger when FIFO level is 7,
     * 0x7 for interrupt trigger when FIFO level is 8,
     * 0x8 for interrupt trigger when FIFO level is 9,
     * 0x9 for interrupt trigger when FIFO level is 10,
     * 0xa for interrupt trigger when FIFO level is 11,
     * 0xb for interrupt trigger when FIFO level is 12,
     * 0xc for interrupt trigger when FIFO level is 13,
     * 0xd for interrupt trigger when FIFO level is 14,
     * 0xe for interrupt trigger when FIFO level is 15,
     * 0xf for interrupt trigger when FIFO level is 16
     */
    uint32_t txchet : 4;
    /* Bits [31:4] is reserved */
    uint32_t rsvd_tfcrx : 28;
} __attribute__((packed, aligned(4))) i2s_tfcr_t;

typedef union _tfcr_u
{
    i2s_tfcr_t tfcr;
    uint32_t reg_data;
} tfcr_t;

typedef struct _i2s_rff
{
    /* Bit  0 is receiver channel FIFO reset,
     * 0x0 for does not flush an individual RX FIFO,
     * 0x1 for flush an indiviadual RX FIFO
     */
    uint32_t rxchfr : 1;
    /*< Bits [31:1] is reserved ,write only */
    uint32_t rsvd_rffx : 31;
} __attribute__((packed, aligned(4))) i2s_rff_t;

typedef union _rff_u
{
    i2s_rff_t rff;
    uint32_t reg_data;
} rff_t;

typedef struct _i2s_tff
{
    /* Bit  0 is transmit channel FIFO reset,
     * 0x0 for does not flush an individual TX FIFO,
     * 0x1 for flush an indiviadual TX FIFO
     */
    uint32_t rtxchfr : 1;
    /*< Bits [31:1] is reserved ,write only */
    uint32_t rsvd_rffx : 31;
} __attribute__((packed, aligned(4))) i2s_tff_t;

typedef union tff_u
{
    i2s_tff_t tff;
    uint32_t reg_data;
} tff_t;

typedef struct _i2s_channel
{
    /* Left  Receive or Left Transmit Register      (0x20) */
    volatile uint32_t left_rxtx;
    /* Right Receive or Right Transmit Register     (0x24) */
    volatile uint32_t right_rxtx;
    /* Receive Enable Register                      (0x28) */
    volatile uint32_t rer;
    /* Transmit Enable Register                     (0x2c) */
    volatile uint32_t ter;
    /* Receive Configuration Register               (0x30) */
    volatile uint32_t rcr;
    /* Transmit Configuration Register              (0x34) */
    volatile uint32_t tcr;
    /* Interrupt Status Register                    (0x38) */
    volatile uint32_t isr;
    /* Interrupt Mask Register                      (0x3c) */
    volatile uint32_t imr;
    /* Receive Overrun Register                     (0x40) */
    volatile uint32_t ror;
    /* Transmit Overrun Register                    (0x44) */
    volatile uint32_t tor;
    /* Receive FIFO Configuration Register          (0x48) */
    volatile uint32_t rfcr;
    /* Transmit FIFO Configuration Register         (0x4c) */
    volatile uint32_t tfcr;
    /* Receive FIFO Flush Register                  (0x50) */
    volatile uint32_t rff;
    /* Transmit FIFO Flush Register                 (0x54) */
    volatile uint32_t tff;
    /* reserved                                (0x58-0x5c) */
    volatile uint32_t reserved1[2];
} __attribute__((packed, aligned(4))) i2s_channel_t;

/****is* i2s.api/dw_i2s_portmap
 * NAME
 *  i2s_t
 * DESCRIPTION
 *  This is the structure used for accessing the i2s register
 *  portmap.
 * EXAMPLE
 *  struct i2s_t *portmap;
 *  portmap = (struct dw_i2s_portmap *) DW_APB_I2S_BASE;
 * SOURCE
 */
typedef struct _i2s
{
    /* I2S Enable Register                          (0x00) */
    volatile uint32_t ier;
    /* I2S Receiver Block Enable Register           (0x04) */
    volatile uint32_t irer;
    /* I2S Transmitter Block Enable Register        (0x08) */
    volatile uint32_t iter;
    /* Clock Enable Register                        (0x0c) */
    volatile uint32_t cer;
    /* Clock Configuration Register                 (0x10) */
    volatile uint32_t ccr;
    /* Receiver Block FIFO Reset Register           (0x04) */
    volatile uint32_t rxffr;
    /* Transmitter Block FIFO Reset Register        (0x18) */
    volatile uint32_t txffr;
    /* reserved                                     (0x1c) */
    volatile uint32_t reserved1;
    volatile i2s_channel_t channel[4];
    /* reserved                               (0x118-0x1bc) */
    volatile uint32_t reserved2[40];
    /*  Receiver Block DMA Register                 (0x1c0) */
    volatile uint32_t rxdma;
    /* Reset Receiver Block DMA Register            (0x1c4) */
    volatile uint32_t rrxdma;
    /* Transmitter Block DMA Register               (0x1c8) */
    volatile uint32_t txdma;
    /* Reset Transmitter Block DMA Register         (0x1cc) */
    volatile uint32_t rtxdma;
    /* reserved                               (0x1d0-0x1ec) */
    volatile uint32_t reserved3[8];
    /* Component Parameter Register 2               (0x1f0) */
    volatile uint32_t i2s_comp_param_2;
    /* Component Parameter Register 1               (0x1f4) */
    volatile uint32_t i2s_comp_param_1;
    /* I2S Component Version Register               (0x1f8) */
    volatile uint32_t i2s_comp_version_1;
    /* I2S Component Type Register                  (0x1fc) */
    volatile uint32_t i2s_comp_type;
} __attribute__((packed, aligned(4))) i2s_t;

/**
 * @brief      I2S object instance
 */
extern volatile i2s_t *const i2s[1];
extern volatile i2s_t *const i2s_slave[1];

/**
* @brief       I2s init
*
* @param[in]   device_num          The device number
* @param[in]   rxtx_mode           I2s work mode
* @param[in]   channel_mask        Channel mask to which channel work
*
*/
void i2s_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask, bool enable_dma);

/**
 * @brief       I2S receive channel configure
 *
 * @param[in]   device_num              The device number
 * @param[in]   channel_num             The channel number
 * @param[in]   word_length             The word length
 * @param[in]   word_select_size        The word select size
 * @param[in]   trigger_level           The trigger level
 */
void i2s_rx_channel_config(i2s_device_number_t device_num,
    i2s_channel_num_t channel_num,
    i2s_word_length_t word_length,
    i2s_word_select_cycles_t word_select_size,
    i2s_fifo_threshold_t trigger_level,
    i2s_work_mode_t word_mode);

/**
 * @brief       I2S transmit channel  enable
 *
 * @param[in]   device_num              The device number
 * @param[in]   channel_num             The channel number
 * @param[in]   word_length             The word length
 * @param[in]   word_select_size        The word select size
 * @param[in]   trigger_level           The trigger level
 */
void i2s_tx_channel_config(i2s_device_number_t device_num,
    i2s_channel_num_t channel_num,
    i2s_word_length_t word_length,
    i2s_word_select_cycles_t word_select_size,
    i2s_fifo_threshold_t trigger_level,
    i2s_work_mode_t word_mode);

/**
 * @brief       Play PCM format audio
 *
 * @param[in]   device_num              The device number
 * @param[in]   channel_num             The channel number
 * @param[in]   buf                     PCM data
 * @param[in]   buf_len                 PCM data length
 * @param[in]   frame                   Transmit amount once
 * @param[in]   bits_per_sample         Sample bit length
 * @param[in]   track_num               Track amount
 */
void i2s_play(i2s_device_number_t device_num, dma_ch_t channel_num,
              const uint8_t *buf, size_t buf_len, size_t frame, size_t bits_per_sample, uint8_t track_num);

/**
 * @brief       Play PCM format audio
 *
 * @param[in]   device_num              The device number
 * @param[in]   sample_rate             The Sample rate
 *
 *
 * @return      The real sample rate
 */
uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate);

/**
 * @brief       Set dma_divide_16 split 32bit data to two 16 bit data and filled in left
*               and right channel. Used with dma_tx_en or dma_rx_en
 *
 * @param[in]   device_num              The device number
 * @param[in]   enable                  The value of dma_divide_16 0:disable 1:enable
 *
 * @return      result
 *     - 0      Success
 *     - Other  Fail
 */
int i2s_set_dma_divide_16(i2s_device_number_t device_num, uint32_t enable);

/**
 * @brief       Get dma_divide_16.
 *
 * @param[in]   device_num              The device number
 *
 * @return      result
 *     - <0     Fail
 *     - other  value of dma_divide_16
 */
int i2s_get_dma_divide_16(i2s_device_number_t device_num);


int i2s_slave_receive_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, uint64_t *buf, size_t buf_len);
int i2s_slave_send_data(i2s_device_number_t device_num, i2s_channel_num_t channel_num, const uint8_t *pcm, size_t buf_len,
                  size_t single_length);
void i2s_slave_rx_channel_config(i2s_device_number_t device_num,
    i2s_channel_num_t channel_num,
    i2s_word_length_t word_length,
    i2s_word_select_cycles_t word_select_size,
    i2s_fifo_threshold_t trigger_level,
    i2s_work_mode_t word_mode);
void i2s_slave_tx_channel_config(i2s_device_number_t device_num,
    i2s_channel_num_t channel_num,
    i2s_word_length_t word_length,
    i2s_word_select_cycles_t word_select_size,
    i2s_fifo_threshold_t trigger_level,
    i2s_work_mode_t word_mode);
void i2s_slave_init(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode, uint32_t channel_mask, bool enable_dma);

void i2s_disable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode);
void i2s_enable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode);

void i2s_slave_disable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode);
void i2s_slave_enable_block(i2s_device_number_t device_num, i2s_transmit_t rxtx_mode);


#ifdef __cplusplus
}
#endif

#endif
