Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / sound / soc / intel / skylake / skl-pcm.c
index 6c6b63a6b338f50f0eb218f231506f0017e56241..e12520e142ff5306e926e644e95bf3f81c5d2903 100644 (file)
@@ -137,6 +137,80 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream,
                skl->supend_active--;
 }
 
+int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       unsigned int format_val;
+       struct hdac_stream *hstream;
+       struct hdac_ext_stream *stream;
+       int err;
+
+       hstream = snd_hdac_get_stream(bus, params->stream,
+                                       params->host_dma_id + 1);
+       if (!hstream)
+               return -EINVAL;
+
+       stream = stream_to_hdac_ext_stream(hstream);
+       snd_hdac_ext_stream_decouple(ebus, stream, true);
+
+       format_val = snd_hdac_calc_stream_format(params->s_freq,
+                               params->ch, params->format, 32, 0);
+
+       dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
+               format_val, params->s_freq, params->ch, params->format);
+
+       snd_hdac_stream_reset(hdac_stream(stream));
+       err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
+       if (err < 0)
+               return err;
+
+       err = snd_hdac_stream_setup(hdac_stream(stream));
+       if (err < 0)
+               return err;
+
+       hdac_stream(stream)->prepared = 1;
+
+       return 0;
+}
+
+int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       unsigned int format_val;
+       struct hdac_stream *hstream;
+       struct hdac_ext_stream *stream;
+       struct hdac_ext_link *link;
+
+       hstream = snd_hdac_get_stream(bus, params->stream,
+                                       params->link_dma_id + 1);
+       if (!hstream)
+               return -EINVAL;
+
+       stream = stream_to_hdac_ext_stream(hstream);
+       snd_hdac_ext_stream_decouple(ebus, stream, true);
+       format_val = snd_hdac_calc_stream_format(params->s_freq,
+                               params->ch, params->format, 24, 0);
+
+       dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
+               format_val, params->s_freq, params->ch, params->format);
+
+       snd_hdac_ext_link_stream_reset(stream);
+
+       snd_hdac_ext_link_stream_setup(stream, format_val);
+
+       list_for_each_entry(link, &ebus->hlink_list, list) {
+               if (link->index == params->link_index)
+                       snd_hdac_ext_link_set_stream_id(link,
+                                       hstream->stream_tag);
+       }
+
+       stream->link_prepared = 1;
+
+       return 0;
+}
+
 static int skl_pcm_open(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -188,32 +262,6 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int skl_get_format(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct skl_dma_params *dma_params;
-       struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
-       int format_val = 0;
-
-       if ((ebus_to_hbus(ebus))->ppcap) {
-               struct snd_pcm_runtime *runtime = substream->runtime;
-
-               format_val = snd_hdac_calc_stream_format(runtime->rate,
-                                               runtime->channels,
-                                               runtime->format,
-                                               32, 0);
-       } else {
-               struct snd_soc_dai *codec_dai = rtd->codec_dai;
-
-               dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
-               if (dma_params)
-                       format_val = dma_params->format;
-       }
-
-       return format_val;
-}
-
 static int skl_be_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -234,37 +282,19 @@ static int skl_be_prepare(struct snd_pcm_substream *substream,
 static int skl_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
        struct skl *skl = get_skl_ctx(dai->dev);
-       unsigned int format_val;
-       int err;
        struct skl_module_cfg *mconfig;
 
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
 
        mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
 
-       format_val = skl_get_format(substream, dai);
-       dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
-                               hdac_stream(stream)->stream_tag, format_val);
-       snd_hdac_stream_reset(hdac_stream(stream));
-
        /* In case of XRUN recovery, reset the FW pipe to clean state */
        if (mconfig && (substream->runtime->status->state ==
                                        SNDRV_PCM_STATE_XRUN))
                skl_reset_pipe(skl->skl_sst, mconfig->pipe);
 
-       err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
-       if (err < 0)
-               return err;
-
-       err = snd_hdac_stream_setup(hdac_stream(stream));
-       if (err < 0)
-               return err;
-
-       hdac_stream(stream)->prepared = 1;
-
-       return err;
+       return 0;
 }
 
 static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -295,6 +325,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
        p_params.s_freq = params_rate(params);
        p_params.host_dma_id = dma_id;
        p_params.stream = substream->stream;
+       p_params.format = params_format(params);
 
        m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
        if (m_cfg)
@@ -438,7 +469,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
                if (!w->ignore_suspend) {
-                       skl_pcm_prepare(substream, dai);
                        /*
                         * enable DMA Resume enable bit for the stream, set the
                         * dpib & lpib position to resume before starting the
@@ -447,7 +477,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                        snd_hdac_ext_stream_drsm_enable(ebus, true,
                                                hdac_stream(stream)->index);
                        snd_hdac_ext_stream_set_dpibr(ebus, stream,
-                                                       stream->dpib);
+                                                       stream->lpib);
                        snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
                }
 
@@ -459,7 +489,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                 * pipeline is started but there is a delay in starting the
                 * DMA channel on the host.
                 */
-               snd_hdac_ext_stream_decouple(ebus, stream, true);
                ret = skl_decoupled_trigger(substream, cmd);
                if (ret < 0)
                        return ret;
@@ -506,9 +535,10 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
        struct hdac_ext_stream *link_dev;
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct hdac_ext_dma_params *dma_params;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct skl_pipe_params p_params = {0};
+       struct hdac_ext_link *link;
+       int stream_tag;
 
        link_dev = snd_hdac_ext_stream_assign(ebus, substream,
                                        HDAC_EXT_STREAM_TYPE_LINK);
@@ -517,16 +547,22 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
 
        snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
 
+       link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
+       if (!link)
+               return -EINVAL;
+
+       stream_tag = hdac_stream(link_dev)->stream_tag;
+
        /* set the stream tag in the codec dai dma params  */
-       dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
-       if (dma_params)
-               dma_params->stream_tag =  hdac_stream(link_dev)->stream_tag;
+       snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0);
 
        p_params.s_fmt = snd_pcm_format_width(params_format(params));
        p_params.ch = params_channels(params);
        p_params.s_freq = params_rate(params);
        p_params.stream = substream->stream;
-       p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1;
+       p_params.link_dma_id = stream_tag - 1;
+       p_params.link_index = link->index;
+       p_params.format = params_format(params);
 
        return skl_tplg_be_update_params(dai, &p_params);
 }
@@ -534,41 +570,15 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
 static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
-       struct hdac_ext_stream *link_dev =
-                       snd_soc_dai_get_dma_data(dai, substream);
-       unsigned int format_val = 0;
-       struct skl_dma_params *dma_params;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct hdac_ext_link *link;
        struct skl *skl = get_skl_ctx(dai->dev);
        struct skl_module_cfg *mconfig = NULL;
 
-       dma_params  = (struct skl_dma_params *)
-                       snd_soc_dai_get_dma_data(codec_dai, substream);
-       if (dma_params)
-               format_val = dma_params->format;
-       dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
-                       hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
-
-       link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
-       if (!link)
-               return -EINVAL;
-
-       snd_hdac_ext_link_stream_reset(link_dev);
-
        /* In case of XRUN recovery, reset the FW pipe to clean state */
        mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
-       if (mconfig && (substream->runtime->status->state ==
-                                       SNDRV_PCM_STATE_XRUN))
+       if (mconfig && !mconfig->pipe->passthru &&
+               (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN))
                skl_reset_pipe(skl->skl_sst, mconfig->pipe);
 
-       snd_hdac_ext_link_stream_setup(link_dev, format_val);
-
-       snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
-       link_dev->link_prepared = 1;
-
        return 0;
 }
 
@@ -583,10 +593,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
        dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
-               skl_link_pcm_prepare(substream, dai);
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               snd_hdac_ext_stream_decouple(ebus, stream, true);
                snd_hdac_ext_link_stream_start(link_dev);
                break;