Commit ffc079a4 authored by Stefan Mavrodiev's avatar Stefan Mavrodiev Committed by Vinod Koul

dmaengine: sun4i: Add support for cyclic requests with dedicated DMA

Currently the cyclic transfers can be used only with normal DMAs. They
can be used by pcm_dmaengine module, which is required for implementing
sound with sun4i-hdmi encoder. This is so because the controller can
accept audio only from a dedicated DMA.

This patch enables them, following the existing style for the
scatter/gather type transfers.
Signed-off-by: default avatarStefan Mavrodiev <stefan@olimex.com>
Acked-by: default avatarMaxime Ripard <mripard@kernel.org>
Link: https://lore.kernel.org/r/20200110141140.28527-2-stefan@olimex.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 4b048178
...@@ -669,43 +669,41 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, ...@@ -669,43 +669,41 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
dma_addr_t src, dest; dma_addr_t src, dest;
u32 endpoints; u32 endpoints;
int nr_periods, offset, plength, i; int nr_periods, offset, plength, i;
u8 ram_type, io_mode, linear_mode;
if (!is_slave_direction(dir)) { if (!is_slave_direction(dir)) {
dev_err(chan2dev(chan), "Invalid DMA direction\n"); dev_err(chan2dev(chan), "Invalid DMA direction\n");
return NULL; return NULL;
} }
if (vchan->is_dedicated) {
/*
* As we are using this just for audio data, we need to use
* normal DMA. There is nothing stopping us from supporting
* dedicated DMA here as well, so if a client comes up and
* requires it, it will be simple to implement it.
*/
dev_err(chan2dev(chan),
"Cyclic transfers are only supported on Normal DMA\n");
return NULL;
}
contract = generate_dma_contract(); contract = generate_dma_contract();
if (!contract) if (!contract)
return NULL; return NULL;
contract->is_cyclic = 1; contract->is_cyclic = 1;
/* Figure out the endpoints and the address we need */ if (vchan->is_dedicated) {
io_mode = SUN4I_DDMA_ADDR_MODE_IO;
linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
} else {
io_mode = SUN4I_NDMA_ADDR_MODE_IO;
linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
}
if (dir == DMA_MEM_TO_DEV) { if (dir == DMA_MEM_TO_DEV) {
src = buf; src = buf;
dest = sconfig->dst_addr; dest = sconfig->dst_addr;
endpoints = SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM) | endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) |
SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) | SUN4I_DMA_CFG_DST_ADDR_MODE(io_mode) |
SUN4I_DMA_CFG_DST_ADDR_MODE(SUN4I_NDMA_ADDR_MODE_IO); SUN4I_DMA_CFG_SRC_DRQ_TYPE(ram_type);
} else { } else {
src = sconfig->src_addr; src = sconfig->src_addr;
dest = buf; dest = buf;
endpoints = SUN4I_DMA_CFG_SRC_DRQ_TYPE(vchan->endpoint) | endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(ram_type) |
SUN4I_DMA_CFG_SRC_ADDR_MODE(SUN4I_NDMA_ADDR_MODE_IO) | SUN4I_DMA_CFG_SRC_DRQ_TYPE(vchan->endpoint) |
SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM); SUN4I_DMA_CFG_SRC_ADDR_MODE(io_mode);
} }
/* /*
...@@ -747,8 +745,13 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, ...@@ -747,8 +745,13 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
dest = buf + offset; dest = buf + offset;
/* Make the promise */ /* Make the promise */
if (vchan->is_dedicated)
promise = generate_ddma_promise(chan, src, dest,
plength, sconfig);
else
promise = generate_ndma_promise(chan, src, dest, promise = generate_ndma_promise(chan, src, dest,
plength, sconfig, dir); plength, sconfig, dir);
if (!promise) { if (!promise) {
/* TODO: should we free everything? */ /* TODO: should we free everything? */
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment