Merge remote-tracking branches 'asoc/topic/omap', 'asoc/topic/qcom', 'asoc/topic...
[sfrench/cifs-2.6.git] / sound / soc / sh / rcar / core.c
index 31202e95be1ee6dc5fde83e44ce955347bc8109c..9f48d75fa992351adffef3d834620e7d2682354e 100644 (file)
  *
  */
 #include <linux/pm_runtime.h>
-#include <linux/shdma-base.h>
 #include "rsnd.h"
 
 #define RSND_RATES SNDRV_PCM_RATE_8000_96000
 #define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
-static struct rsnd_of_data rsnd_of_data_gen1 = {
+static const struct rsnd_of_data rsnd_of_data_gen1 = {
        .flags = RSND_GEN1,
 };
 
-static struct rsnd_of_data rsnd_of_data_gen2 = {
+static const struct rsnd_of_data rsnd_of_data_gen2 = {
        .flags = RSND_GEN2,
 };
 
-static struct of_device_id rsnd_of_match[] = {
+static const struct of_device_id rsnd_of_match[] = {
        { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 },
        { .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 },
        {},
@@ -138,15 +137,12 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
        return mod->ops->name;
 }
 
-char *rsnd_mod_dma_name(struct rsnd_mod *mod)
+struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod)
 {
-       if (!mod || !mod->ops)
-               return "unknown";
-
-       if (!mod->ops->dma_name)
-               return mod->ops->name;
+       if (!mod || !mod->ops || !mod->ops->dma_req)
+               return NULL;
 
-       return mod->ops->dma_name(mod);
+       return mod->ops->dma_req(mod);
 }
 
 int rsnd_mod_init(struct rsnd_mod *mod,
@@ -174,228 +170,6 @@ void rsnd_mod_quit(struct rsnd_mod *mod)
                clk_unprepare(mod->clk);
 }
 
-/*
- *     rsnd_dma functions
- */
-void rsnd_dma_stop(struct rsnd_dma *dma)
-{
-       dmaengine_terminate_all(dma->chan);
-}
-
-static void rsnd_dma_complete(void *data)
-{
-       struct rsnd_dma *dma = (struct rsnd_dma *)data;
-       struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
-       struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
-
-       /*
-        * 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);
-}
-
-void rsnd_dma_start(struct rsnd_dma *dma)
-{
-       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_substream *substream = io->substream;
-       struct device *dev = rsnd_priv_to_dev(priv);
-       struct dma_async_tx_descriptor *desc;
-
-       desc = dmaengine_prep_dma_cyclic(dma->chan,
-                                        (dma->addr) ? dma->addr :
-                                        substream->runtime->dma_addr,
-                                        snd_pcm_lib_buffer_bytes(substream),
-                                        snd_pcm_lib_period_bytes(substream),
-                                        dma->dir,
-                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (!desc) {
-               dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
-               return;
-       }
-
-       desc->callback          = rsnd_dma_complete;
-       desc->callback_param    = dma;
-
-       if (dmaengine_submit(desc) < 0) {
-               dev_err(dev, "dmaengine_submit() fail\n");
-               return;
-       }
-
-       dma_async_issue_pending(dma->chan);
-}
-
-int rsnd_dma_available(struct rsnd_dma *dma)
-{
-       return !!dma->chan;
-}
-
-#define DMA_NAME_SIZE 16
-#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */
-static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
-{
-       if (mod)
-               return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d",
-                        rsnd_mod_dma_name(mod), rsnd_mod_id(mod));
-       else
-               return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem");
-
-}
-
-static void rsnd_dma_of_name(struct rsnd_mod *mod_from,
-                            struct rsnd_mod *mod_to,
-                            char *dma_name)
-{
-       int index = 0;
-
-       index = _rsnd_dma_of_name(dma_name + index, mod_from);
-       *(dma_name + index++) = '_';
-       index = _rsnd_dma_of_name(dma_name + index, mod_to);
-}
-
-static void rsnd_dma_of_path(struct rsnd_dma *dma,
-                            int is_play,
-                            struct rsnd_mod **mod_from,
-                            struct rsnd_mod **mod_to)
-{
-       struct rsnd_mod *this = rsnd_dma_to_mod(dma);
-       struct rsnd_dai_stream *io = rsnd_mod_to_io(this);
-       struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
-       struct rsnd_mod *src = rsnd_io_to_mod_src(io);
-       struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
-       struct rsnd_mod *mod[MOD_MAX];
-       int i, index;
-
-
-       for (i = 0; i < MOD_MAX; i++)
-               mod[i] = NULL;
-
-       /*
-        * in play case...
-        *
-        * src -> dst
-        *
-        * mem -> SSI
-        * mem -> SRC -> SSI
-        * mem -> SRC -> DVC -> SSI
-        */
-       mod[0] = NULL; /* for "mem" */
-       index = 1;
-       for (i = 1; i < MOD_MAX; i++) {
-               if (!src) {
-                       mod[i] = ssi;
-               } else if (!dvc) {
-                       mod[i] = src;
-                       src = NULL;
-               } else {
-                       if ((!is_play) && (this == src))
-                               this = dvc;
-
-                       mod[i] = (is_play) ? src : dvc;
-                       i++;
-                       mod[i] = (is_play) ? dvc : src;
-                       src = NULL;
-                       dvc = NULL;
-               }
-
-               if (mod[i] == this)
-                       index = i;
-
-               if (mod[i] == ssi)
-                       break;
-       }
-
-       if (is_play) {
-               *mod_from = mod[index - 1];
-               *mod_to   = mod[index];
-       } else {
-               *mod_from = mod[index];
-               *mod_to   = mod[index - 1];
-       }
-}
-
-int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
-                 int is_play, int id)
-{
-       struct device *dev = rsnd_priv_to_dev(priv);
-       struct dma_slave_config cfg;
-       struct rsnd_mod *mod_from;
-       struct rsnd_mod *mod_to;
-       char dma_name[DMA_NAME_SIZE];
-       dma_cap_mask_t mask;
-       int ret;
-
-       if (dma->chan) {
-               dev_err(dev, "it already has dma channel\n");
-               return -EIO;
-       }
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-
-       rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to);
-       rsnd_dma_of_name(mod_from, mod_to, dma_name);
-
-       cfg.slave_id    = id;
-       cfg.direction   = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-       cfg.src_addr    = rsnd_gen_dma_addr(priv, mod_from, is_play, 1);
-       cfg.dst_addr    = rsnd_gen_dma_addr(priv, mod_to,   is_play, 0);
-       cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-
-       dev_dbg(dev, "dma : %s %pad -> %pad\n",
-               dma_name, &cfg.src_addr, &cfg.dst_addr);
-
-       dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
-                                                    (void *)id, dev,
-                                                    dma_name);
-       if (!dma->chan) {
-               dev_err(dev, "can't get dma channel\n");
-               goto rsnd_dma_channel_err;
-       }
-
-       ret = dmaengine_slave_config(dma->chan, &cfg);
-       if (ret < 0)
-               goto rsnd_dma_init_err;
-
-       dma->addr = is_play ? cfg.src_addr : cfg.dst_addr;
-       dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-
-       return 0;
-
-rsnd_dma_init_err:
-       rsnd_dma_quit(priv, dma);
-rsnd_dma_channel_err:
-
-       /*
-        * DMA failed. try to PIO mode
-        * see
-        *      rsnd_ssi_fallback()
-        *      rsnd_rdai_continuance_probe()
-        */
-       return -EAGAIN;
-}
-
-void  rsnd_dma_quit(struct rsnd_priv *priv,
-                   struct rsnd_dma *dma)
-{
-       if (dma->chan)
-               dma_release_channel(dma->chan);
-
-       dma->chan = NULL;
-}
-
 /*
  *     settting function
  */
@@ -429,7 +203,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 ({                                                             \
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);         \
        struct device *dev = rsnd_priv_to_dev(priv);            \
-       u32 mask = 1 << __rsnd_mod_shift_##func;                        \
+       u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \
        u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func;   \
        int ret = 0;                                                    \
        if ((mod->status & mask) == call) {                             \
@@ -471,7 +245,7 @@ static int rsnd_dai_connect(struct rsnd_mod *mod,
                struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
                struct device *dev = rsnd_priv_to_dev(priv);
 
-               dev_err(dev, "%s%d is not empty\n",
+               dev_err(dev, "%s[%d] is not empty\n",
                        rsnd_mod_name(mod),
                        rsnd_mod_id(mod));
                return -EIO;
@@ -887,20 +661,28 @@ static int rsnd_dai_probe(struct platform_device *pdev,
                drv[i].name     = rdai[i].name;
                drv[i].ops      = &rsnd_soc_dai_ops;
                if (pmod) {
+                       snprintf(rdai[i].playback.name, RSND_DAI_NAME_SIZE,
+                                "DAI%d Playback", i);
+
                        drv[i].playback.rates           = RSND_RATES;
                        drv[i].playback.formats         = RSND_FMTS;
                        drv[i].playback.channels_min    = 2;
                        drv[i].playback.channels_max    = 2;
+                       drv[i].playback.stream_name     = rdai[i].playback.name;
 
                        rdai[i].playback.info = &info->dai_info[i].playback;
                        rdai[i].playback.rdai = rdai + i;
                        rsnd_path_init(priv, &rdai[i], &rdai[i].playback);
                }
                if (cmod) {
+                       snprintf(rdai[i].capture.name, RSND_DAI_NAME_SIZE,
+                                "DAI%d Capture", i);
+
                        drv[i].capture.rates            = RSND_RATES;
                        drv[i].capture.formats          = RSND_FMTS;
                        drv[i].capture.channels_min     = 2;
                        drv[i].capture.channels_max     = 2;
+                       drv[i].capture.stream_name      = rdai[i].capture.name;
 
                        rdai[i].capture.info = &info->dai_info[i].capture;
                        rdai[i].capture.rdai = rdai + i;
@@ -946,6 +728,15 @@ static int rsnd_pcm_open(struct snd_pcm_substream *substream)
 static int rsnd_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
+       struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
+       struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+       struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
+       int ret;
+
+       ret = rsnd_dai_call(hw_params, io, substream, hw_params);
+       if (ret)
+               return ret;
+
        return snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
 }
@@ -1210,6 +1001,7 @@ static int rsnd_probe(struct platform_device *pdev)
                            const struct rsnd_of_data *of_data,
                            struct rsnd_priv *priv) = {
                rsnd_gen_probe,
+               rsnd_dma_probe,
                rsnd_ssi_probe,
                rsnd_src_probe,
                rsnd_dvc_probe,