Merge remote-tracking branch 'asoc/topic/mxs' into asoc-next
[linux-block.git] / sound / soc / mxs / mxs-saif.c
index 14152f6f70ddccaada89a26176c6b9437e814b06..54e622acac330d82a92d95164ae79e89cfb461e4 100644 (file)
@@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
        struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
        struct mxs_saif *master_saif;
        u32 delay;
+       int ret;
 
        master_saif = mxs_saif_get_master(saif);
        if (!master_saif)
@@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (saif->state == MXS_SAIF_STATE_RUNNING)
+                       return 0;
+
                dev_dbg(cpu_dai->dev, "start\n");
 
-               clk_enable(master_saif->clk);
-               if (!master_saif->mclk_in_use)
-                       __raw_writel(BM_SAIF_CTRL_RUN,
-                               master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+               ret = clk_enable(master_saif->clk);
+               if (ret) {
+                       dev_err(saif->dev, "Failed to enable master clock\n");
+                       return ret;
+               }
 
                /*
                 * If the saif's master is not himself, we also need to enable
                 * itself clk for its internal basic logic to work.
                 */
                if (saif != master_saif) {
-                       clk_enable(saif->clk);
+                       ret = clk_enable(saif->clk);
+                       if (ret) {
+                               dev_err(saif->dev, "Failed to enable master clock\n");
+                               clk_disable(master_saif->clk);
+                               return ret;
+                       }
+
                        __raw_writel(BM_SAIF_CTRL_RUN,
                                saif->base + SAIF_CTRL + MXS_SET_ADDR);
                }
 
+               if (!master_saif->mclk_in_use)
+                       __raw_writel(BM_SAIF_CTRL_RUN,
+                               master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
                         * write data to saif data register to trigger
@@ -543,6 +558,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
                }
 
                master_saif->ongoing = 1;
+               saif->state = MXS_SAIF_STATE_RUNNING;
 
                dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
                        __raw_readl(saif->base + SAIF_CTRL),
@@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (saif->state == MXS_SAIF_STATE_STOPPED)
+                       return 0;
+
                dev_dbg(cpu_dai->dev, "stop\n");
 
                /* wait a while for the current sample to complete */
@@ -575,6 +594,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
                }
 
                master_saif->ongoing = 0;
+               saif->state = MXS_SAIF_STATE_STOPPED;
 
                break;
        default: