ALSA 驱动中dma的配置:
/* * prepare DMA for pcm */ int i2s_dma_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct sep0611_runtime_data *prtd = runtime->private_data; struct dma_info *p_dma_info; unsigned long i2s_fifo_width = 1; /* 16 bits in default */ int ret; /* we need call the i2s_dma_prepare after set hw_params, such as in pcm_prepare */ if(runtime->format == 0){ printk("ERR:please ensure the hw_params has been set correctly\n"); return -EINVAL; } p_dma_info = kmalloc(sizeof(struct dma_info), GFP_KERNEL); if(!p_dma_info){ return -ENOMEM; } if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ p_dma_info->trans_type = MEM_TO_DEV; p_dma_info->src_addr = prtd->dma_buffer; p_dma_info->dst_addr = I2S_BASE + I2S_TXDMA; /* * match with tx data of (S16_LE | S20_3LE | S24_3LE | S32_LE) */ if(runtime->format != SNDRV_PCM_FORMAT_S16_LE) i2s_fifo_width = 2; /* CTLx and CFGx */ p_dma_info->ctrl_hi = DMAC_DONE (0) | DMAC_BLK_TRAN_SZ(prtd->period_len/8); p_dma_info->ctrl_lo = DMAC_SRC_LLP_EN (1) | DMAC_DST_LLP_EN (0) | DMAC_SRC_MASTER_SEL(0)\ | DMAC_DST_MASTER_SEL(1)| DMAC_TRAN_TYPE_FLOW_CTL(1)| DMAC_DST_SCAT_EN (0) \ | DMAC_SRC_GATH_EN (0)| DMAC_SRC_BST_SZ (2)| DMAC_DST_BST_SZ (3) \ | DMAC_SRC_INCR (0)| DMAC_DST_INCR (3)| DMAC_SRC_TRAN_WIDTH(3)\ | DMAC_DST_TRAN_WIDTH(i2s_fifo_width) | DMAC_INT_EN(1); p_dma_info->cfg_hi = DMAC_DST_PER (7) | DMAC_SRC_PER (6) | DMAC_SRC_STAT_UPD_EN(0) \ | DMAC_DST_STAT_UPD_EN(0) | DMAC_PROT_CTL (1) | DMAC_FIFO_MODE(0) \ | DMAC_FLOW_CTL_MODE (0); p_dma_info->cfg_lo = DMAC_AUTO_RELOAD_DST(0) | DMAC_AUTO_RELOAD_SRC(0) | DMAC_MAX_AMBA_BST_LEN(0) \ | DMAC_SRC_HS_POL (0) | DMAC_DST_HS_POL (0) | DMAC_BUS_LOCK (0) \ | DMAC_CH_LOCK (0) | DMAC_BUS_LOCK_LEVEL(1)| DMAC_HW_SW_SEL_SRC (1) \ | DMAC_HW_SW_SEL_DST (0) | DMAC_CH_SUSP (0) | DMAC_CH_PRIOR (0); } else{ p_dma_info->trans_type = DEV_TO_MEM; p_dma_info->src_addr = I2S_BASE + I2S_RXDMA; p_dma_info->dst_addr = prtd->dma_buffer; /* CTLx and CFGx */ p_dma_info->ctrl_hi = DMAC_DONE(0) | DMAC_BLK_TRAN_SZ(prtd->period_len/2); p_dma_info->ctrl_lo = DMAC_SRC_LLP_EN (0)| DMAC_DST_LLP_EN (1) | DMAC_SRC_MASTER_SEL (1) \ | DMAC_DST_MASTER_SEL(0) | DMAC_TRAN_TYPE_FLOW_CTL(2) | DMAC_DST_SCAT_EN (0) \ | DMAC_SRC_GATH_EN (0) | DMAC_SRC_BST_SZ (2) | DMAC_DST_BST_SZ (3) \ | DMAC_SRC_INCR (3) | DMAC_DST_INCR (0) | DMAC_SRC_TRAN_WIDTH (i2s_fifo_width) \ | DMAC_DST_TRAN_WIDTH(2) | DMAC_INT_EN(1); p_dma_info->cfg_hi = DMAC_DST_PER(7) | DMAC_SRC_PER(6) | DMAC_SRC_STAT_UPD_EN(0) \ | DMAC_DST_STAT_UPD_EN(0) | DMAC_PROT_CTL (1) | DMAC_FIFO_MODE (0) \ | DMAC_FLOW_CTL_MODE (0); p_dma_info->cfg_lo = DMAC_AUTO_RELOAD_DST(0) | DMAC_AUTO_RELOAD_SRC(0) | DMAC_MAX_AMBA_BST_LEN(0) \ | DMAC_SRC_HS_POL (0) | DMAC_DST_HS_POL (0) | DMAC_BUS_LOCK (0) \ | DMAC_CH_LOCK (0) | DMAC_BUS_LOCK_LEVEL (1) | DMAC_HW_SW_SEL_SRC (0) \ | DMAC_HW_SW_SEL_DST (1) | DMAC_CH_SUSP (0) | DMAC_CH_PRIOR (0); } /* store p_dma_info in prtd */ prtd->dma_info = p_dma_info; ret = <SPAN style="BACKGROUND-COLOR: rgb(255,255,255)">set_dma_cll</SPAN>(p_dma_info, prtd->buffer_len, prtd->period_len); if(ret < 0){ return -ENOMEM; } load_first_llp(prtd->dma_info, prtd->dma_params->channel); return 0; }ALSA 驱动中dma的配置
内容版权声明:除非注明,否则皆为本站原创文章。