diff options
Diffstat (limited to 'sound/soc/sof/ipc3-topology.c')
| -rw-r--r-- | sound/soc/sof/ipc3-topology.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index be61e377e59e..f449362a2905 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -20,6 +20,9 @@ /* size of tplg ABI in bytes */ #define SOF_IPC3_TPLG_ABI_SIZE 3 +/* Base of SOF_DAI_INTEL_ALH, this should be aligned with SOC_SDW_INTEL_BIDIR_PDI_BASE */ +#define INTEL_ALH_DAI_INDEX_BASE 2 + struct sof_widget_data { int ctrl_type; int ipc_cmd; @@ -1585,14 +1588,26 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*comp_dai), 1); if (ret < 0) - goto free; + goto free_comp; /* update comp_tokens */ ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(comp_dai->config), 1); if (ret < 0) - goto free; + goto free_comp; + + /* Subtract the base to match the FW dai index. */ + if (comp_dai->type == SOF_DAI_INTEL_ALH) { + if (comp_dai->dai_index < INTEL_ALH_DAI_INDEX_BASE) { + dev_err(sdev->dev, + "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n", + comp_dai->dai_index, INTEL_ALH_DAI_INDEX_BASE); + ret = -EINVAL; + goto free_comp; + } + comp_dai->dai_index -= INTEL_ALH_DAI_INDEX_BASE; + } dev_dbg(scomp->dev, "dai %s: type %d index %d\n", swidget->widget->name, comp_dai->type, comp_dai->dai_index); @@ -2167,8 +2182,16 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * case SOF_DAI_INTEL_ALH: if (data) { /* save the dai_index during hw_params and reuse it for hw_free */ - if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) - config->dai_index = data->dai_index; + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { + /* Subtract the base to match the FW dai index. */ + if (data->dai_index < INTEL_ALH_DAI_INDEX_BASE) { + dev_err(sdev->dev, + "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n", + config->dai_index, INTEL_ALH_DAI_INDEX_BASE); + return -EINVAL; + } + config->dai_index = data->dai_index - INTEL_ALH_DAI_INDEX_BASE; + } config->alh.stream_id = data->dai_data; } break; @@ -2363,28 +2386,16 @@ static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) { struct snd_sof_widget *swidget; - struct snd_sof_pcm *spcm; - int dir, ret; + int ret; /* * free all PCMs and their associated DAPM widgets if their connected DAPM widget * list is not NULL. This should only be true for paused streams at this point. * This is equivalent to the handling of FE DAI suspend trigger for running streams. */ - list_for_each_entry(spcm, &sdev->pcm_list, list) { - for_each_pcm_streams(dir) { - struct snd_pcm_substream *substream = spcm->stream[dir].substream; - - if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored) - continue; - - if (spcm->stream[dir].list) { - ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); - if (ret < 0) - return ret; - } - } - } + ret = sof_pcm_free_all_streams(sdev); + if (ret) + return ret; /* * free any left over DAI widgets. This is equivalent to the handling of suspend trigger @@ -2462,11 +2473,6 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif if (ret < 0) return ret; - /* free all the scheduler widgets now */ - ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); - if (ret < 0) - return ret; - /* * Tear down all pipelines associated with PCMs that did not get suspended * and unset the prepare flag so that they can be set up again during resume. @@ -2482,6 +2488,11 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif } } + /* free all the scheduler widgets now. This will also power down the secondary cores */ + ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); + if (ret < 0) + return ret; + list_for_each_entry(sroute, &sdev->route_list, list) sroute->setup = false; |
