diff options
Diffstat (limited to 'sound/soc/sof/sof-audio.c')
-rw-r--r-- | sound/soc/sof/sof-audio.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 28976098a89e..62092e2d609c 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -9,7 +9,9 @@ // #include <linux/bitfield.h> +#include <trace/events/sof.h> #include "sof-audio.h" +#include "sof-of-dev.h" #include "ops.h" static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget) @@ -35,6 +37,8 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (!swidget->private) return 0; + trace_sof_widget_free(swidget); + /* only free when use_count is 0 */ if (--swidget->use_count) return 0; @@ -85,6 +89,8 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (!swidget->private) return 0; + trace_sof_widget_setup(swidget); + /* widget already set up */ if (++swidget->use_count > 1) return 0; @@ -265,14 +271,16 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg struct snd_sof_widget *swidget = widget->dobj.private; struct snd_soc_dapm_path *p; - if (!widget_ops[widget->id].ipc_unprepare || !swidget->prepared) - goto sink_unprepare; + /* 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) + /* unprepare the source widget */ + widget_ops[widget->id].ipc_unprepare(swidget); - /* unprepare the source widget */ - widget_ops[widget->id].ipc_unprepare(swidget); swidget->prepared = false; -sink_unprepare: /* unprepare all widgets in the sink paths */ snd_soc_dapm_widget_for_each_sink_path(widget, p) { if (!p->walking && p->sink->dobj.private) { @@ -784,6 +792,28 @@ int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL(sof_dai_get_bclk); +static struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *sof_pdata = sdev->pdata; + const struct sof_dev_desc *desc = sof_pdata->desc; + struct snd_sof_of_mach *mach = desc->of_machines; + + if (!mach) + return NULL; + + for (; mach->compatible; mach++) { + if (of_machine_is_compatible(mach->compatible)) { + sof_pdata->tplg_filename = mach->sof_tplg_filename; + if (mach->fw_filename) + sof_pdata->fw_filename = mach->fw_filename; + + return mach; + } + } + + return NULL; +} + /* * SOF Driver enumeration. */ @@ -794,6 +824,7 @@ int sof_machine_check(struct snd_sof_dev *sdev) struct snd_soc_acpi_mach *mach; if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) { + const struct snd_sof_of_mach *of_mach; /* find machine */ mach = snd_sof_machine_select(sdev); @@ -803,6 +834,12 @@ int sof_machine_check(struct snd_sof_dev *sdev) return 0; } + of_mach = sof_of_machine_select(sdev); + if (of_mach) { + sof_pdata->of_machine = of_mach; + return 0; + } + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); return -ENODEV; |