-
Notifications
You must be signed in to change notification settings - Fork 140
Refactor pipeline management #5262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
85c69ce
d5ba315
524fcf2
12cdbf4
b47c706
3a625fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -211,9 +211,12 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, | |
| static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, | ||
| struct snd_soc_dai *cpu_dai) | ||
| { | ||
| struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); | ||
| const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); | ||
| struct hdac_ext_stream *hext_stream; | ||
| struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai); | ||
| struct snd_sof_widget *swidget = w->dobj.private; | ||
| int ret; | ||
|
|
||
| if (!ops) { | ||
| dev_err(cpu_dai->dev, "DAI widget ops not set\n"); | ||
|
|
@@ -222,9 +225,23 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, | |
|
|
||
| hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); | ||
| if (!hext_stream) | ||
| return 0; | ||
| goto free; | ||
|
|
||
| ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true); | ||
| if (ret < 0) | ||
| return ret; | ||
|
|
||
| free: | ||
| if (sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, substream->stream); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
|
|
||
| return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true); | ||
| if (sof_is_widget_pipeline_be_managed(w)) | ||
| snd_sof_unprepare_widgets_in_pipeline(w, swidget->spipe, substream->stream); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream, | ||
|
|
@@ -316,14 +333,31 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i | |
|
|
||
| switch (cmd) { | ||
| case SNDRV_PCM_TRIGGER_STOP: | ||
| ret = hda_link_dma_cleanup(substream, hext_stream, dai, false); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, "%s: failed to clean up link DMA during stop\n", | ||
| __func__); | ||
| return ret; | ||
| } | ||
| break; | ||
| case SNDRV_PCM_TRIGGER_SUSPEND: | ||
| ret = hda_link_dma_cleanup(substream, hext_stream, dai, | ||
| cmd == SNDRV_PCM_TRIGGER_STOP ? false : true); | ||
| { | ||
| struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); | ||
|
|
||
| ret = hda_link_dma_cleanup(substream, hext_stream, dai, true); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); | ||
| dev_err(sdev->dev, "%s: failed to clean up link DMA during suspend\n", | ||
| __func__); | ||
| return ret; | ||
| } | ||
|
|
||
| if (sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, substream->stream); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
| break; | ||
| } | ||
| default: | ||
| break; | ||
| } | ||
|
|
@@ -336,9 +370,33 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i | |
| static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) | ||
| { | ||
| struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); | ||
| const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); | ||
| struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); | ||
| struct snd_sof_widget *swidget = w->dobj.private; | ||
| struct snd_sof_dev *sdev = widget_to_sdev(w); | ||
| int stream = substream->stream; | ||
| int ret; | ||
|
|
||
| if (!ops) { | ||
| dev_err(sdev->dev, "DAI widget ops not set\n"); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| /* if this is a prepare without a hw_free or a suspend, free the BE pipeline */ | ||
| if (swidget->spipe->complete && sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, stream); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
|
|
||
| ret = hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any specific reason that we always call hw_params in .prepare?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because sometimes we dont have a hw_free like in the case of xruns and we'll need to do everything again.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prepare() should be fast. We should call this out in comments - we need to do X,Y out of cycle because Z |
||
| if (ret < 0) | ||
| return ret; | ||
|
|
||
| if (sof_is_widget_pipeline_be_managed(w)) | ||
| return snd_sof_set_up_be_pipeline(w, stream); | ||
|
|
||
| return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); | ||
| return 0; | ||
| } | ||
|
|
||
| static const struct snd_soc_dai_ops hda_dai_ops = { | ||
|
|
@@ -460,10 +518,27 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, | |
| static int non_hda_dai_prepare(struct snd_pcm_substream *substream, | ||
| struct snd_soc_dai *cpu_dai) | ||
| { | ||
| struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); | ||
| struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); | ||
| struct snd_sof_widget *swidget = w->dobj.private; | ||
| int stream = substream->stream; | ||
| int ret; | ||
|
|
||
| /* if this is a prepare without a hw_free or a suspend, free the BE pipeline */ | ||
| if (swidget->spipe->complete && sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, stream); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
|
|
||
| ret = non_hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); | ||
| if (ret < 0) | ||
| return ret; | ||
|
|
||
| if (sof_is_widget_pipeline_be_managed(w)) | ||
| return snd_sof_set_up_be_pipeline(w, stream); | ||
|
|
||
| return non_hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); | ||
| return 0; | ||
| } | ||
|
|
||
| static const struct snd_soc_dai_ops ssp_dai_ops = { | ||
|
|
@@ -638,6 +713,38 @@ int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |
| } | ||
| EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON"); | ||
|
|
||
| int sdw_hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, | ||
| struct snd_soc_dai *cpu_dai, int link_id, int intel_alh_id) | ||
| { | ||
| struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); | ||
| const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); | ||
| struct snd_sof_widget *swidget = w->dobj.private; | ||
| int stream = substream->stream; | ||
| int ret; | ||
|
|
||
| if (!ops) { | ||
| dev_err(cpu_dai->dev, "DAI widget ops not set\n"); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| /* if this is a prepare without a hw_free or a suspend, free the BE pipeline */ | ||
| if (swidget->spipe->complete && sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, stream); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
|
|
||
| ret = sdw_hda_dai_hw_params(substream, params, cpu_dai, link_id, intel_alh_id); | ||
| if (ret < 0) | ||
| return ret; | ||
|
|
||
| if (sof_is_widget_pipeline_be_managed(w)) | ||
| return snd_sof_set_up_be_pipeline(w, stream); | ||
|
|
||
| return 0; | ||
| } | ||
| EXPORT_SYMBOL_NS(sdw_hda_dai_prepare, "SND_SOC_SOF_INTEL_HDA_COMMON"); | ||
|
|
||
| static int hda_dai_suspend(struct hdac_bus *bus) | ||
| { | ||
| struct snd_soc_pcm_runtime *rtd; | ||
|
|
@@ -663,10 +770,11 @@ static int hda_dai_suspend(struct hdac_bus *bus) | |
| struct snd_soc_dai *cpu_dai; | ||
| struct snd_sof_dev *sdev; | ||
| struct snd_sof_dai *sdai; | ||
| int dir = s->direction; | ||
|
|
||
| rtd = snd_soc_substream_to_rtd(hext_stream->link_substream); | ||
| cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); | ||
| w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); | ||
| w = snd_soc_dai_get_widget(cpu_dai, dir); | ||
| swidget = w->dobj.private; | ||
| sdev = widget_to_sdev(w); | ||
| sdai = swidget->private; | ||
|
|
@@ -689,6 +797,12 @@ static int hda_dai_suspend(struct hdac_bus *bus) | |
| hext_stream, cpu_dai, true); | ||
| if (ret < 0) | ||
| return ret; | ||
|
|
||
| if (sof_is_widget_pipeline_be_managed(w)) { | ||
| ret = snd_sof_free_be_pipeline(w, dir); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.