static void mmp_tdma_free_chan_resources(struct dma_chan *chan) { struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); if (tdmac->irq) devm_free_irq(tdmac->dev, tdmac->irq, tdmac); mmp_tdma_free_descriptor(tdmac); return; }
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); /* * need to free descriptor as audio HAL doesn't close the * stream when audio stream ends */ if (tdmac->desc_arr) mmp_tdma_free_descriptor(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; }