ASoC:intel:skl:fix a simultaneous playback & capture issue on hda platform

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.wang@linux.intel.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Rander Wang 2019-03-08 16:38:59 +08:00 committed by Mark Brown
parent 03d0aa4d4f
commit c899df3e9b
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0

View file

@ -181,6 +181,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);
@ -199,10 +200,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;
@ -645,6 +649,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);
@ -654,7 +659,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;
}