ASoC: rsnd: adds struct rsnd_dai_stream as on each fuction as parameter
[deliverable/linux.git] / sound / soc / sh / rcar / core.c
index 9f48d75fa992351adffef3d834620e7d2682354e..54297d74ea1ff6df14249299f394c02792fc8f91 100644 (file)
@@ -145,7 +145,8 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod)
        return mod->ops->dma_req(mod);
 }
 
-int rsnd_mod_init(struct rsnd_mod *mod,
+int rsnd_mod_init(struct rsnd_priv *priv,
+                 struct rsnd_mod *mod,
                   struct rsnd_mod_ops *ops,
                   struct clk *clk,
                   enum rsnd_mod_type type,
@@ -160,6 +161,7 @@ int rsnd_mod_init(struct rsnd_mod *mod,
        mod->ops        = ops;
        mod->type       = type;
        mod->clk        = clk;
+       mod->priv       = priv;
 
        return ret;
 }
@@ -170,6 +172,14 @@ void rsnd_mod_quit(struct rsnd_mod *mod)
                clk_unprepare(mod->clk);
 }
 
+int rsnd_mod_is_working(struct rsnd_mod *mod)
+{
+       struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+
+       /* see rsnd_dai_stream_init/quit() */
+       return !!io->substream;
+}
+
 /*
  *     settting function
  */
@@ -199,26 +209,31 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 /*
  *     rsnd_dai functions
  */
-#define __rsnd_mod_call(mod, func, param...)                   \
+#define __rsnd_mod_call(mod, io, func, param...)               \
 ({                                                             \
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);         \
        struct device *dev = rsnd_priv_to_dev(priv);            \
-       u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \
-       u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func;   \
+       u32 mask = 0xF << __rsnd_mod_shift_##func;                      \
+       u8 val  = (mod->status >> __rsnd_mod_shift_##func) & 0xF;       \
+       u8 add  = ((val + __rsnd_mod_add_##func) & 0xF);                \
        int ret = 0;                                                    \
-       if ((mod->status & mask) == call) {                             \
-               dev_dbg(dev, "%s[%d] %s\n",                             \
-                       rsnd_mod_name(mod), rsnd_mod_id(mod), #func);   \
-               ret = (mod)->ops->func(mod, param);                     \
-               mod->status = (mod->status & ~mask) | (~call & mask);   \
+       int called = 0;                                                 \
+       if (val == __rsnd_mod_call_##func) {                            \
+               called = 1;                                             \
+               ret = (mod)->ops->func(mod, io, param);                 \
+               mod->status = (mod->status & ~mask) +                   \
+                       (add << __rsnd_mod_shift_##func);               \
        }                                                               \
+       dev_dbg(dev, "%s[%d] 0x%08x %s\n",                              \
+               rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status,      \
+               called ? #func : "");                                   \
        ret;                                                            \
 })
 
-#define rsnd_mod_call(mod, func, param...)     \
+#define rsnd_mod_call(mod, io, func, param...) \
        (!(mod) ? -ENODEV :                     \
         !((mod)->ops->func) ? 0 :              \
-        __rsnd_mod_call(mod, func, param))
+        __rsnd_mod_call(mod, io, func, param))
 
 #define rsnd_dai_call(fn, io, param...)                                \
 ({                                                             \
@@ -228,7 +243,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
                mod = (io)->mod[i];                             \
                if (!mod)                                       \
                        continue;                               \
-               ret = rsnd_mod_call(mod, fn, param);            \
+               ret = rsnd_mod_call(mod, io, fn, param);        \
                if (ret < 0)                                    \
                        break;                                  \
        }                                                       \
@@ -272,9 +287,10 @@ struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
        return priv->rdai + id;
 }
 
+#define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai)
 static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
 {
-       struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
+       struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
 
        return rsnd_rdai_get(priv, dai->id);
 }
@@ -293,7 +309,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional)
        return pos;
 }
 
-void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
+bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
 {
        io->byte_pos += byte;
 
@@ -310,11 +326,27 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
                        io->next_period_byte = io->byte_per_period;
                }
 
-               snd_pcm_period_elapsed(substream);
+               return true;
        }
+
+       return false;
 }
 
-static int rsnd_dai_stream_init(struct rsnd_dai_stream *io,
+void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io)
+{
+       struct snd_pcm_substream *substream = io->substream;
+
+       /*
+        * this function should be called...
+        *
+        * - if rsnd_dai_pointer_update() returns true
+        * - without spin lock
+        */
+
+       snd_pcm_period_elapsed(substream);
+}
+
+static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
                                struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -326,8 +358,11 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io,
                                  runtime->channels *
                                  samples_to_bytes(runtime, 1);
        io->next_period_byte    = io->byte_per_period;
+}
 
-       return 0;
+static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io)
+{
+       io->substream           = NULL;
 }
 
 static
@@ -351,20 +386,18 @@ struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
 static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
                            struct snd_soc_dai *dai)
 {
-       struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
+       struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
        struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
        struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
        int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io));
        int ret;
        unsigned long flags;
 
-       rsnd_lock(priv, flags);
+       spin_lock_irqsave(&priv->lock, flags);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               ret = rsnd_dai_stream_init(io, substream);
-               if (ret < 0)
-                       goto dai_trigger_end;
+               rsnd_dai_stream_init(io, substream);
 
                ret = rsnd_platform_call(priv, dai, start, ssi_id);
                if (ret < 0)
@@ -390,13 +423,15 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
                ret = rsnd_platform_call(priv, dai, stop, ssi_id);
                if (ret < 0)
                        goto dai_trigger_end;
+
+               rsnd_dai_stream_quit(io);
                break;
        default:
                ret = -EINVAL;
        }
 
 dai_trigger_end:
-       rsnd_unlock(priv, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        return ret;
 }
@@ -833,12 +868,14 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
                            struct rsnd_kctrl_cfg *cfg,
                            void (*update)(struct rsnd_mod *mod))
 {
+       struct snd_soc_card *soc_card = rtd->card;
        struct snd_card *card = rtd->card->snd_card;
        struct snd_kcontrol *kctrl;
        struct snd_kcontrol_new knew = {
                .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name           = name,
                .info           = rsnd_kctrl_info,
+               .index          = rtd - soc_card->rtd,
                .get            = rsnd_kctrl_get,
                .put            = rsnd_kctrl_put,
                .private_value  = (unsigned long)cfg,
This page took 0.026583 seconds and 5 git commands to generate.