ASoC: fsi: use dmaengine_prep_dma_cyclic() for DMA transfer
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 23 Jun 2014 00:55:59 +0000 (17:55 -0700)
committerMark Brown <broonie@linaro.org>
Sat, 28 Jun 2014 13:41:18 +0000 (14:41 +0100)
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>
sound/soc/sh/fsi.c

index 820a40833c04c1634c0c1de6eb8fb57e493124da..a57eb96e57ebcd6fa3f8244962ccb06848887ce1 100644 (file)
@@ -232,10 +232,7 @@ struct fsi_stream {
         * these are for DMAEngine
         */
        struct dma_chan         *chan;
-       struct work_struct      work;
        int                     dma_id;
-       int                     loop_cnt;
-       int                     additional_pos;
 };
 
 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) |
                         BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
 
-       io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */
-       io->additional_pos = 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)
 {
        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_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 fsi_priv *fsi = fsi_stream_to_priv(io);
-       struct snd_soc_dai *dai;
+       struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+       struct snd_pcm_substream *substream = io->substream;
        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 len, i;
-       dma_addr_t buf;
-
-       if (!fsi_stream_is_working(fsi, io))
-               return;
-
-       dai     = fsi_get_dai(io->substream);
-       runtime = io->substream->runtime;
-       dir     = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-       len     = samples_to_bytes(runtime, io->period_samples);
-
-       for (i = 0; i < io->loop_cnt; i++) {
-               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;
-               }
+       enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       int ret = -EIO;
+
+       desc = dmaengine_prep_dma_cyclic(io->chan,
+                                        substream->runtime->dma_addr,
+                                        snd_pcm_lib_buffer_bytes(substream),
+                                        snd_pcm_lib_period_bytes(substream),
+                                        dir,
+                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc) {
+               dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n");
+               goto fsi_dma_transfer_err;
+       }
 
-               dma_async_issue_pending(io->chan);
+       desc->callback          = fsi_dma_complete;
+       desc->callback_param    = io;
 
-               io->additional_pos = 1;
+       if (dmaengine_submit(desc) < 0) {
+               dev_err(dai->dev, "tx_submit() fail\n");
+               goto fsi_dma_transfer_err;
        }
 
-       io->loop_cnt = 1;
+       dma_async_issue_pending(io->chan);
 
        /*
         * FIXME
@@ -1370,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
                        fsi_reg_write(fsi, DIFF_ST, 0);
                }
        }
-}
 
-static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
-{
-       schedule_work(&io->work);
+       ret = 0;
 
-       return 0;
+fsi_dma_transfer_err:
+       return ret;
 }
 
 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);
        }
 
-       INIT_WORK(&io->work, fsi_dma_do_work);
-
        return 0;
 }
 
 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       cancel_work_sync(&io->work);
-
        fsi_stream_stop(fsi, io);
 
        if (io->chan)
@@ -1618,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
                if (!ret)
                        ret = fsi_hw_startup(fsi, io, dai->dev);
                if (!ret)
-                       ret = fsi_stream_transfer(io);
+                       ret = fsi_stream_start(fsi, io);
                if (!ret)
-                       fsi_stream_start(fsi, io);
+                       ret = fsi_stream_transfer(io);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
                if (!ret)