diff options
-rw-r--r-- | sound/soc/sof/control.c | 44 | ||||
-rw-r--r-- | sound/soc/sof/pcm.c | 18 | ||||
-rw-r--r-- | sound/soc/sof/pm.c | 12 | ||||
-rw-r--r-- | sound/soc/sof/sof-audio.c | 57 | ||||
-rw-r--r-- | sound/soc/sof/sof-audio.h | 6 | ||||
-rw-r--r-- | sound/soc/sof/sof-priv.h | 6 | ||||
-rw-r--r-- | sound/soc/sof/topology.c | 91 | ||||
-rw-r--r-- | sound/soc/sof/trace.c | 8 |
8 files changed, 138 insertions, 104 deletions
diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index e0e9efd25d34..75e13f4fd1eb 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -22,9 +22,9 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->volume_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_get) return tplg_ops->control->volume_get(scontrol, ucontrol); return 0; @@ -37,9 +37,9 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->volume_put) + if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_put) return tplg_ops->control->volume_put(scontrol, ucontrol); return false; @@ -74,9 +74,9 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->switch_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_get) return tplg_ops->control->switch_get(scontrol, ucontrol); return 0; @@ -89,9 +89,9 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->switch_put) + if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_put) return tplg_ops->control->switch_put(scontrol, ucontrol); return false; @@ -104,9 +104,9 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = se->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->enum_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_get) return tplg_ops->control->enum_get(scontrol, ucontrol); return 0; @@ -119,9 +119,9 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = se->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->enum_put) + if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_put) return tplg_ops->control->enum_put(scontrol, ucontrol); return false; @@ -134,9 +134,9 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->bytes_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_get) return tplg_ops->control->bytes_get(scontrol, ucontrol); return 0; @@ -149,9 +149,9 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->bytes_put) + if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_put) return tplg_ops->control->bytes_put(scontrol, ucontrol); return 0; @@ -165,13 +165,13 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); /* make sure we have at least a header */ if (size < sizeof(struct snd_ctl_tlv)) return -EINVAL; - if (tplg_ops->control->bytes_ext_put) + if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_put) return tplg_ops->control->bytes_ext_put(scontrol, binary_data, size); return 0; @@ -184,7 +184,7 @@ int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int _ struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); int ret, err; ret = pm_runtime_resume_and_get(scomp->dev); @@ -193,7 +193,7 @@ int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int _ return ret; } - if (tplg_ops->control->bytes_ext_volatile_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_volatile_get) ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size); pm_runtime_mark_last_busy(scomp->dev); @@ -212,9 +212,9 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->bytes_ext_get) + if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_get) return tplg_ops->control->bytes_ext_get(scontrol, binary_data, size); return 0; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 14571b821eca..952fc698a586 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -125,8 +125,8 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); struct snd_sof_platform_stream_params platform_params = { 0 }; - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_pcm *spcm; int ret; @@ -143,7 +143,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, * Handle repeated calls to hw_params() without free_pcm() in * between. At least ALSA OSS emulation depends on this. */ - if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { ret = pcm_ops->hw_free(component, substream); if (ret < 0) return ret; @@ -177,7 +177,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, return ret; } - if (pcm_ops->hw_params) { + if (pcm_ops && pcm_ops->hw_params) { ret = pcm_ops->hw_params(component, substream, params, &platform_params); if (ret < 0) return ret; @@ -196,7 +196,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); struct snd_sof_pcm *spcm; int ret, err = 0; @@ -212,7 +212,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, spcm->pcm.pcm_id, substream->stream); /* free PCM in the DSP */ - if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { ret = pcm_ops->hw_free(component, substream); if (ret < 0) err = ret; @@ -279,7 +279,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); struct snd_sof_pcm *spcm; bool reset_hw_params = false; bool free_widget_list = false; @@ -344,7 +344,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, if (!ipc_first) snd_sof_pcm_platform_trigger(sdev, substream, cmd); - if (pcm_ops->trigger) + if (pcm_ops && pcm_ops->trigger) ret = pcm_ops->trigger(component, substream, cmd); /* need to STOP DMA even if trigger IPC failed */ @@ -569,7 +569,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); /* no topology exists for this BE, try a common configuration */ if (!dai) { @@ -590,7 +590,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa return 0; } - if (pcm_ops->dai_link_fixup) + if (pcm_ops && pcm_ops->dai_link_fixup) return pcm_ops->dai_link_fixup(rtd, params); return 0; diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index df740be645e8..e7fce9e4a0d2 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -73,8 +73,8 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev) static int sof_resume(struct device *dev, bool runtime_resume) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); - const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); u32 old_state = sdev->dsp_power_state.state; int ret; @@ -155,7 +155,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) } /* restore pipelines */ - if (tplg_ops->set_up_all_pipelines) { + if (tplg_ops && tplg_ops->set_up_all_pipelines) { ret = tplg_ops->set_up_all_pipelines(sdev, false); if (ret < 0) { dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret); @@ -179,8 +179,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) static int sof_suspend(struct device *dev, bool runtime_suspend) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); - const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); pm_message_t pm_state; u32 target_state = 0; int ret; @@ -277,7 +277,7 @@ suspend: int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev) { - const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; + const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); /* Notify DSP of upcoming power down */ if (sof_ops(sdev)->remove && pm_ops && pm_ops->ctx_save) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 7306a2649857..e1ab8380e7d8 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -16,12 +16,12 @@ static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget) { - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_route *sroute; list_for_each_entry(sroute, &sdev->route_list, list) if (sroute->src_widget == widget || sroute->sink_widget == widget) { - if (sroute->setup && tplg_ops->route_free) + if (sroute->setup && tplg_ops && tplg_ops->route_free) tplg_ops->route_free(sdev, sroute); sroute->setup = false; @@ -30,7 +30,7 @@ static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_so int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); int err = 0; int ret; @@ -47,7 +47,7 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) sof_reset_route_setup_status(sdev, swidget); /* continue to disable core even if IPC fails */ - if (tplg_ops->widget_free) + if (tplg_ops && tplg_ops->widget_free) err = tplg_ops->widget_free(sdev, swidget); /* @@ -82,7 +82,7 @@ EXPORT_SYMBOL(sof_widget_free); int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); int ret; /* skip if there is no private data */ @@ -124,7 +124,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) } /* setup widget in the DSP */ - if (tplg_ops->widget_setup) { + if (tplg_ops && tplg_ops->widget_setup) { ret = tplg_ops->widget_setup(sdev, swidget); if (ret < 0) goto core_put; @@ -134,7 +134,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (WIDGET_IS_DAI(swidget->id)) { unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE; - if (tplg_ops->dai_config) { + if (tplg_ops && tplg_ops->dai_config) { ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); if (ret < 0) goto widget_free; @@ -142,7 +142,7 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) } /* restore kcontrols for widget */ - if (tplg_ops->control->widget_kcontrol_setup) { + if (tplg_ops && tplg_ops->control && tplg_ops->control->widget_kcontrol_setup) { ret = tplg_ops->control->widget_kcontrol_setup(sdev, swidget); if (ret < 0) goto widget_free; @@ -169,12 +169,11 @@ EXPORT_SYMBOL(sof_widget_setup); int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink) { - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *src_widget = wsource->dobj.private; struct snd_sof_widget *sink_widget = wsink->dobj.private; struct snd_sof_route *sroute; bool route_found = false; - int ret; /* ignore routes involving virtual widgets in topology */ switch (src_widget->id) { @@ -212,9 +211,12 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc if (sroute->setup) return 0; - ret = ipc_tplg_ops->route_setup(sdev, sroute); - if (ret < 0) - return ret; + if (tplg_ops && tplg_ops->route_setup) { + int ret = tplg_ops->route_setup(sdev, sroute); + + if (ret < 0) + return ret; + } sroute->setup = true; return 0; @@ -266,16 +268,17 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, static void sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget) { - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *swidget = widget->dobj.private; + const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_soc_dapm_path *p; /* return if the widget is in use or if it is already unprepared */ if (!swidget->prepared || swidget->use_count > 1) return; - if (widget_ops[widget->id].ipc_unprepare) + widget_ops = tplg_ops ? tplg_ops->widget : NULL; + if (widget_ops && widget_ops[widget->id].ipc_unprepare) /* unprepare the source widget */ widget_ops[widget->id].ipc_unprepare(swidget); @@ -297,12 +300,16 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget struct snd_sof_platform_stream_params *platform_params, struct snd_pcm_hw_params *pipeline_params, int dir) { - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *swidget = widget->dobj.private; + const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_soc_dapm_path *p; int ret; + widget_ops = tplg_ops ? tplg_ops->widget : NULL; + if (!widget_ops) + return 0; + if (!widget_ops[widget->id].ipc_prepare || swidget->prepared) goto sink_prepare; @@ -483,7 +490,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, struct snd_sof_platform_stream_params *platform_params, int dir) { - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; struct snd_soc_dapm_widget *widget; int i, ret; @@ -537,8 +544,8 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, if (pipe_widget->complete) continue; - if (ipc_tplg_ops->pipeline_complete) { - pipe_widget->complete = ipc_tplg_ops->pipeline_complete(sdev, pipe_widget); + if (tplg_ops && tplg_ops->pipeline_complete) { + pipe_widget->complete = tplg_ops->pipeline_complete(sdev, pipe_widget); if (pipe_widget->complete < 0) { ret = pipe_widget->complete; goto widget_free; @@ -626,11 +633,11 @@ bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_sof_pcm *spcm, int dir, bool free_widget_list) { - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); int ret; /* Send PCM_FREE IPC to reset pipeline */ - if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { ret = pcm_ops->hw_free(sdev->component, substream); if (ret < 0) return ret; @@ -760,13 +767,13 @@ static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type) struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); /* use the tplg configured mclk if existed */ if (!dai) return 0; - if (tplg_ops->dai_get_clk) + if (tplg_ops && tplg_ops->dai_get_clk) return tplg_ops->dai_get_clk(sdev, dai, clk_type); return 0; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 29cf951e3526..8e4abb1f5f73 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -166,7 +166,7 @@ struct sof_ipc_tplg_widget_ops { * initialized to 0. * @control: Pointer to the IPC-specific ops for topology kcontrol IO * @route_setup: Function pointer for setting up pipeline connections - * @route_free: Optional op for freeing pipeline connections. + * @route_free: Function pointer for freeing pipeline connections. * @token_list: List of all tokens supported by the IPC version. The size of the token_list * array should be SOF_TOKEN_COUNT. The unused elements in the array will be * initialized to 0. @@ -179,7 +179,9 @@ struct sof_ipc_tplg_widget_ops { * @dai_get_clk: Function pointer for getting the DAI clock setting * @set_up_all_pipelines: Function pointer for setting up all topology pipelines * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines - * @parse_manifest: Optional function pointer for ipc4 specific parsing of topology manifest + * @parse_manifest: Function pointer for ipc4 specific parsing of topology manifest + * + * Note: function pointers (ops) are optional */ struct sof_ipc_tplg_ops { const struct sof_ipc_tplg_widget_ops *widget; diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 6760fd895950..752bf46c7bc9 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -444,7 +444,7 @@ struct sof_ipc_pcm_ops; * @pm: Pointer to PM ops * @pcm: Pointer to PCM ops * @fw_loader: Pointer to Firmware Loader ops - * @fw_tracing: Pointer to Firmware tracing ops + * @fw_tracing: Optional pointer to Firmware tracing ops * * @init: Optional pointer for IPC related initialization * @exit: Optional pointer for IPC related cleanup @@ -502,6 +502,10 @@ struct snd_sof_ipc { const struct sof_ipc_ops *ops; }; +/* Helper to retrieve the IPC ops */ +#define sof_ipc_get_ops(sdev, ops_name) \ + (((sdev)->ipc && (sdev)->ipc->ops) ? (sdev)->ipc->ops->ops_name : NULL) + /* * SOF Device Level. */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index c668bd9d21ec..560771ba8fb9 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -54,11 +54,16 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so size_t object_size, int token_instance_num) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_token_info *token_list = ipc_tplg_ops->token_list; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_token_info *token_list; const struct sof_topology_token *tokens; int i, j; + token_list = tplg_ops ? tplg_ops->token_list : NULL; + /* nothing to do if token_list is NULL */ + if (!token_list) + return 0; + if (token_list[token_id].count < 0) { dev_err(scomp->dev, "Invalid token count for token ID: %d\n", token_id); return -EINVAL; @@ -263,9 +268,9 @@ static int set_up_volume_table(struct snd_sof_control *scontrol, { struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (tplg_ops->control->set_up_volume_table) + if (tplg_ops && tplg_ops->control && tplg_ops->control->set_up_volume_table) return tplg_ops->control->set_up_volume_table(scontrol, tlv, size); dev_err(scomp->dev, "Mandatory op %s not set\n", __func__); @@ -490,13 +495,14 @@ static int sof_copy_tuples(struct snd_sof_dev *sdev, struct snd_soc_tplg_vendor_ int array_size, u32 token_id, int token_instance_num, struct snd_sof_tuple *tuples, int tuples_size, int *num_copied_tuples) { - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_token_info *token_list = ipc_tplg_ops->token_list; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_token_info *token_list; const struct sof_topology_token *tokens; int found = 0; int num_tokens, asize; int i, j; + token_list = tplg_ops ? tplg_ops->token_list : NULL; /* nothing to do if token_list is NULL */ if (!token_list) return 0; @@ -1015,14 +1021,14 @@ static int sof_control_unload(struct snd_soc_component *scomp, struct snd_soc_dobj *dobj) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_control *scontrol = dobj->private; int ret = 0; dev_dbg(scomp->dev, "tplg: unload control name : %s\n", scontrol->name); - if (ipc_tplg_ops->control_free) { - ret = ipc_tplg_ops->control_free(sdev, scontrol); + if (tplg_ops && tplg_ops->control_free) { + ret = tplg_ops->control_free(sdev, scontrol); if (ret < 0) dev_err(scomp->dev, "failed to free control: %s\n", scontrol->name); } @@ -1201,12 +1207,17 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s enum sof_tokens *object_token_list, int count) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_token_info *token_list = ipc_tplg_ops->token_list; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_soc_tplg_private *private = &tw->priv; + const struct sof_token_info *token_list; int num_tuples = 0; int ret, i; + token_list = tplg_ops ? tplg_ops->token_list : NULL; + /* nothing to do if token_list is NULL */ + if (!token_list) + return 0; + if (count > 0 && !object_token_list) { dev_err(scomp->dev, "No token list for widget %s\n", swidget->widget->name); return -EINVAL; @@ -1375,13 +1386,13 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_dapm_widget *tw) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_soc_tplg_private *priv = &tw->priv; + enum sof_tokens *token_list = NULL; struct snd_sof_widget *swidget; struct snd_sof_dai *dai; - enum sof_tokens *token_list; - int token_list_size; + int token_list_size = 0; int ret = 0; swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); @@ -1440,8 +1451,11 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, swidget->num_sink_pins, swidget->num_source_pins, strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? w->sname : "none"); - token_list = widget_ops[w->id].token_list; - token_list_size = widget_ops[w->id].token_list_size; + widget_ops = tplg_ops ? tplg_ops->widget : NULL; + if (widget_ops) { + token_list = widget_ops[w->id].token_list; + token_list_size = widget_ops[w->id].token_list_size; + } /* handle any special case widgets */ switch (w->id) { @@ -1525,7 +1539,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, /* bind widget to external event */ if (tw->event_type) { - if (widget_ops[w->id].bind_event) { + if (widget_ops && widget_ops[w->id].bind_event) { ret = widget_ops[w->id].bind_event(scomp, swidget, le16_to_cpu(tw->event_type)); if (ret) { @@ -1565,8 +1579,8 @@ static int sof_widget_unload(struct snd_soc_component *scomp, struct snd_soc_dobj *dobj) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_ipc_tplg_widget_ops *widget_ops; const struct snd_kcontrol_new *kc; struct snd_soc_dapm_widget *widget; struct snd_sof_control *scontrol; @@ -1626,7 +1640,8 @@ static int sof_widget_unload(struct snd_soc_component *scomp, out: /* free IPC related data */ - if (widget_ops[swidget->id].ipc_free) + widget_ops = tplg_ops ? tplg_ops->widget : NULL; + if (widget_ops && widget_ops[swidget->id].ipc_free) widget_ops[swidget->id].ipc_free(swidget); ida_destroy(&swidget->src_queue_ida); @@ -1784,9 +1799,9 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ struct snd_soc_tplg_link_config *cfg) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_token_info *token_list = ipc_tplg_ops->token_list; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_soc_tplg_private *private = &cfg->priv; + const struct sof_token_info *token_list; struct snd_sof_dai_link *slink; u32 token_id = 0; int num_tuples = 0; @@ -1856,6 +1871,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ return ret; } + token_list = tplg_ops ? tplg_ops->token_list : NULL; if (!token_list) goto out; @@ -2100,16 +2116,18 @@ static int sof_set_pipe_widget(struct snd_sof_dev *sdev, struct snd_sof_widget * static int sof_complete(struct snd_soc_component *scomp) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *swidget, *comp_swidget; - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget; + const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_sof_control *scontrol; int ret; + widget_ops = tplg_ops ? tplg_ops->widget : NULL; + /* first update all control IPC structures based on the IPC version */ - if (ipc_tplg_ops->control_setup) + if (tplg_ops && tplg_ops->control_setup) list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { - ret = ipc_tplg_ops->control_setup(sdev, scontrol); + ret = tplg_ops->control_setup(sdev, scontrol); if (ret < 0) { dev_err(sdev->dev, "failed updating IPC struct for control %s\n", scontrol->name); @@ -2123,7 +2141,7 @@ static int sof_complete(struct snd_soc_component *scomp) * associated memories. */ list_for_each_entry(swidget, &sdev->widget_list, list) { - if (widget_ops[swidget->id].ipc_setup) { + if (widget_ops && widget_ops[swidget->id].ipc_setup) { ret = widget_ops[swidget->id].ipc_setup(swidget); if (ret < 0) { dev_err(sdev->dev, "failed updating IPC struct for %s\n", @@ -2155,15 +2173,16 @@ static int sof_complete(struct snd_soc_component *scomp) /* verify topology components loading including dynamic pipelines */ if (sof_debug_check_flag(SOF_DBG_VERIFY_TPLG)) { - if (ipc_tplg_ops->set_up_all_pipelines && ipc_tplg_ops->tear_down_all_pipelines) { - ret = ipc_tplg_ops->set_up_all_pipelines(sdev, true); + if (tplg_ops && tplg_ops->set_up_all_pipelines && + tplg_ops->tear_down_all_pipelines) { + ret = tplg_ops->set_up_all_pipelines(sdev, true); if (ret < 0) { dev_err(sdev->dev, "Failed to set up all topology pipelines: %d\n", ret); return ret; } - ret = ipc_tplg_ops->tear_down_all_pipelines(sdev, true); + ret = tplg_ops->tear_down_all_pipelines(sdev, true); if (ret < 0) { dev_err(sdev->dev, "Failed to tear down topology pipelines: %d\n", ret); @@ -2173,8 +2192,8 @@ static int sof_complete(struct snd_soc_component *scomp) } /* set up static pipelines */ - if (ipc_tplg_ops->set_up_all_pipelines) - return ipc_tplg_ops->set_up_all_pipelines(sdev, false); + if (tplg_ops && tplg_ops->set_up_all_pipelines) + return tplg_ops->set_up_all_pipelines(sdev, false); return 0; } @@ -2184,10 +2203,10 @@ static int sof_manifest(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_manifest *man) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - if (ipc_tplg_ops->parse_manifest) - return ipc_tplg_ops->parse_manifest(scomp, index, man); + if (tplg_ops && tplg_ops->parse_manifest) + return tplg_ops->parse_manifest(scomp, index, man); return 0; } diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index 6f662642d611..b2ab51e5214a 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -6,19 +6,21 @@ int sof_fw_trace_init(struct snd_sof_dev *sdev) { - if (!sdev->ipc->ops->fw_tracing) { + const struct sof_ipc_fw_tracing_ops *fw_tracing = sof_ipc_get_ops(sdev, fw_tracing); + + if (!fw_tracing) { dev_info(sdev->dev, "Firmware tracing is not available\n"); sdev->fw_trace_is_supported = false; return 0; } - return sdev->ipc->ops->fw_tracing->init(sdev); + return fw_tracing->init(sdev); } void sof_fw_trace_free(struct snd_sof_dev *sdev) { - if (!sdev->fw_trace_is_supported || !sdev->ipc->ops->fw_tracing) + if (!sdev->fw_trace_is_supported) return; if (sdev->ipc->ops->fw_tracing->free) |