420 lines
13 KiB
C
420 lines
13 KiB
C
/**
|
|
* @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 <debug.h>
|
|
#include <reg.h>
|
|
#include <stdbool.h>
|
|
#include <types.h>
|
|
|
|
#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_ */
|