/** * @file sdrv_i2s.h * @brief SemiDrive I2S driver header file. * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #ifndef SDRV_I2S_DRIVER_H_ #define SDRV_I2S_DRIVER_H_ #include #include #include #include #include "sdrv_ckgen.h" #include "sdrv_common.h" #include "sdrv_dma.h" #define SDRV_I2S_DAIFMT_FORMAT_MASK 0x0f /* i2s standard phillips interface mode */ #define SDRV_I2S_DAIFMT_STANDARD_PHILLIPS 1 /* i2s left justified interface mode */ #define SDRV_I2S_DAIFMT_LEFT_JUSTIFIED 2 /* i2s right justified interface mode */ #define SDRV_I2S_DAIFMT_RIGHT_JUSTIFIED 3 /* i2s dsp mode-A */ #define SDRV_I2S_DAIFMT_DSP_A 4 /* i2s dsp mode-B */ #define SDRV_I2S_DAIFMT_DSP_B 5 /* transfer control mode master or slave */ #define SDRV_I2S_DAIFMT_MASTER_MASK (0x0f0) #define SDRV_I2S_DAIFMT_CODEC_SLAVE (1 << 4) #define SDRV_I2S_DAIFMT_CODEC_MASTER (2 << 4) #define SDRV_I2S_DAIFMT_INV_MASK 0x0f00 #define SDRV_I2S_DAIFMT_INV_OFFSET 8 /* normal bit clock + frame */ #define SDRV_I2S_DAIFMT_NB_NF (0 << SDRV_I2S_DAIFMT_INV_OFFSET) /* normal BCLK + inv FRM */ #define SDRV_I2S_DAIFMT_NB_IF (SDRV_I2S_DAIFMT_INV_OFFSET) /* invert BCLK + nor FRM */ #define SDRV_I2S_DAIFMT_IB_NF (3 << SDRV_I2S_DAIFMT_INV_OFFSET) /* invert BCLK + FRM */ #define SDRV_I2S_DAIFMT_IB_IF (4 << SDRV_I2S_DAIFMT_INV_OFFSET) #define SDRV_I2S_XFER_NUM_BUFFERS (4U) #define SDRV_I2S_CHNNELS_COUNT 2 #define SDRV_I2S_CHNNELS_BYTES (SDRV_I2S_SAMPLE_WIDTH_16BITS / 8) #define SDRV_I2S_DMA_PERIOD_FRAME_SIZE 1024 * 4 #define SDRV_I2S_DMA_PERIOD_BYTES \ SDRV_I2S_DMA_PERIOD_FRAME_SIZE *SDRV_I2S_CHNNELS_COUNT \ *SDRV_I2S_CHNNELS_BYTES #define SDRV_I2S_DMA_PERIOD_COUNT 2 #define SDRV_I2S_DMA_BUF_TOTAL_SIZE \ SDRV_I2S_DMA_PERIOD_SIZE *SDRV_I2S_DMA_PERIOD_COUNT #define SDRV_I2S_SEL_CHNULL 0x00 #define SDRV_I2S_SEL_DATALINE0 (0x01 << 0) #define SDRV_I2S_SEL_DATALINE1 (0x01 << 1) #define SDRV_I2S_SEL_DATALINE2 (0x01 << 2) #define SDRV_I2S_SEL_DATALINE3 (0x01 << 3) #define SDRV_I2S_SEL_DATALINE4 (0x01 << 4) #define SDRV_I2S_SEL_DATALINE5 (0x01 << 5) #define SDRV_I2S_SEL_DATALINE6 (0x01 << 6) #define SDRV_I2S_SEL_DATALINE7 (0x01 << 7) /** * @brief i2s channel num * */ typedef enum i2s_channel { SDRV_I2S_CHANNEL_NUM_MONO = 1, SDRV_I2S_CHANNEL_NUM_STEREO = 2, SDRV_I2S_CHANNEL_NUM_3CHANS = 3, SDRV_I2S_CHANNEL_NUM_4CHANS = 4, SDRV_I2S_CHANNEL_NUM_5CHANS = 5, SDRV_I2S_CHANNEL_NUM_6CHANS = 6, SDRV_I2S_CHANNEL_NUM_7CHANS = 7, SDRV_I2S_CHANNEL_NUM_8CHANS = 8, SDRV_I2S_CHANNEL_NUM_9CHANS = 9, SDRV_I2S_CHANNEL_NUM_10CHANS = 10, SDRV_I2S_CHANNEL_NUM_11CHANS = 11, SDRV_I2S_CHANNEL_NUM_12CHANS = 12, SDRV_I2S_CHANNEL_NUM_13CHANS = 13, SDRV_I2S_CHANNEL_NUM_14CHANS = 14, SDRV_I2S_CHANNEL_NUM_15CHANS = 15, SDRV_I2S_CHANNEL_NUM_16CHANS = 16, } sdrv_i2s_channel_t; /** * @brief i2s sample rate * */ typedef enum sdrv_i2s_sample_rate { SDRV_I2S_SR_NO_INIT = 0, SDRV_I2S_SR_5512 = 5512, SDRV_I2S_SR_8000 = 8000, SDRV_I2S_SR_11025 = 11025, SDRV_I2S_SR_16000 = 16000, SDRV_I2S_SR_22050 = 22050, SDRV_I2S_SR_32000 = 32000, SDRV_I2S_SR_44100 = 44100, SDRV_I2S_SR_48000 = 48000, SDRV_I2S_SR_64000 = 64000, SDRV_I2S_SR_88200 = 88200, SDRV_I2S_SR_96000 = 96000, SDRV_I2S_SR_176400 = 176400, SDRV_I2S_SR_192000 = 192000, } sdrv_i2s_sample_rate_t; /** * @brief sample width * */ typedef enum sdrv_i2s_sample_width { SDRV_I2S_SAMPLE_WIDTH_8BITS = 8, SDRV_I2S_SAMPLE_WIDTH_16BITS = 16, SDRV_I2S_SAMPLE_WIDTH_24BITS = 24, SDRV_I2S_SAMPLE_WIDTH_32BITS = 32, } sdrv_i2s_sample_width_t; /** * @brief slot width * */ typedef enum sdrv_i2s_slot_width { SDRV_I2S_SLOT_WIDTH_8BITS = 8, SDRV_I2S_SLOT_WIDTH_16BITS = 16, SDRV_I2S_SLOT_WIDTH_24BITS = 24, SDRV_I2S_SLOT_WIDTH_32BITS = 32, } sdrv_i2s_slot_width_t; /** * @brief playback capture type * */ typedef enum { SDRV_I2S_STREAM_PLAYBACK = 0, SDRV_I2S_STREAM_CAPTURE, SDRV_I2S_STREAM_MAX, } sdrv_i2s_stream_type_t; /** * @brief sdrv i2s sync mode ,select sck and ws source * */ typedef enum sdrv_i2s_clk_sync_type { /**< tx clk synchronization, rx will shares tx clk */ SDRV_I2S_CLK_TX_SYNC = 0, /**< rx clk synchronization, tx will shares rx clk */ SDRV_I2S_CLK_RX_SYNC, /**< async mode,tx and rx work on their respective clocks*/ SDRV_I2S_CLK_TX_RX_ASYNC, } sdrv_i2s_clk_sync_type_t; /** * @brief i2s dma buff descriptions,which is used to transfer data in dma mod * * */ typedef struct sdrv_i2s_dma_buf { uint8_t *addr; /**< dma mode ,buffer address */ uint32_t buffer_bytes; /**< buffer size */ uint32_t period_bytes; /**< one period size */ uint32_t periods; /**< period count */ uint32_t appl_ptr; /**< app write pointer during playback, dma read pointer during capture */ uint32_t hw_ptr; /**< dma read pointer during playback, dma write pointer during capture */ uint32_t boundary; /**< dma buff boundary */ } sdrv_i2s_dma_buf_t; typedef enum sdrv_i2s_status { /**< status for Success. */ SDRV_I2S_STATUS_SUCCESS = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_COMMON, 0), /**< status for Fail. */ SDRV_I2S_STATUS_FAIL = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_I2S, 1), /**< status for invalid argument check*/ SDRV_I2S_STATUS_INVALID_PARAMS = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_I2S, 2), /**< status for overrun */ SDRV_I2S_STATUS_OVERRUN = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_I2S, 3), /**< status for underrun */ SDRV_I2S_STATUS_UNDERRUN = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_I2S, 4), } sdrv_i2s_status_t; /** * @brief sdrv i2s transfer descriptions * */ typedef struct sdrv_i2s_transfer { uint8_t *data; /**< audio data addr */ uint32_t length; /**< audio data length */ uint8_t id; /**< transfer tag */ } sdrv_i2s_transfer_t; /* @brief sdrv i2s transfer callback function. */ typedef void (*sdrv_i2s_callback)(sdrv_i2s_transfer_t *transfer, void *context, sdrv_i2s_status_t state); /** * @brief sdrv i2s configurations params, * */ typedef struct sdrv_i2s_params { uint32_t fmt; /**< i2s data format */ sdrv_i2s_channel_t channels; /**< data channels */ sdrv_i2s_sample_width_t sample_width; /**< data width */ sdrv_i2s_sample_rate_t sample_rate; /**< data sample rate */ unsigned int period_bytes; /**< dma mode need set, dma generates an interrupt transmission data size */ unsigned int periods; /**< dma mode need set, period num */ sdrv_i2s_channel_t slots; /**< slot num */ sdrv_i2s_slot_width_t slot_width; /* slot data width */ unsigned int tx_slot_mask; /**< slot mask ,1 :slot enable; 0:slot disable */ unsigned int rx_slot_mask; /**< slot mask ,1 :slot enable; 0:slot disable */ bool usedma; /**< true :dma mode; false:irq mode */ uint8_t *dma_buff; /**< dma mode need set dma_buf addr, size=period_count*period_size */ } sdrv_i2s_params_t; /** * @brief i2s mclk direction selection in or out * */ typedef enum sdrv_i2s_mclk_dir { SDRV_I2S_MCLK_IN = 0, /**< i2s mclk in */ SDRV_I2S_MCLK_OUT, /**< i2s mclk out,default out */ } sdrv_i2s_mclk_dir_t; /** * @brief i2s mclk selection mclk0 or mclk1 * */ typedef enum sdrv_i2s_mclk_sel { SDRV_I2S_MCLK_NULL = 0, SDRV_I2S_MCLK_0, SDRV_I2S_MCLK_1, } sdrv_i2s_mclk_sel_t; /** * @brief i2s controller configurations * */ typedef struct sdrv_i2s_config { paddr_t base; /**< i2s module base addr */ int id; /**< reserved */ uint32_t irq; /**< i2s module irq num */ sdrv_ckgen_node_t *clk; /**< i2s module clk */ paddr_t dma_base; /**< dma used by i2s, which is dma base addr */ sdrv_dma_channel_id_e tx_channel_id; /**< dma used by i2s, which is dma channel */ sdrv_dma_channel_id_e rx_channel_id; /**< dma used by i2s, which is dma channel */ sdrv_i2s_clk_sync_type_t sync_mode; /**< tx rx synchronization */ uint8_t tx_chsel; /**< tx data pin */ uint8_t rx_chsel; /**< rx data pin */ sdrv_i2s_mclk_dir_t mclk_dir; /**< mclk in or out ,default out */ sdrv_i2s_mclk_sel_t mclk_sel; /**< which mclk is selected */ } sdrv_i2s_config_t; /** * @brief i2s dma fifo descriptions * */ typedef struct sdrv_i2s_dma_data { paddr_t addr; /**< i2s fifo base addr */ sdrv_dma_bus_width_e addr_width; /**< i2s fifo width */ unsigned int maxburst; /**< i2s fifo max transfer size */ unsigned int fifo_size; /**< i2s fifo fifo size */ } sdrv_i2s_dma_data_t; /** * @brief playback capture descriptions * */ typedef struct sdrv_i2s_stream { /**< i2s config params ;such as fmt channels sample_width sample_rate */ sdrv_i2s_params_t params; /**< stream status; true : running false:idle */ bool active; /**< clk status; true for enable ; false for disable */ bool clk_enable; /**< data pack mode in fifo */ bool pack_mode; /**< i2s request dma transfer when fifo data is >= threshold for playback * i2s request dma transfer when fifo data is <= threshold for capture */ unsigned threshold; /**< app transfer queue , the max size is SDRV_I2S_XFER_NUM_BUFFERS */ sdrv_i2s_transfer_t queue[SDRV_I2S_XFER_NUM_BUFFERS]; uint8_t queue_appl; /**< app submit enqueue transfer index */ uint8_t queue_hw; /**< hw dequeue transfer index */ /**< app callback to notify user transfer status */ sdrv_i2s_callback callback; /**< callback context */ void *context; /**< dma module instance handle */ sdrv_dma_t dma_instance; /**< dma module channel handle */ sdrv_dma_channel_t dma_channel; /**< i2s dma fifo descriptions */ sdrv_i2s_dma_data_t dma_data; /**< dma buff descriptions */ sdrv_i2s_dma_buf_t dma_buf; } sdrv_i2s_stream_t; /** * @brief i2s controller descriptions * */ typedef struct sdrv_i2s { sdrv_i2s_config_t *cfg; /**< i2s module cfg infomation */ uint32_t clk_rate; /**< i2s module work clk rate */ sdrv_i2s_stream_t stream[2]; /**< playback capture descriptions */ } sdrv_i2s_t; /** * @brief initializes i2s module controller * * This fuction initializes i2s module * function. * * @param [in] i2s sdrv i2s controller * @param [in] cfg sdrv i2s controller configurations * @return sdrv_i2s_status_t * */ sdrv_i2s_status_t sdrv_i2s_init(sdrv_i2s_t *i2s, sdrv_i2s_config_t *cfg); /** * @brief get i2s module default params * * This fuction is used to get i2s module default params * * @param [in] i2s sdrv i2s controller * @param [out] params sdrv i2s params * @param [in] type playback or capture type * @return sdrv_i2s_status_t * */ sdrv_i2s_status_t sdrv_i2s_get_default_params(sdrv_i2s_t *i2s, sdrv_i2s_params_t *params, sdrv_i2s_stream_type_t type); /** * @brief set i2s params * * This fuction is used to set i2s module params * * @param [in] i2s sdrv i2s controller * @param [in] params sdrv i2s params * @param [in] type playback or capture type * @ return sdrv_i2s_status_t * * */ sdrv_i2s_status_t sdrv_i2s_set_params(sdrv_i2s_t *i2s, sdrv_i2s_params_t *params, sdrv_i2s_stream_type_t type); /** * @brief create i2s transfer and attach callback * * This fuction is used to create transfer and attach transfer callback * * @param [in] i2s sdrv i2s controller * @param [in] callback sdrv i2s transfer callback function. * @param [in] context sdrv i2s transfer callback param. * @param [in] type playback or capture type * @return sdrv_i2s_status_t */ sdrv_i2s_status_t sdrv_i2s_create_transfer(sdrv_i2s_t *i2s, sdrv_i2s_callback callback, void *context, sdrv_i2s_stream_type_t type); /** * @brief submit i2s transfer in queue * * This fuction is used to submit transfer, which's max num is * SDRV_I2S_XFER_NUM_BUFFERS * * @param [in] i2s sdrv i2s controller * @param [in] transfer sdrv i2s transfer * @param [in] type playback or capture type * @return sdrv_i2s_status_t */ sdrv_i2s_status_t sdrv_i2s_submit_transfer(sdrv_i2s_t *i2s, sdrv_i2s_transfer_t *transfer, sdrv_i2s_stream_type_t type); /** * @brief start i2s transfer * * This fuction is used to start i2s transfer * * @param [in] i2s sdrv i2s controller * @param [in] type playback or capture type * @return sdrv_i2s_status_t */ sdrv_i2s_status_t sdrv_i2s_start(sdrv_i2s_t *i2s, sdrv_i2s_stream_type_t type); /** * @brief stop i2s transfer * * * This fuction is used to stop i2s transfer * * @param [in] i2s sdrv i2s controller * @param [in] type playback or capture type * @return sdrv_i2s_status_t */ sdrv_i2s_status_t sdrv_i2s_stop(sdrv_i2s_t *i2s, sdrv_i2s_stream_type_t type); #endif /* SDRV_I2S_DRIVER_H_ */