Lines Matching +full:sink +full:- +full:only
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
13 #include "sof-audio.h"
19 switch (widget->id) { in is_virtual_widget()
23 dev_dbg(sdev->dev, "%s: %s is a virtual widget\n", func, widget->name); in is_virtual_widget()
35 list_for_each_entry(sroute, &sdev->route_list, list) in sof_reset_route_setup_status()
36 if (sroute->src_widget == widget || sroute->sink_widget == widget) { in sof_reset_route_setup_status()
37 if (sroute->setup && tplg_ops && tplg_ops->route_free) in sof_reset_route_setup_status()
38 tplg_ops->route_free(sdev, sroute); in sof_reset_route_setup_status()
40 sroute->setup = false; in sof_reset_route_setup_status()
48 struct snd_sof_pipeline *spipe = swidget->spipe; in sof_widget_free_unlocked()
52 if (!swidget->private) in sof_widget_free_unlocked()
57 /* only free when use_count is 0 */ in sof_widget_free_unlocked()
58 if (--swidget->use_count) in sof_widget_free_unlocked()
65 if (WIDGET_IS_DAI(swidget->id)) { in sof_widget_free_unlocked()
71 if (tplg_ops && tplg_ops->dai_config) { in sof_widget_free_unlocked()
72 err = tplg_ops->dai_config(sdev, swidget, flags, &data); in sof_widget_free_unlocked()
74 dev_err(sdev->dev, "failed to free config for widget %s\n", in sof_widget_free_unlocked()
75 swidget->widget->name); in sof_widget_free_unlocked()
80 if (tplg_ops && tplg_ops->widget_free) { in sof_widget_free_unlocked()
81 ret = tplg_ops->widget_free(sdev, swidget); in sof_widget_free_unlocked()
90 if (swidget->id == snd_soc_dapm_scheduler) { in sof_widget_free_unlocked()
93 for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { in sof_widget_free_unlocked()
96 dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n", in sof_widget_free_unlocked()
97 i, swidget->widget->name); in sof_widget_free_unlocked()
102 swidget->spipe->complete = 0; in sof_widget_free_unlocked()
109 if (swidget->spipe && swidget->dynamic_pipeline_widget && in sof_widget_free_unlocked()
110 swidget->id != snd_soc_dapm_scheduler) { in sof_widget_free_unlocked()
111 ret = sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); in sof_widget_free_unlocked()
117 dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name); in sof_widget_free_unlocked()
126 mutex_lock(&swidget->setup_mutex); in sof_widget_free()
128 mutex_unlock(&swidget->setup_mutex); in sof_widget_free()
138 struct snd_sof_pipeline *spipe = swidget->spipe; in sof_widget_setup_unlocked()
144 if (!swidget->private) in sof_widget_setup_unlocked()
150 if (++swidget->use_count > 1) in sof_widget_setup_unlocked()
157 * widget in a given pipeline to ensure that it is freed only after the last in sof_widget_setup_unlocked()
160 if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { in sof_widget_setup_unlocked()
161 if (!swidget->spipe || !swidget->spipe->pipe_widget) { in sof_widget_setup_unlocked()
162 dev_err(sdev->dev, "No pipeline set for %s\n", swidget->widget->name); in sof_widget_setup_unlocked()
163 ret = -EINVAL; in sof_widget_setup_unlocked()
167 ret = sof_widget_setup_unlocked(sdev, swidget->spipe->pipe_widget); in sof_widget_setup_unlocked()
173 if (swidget->id == snd_soc_dapm_scheduler) { in sof_widget_setup_unlocked()
174 for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { in sof_widget_setup_unlocked()
177 dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n", in sof_widget_setup_unlocked()
178 i, swidget->widget->name); in sof_widget_setup_unlocked()
185 if (tplg_ops && tplg_ops->widget_setup) { in sof_widget_setup_unlocked()
186 ret = tplg_ops->widget_setup(sdev, swidget); in sof_widget_setup_unlocked()
192 if (WIDGET_IS_DAI(swidget->id)) { in sof_widget_setup_unlocked()
199 if (tplg_ops && tplg_ops->dai_config) { in sof_widget_setup_unlocked()
200 ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); in sof_widget_setup_unlocked()
207 if (tplg_ops && tplg_ops->control && tplg_ops->control->widget_kcontrol_setup) { in sof_widget_setup_unlocked()
208 ret = tplg_ops->control->widget_kcontrol_setup(sdev, swidget); in sof_widget_setup_unlocked()
213 dev_dbg(sdev->dev, "widget %s setup complete\n", swidget->widget->name); in sof_widget_setup_unlocked()
222 if (swidget->id != snd_soc_dapm_scheduler) { in sof_widget_setup_unlocked()
223 sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); in sof_widget_setup_unlocked()
228 for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) { in sof_widget_setup_unlocked()
236 swidget->use_count--; in sof_widget_setup_unlocked()
245 mutex_lock(&swidget->setup_mutex); in sof_widget_setup()
247 mutex_unlock(&swidget->setup_mutex); in sof_widget_setup()
257 struct snd_sof_widget *src_widget = wsource->dobj.private; in sof_route_setup()
258 struct snd_sof_widget *sink_widget = wsink->dobj.private; in sof_route_setup()
263 if (is_virtual_widget(sdev, src_widget->widget, __func__) || in sof_route_setup()
264 is_virtual_widget(sdev, sink_widget->widget, __func__)) in sof_route_setup()
267 /* find route matching source and sink widgets */ in sof_route_setup()
268 list_for_each_entry(sroute, &sdev->route_list, list) in sof_route_setup()
269 if (sroute->src_widget == src_widget && sroute->sink_widget == sink_widget) { in sof_route_setup()
275 dev_err(sdev->dev, "error: cannot find SOF route for source %s -> %s sink\n", in sof_route_setup()
276 wsource->name, wsink->name); in sof_route_setup()
277 return -EINVAL; in sof_route_setup()
281 if (sroute->setup) in sof_route_setup()
284 if (tplg_ops && tplg_ops->route_setup) { in sof_route_setup()
285 int ret = tplg_ops->route_setup(sdev, sroute); in sof_route_setup()
291 sroute->setup = true; in sof_route_setup()
306 * Set up connections between widgets in the sink/source paths based on direction. in sof_setup_pipeline_connections()
307 * Some non-SOF widgets exist in topology either for compatibility or for the in sof_setup_pipeline_connections()
313 if (!widget->dobj.private) in sof_setup_pipeline_connections()
317 if (!widget_in_list(list, p->sink)) in sof_setup_pipeline_connections()
320 if (p->sink->dobj.private) { in sof_setup_pipeline_connections()
321 ret = sof_route_setup(sdev, widget, p->sink); in sof_setup_pipeline_connections()
329 if (!widget->dobj.private) in sof_setup_pipeline_connections()
333 if (!widget_in_list(list, p->source)) in sof_setup_pipeline_connections()
336 if (p->source->dobj.private) { in sof_setup_pipeline_connections()
337 ret = sof_route_setup(sdev, p->source, widget); in sof_setup_pipeline_connections()
351 list_for_each_entry(sroute, &sdev->route_list, list) { in sof_setup_pipeline_connections()
355 if (sroute->setup) in sof_setup_pipeline_connections()
358 src_widget_in_dapm_list = widget_in_list(list, sroute->src_widget->widget); in sof_setup_pipeline_connections()
359 sink_widget_in_dapm_list = widget_in_list(list, sroute->sink_widget->widget); in sof_setup_pipeline_connections()
362 * if both source and sink are in the DAPM list, the route must already have been in sof_setup_pipeline_connections()
370 * At this point either the source widget or the sink widget is in the DAPM list in sof_setup_pipeline_connections()
376 swidget = sroute->sink_widget; in sof_setup_pipeline_connections()
378 swidget = sroute->src_widget; in sof_setup_pipeline_connections()
380 mutex_lock(&swidget->setup_mutex); in sof_setup_pipeline_connections()
381 if (!swidget->use_count) { in sof_setup_pipeline_connections()
382 mutex_unlock(&swidget->setup_mutex); in sof_setup_pipeline_connections()
386 if (tplg_ops && tplg_ops->route_setup) { in sof_setup_pipeline_connections()
388 * this route will get freed when either the source widget or the sink in sof_setup_pipeline_connections()
391 ret = tplg_ops->route_setup(sdev, sroute); in sof_setup_pipeline_connections()
393 sroute->setup = true; in sof_setup_pipeline_connections()
396 mutex_unlock(&swidget->setup_mutex); in sof_setup_pipeline_connections()
410 struct snd_sof_widget *swidget = widget->dobj.private; in sof_unprepare_widgets_in_path()
418 if (!swidget || !swidget->prepared || swidget->use_count > 0) in sof_unprepare_widgets_in_path()
421 widget_ops = tplg_ops ? tplg_ops->widget : NULL; in sof_unprepare_widgets_in_path()
422 if (widget_ops && widget_ops[widget->id].ipc_unprepare) in sof_unprepare_widgets_in_path()
424 widget_ops[widget->id].ipc_unprepare(swidget); in sof_unprepare_widgets_in_path()
426 swidget->prepared = false; in sof_unprepare_widgets_in_path()
429 /* unprepare all widgets in the sink paths */ in sof_unprepare_widgets_in_path()
431 if (!widget_in_list(list, p->sink)) in sof_unprepare_widgets_in_path()
433 if (!p->walking && p->sink->dobj.private) { in sof_unprepare_widgets_in_path()
434 p->walking = true; in sof_unprepare_widgets_in_path()
435 sof_unprepare_widgets_in_path(sdev, p->sink, list); in sof_unprepare_widgets_in_path()
436 p->walking = false; in sof_unprepare_widgets_in_path()
449 struct snd_sof_widget *swidget = widget->dobj.private; in sof_prepare_widgets_in_path()
457 widget_ops = tplg_ops ? tplg_ops->widget : NULL; in sof_prepare_widgets_in_path()
461 if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared) in sof_prepare_widgets_in_path()
465 ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params, in sof_prepare_widgets_in_path()
468 dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name); in sof_prepare_widgets_in_path()
472 swidget->prepared = true; in sof_prepare_widgets_in_path()
475 /* prepare all widgets in the sink paths */ in sof_prepare_widgets_in_path()
477 if (!widget_in_list(list, p->sink)) in sof_prepare_widgets_in_path()
479 if (!p->walking && p->sink->dobj.private) { in sof_prepare_widgets_in_path()
480 p->walking = true; in sof_prepare_widgets_in_path()
481 ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, in sof_prepare_widgets_in_path()
484 p->walking = false; in sof_prepare_widgets_in_path()
487 if (widget_ops[widget->id].ipc_unprepare && in sof_prepare_widgets_in_path()
488 swidget && swidget->prepared && swidget->use_count == 0) { in sof_prepare_widgets_in_path()
489 widget_ops[widget->id].ipc_unprepare(swidget); in sof_prepare_widgets_in_path()
490 swidget->prepared = false; in sof_prepare_widgets_in_path()
501 * free all widgets in the sink path starting from the source widget
507 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; in sof_free_widgets_in_path()
515 if (widget->dobj.private) { in sof_free_widgets_in_path()
516 err = sof_widget_free(sdev, widget->dobj.private); in sof_free_widgets_in_path()
521 /* free all widgets in the sink paths even in case of error to keep use counts balanced */ in sof_free_widgets_in_path()
523 if (!p->walking) { in sof_free_widgets_in_path()
524 if (!widget_in_list(list, p->sink)) in sof_free_widgets_in_path()
527 p->walking = true; in sof_free_widgets_in_path()
529 err = sof_free_widgets_in_path(sdev, p->sink, dir, spcm); in sof_free_widgets_in_path()
532 p->walking = false; in sof_free_widgets_in_path()
540 * set up all widgets in the sink path starting from the source widget
547 struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list; in sof_set_up_widgets_in_path()
548 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; in sof_set_up_widgets_in_path()
549 struct snd_sof_widget *swidget = widget->dobj.private; in sof_set_up_widgets_in_path()
560 ret = sof_widget_setup(sdev, widget->dobj.private); in sof_set_up_widgets_in_path()
565 if (!pipeline_list->pipelines) in sof_set_up_widgets_in_path()
571 * order source to sink. in sof_set_up_widgets_in_path()
573 for (i = 0; i < pipeline_list->count; i++) { in sof_set_up_widgets_in_path()
574 spipe = pipeline_list->pipelines[i]; in sof_set_up_widgets_in_path()
575 if (spipe == swidget->spipe) in sof_set_up_widgets_in_path()
579 if (i == pipeline_list->count) { in sof_set_up_widgets_in_path()
580 pipeline_list->count++; in sof_set_up_widgets_in_path()
581 pipeline_list->pipelines[i] = swidget->spipe; in sof_set_up_widgets_in_path()
587 if (!p->walking) { in sof_set_up_widgets_in_path()
588 if (!widget_in_list(list, p->sink)) in sof_set_up_widgets_in_path()
591 p->walking = true; in sof_set_up_widgets_in_path()
593 ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, spcm); in sof_set_up_widgets_in_path()
594 p->walking = false; in sof_set_up_widgets_in_path()
612 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; in sof_walk_widgets_in_order()
626 if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in) in sof_walk_widgets_in_order()
630 if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out) in sof_walk_widgets_in_order()
663 dev_err(sdev->dev, "Invalid widget op %d\n", op); in sof_walk_widgets_in_order()
664 return -EINVAL; in sof_walk_widgets_in_order()
667 dev_err(sdev->dev, "Failed to %s connected widgets\n", str); in sof_walk_widgets_in_order()
681 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; in sof_widget_list_setup()
717 struct snd_sof_widget *swidget = widget->dobj.private; in sof_widget_list_setup()
721 if (!swidget || sdev->dspless_mode_selected) in sof_widget_list_setup()
724 spipe = swidget->spipe; in sof_widget_list_setup()
726 dev_err(sdev->dev, "no pipeline found for %s\n", in sof_widget_list_setup()
727 swidget->widget->name); in sof_widget_list_setup()
728 ret = -EINVAL; in sof_widget_list_setup()
732 pipe_widget = spipe->pipe_widget; in sof_widget_list_setup()
734 dev_err(sdev->dev, "error: no pipeline widget found for %s\n", in sof_widget_list_setup()
735 swidget->widget->name); in sof_widget_list_setup()
736 ret = -EINVAL; in sof_widget_list_setup()
740 if (spipe->complete) in sof_widget_list_setup()
743 if (tplg_ops && tplg_ops->pipeline_complete) { in sof_widget_list_setup()
744 spipe->complete = tplg_ops->pipeline_complete(sdev, pipe_widget); in sof_widget_list_setup()
745 if (spipe->complete < 0) { in sof_widget_list_setup()
746 ret = spipe->complete; in sof_widget_list_setup()
764 struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list; in sof_widget_list_free()
765 struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; in sof_widget_list_free()
779 spcm->stream[dir].list = NULL; in sof_widget_list_free()
781 pipeline_list->count = 0; in sof_widget_list_free()
787 * helper to determine if there are only D0i3 compatible
797 list_for_each_entry(spcm, &sdev->pcm_list, list) { in snd_sof_dsp_only_d0i3_compatible_stream_active()
799 substream = spcm->stream[dir].substream; in snd_sof_dsp_only_d0i3_compatible_stream_active()
800 if (!substream || !substream->runtime) in snd_sof_dsp_only_d0i3_compatible_stream_active()
804 * substream->runtime being not NULL indicates in snd_sof_dsp_only_d0i3_compatible_stream_active()
808 if (!spcm->stream[dir].d0i3_compatible) in snd_sof_dsp_only_d0i3_compatible_stream_active()
823 list_for_each_entry(spcm, &sdev->pcm_list, list) { in snd_sof_stream_suspend_ignored()
824 if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored || in snd_sof_stream_suspend_ignored()
825 spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored) in snd_sof_stream_suspend_ignored()
839 if (spcm->prepared[substream->stream]) { in sof_pcm_stream_free()
841 if (pcm_ops && pcm_ops->platform_stop_during_hw_free) in sof_pcm_stream_free()
845 if (pcm_ops && pcm_ops->hw_free) { in sof_pcm_stream_free()
846 ret = pcm_ops->hw_free(sdev->component, substream); in sof_pcm_stream_free()
848 dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n", in sof_pcm_stream_free()
854 spcm->prepared[substream->stream] = false; in sof_pcm_stream_free()
855 spcm->pending_stop[substream->stream] = false; in sof_pcm_stream_free()
861 dev_err(sdev->dev, "%s: platform hw free failed %d\n", in sof_pcm_stream_free()
871 dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n", in sof_pcm_stream_free()
891 list_for_each_entry(spcm, &sdev->pcm_list, list) { in snd_sof_find_spcm_name()
893 if (strcmp(spcm->pcm.dai_name, name) == 0) in snd_sof_find_spcm_name()
897 if (*spcm->pcm.caps[0].name && in snd_sof_find_spcm_name()
898 !strcmp(spcm->pcm.caps[0].name, name)) in snd_sof_find_spcm_name()
902 if (*spcm->pcm.caps[1].name && in snd_sof_find_spcm_name()
903 !strcmp(spcm->pcm.caps[1].name, name)) in snd_sof_find_spcm_name()
918 list_for_each_entry(spcm, &sdev->pcm_list, list) { in snd_sof_find_spcm_comp()
920 if (spcm->stream[dir].comp_id == comp_id) { in snd_sof_find_spcm_comp()
936 list_for_each_entry(swidget, &sdev->widget_list, list) { in snd_sof_find_swidget()
937 if (strcmp(name, swidget->widget->name) == 0) in snd_sof_find_swidget()
958 list_for_each_entry(swidget, &sdev->widget_list, list) { in snd_sof_find_swidget_sname()
959 if (!strcmp(pcm_name, swidget->widget->sname) && in snd_sof_find_swidget_sname()
960 swidget->id == type) in snd_sof_find_swidget_sname()
973 list_for_each_entry(dai, &sdev->dai_list, list) { in snd_sof_find_dai()
974 if (dai->name && (strcmp(name, dai->name) == 0)) in snd_sof_find_dai()
986 snd_sof_find_dai(component, (char *)rtd->dai_link->name); in sof_dai_get_param()
994 if (tplg_ops && tplg_ops->dai_get_param) in sof_dai_get_param()
995 return tplg_ops->dai_get_param(sdev, dai, param_type); in sof_dai_get_param()