ASoC: rsnd: move priv member settings to upper side
[deliverable/linux.git] / sound / soc / sh / rcar / core.c
index 743de5e3b1e1ed4cba8f5dcfce3a5d3cfd9471bf..a8e6aa6cb3346d686dd513e1819e8427f97de073 100644 (file)
@@ -132,6 +132,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
 /*
  *     rsnd_dma functions
  */
+static void __rsnd_dma_start(struct rsnd_dma *dma);
 static void rsnd_dma_continue(struct rsnd_dma *dma)
 {
        /* push next A or B plane */
@@ -142,8 +143,9 @@ static void rsnd_dma_continue(struct rsnd_dma *dma)
 void rsnd_dma_start(struct rsnd_dma *dma)
 {
        /* push both A and B plane*/
+       dma->offset = 0;
        dma->submit_loop = 2;
-       schedule_work(&dma->work);
+       __rsnd_dma_start(dma);
 }
 
 void rsnd_dma_stop(struct rsnd_dma *dma)
@@ -156,12 +158,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma)
 static void rsnd_dma_complete(void *data)
 {
        struct rsnd_dma *dma = (struct rsnd_dma *)data;
-       struct rsnd_priv *priv = dma->priv;
+       struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
+       struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma));
+       struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
        unsigned long flags;
 
        rsnd_lock(priv, flags);
 
-       dma->complete(dma);
+       /*
+        * Renesas sound Gen1 needs 1 DMAC,
+        * Gen2 needs 2 DMAC.
+        * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri.
+        * But, Audio-DMAC-peri-peri doesn't have interrupt,
+        * and this driver is assuming that here.
+        *
+        * If Audio-DMAC-peri-peri has interrpt,
+        * rsnd_dai_pointer_update() will be called twice,
+        * ant it will breaks io->byte_pos
+        */
+
+       rsnd_dai_pointer_update(io, io->byte_per_period);
 
        if (dma->submit_loop)
                rsnd_dma_continue(dma);
@@ -169,20 +185,23 @@ static void rsnd_dma_complete(void *data)
        rsnd_unlock(priv, flags);
 }
 
-static void rsnd_dma_do_work(struct work_struct *work)
+static void __rsnd_dma_start(struct rsnd_dma *dma)
 {
-       struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work);
-       struct rsnd_priv *priv = dma->priv;
+       struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
+       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+       struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+       struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct dma_async_tx_descriptor *desc;
        dma_addr_t buf;
-       size_t len;
+       size_t len = io->byte_per_period;
        int i;
 
        for (i = 0; i < dma->submit_loop; i++) {
 
-               if (dma->inquiry(dma, &buf, &len) < 0)
-                       return;
+               buf = runtime->dma_addr +
+                       rsnd_dai_pointer_offset(io, dma->offset + len);
+               dma->offset = len;
 
                desc = dmaengine_prep_slave_single(
                        dma->chan, buf, len, dma->dir,
@@ -204,16 +223,20 @@ static void rsnd_dma_do_work(struct work_struct *work)
        }
 }
 
+static void rsnd_dma_do_work(struct work_struct *work)
+{
+       struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work);
+
+       __rsnd_dma_start(dma);
+}
+
 int rsnd_dma_available(struct rsnd_dma *dma)
 {
        return !!dma->chan;
 }
 
 int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
-                 int is_play, int id,
-                 int (*inquiry)(struct rsnd_dma *dma,
-                                 dma_addr_t *buf, int *len),
-                 int (*complete)(struct rsnd_dma *dma))
+                 int is_play, int id)
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct dma_slave_config cfg;
@@ -246,9 +269,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
                goto rsnd_dma_init_err;
 
        dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-       dma->priv = priv;
-       dma->inquiry = inquiry;
-       dma->complete = complete;
        INIT_WORK(&dma->work, rsnd_dma_do_work);
 
        return 0;
@@ -301,6 +321,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai,
        }
 
        list_add_tail(&mod->list, &io->head);
+       mod->io = io;
 
        return 0;
 }
@@ -308,6 +329,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai,
 int rsnd_dai_disconnect(struct rsnd_mod *mod)
 {
        list_del_init(&mod->list);
+       mod->io = NULL;
 
        return 0;
 }
@@ -572,6 +594,10 @@ static int rsnd_dai_probe(struct platform_device *pdev,
                return -ENOMEM;
        }
 
+       priv->dai_nr    = dai_nr;
+       priv->daidrv    = drv;
+       priv->rdai      = rdai;
+
        for (i = 0; i < dai_nr; i++) {
 
                pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1);
@@ -608,10 +634,6 @@ static int rsnd_dai_probe(struct platform_device *pdev,
                        cmod ? "capture" : "  --   ");
        }
 
-       priv->dai_nr    = dai_nr;
-       priv->daidrv    = drv;
-       priv->rdai      = rdai;
-
        return 0;
 }
 
@@ -738,23 +760,23 @@ static int rsnd_probe(struct platform_device *pdev)
         *      init each module
         */
        ret = rsnd_gen_probe(pdev, info, priv);
-       if (ret < 0)
+       if (ret)
                return ret;
 
-       ret = rsnd_scu_probe(pdev, info, priv);
-       if (ret < 0)
+       ret = rsnd_ssi_probe(pdev, info, priv);
+       if (ret)
                return ret;
 
-       ret = rsnd_adg_probe(pdev, info, priv);
-       if (ret < 0)
+       ret = rsnd_scu_probe(pdev, info, priv);
+       if (ret)
                return ret;
 
-       ret = rsnd_ssi_probe(pdev, info, priv);
-       if (ret < 0)
+       ret = rsnd_adg_probe(pdev, info, priv);
+       if (ret)
                return ret;
 
        ret = rsnd_dai_probe(pdev, info, priv);
-       if (ret < 0)
+       if (ret)
                return ret;
 
        /*
This page took 0.025817 seconds and 5 git commands to generate.