aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/sof-audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/sof-audio.c')
-rw-r--r--sound/soc/sof/sof-audio.c47
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;