ASoC: fsi: use dmaengine_prep_dma_cyclic() for DMA transfer
Current FSI driver is using DMAEngine directly, but, ASoC is requesting to use common DMA transfer method, like snd_dmaengine_pcm_trigger() or dmaengine_pcm_ops. It is difficult to switch at this point, since Renesas driver is also supporting PIO transfer. This patch uses dmaengine_prep_dma_cyclic() instead of dmaengine_prep_slave_single(). It is used in requested method, and is good first step to switch over. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
parent
d403e24908
commit
8457e0e9e2
|
@ -232,10 +232,7 @@ struct fsi_stream {
|
||||||
* these are for DMAEngine
|
* these are for DMAEngine
|
||||||
*/
|
*/
|
||||||
struct dma_chan *chan;
|
struct dma_chan *chan;
|
||||||
struct work_struct work;
|
|
||||||
int dma_id;
|
int dma_id;
|
||||||
int loop_cnt;
|
|
||||||
int additional_pos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fsi_clk {
|
struct fsi_clk {
|
||||||
|
@ -1281,24 +1278,9 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
|
||||||
io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
|
io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
|
||||||
BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
|
BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
|
||||||
|
|
||||||
io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */
|
|
||||||
io->additional_pos = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional)
|
|
||||||
{
|
|
||||||
struct snd_pcm_runtime *runtime = io->substream->runtime;
|
|
||||||
int period = io->period_pos + additional;
|
|
||||||
|
|
||||||
if (period >= runtime->periods)
|
|
||||||
period = 0;
|
|
||||||
|
|
||||||
return runtime->dma_addr +
|
|
||||||
samples_to_bytes(runtime, period * io->period_samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsi_dma_complete(void *data)
|
static void fsi_dma_complete(void *data)
|
||||||
{
|
{
|
||||||
struct fsi_stream *io = (struct fsi_stream *)data;
|
struct fsi_stream *io = (struct fsi_stream *)data;
|
||||||
|
@ -1307,53 +1289,37 @@ static void fsi_dma_complete(void *data)
|
||||||
fsi_pointer_update(io, io->period_samples);
|
fsi_pointer_update(io, io->period_samples);
|
||||||
|
|
||||||
fsi_count_fifo_err(fsi);
|
fsi_count_fifo_err(fsi);
|
||||||
fsi_stream_transfer(io);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fsi_dma_do_work(struct work_struct *work)
|
static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
|
||||||
{
|
{
|
||||||
struct fsi_stream *io = container_of(work, struct fsi_stream, work);
|
struct snd_soc_dai *dai = fsi_get_dai(io->substream);
|
||||||
struct fsi_priv *fsi = fsi_stream_to_priv(io);
|
struct snd_pcm_substream *substream = io->substream;
|
||||||
struct snd_soc_dai *dai;
|
|
||||||
struct dma_async_tx_descriptor *desc;
|
struct dma_async_tx_descriptor *desc;
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
enum dma_data_direction dir;
|
|
||||||
int is_play = fsi_stream_is_play(fsi, io);
|
int is_play = fsi_stream_is_play(fsi, io);
|
||||||
int len, i;
|
enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
|
||||||
dma_addr_t buf;
|
int ret = -EIO;
|
||||||
|
|
||||||
if (!fsi_stream_is_working(fsi, io))
|
desc = dmaengine_prep_dma_cyclic(io->chan,
|
||||||
return;
|
substream->runtime->dma_addr,
|
||||||
|
snd_pcm_lib_buffer_bytes(substream),
|
||||||
dai = fsi_get_dai(io->substream);
|
snd_pcm_lib_period_bytes(substream),
|
||||||
runtime = io->substream->runtime;
|
dir,
|
||||||
dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
len = samples_to_bytes(runtime, io->period_samples);
|
if (!desc) {
|
||||||
|
dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n");
|
||||||
for (i = 0; i < io->loop_cnt; i++) {
|
goto fsi_dma_transfer_err;
|
||||||
buf = fsi_dma_get_area(io, io->additional_pos);
|
|
||||||
|
|
||||||
desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
|
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
|
||||||
if (!desc) {
|
|
||||||
dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc->callback = fsi_dma_complete;
|
|
||||||
desc->callback_param = io;
|
|
||||||
|
|
||||||
if (dmaengine_submit(desc) < 0) {
|
|
||||||
dev_err(dai->dev, "tx_submit() fail\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma_async_issue_pending(io->chan);
|
|
||||||
|
|
||||||
io->additional_pos = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
io->loop_cnt = 1;
|
desc->callback = fsi_dma_complete;
|
||||||
|
desc->callback_param = io;
|
||||||
|
|
||||||
|
if (dmaengine_submit(desc) < 0) {
|
||||||
|
dev_err(dai->dev, "tx_submit() fail\n");
|
||||||
|
goto fsi_dma_transfer_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_async_issue_pending(io->chan);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME
|
* FIXME
|
||||||
|
@ -1370,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
|
||||||
fsi_reg_write(fsi, DIFF_ST, 0);
|
fsi_reg_write(fsi, DIFF_ST, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
|
ret = 0;
|
||||||
{
|
|
||||||
schedule_work(&io->work);
|
|
||||||
|
|
||||||
return 0;
|
fsi_dma_transfer_err:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
|
static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
|
||||||
|
@ -1437,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
|
||||||
return fsi_stream_probe(fsi, dev);
|
return fsi_stream_probe(fsi, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_WORK(&io->work, fsi_dma_do_work);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
|
static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
|
||||||
{
|
{
|
||||||
cancel_work_sync(&io->work);
|
|
||||||
|
|
||||||
fsi_stream_stop(fsi, io);
|
fsi_stream_stop(fsi, io);
|
||||||
|
|
||||||
if (io->chan)
|
if (io->chan)
|
||||||
|
@ -1618,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = fsi_hw_startup(fsi, io, dai->dev);
|
ret = fsi_hw_startup(fsi, io, dai->dev);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = fsi_stream_transfer(io);
|
ret = fsi_stream_start(fsi, io);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
fsi_stream_start(fsi, io);
|
ret = fsi_stream_transfer(io);
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
Loading…
Reference in a new issue