diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index de40a5e227f4c8..5099e49151242c 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -45,6 +45,7 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + struct snd_sof_pipeline *spipe = swidget->spipe; struct snd_sof_widget *pipe_widget; int err = 0; int ret; @@ -85,16 +86,21 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, err = ret; } - /* - * disable widget core. continue to route setup status and complete flag - * even if this fails and return the appropriate error - */ - ret = snd_sof_dsp_core_put(sdev, swidget->core); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n", - swidget->core, swidget->widget->name); - if (!err) - err = ret; + /* disable cores associated with all modules in the pipeline and clear the complete flag */ + if (swidget->id == snd_soc_dapm_scheduler) { + int i; + + for (i = 0; i < sdev->num_cores; i++) { + if (!(spipe->core_mask & BIT(i))) + continue; + + ret = snd_sof_dsp_core_put(sdev, i); + dev_err(sdev->dev, "error: failed to disable target core: %d for pipeline %s\n", + i, swidget->widget->name); + if (!err) + err = ret; + } + swidget->spipe->complete = 0; } /* @@ -107,10 +113,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, err = ret; } - /* clear pipeline complete */ - if (swidget->id == snd_soc_dapm_scheduler) - swidget->spipe->complete = 0; - if (!err) dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name); @@ -133,8 +135,10 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + struct snd_sof_pipeline *spipe = swidget->spipe; bool use_count_decremented = false; int ret; + int i; /* skip if there is no private data */ if (!swidget->private) @@ -165,19 +169,26 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, goto use_count_dec; } - /* enable widget core */ - ret = snd_sof_dsp_core_get(sdev, swidget->core); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to enable target core for widget %s\n", - swidget->widget->name); - goto pipe_widget_free; + /* enabled cores associated with all modules in a pipeline */ + if (swidget->id == snd_soc_dapm_scheduler) { + for (i = 0; i < sdev->num_cores; i++) { + if (!(spipe->core_mask & BIT(i))) + continue; + + ret = snd_sof_dsp_core_get(sdev, i); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to enable target core %d for pipeline %s\n", + i, swidget->widget->name); + goto pipe_widget_free; + } + } } /* setup widget in the DSP */ if (tplg_ops && tplg_ops->widget_setup) { ret = tplg_ops->widget_setup(sdev, swidget); if (ret < 0) - goto core_put; + goto pipe_widget_free; } /* send config for DAI components */ @@ -207,15 +218,20 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, return 0; widget_free: - /* widget use_count and core ref_count will both be decremented by sof_widget_free() */ + /* widget use_count will be decremented by sof_widget_free() */ sof_widget_free_unlocked(sdev, swidget); use_count_decremented = true; -core_put: - if (!use_count_decremented) - snd_sof_dsp_core_put(sdev, swidget->core); pipe_widget_free: - if (swidget->id != snd_soc_dapm_scheduler) + if (swidget->id != snd_soc_dapm_scheduler) { sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); + } else { + int j; + + /* free all enabled cores */ + for (j = 0; j < i; j++) + if (spipe->core_mask & BIT(j)) + snd_sof_dsp_core_put(sdev, j); + } use_count_dec: if (!use_count_decremented) swidget->use_count--;