Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,12 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,

memset(&pcm_substream, 0, sizeof(pcm_substream));
if (substream) {
link_dev = snd_soc_dai_get_dma_data(dai, substream);
hstream = substream->runtime->private_data;
bus = hstream->bus;
rtd = snd_pcm_substream_chip(substream);
link_dev = snd_soc_dai_get_dma_data(dai, substream);
snd_hdac_ext_stream_decouple(bus, link_dev, false);
name = rtd->codec_dai->component->name;
bus = hstream->bus;

link = snd_hdac_ext_bus_get_link(bus, name);
if (!link)
return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/intel/hda-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
return -EINVAL;
}

dsp_stream = hda_dsp_stream_get(sdev, direction);
dsp_stream = hda_dsp_stream_get(sdev, NULL, direction);

if (!dsp_stream) {
dev_err(sdev->dev, "error: no stream available\n");
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/intel/hda-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
struct hdac_ext_stream *dsp_stream;
int direction = substream->stream;

dsp_stream = hda_dsp_stream_get(sdev, direction);
dsp_stream = hda_dsp_stream_get(sdev, substream, direction);

if (!dsp_stream) {
dev_err(sdev->dev, "error: no stream available\n");
Expand Down
60 changes: 58 additions & 2 deletions sound/soc/sof/intel/hda-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,75 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
return 0;
}

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/*
* return 1 for two cases
* (1) for a free host stream, check whether the matched
* (with the same stream tag number) link stream is free.
* (2) if the matched link stream is used, check whether
* this is used by one BE of this FE pcm.
*/
static int check_link_stream(struct snd_pcm_substream *substream,
struct hdac_stream *hstream)
{
struct snd_soc_pcm_runtime *fe = substream->private_data;
int direction = substream->stream;
struct snd_soc_pcm_runtime *be_rtd;
struct hdac_ext_stream *link_dev;
struct hdac_ext_stream *stream;
struct snd_soc_dai *cpu_dai;
struct snd_soc_dpcm *dpcm;

stream = stream_to_hdac_ext_stream(hstream);

/* this link stream is free */
if (!stream->link_locked)
return 1;

for_each_dpcm_be(fe, direction, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
struct snd_pcm_substream *be_substream =
snd_soc_dpcm_get_substream(be, direction);

if (!be_substream)
continue;

if (be->dpcm[direction].state != SND_SOC_DPCM_STATE_OPEN)
continue;

be_rtd = be_substream->private_data;
cpu_dai = be_rtd->cpu_dai;
link_dev = snd_soc_dai_get_dma_data(cpu_dai, substream);

/* one BE of this FE uses the same stream tag as this FE */
if (link_dev && hstream->stream_tag ==
hdac_stream(link_dev)->stream_tag)
return 1;
}

return 0;
}
#endif

/* get next unused stream */
struct hdac_ext_stream *
hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
hda_dsp_stream_get(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
int direction)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct hdac_ext_stream *stream = NULL;
struct hdac_stream *s;

spin_lock_irq(&bus->reg_lock);

/* get an unused stream */
list_for_each_entry(s, &bus->stream_list, list) {
if (s->direction == direction && !s->opened) {
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
if (substream &&
!check_link_stream(substream, s))
continue;
#endif
s->opened = true;
stream = stream_to_hdac_ext_stream(s);
break;
Expand Down
14 changes: 11 additions & 3 deletions sound/soc/sof/intel/hda-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,25 @@ static int hda_dsp_trace_prepare(struct snd_sof_dev *sdev)
int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
struct hdac_bus *bus = sof_to_bus(sdev);
struct hdac_stream *hstream = NULL;
int ret;

hda->dtrace_stream = hda_dsp_stream_get(sdev,
SNDRV_PCM_STREAM_CAPTURE);
/* dma trace uses the last stream */
list_for_each_entry_reverse(hstream, &bus->stream_list, list) {
if (hstream->direction == SNDRV_PCM_STREAM_CAPTURE) {
hstream->opened = true;
break;
}
}

if (!hda->dtrace_stream) {
if (!hstream) {
dev_err(sdev->dev,
"error: no available capture stream for DMA trace\n");
return -ENODEV;
}

hda->dtrace_stream = stream_to_hdac_ext_stream(hstream);
*stream_tag = hda->dtrace_stream->hstream.stream_tag;

/*
Expand Down
4 changes: 3 additions & 1 deletion sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,9 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
struct hdac_stream *stream);

struct hdac_ext_stream *
hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction);
hda_dsp_stream_get(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
int direction);
int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
struct hdac_ext_stream *stream,
Expand Down