static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac) { unsigned int tdcr; mmp_tdma_disable_chan(tdmac); if (tdmac->dir == DMA_MEM_TO_DEV) tdcr = TDCR_DSTDIR_ADDR_HOLD | TDCR_SRCDIR_ADDR_INC; else if (tdmac->dir == DMA_DEV_TO_MEM) tdcr = TDCR_SRCDIR_ADDR_HOLD | TDCR_DSTDIR_ADDR_INC; if (tdmac->type == MMP_AUD_TDMA) { tdcr |= TDCR_PACKMOD; switch (tdmac->burst_sz) { case 4: tdcr |= TDCR_BURSTSZ_4B; break; case 8: tdcr |= TDCR_BURSTSZ_8B; break; case 16: tdcr |= TDCR_BURSTSZ_16B; break; case 32: tdcr |= TDCR_BURSTSZ_32B; break; case 64: tdcr |= TDCR_BURSTSZ_64B; break; case 128: tdcr |= TDCR_BURSTSZ_128B; break; default: dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n"); return -EINVAL; } switch (tdmac->buswidth) { case DMA_SLAVE_BUSWIDTH_1_BYTE: tdcr |= TDCR_SSZ_8_BITS; break; case DMA_SLAVE_BUSWIDTH_2_BYTES: tdcr |= TDCR_SSZ_16_BITS; break; case DMA_SLAVE_BUSWIDTH_4_BYTES: tdcr |= TDCR_SSZ_32_BITS; break; default: dev_err(tdmac->dev, "mmp_tdma: unknown bus size.\n"); return -EINVAL; } } else if (tdmac->type == PXA910_SQU) { tdcr |= TDCR_BURSTSZ_SQU_32B; tdcr |= TDCR_SSPMOD; } writel(tdcr, tdmac->reg_base + TDCR); return 0; }
static int mmp_tdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); struct dma_slave_config *dmaengine_cfg = (void *)arg; int ret = 0; switch (cmd) { case DMA_TERMINATE_ALL: mmp_tdma_disable_chan(tdmac); break; case DMA_PAUSE: mmp_tdma_pause_chan(tdmac); break; case DMA_RESUME: mmp_tdma_resume_chan(tdmac); break; case DMA_SLAVE_CONFIG: if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { tdmac->dev_addr = dmaengine_cfg->src_addr; tdmac->burst_sz = dmaengine_cfg->src_maxburst; tdmac->buswidth = dmaengine_cfg->src_addr_width; } else { tdmac->dev_addr = dmaengine_cfg->dst_addr; tdmac->burst_sz = dmaengine_cfg->dst_maxburst; tdmac->buswidth = dmaengine_cfg->dst_addr_width; } tdmac->dir = dmaengine_cfg->direction; return mmp_tdma_config_chan(tdmac); default: ret = -ENOSYS; } return ret; }
static int mmp_tdma_terminate_all(struct dma_chan *chan) { struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); mmp_tdma_disable_chan(chan); /* disable interrupt */ mmp_tdma_enable_irq(tdmac, false); return 0; }