/** * @file sdrv_pdm.h * @brief SemiDrive pdm driver header file. * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #ifndef SDRV_PDM_H_ #define SDRV_PDM_H_ #include #include "sdrv_ckgen.h" #include "sdrv_common.h" #include "sdrv_dma.h" /* sdrv pdm max transfres */ #define SDRV_PDM_XFER_NUM_TRANSFERS (4U) /* sdrv pdm dma buff size default value */ #define SDRV_PDM_CHANNELS_COUNT 1 #define SDRV_PDM_CHANNELS_BYTES (SDRV_PDM_SAMPLE_WIDTH_16BITS / 8) #define SDRV_PDM_DMA_PERIOD_FRAME_SIZE 1024 * 4 #define SDRV_PDM_DMA_PERIOD_SIZE \ SDRV_PDM_DMA_PERIOD_FRAME_SIZE *SDRV_PDM_CHANNELS_COUNT \ *SDRV_PDM_CHANNELS_BYTES #define SDRV_PDM_DMA_PERIOD_COUNT 2 #define SDRV_PDM_DMA_BUF_TOTAL_SIZE \ SDRV_PDM_DMA_PERIOD_SIZE *SDRV_PDM_DMA_PERIOD_COUNT /** * @brief pdm channel * */ typedef enum sdrv_pdm_channel { SDRV_PDM_CHANNEL_LEFT = 0x00, SDRV_PDM_CHANNEL_RIGHT = 0x01, SDRV_PDM_CHANNEL_STEREO = 0x02, } sdrv_pdm_channel_t; /** * @brief pdm gain * */ typedef enum sdrv_pdm_gain { SDRV_PDM_GAIN_N6DB = 0x01, SDRV_PDM_GAIN_N12DB = 0x02, SDRV_PDM_GAIN_N18DB = 0x03, SDRV_PDM_GAIN_N24DB = 0x04, SDRV_PDM_GAIN_P0DB = 0x05, SDRV_PDM_GAIN_P6DB = 0x06, SDRV_PDM_GAIN_P12DB = 0x07, SDRV_PDM_GAIN_P18DB = 0x08, SDRV_PDM_GAIN_P24DB = 0x09, } sdrv_pdm_gain_t; /** * @brief pdm sample rate * */ typedef enum sdrv_pdm_sample_rate { SDRV_PDM_SR_5512 = 5512, SDRV_PDM_SR_8000 = 8000, SDRV_PDM_SR_11025 = 11025, SDRV_PDM_SR_16000 = 16000, SDRV_PDM_SR_22050 = 22050, SDRV_PDM_SR_32000 = 32000, SDRV_PDM_SR_44100 = 44100, SDRV_PDM_SR_48000 = 48000, SDRV_PDM_SR_64000 = 64000, SDRV_PDM_SR_88200 = 88200, SDRV_PDM_SR_96000 = 96000, SDRV_PDM_SR_176400 = 176400, SDRV_PDM_SR_192000 = 192000, } sdrv_pdm_sample_rate_t; /** * @brief pdm sample width * */ typedef enum sdrv_pdm_sample_width { SDRV_PDM_SAMPLE_WIDTH_8BITS = 8, SDRV_PDM_SAMPLE_WIDTH_16BITS = 16, SDRV_PDM_SAMPLE_WIDTH_24BITS = 24, SDRV_PDM_SAMPLE_WIDTH_32BITS = 32, } sdrv_pdm_sample_width_t; /** * @brief pdm status * */ typedef enum sdrv_pdm_status { /* status for Success */ SDRV_PDM_STATUS_SUCCESS = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_COMMON, 0), /* status for Fail */ SDRV_PDM_STATUS_FAIL = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_PDM, 1), /* status for invalid argument check */ SDRV_PDM_STATUS_INVALID_PARAMS = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_PDM, 2), /* status for Overrun */ SDRV_PDM_STATUS_OVERRUN = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_PDM, 3), /* status for underrun */ SDRV_PDM_STATUS_UNDERRUN = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_PDM, 4), } sdrv_pdm_status_t; /** * @brief pdm dma fifo descriptions * */ typedef struct sdrv_pdm_dma_data { /**< pdm fifo base addr */ paddr_t addr; /**< pdm fifo width */ sdrv_dma_bus_width_e addr_width; /**< pdm fifo max transfer size */ unsigned int max_burst; /**< pdm fifo fifo size */ unsigned int fifo_size; } sdrv_pdm_dma_data_t; /** * @brief pdm dma buff descriptions * * */ typedef struct sdrv_pdm_dma_buf { /**< dma mode ,buffer address */ uint8_t *addr; /**< buffer size */ int32_t buffer_bytes; /**< buffer period_size */ int32_t period_bytes; /**< buffer period count */ int32_t periods; /**< app write pointer during playback, dma read pointer during capture */ uint32_t appl_ptr; /**< dma read pointer during playback, dma write pointer during capture */ uint32_t hw_ptr; /**< dma buff boundary */ uint32_t boundary; } sdrv_pdm_dma_buf_t; /** * @brief pdm transfer * */ typedef struct sdrv_pdm_transfer { /**< audio data addr */ uint8_t *data; /**< audio data length */ uint32_t length; /**< transfer tag */ uint8_t id; } sdrv_pdm_transfer_t; /* @brief sdrv pdm transfer callback function. */ typedef void (*sdrv_pdm_callback)(sdrv_pdm_transfer_t *transfer, void *context, sdrv_pdm_status_t state); /** * @brief pdm config params * */ typedef struct sdrv_pdm_params { /**< data channels */ sdrv_pdm_channel_t channels; /**< data width */ sdrv_pdm_sample_width_t sample_width; /**< data sample rate */ sdrv_pdm_sample_rate_t sample_rate; /**< data gain */ sdrv_pdm_gain_t gain; /**< dma mode must set, dma generates an interrupt transmission data size */ unsigned int period_bytes; /**< dma mode must set, dma generates an interrupt transmission data size */ unsigned int periods; /**< dma mode need set dma_buf addr, size=period_count*period_size */ uint8_t *dma_buff; /**< true :dma mode; false:irq mode */ bool usedma; } sdrv_pdm_params_t; /** * @brief pdm capture stream descriptions * */ typedef struct sdrv_pdm_stream { /**< pdm config params */ sdrv_pdm_params_t params; /**< app submit transfer ,max is SDRV_PDM_XFER_NUM_TRANSFERS */ sdrv_pdm_transfer_t queue[SDRV_PDM_XFER_NUM_TRANSFERS]; /**< stream status; true : running false:idle */ bool active; /**< app submit enqueue transfer index */ uint8_t queue_appl; /**< hw dequeue transfer index */ uint8_t queue_hw; /**< user callback */ sdrv_pdm_callback callback; /**< user callback context */ void *context; /**< data pack or loose mode in fifo */ bool pack_mode; /**< data format in fifo */ bool data_lsb; /**< pdm request dma transfer when fifo data is <= threshold for capture */ unsigned threshold; /**< dma module instance handle */ sdrv_dma_t dma_instance; /**< dma module channel handle */ sdrv_dma_channel_t dma_channel; /**< dma fifo descriptions */ sdrv_pdm_dma_data_t dma_data; /**< dma mode must set dma_buf addr, size=period_count*period_size */ sdrv_pdm_dma_buf_t dma_buf; bool dma_abort; } sdrv_pdm_stream_t; /** * @brief pdm board config * */ typedef struct sdrv_pdm_config { /**< pdm module base addr */ paddr_t base; /**< pdm index in saci */ int id; /**< pdm module irq num */ uint32_t irq; /**< pdm module clk */ sdrv_ckgen_node_t *clk; /**< dma used by pdm, which is dma base addr */ paddr_t dma_base; /**< dma used by pdm, which is dma channel */ sdrv_dma_channel_id_e dma_channel; } sdrv_pdm_config_t; /** * @brief pdm module descriptions * */ typedef struct sdrv_pdm { /**< pdm board config */ sdrv_pdm_config_t *config; /**< pdm_ctrl work clk rate */ uint32_t clk_rate; /**< pdm capture descriptions */ sdrv_pdm_stream_t stream; } sdrv_pdm_t; /** * @brief sdrv pdm controller initialization. * * This function is used to initialize pdm module * function. * * @param [in] pdm sdrv pdm controller * @param [in] cfg sdrv pdm controller configurations * @return sdrv_pdm_status_t * */ sdrv_pdm_status_t sdrv_pdm_init(sdrv_pdm_t *pdm, sdrv_pdm_config_t *cfg); /** * @brief sdrv_pdm_get_default_params * * This function is used to get pdm default params * * @param [in] pdm sdrv pdm controller * @param [out] params sdrv pdm params * @return sdrv_pdm_status_t * */ sdrv_pdm_status_t sdrv_pdm_get_default_params(sdrv_pdm_t *pdm, sdrv_pdm_params_t *params); /** * @brief sdrv_pdm_set_params * * This function is used to set pdm params * * @param [in] pdm sdrv pdm controller * @param [in] params sdrv pdm params * @return sdrv_pdm_status_t * * */ sdrv_pdm_status_t sdrv_pdm_set_params(sdrv_pdm_t *pdm, sdrv_pdm_params_t *params); /** * @brief sdrv_pdm_create_transfer * * This function is used to create transfer and attach transfer callback * * @param [in] pdm sdrv pdm controller * @param [in] callback sdrv pdm transfer callback function. * @param [in] context sdrv pdm transfer callback param. * @return sdrv_pdm_status_t */ sdrv_pdm_status_t sdrv_pdm_create_transfer(sdrv_pdm_t *pdm, sdrv_pdm_callback callback, void *context); /** * @brief sdrv_pdm_submit_transfer * * This function is used to submit transfer, which's max num is * SDRV_PDM_XFER_NUM_BUFFERS * * @param [in] pdm sdrv pdm controller * @param [in] transfer sdrv pdm transfer * @return sdrv_pdm_status_t */ sdrv_pdm_status_t sdrv_pdm_submit_transfer(sdrv_pdm_t *pdm, sdrv_pdm_transfer_t *transfer); /** * @brief sdrv_pdm_start * * This function is used to start pdm transfer * * @param [in] pdm sdrv pdm controller * @return sdrv_pdm_status_t */ sdrv_pdm_status_t sdrv_pdm_start(sdrv_pdm_t *pdm); /** * @brief sdrv_pdm_stop * * This function is used to stop pdm transfer * * @param [in] pdm sdrv pdm controller * @return sdrv_pdm_status_t */ sdrv_pdm_status_t sdrv_pdm_stop(sdrv_pdm_t *pdm); #endif /* SDRV_PDM_H_ */