diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c1e4f467efda..b0a135b9af50 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -636,6 +636,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_s void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); +int snd_soc_dapm_ignore_suspend_widgets(struct snd_soc_card *card); int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e3eb617d832..7d6fa79f48e3 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1057,10 +1057,14 @@ struct snd_soc_card { int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; int num_dapm_routes; + const char **ignore_suspend_widgets; + int num_ignore_suspend_widgets; const struct snd_soc_dapm_widget *of_dapm_widgets; int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; + const char **of_ignore_suspend_widgets; + int num_of_ignore_suspend_widgets; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; @@ -1339,6 +1343,7 @@ void snd_soc_of_parse_node_prefix(struct device_node *np, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_ignore_suspend_widgets(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt); unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3fecf9fc903c..705181dae472 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2289,6 +2289,10 @@ static int snd_soc_bind_card(struct snd_soc_card *card) if (ret < 0) goto probe_end; + ret = snd_soc_dapm_ignore_suspend_widgets(card); + if (ret < 0) + goto probe_end; + snd_soc_dapm_new_widgets(card); snd_soc_card_fixup_controls(card); @@ -3294,6 +3298,45 @@ int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname) } EXPORT_SYMBOL_GPL(snd_soc_of_parse_aux_devs); +int snd_soc_of_parse_ignore_suspend_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + int num_widgets; + const char **widgets; + int i; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(char *), GFP_KERNEL); + if (!widgets) + return -ENOMEM; + + for (i = 0; i < num_widgets; i++) { + const char *name; + int ret = of_property_read_string_index(np, propname, i, &name); + + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' could not be read: %d\n", + propname, ret); + return -EINVAL; + } + widgets[i] = name; + } + + card->num_of_ignore_suspend_widgets = num_widgets; + card->of_ignore_suspend_widgets = widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_ignore_suspend_widgets); + unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt) { unsigned int inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a26771c8e6ee..4e3feb43836c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4604,6 +4604,36 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) } } +int snd_soc_dapm_ignore_suspend_widgets(struct snd_soc_card *card) +{ + struct snd_soc_dapm_widget *w; + int i; + + for (i = 0; i < card->num_ignore_suspend_widgets; i++) { + w = dapm_find_widget(snd_soc_card_to_dapm(card), + card->ignore_suspend_widgets[i], true); + if (!w) { + dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n", + card->ignore_suspend_widgets[i]); + return -EINVAL; + } + w->ignore_suspend = 1; + } + + for (i = 0; i < card->num_of_ignore_suspend_widgets; i++) { + w = dapm_find_widget(snd_soc_card_to_dapm(card), + card->of_ignore_suspend_widgets[i], true); + if (!w) { + dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n", + card->of_ignore_suspend_widgets[i]); + return -EINVAL; + } + w->ignore_suspend = 1; + } + + return 0; +} + static void dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event) { struct snd_soc_dai *dai;