diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 2cc11d8b0f7080..3fb118c9e6207d 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -58,7 +58,7 @@ hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size, struct hdac_stream *hstream; int ret; - hext_stream = hda_dsp_stream_get(sdev, direction, 0); + hext_stream = hda_dsp_stream_get(sdev, direction, 0, HDA_STREAM_USE_HOST_LINK_DMA); if (!hext_stream) { dev_err(sdev->dev, "error: no stream available\n"); @@ -110,7 +110,7 @@ hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size, hstream->bufsize = 0; hstream->format_val = 0; out_put: - hda_dsp_stream_put(sdev, direction, hstream->stream_tag); + hda_dsp_stream_put(sdev, direction, hstream->stream_tag, HDA_STREAM_USE_HOST_LINK_DMA); return ERR_PTR(ret); } EXPORT_SYMBOL_NS(hda_cl_prepare, "SND_SOC_SOF_INTEL_HDA_COMMON"); @@ -286,7 +286,8 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_SD_CTL_DMA_START, 0); - hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag); + hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag, + HDA_STREAM_USE_HOST_LINK_DMA); hstream->running = 0; hstream->substream = NULL; diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 1dd8d2092c3b4f..a517b63ddeac44 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -260,7 +260,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, spcm->stream[substream->stream].d0i3_compatible) flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE; - dsp_stream = hda_dsp_stream_get(sdev, direction, flags); + dsp_stream = hda_dsp_stream_get(sdev, direction, flags, HDA_STREAM_USE_HOST_DMA); if (!dsp_stream) { dev_err(sdev->dev, "error: no stream available\n"); return -ENODEV; @@ -326,7 +326,7 @@ int hda_dsp_pcm_close(struct snd_sof_dev *sdev, int direction = substream->stream; int ret; - ret = hda_dsp_stream_put(sdev, direction, hstream->stream_tag); + ret = hda_dsp_stream_put(sdev, direction, hstream->stream_tag, HDA_STREAM_USE_HOST_DMA); if (ret) { dev_dbg(sdev->dev, "stream %s not opened!\n", substream->name); diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index b06933cebc4547..4db6cf4423de24 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -32,7 +32,7 @@ static int hda_probes_compr_startup(struct sof_client_dev *cdev, struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); struct hdac_ext_stream *hext_stream; - hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0); + hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0, HDA_STREAM_USE_HOST_DMA); if (!hext_stream) return -EBUSY; @@ -54,7 +54,7 @@ static int hda_probes_compr_shutdown(struct sof_client_dev *cdev, int ret; ret = hda_dsp_stream_put(sdev, cstream->direction, - hdac_stream(hext_stream)->stream_tag); + hdac_stream(hext_stream)->stream_tag, HDA_STREAM_USE_HOST_DMA); if (ret < 0) { dev_dbg(sdev->dev, "stream put failed: %d\n", ret); return ret; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 9c3b3a9aaf83c9..7efdced83a105f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -211,7 +211,8 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, /* get next unused stream */ struct hdac_ext_stream * -hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) +hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags, + enum sof_hda_stream_type type) { const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; @@ -233,7 +234,14 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) if (hda_stream->host_reserved) continue; + /* check if the link stream is available if the link dma is used */ + if (type == HDA_STREAM_USE_HOST_LINK_DMA && hext_stream->link_locked) + continue; + s->opened = true; + if (type == HDA_STREAM_USE_HOST_LINK_DMA) + hext_stream->link_locked = true; + break; } } @@ -265,13 +273,15 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) } /* free a stream */ -int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) +int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag, + enum sof_hda_stream_type type) { const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *hext_stream; + struct hdac_ext_stream *link_stream; struct hdac_stream *s; bool dmi_l1_enable = true; bool found = false; @@ -292,6 +302,10 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) if (s->direction == direction && s->stream_tag == stream_tag) { s->opened = false; found = true; + + if (type == HDA_STREAM_USE_HOST_LINK_DMA) + link_stream = hext_stream; + } else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { dmi_l1_enable = false; } @@ -312,6 +326,9 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) return -ENODEV; } + if (type == HDA_STREAM_USE_HOST_LINK_DMA) + snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK); + return 0; } diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 5da8188ffcfe1f..6439dcab3e5f84 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -43,7 +43,8 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, int ret; hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE, - SOF_HDA_STREAM_DMI_L1_COMPATIBLE); + SOF_HDA_STREAM_DMI_L1_COMPATIBLE, + HDA_STREAM_USE_HOST_DMA); if (!hda->dtrace_stream) { dev_err(sdev->dev, @@ -61,7 +62,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, if (ret < 0) { dev_err(sdev->dev, "error: hdac trace init failed: %d\n", ret); hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_CAPTURE, - dtrace_params->stream_tag); + dtrace_params->stream_tag, HDA_STREAM_USE_HOST_DMA); hda->dtrace_stream = NULL; dtrace_params->stream_tag = 0; } @@ -79,7 +80,7 @@ int hda_dsp_trace_release(struct snd_sof_dev *sdev) hstream = &hda->dtrace_stream->hstream; hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_CAPTURE, - hstream->stream_tag); + hstream->stream_tag, HDA_STREAM_USE_HOST_DMA); hda->dtrace_stream = NULL; return 0; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 562fe8be79c1e3..bcedcd29f47007 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -487,6 +487,11 @@ enum sof_hda_D0_substate { SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */ }; +enum sof_hda_stream_type { + HDA_STREAM_USE_HOST_DMA, + HDA_STREAM_USE_HOST_LINK_DMA, +}; + struct sof_ace3_mic_privacy { bool active; struct work_struct work; @@ -693,8 +698,10 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); struct hdac_ext_stream * - hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags); -int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag); + hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags, + enum sof_hda_stream_type type); +int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag, + enum sof_hda_stream_type type); int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, int enable, u32 size);