tlv32aic32 外部DAC的I2S音频流运行过程分析
tlv32aic32 外部DAC的I2S音频流运行过程分析
#include "codec_tlv32aic32.h"
AF_TRACE_DEBUG();
struct af_stream_cfg_t *role;
enum AF_RESULT_T ret;
enum AUD_STREAM_USE_DEVICE_T device;
struct HAL_DMA_CH_CFG_T *dma_cfg = NULL;
role = af_get_stream_role(id, stream);
TRACE(3,"[%s] id = %d, stream = %d", __func__, id, stream);
ASSERT(cfg->data_ptr != NULL, "[%s] ERROR: data_ptr == NULL!!!", __func__);
ASSERT(((uint32_t)cfg->data_ptr) % 4 == 0, "[%s] ERROR: data_ptr(%p) is not align!!!", __func__, cfg->data_ptr);
ASSERT(cfg->data_size != 0, "[%s] ERROR: data_size == 0!!!", __func__);
ret = AF_RES_FAILD;
af_lock_thread();
//check af is open
if (role->ctl.status != AF_STATUS_OPEN_CLOSE) {
TRACE(2,"[%s] ERROR: status = %d",__func__, role->ctl.status);
goto _exit;
}
role->cfg = *cfg;
device = cfg->device;
role->ctl.use_device = device;
dma_cfg = &role->dma_cfg;
memset(dma_cfg, 0, sizeof(*dma_cfg));
dma_cfg->handler = af_dma_irq_handler;
if (stream == AUD_STREAM_PLAYBACK) {
AF_TRACE_DEBUG();
dma_cfg->src_periph = (enum HAL_DMA_PERIPH_T)0;
dma_cfg->type = HAL_DMA_FLOW_M2P_DMA;
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
//trace(0,"tlv32aic32_open()\n");
tlv32aic32_open();
tlv32aic32_stream_open(stream);----------à hal_i2s_open
dma_cfg->dst_periph = HAL_AUDMA_I2S0_TX;
#endif
af_stream_update_dma_buffer(id, stream, role, cfg);
role->handler = cfg->handler;
af_set_status(id, stream, AF_STATUS_STREAM_OPEN_CLOSE);
#ifndef RTOS
af_clear_flag(&af_flag_signal, 1 << (id * 2 + stream));
af_set_flag(&af_flag_open, 1 << (id * 2 + stream));
#endif
#ifdef DMA_RPC_CLI
if (dma_rpcif_enabled(id, stream)) {
dma_rpc_stream_open(id, stream, (void *)&role->cfg);
}
#endif
AF_TRACE_DEBUG();
ret = af_stream_setup_internal(id, stream, &role->cfg, false);
_exit:
af_unlock_thread();
af_stream_sw_gain_open(id, stream, cfg->sample_rate, cfg->bits, cfg->channel_num,
AUDIO_OUTPUT_SW_GAIN_MODE_IIR);
#ifdef DMA_RPC_CLI
if (dma_rpcif_enabled(id, stream)) {
dma_cfg->ch = dma_rpc_get_chan(dma_cfg->dst_periph, HAL_DMA_HIGH_PRIO);
role->dma_base = dma_rpc_get_base_addr(dma_cfg->ch);
} else
#endif
{
dma_cfg->ch = hal_audma_get_chan(dma_cfg->dst_periph, HAL_DMA_HIGH_PRIO);
role->dma_base = hal_audma_get_base_addr(dma_cfg->ch);
}
AF_TRACE_DEBUG();
dma_cfg->dst_periph = (enum HAL_DMA_PERIPH_T)0;
dma_cfg->type = HAL_DMA_FLOW_P2M_DMA;
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
tlv32aic32_open();
tlv32aic32_stream_open(stream);
dma_cfg->src_periph = HAL_AUDMA_I2S0_RX;
#endif
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
struct tlv32aic32_config_t tlv32aic32_cfg;
memset(&tlv32aic32_cfg, 0, sizeof(tlv32aic32_cfg));
tlv32aic32_cfg.bits = cfg->bits;
tlv32aic32_cfg.channel_num = cfg->channel_num;
tlv32aic32_cfg.channel_map = cfg->channel_map;
tlv32aic32_cfg.sample_rate = cfg->sample_rate;
tlv32aic32_cfg.use_dma = AF_TRUE;
tlv32aic32_cfg.chan_sep_buf = cfg->chan_sep_buf;
tlv32aic32_cfg.sync_start = cfg->sync_start;
tlv32aic32_cfg.slot_cycles = cfg->slot_cycles;
tlv32aic32_stream_setup(stream, &tlv32aic32_cfg);------à hal_i2s_setup_stream
#endif
memset(&i2s_cfg, 0, sizeof(i2s_cfg));
i2s_cfg.use_dma = AF_TRUE;
i2s_cfg.chan_sep_buf = cfg->chan_sep_buf;
i2s_cfg.sync_start = cfg->sync_start;
i2s_cfg.cycles = cfg->slot_cycles;
i2s_cfg.bits = cfg->bits;
i2s_cfg.channel_num = cfg->channel_num;
i2s_cfg.channel_map = cfg->channel_map;
i2s_cfg.sample_rate = cfg->sample_rate;
i2s_cfg.ext_mclk_freq = cfg->ext_mclk_freq;
hal_i2s_setup_stream(i2s_id, stream, &i2s_cfg);
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
tlv32aic32_stream_start(stream);----------à hal_i2s_start_stream
#endif
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
tlv32aic32_stream_stop(stream);
#endif
#ifdef AF_DEVICE_EXT_CODEC
} else if (device == AUD_STREAM_USE_EXT_CODEC) {
AF_TRACE_DEBUG();
tlv32aic32_stream_close(stream);
#endif
af_unlock_thread();
分析结论:
增加了lock锁机制,open , setup, 以及start 都有一对锁,调用的i2s底层是一样的,
以及DMA 中断相关配置 ,更新DMA buf的配置。
音频引擎框架增加了一些机制!
