[ Upstream commit c899df3e9b0bf7b76e642aed1a214582ea7012d5 ]

If playback and capture are enabled concurrently, when the capture stops
the output becomes inaudile. The playback application will become stuck
and underrun after a timeout.

This is caused by mistaken use of the stream_id, which should only be
set for playback and not for capture

Tested on Apollolake and Kabylake with SST driver.

Signed-off-by: Rander Wang <rander.w...@linux.intel.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.boss...@linux.intel.com>
Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 sound/soc/intel/skylake/skl-pcm.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/sound/soc/intel/skylake/skl-pcm.c 
b/sound/soc/intel/skylake/skl-pcm.c
index 823e39103edd3..6b2c8c6e7a00f 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -180,6 +180,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct 
skl_pipe_params *params)
        struct hdac_stream *hstream;
        struct hdac_ext_stream *stream;
        struct hdac_ext_link *link;
+       unsigned char stream_tag;
 
        hstream = snd_hdac_get_stream(bus, params->stream,
                                        params->link_dma_id + 1);
@@ -198,10 +199,13 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct 
skl_pipe_params *params)
 
        snd_hdac_ext_link_stream_setup(stream, format_val);
 
-       list_for_each_entry(link, &bus->hlink_list, list) {
-               if (link->index == params->link_index)
-                       snd_hdac_ext_link_set_stream_id(link,
-                                       hstream->stream_tag);
+       stream_tag = hstream->stream_tag;
+       if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               list_for_each_entry(link, &bus->hlink_list, list) {
+                       if (link->index == params->link_index)
+                               snd_hdac_ext_link_set_stream_id(link,
+                                                               stream_tag);
+               }
        }
 
        stream->link_prepared = 1;
@@ -640,6 +644,7 @@ static int skl_link_hw_free(struct snd_pcm_substream 
*substream,
        struct hdac_ext_stream *link_dev =
                                snd_soc_dai_get_dma_data(dai, substream);
        struct hdac_ext_link *link;
+       unsigned char stream_tag;
 
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
 
@@ -649,7 +654,11 @@ static int skl_link_hw_free(struct snd_pcm_substream 
*substream,
        if (!link)
                return -EINVAL;
 
-       snd_hdac_ext_link_clear_stream_id(link, 
hdac_stream(link_dev)->stream_tag);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               stream_tag = hdac_stream(link_dev)->stream_tag;
+               snd_hdac_ext_link_clear_stream_id(link, stream_tag);
+       }
+
        snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
        return 0;
 }
-- 
2.20.1



Reply via email to