Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 150
Fix pipeline set up with multi-stream capture#3858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -263,7 +263,8 @@ 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) | ||
| sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, | ||
| struct snd_soc_dapm_widget_list *list) | ||
| { | ||
| 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; | ||
| @@ -282,9 +283,11 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg | ||
| /* unprepare all widgets in the sink paths */ | ||
| snd_soc_dapm_widget_for_each_sink_path(widget, p) { | ||
| if (!widget_in_list(list, p->sink)) | ||
| continue; | ||
| if (!p->walking && p->sink->dobj.private) { | ||
| p->walking = true; | ||
| sof_unprepare_widgets_in_path(sdev, p->sink); | ||
| sof_unprepare_widgets_in_path(sdev, p->sink, list); | ||
| p->walking = false; | ||
| } | ||
| } | ||
| @@ -294,7 +297,8 @@ static int | ||
| sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, | ||
| struct snd_pcm_hw_params *fe_params, | ||
| struct snd_sof_platform_stream_params *platform_params, | ||
| struct snd_pcm_hw_params *pipeline_params, int dir) | ||
| struct snd_pcm_hw_params *pipeline_params, int dir, | ||
| struct snd_soc_dapm_widget_list *list) | ||
| { | ||
| 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; | ||
| @@ -318,10 +322,13 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget | ||
| sink_prepare: | ||
| /* prepare all widgets in the sink paths */ | ||
| snd_soc_dapm_widget_for_each_sink_path(widget, p) { | ||
| if (!widget_in_list(list, p->sink)) | ||
| continue; | ||
| if (!p->walking && p->sink->dobj.private) { | ||
| p->walking = true; | ||
| ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, | ||
| platform_params, pipeline_params, dir); | ||
| platform_params, pipeline_params, dir, | ||
| list); | ||
| p->walking = false; | ||
| if (ret < 0) { | ||
| /* unprepare the source widget */ | ||
| @@ -342,27 +349,27 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget | ||
| * (DAI type for capture, AIF type for playback) | ||
| */ | ||
| static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, | ||
| int dir) | ||
| int dir, struct snd_soc_dapm_widget_list *list) | ||
| { | ||
| struct snd_soc_dapm_path *p; | ||
| int err; | ||
| int ret = 0; | ||
| /* free all widgets even in case of error to keep use counts balanced */ | ||
| if (widget->dobj.private) { | ||
| err = sof_widget_free(sdev, widget->dobj.private); | ||
| if (err < 0) | ||
| ret = err; | ||
| } | ||
| /* free all widgets in the sink paths even in case of error to keep use counts balanced */ | ||
| snd_soc_dapm_widget_for_each_sink_path(widget, p) { | ||
| if (!p->walking && p->sink->dobj.private && widget->dobj.private) { | ||
| p->walking = true; | ||
| if (WIDGET_IS_AIF_OR_DAI(widget->id)) { | ||
| err = sof_widget_free(sdev, widget->dobj.private); | ||
| if (err < 0) | ||
| ret = err; | ||
| } | ||
plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if (!p->walking) { | ||
| if (!widget_in_list(list, p->sink)) | ||
| continue; | ||
| err = sof_widget_free(sdev, p->sink->dobj.private); | ||
| if (err < 0) | ||
| ret = err; | ||
| p->walking = true; | ||
| err = sof_free_widgets_in_path(sdev, p->sink, dir); | ||
| err = sof_free_widgets_in_path(sdev, p->sink, dir, list); | ||
| if (err < 0) | ||
| ret = err; | ||
| p->walking = false; | ||
| @@ -378,37 +385,31 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap | ||
| * The error path in this function ensures that all successfully set up widgets getting freed. | ||
| */ | ||
| static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, | ||
| int dir) | ||
| int dir, struct snd_soc_dapm_widget_list *list) | ||
| { | ||
| struct snd_soc_dapm_path *p; | ||
| int ret; | ||
| if (widget->dobj.private) { | ||
| ret = sof_widget_setup(sdev, widget->dobj.private); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
| snd_soc_dapm_widget_for_each_sink_path(widget, p) { | ||
| if (!p->walking && p->sink->dobj.private && widget->dobj.private) { | ||
| p->walking = true; | ||
| if (WIDGET_IS_AIF_OR_DAI(widget->id)) { | ||
| ret = sof_widget_setup(sdev, widget->dobj.private); | ||
| if (ret < 0) | ||
| goto out; | ||
| } | ||
plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if (!p->walking) { | ||
| if (!widget_in_list(list, p->sink)) | ||
| continue; | ||
| ret = sof_widget_setup(sdev, p->sink->dobj.private); | ||
| if (ret < 0) { | ||
| if (WIDGET_IS_AIF_OR_DAI(widget->id)) | ||
| sof_widget_free(sdev, widget->dobj.private); | ||
| goto out; | ||
| } | ||
| p->walking = true; | ||
| ret = sof_set_up_widgets_in_path(sdev, p->sink, dir); | ||
| ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, list); | ||
| p->walking = false; | ||
| if (ret < 0) { | ||
| if (WIDGET_IS_AIF_OR_DAI(widget->id)) | ||
| if (widget->dobj.private) | ||
plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| sof_widget_free(sdev, widget->dobj.private); | ||
| sof_widget_free(sdev, p->sink->dobj.private); | ||
| } | ||
| out: | ||
| p->walking = false; | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| } | ||
| @@ -437,11 +438,11 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l | ||
| switch (op) { | ||
| case SOF_WIDGET_SETUP: | ||
| ret = sof_set_up_widgets_in_path(sdev, widget, dir); | ||
| ret = sof_set_up_widgets_in_path(sdev, widget, dir, list); | ||
| str = "set up"; | ||
| break; | ||
| case SOF_WIDGET_FREE: | ||
| ret = sof_free_widgets_in_path(sdev, widget, dir); | ||
| ret = sof_free_widgets_in_path(sdev, widget, dir, list); | ||
| str = "free"; | ||
| break; | ||
| case SOF_WIDGET_PREPARE: | ||
| @@ -457,12 +458,12 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l | ||
| */ | ||
| memcpy(&pipeline_params, fe_params, sizeof(*fe_params)); | ||
| ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, | ||
| platform_params, &pipeline_params, dir); | ||
| ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, platform_params, | ||
| &pipeline_params, dir, list); | ||
| break; | ||
| } | ||
| case SOF_WIDGET_UNPREPARE: | ||
| sof_unprepare_widgets_in_path(sdev, widget); | ||
| sof_unprepare_widgets_in_path(sdev, widget, list); | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "Invalid widget op %d\n", op); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How this happens?
We walk from source to sink, so walk through the widgets which are in the path.
How we are enabling a widget (which is in the path) which is not in the path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ujfalusi snd_soc_dapm_widget_for_each_sink_path() looks at all paths leaving the widget not just the ones that have an active DAPM widget associated with the PCM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ranj063, oh yes, I see now, thanks!