diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index f24eafefbdff..33c4a3e9c1d4 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); @@ -686,6 +687,7 @@ int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); +bool snd_soc_dapm_pin_has_prefix(struct snd_soc_card *card, const char *pin); void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card); /* dapm path query */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 967b68d4d142..77a7539ef37f 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; @@ -1337,6 +1341,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/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c index 40e0043cfe15..fd4624786b62 100644 --- a/sound/soc/fsl/imx-rpmsg.c +++ b/sound/soc/fsl/imx-rpmsg.c @@ -87,7 +87,6 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) int ret; if (data->lpa) { - struct snd_soc_component *codec_comp; struct device_node *codec_np; struct device_driver *codec_drv; struct device *codec_dev = NULL; @@ -107,22 +106,6 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) } } if (codec_dev) { - codec_comp = snd_soc_lookup_component_nolocked(codec_dev, NULL); - if (codec_comp) { - int i, num_widgets; - const char *widgets; - struct snd_soc_dapm_context *dapm; - - num_widgets = of_property_count_strings(data->card.dev->of_node, - "ignore-suspend-widgets"); - for (i = 0; i < num_widgets; i++) { - of_property_read_string_index(data->card.dev->of_node, - "ignore-suspend-widgets", - i, &widgets); - dapm = snd_soc_component_to_dapm(codec_comp); - snd_soc_dapm_ignore_suspend(dapm, widgets); - } - } codec_drv = codec_dev->driver; if (codec_drv->pm) { memcpy(&lpa_pm, codec_drv->pm, sizeof(lpa_pm)); @@ -274,6 +257,15 @@ static int imx_rpmsg_probe(struct platform_device *pdev) } } + if (data->lpa && of_property_present(np, "ignore-suspend-widgets")) { + ret = snd_soc_of_parse_ignore_suspend_widgets(&data->card, + "ignore-suspend-widgets"); + if (ret) { + dev_err(&pdev->dev, "failed to parse ignore-suspend-widgets: %d\n", ret); + goto fail; + } + } + platform_set_drvdata(pdev, &data->card); snd_soc_card_set_drvdata(&data->card, data); ret = devm_snd_soc_register_card(&pdev->dev, &data->card); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2c05299604b3..ec744b9d6fd1 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); @@ -3279,6 +3283,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 10f5fb771e30..4ad126bd4f70 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2912,20 +2912,18 @@ static struct snd_soc_dapm_widget *dapm_find_widget( { struct snd_soc_dapm_widget *w; struct snd_soc_dapm_widget *fallback = NULL; - char prefixed_pin[80]; - const char *pin_name; - const char *prefix = dapm_prefix(dapm); - - if (prefix) { - snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s", - prefix, pin); - pin_name = prefixed_pin; - } else { - pin_name = pin; - } + bool pin_has_prefix = snd_soc_dapm_pin_has_prefix(dapm->card, pin); + bool match; for_each_card_widgets(dapm->card, w) { - if (!strcmp(w->name, pin_name)) { + match = false; + + if (!strcmp(pin, w->name)) + match = true; + else if (!pin_has_prefix && !snd_soc_dapm_widget_name_cmp(w, pin)) + match = true; + + if (match) { if (w->dapm == dapm) return w; else @@ -4612,6 +4610,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; @@ -4878,6 +4906,33 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, } EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); +/** + * snd_soc_dapm_pin_has_prefix - check if given pin has a known prefix + * @card: card to be checked + * @pin: pin name + * + * Returns true if given pin has a known prefix + */ +bool snd_soc_dapm_pin_has_prefix(struct snd_soc_card *card, const char *pin) +{ + struct snd_soc_component *component; + const char *prefix; + size_t prefix_len; + + for_each_card_components(card, component) { + prefix = component->name_prefix; + if (!prefix) + continue; + + prefix_len = strlen(prefix); + if (!strncmp(pin, prefix, prefix_len) && pin[prefix_len] == ' ') + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_pin_has_prefix); + /** * snd_soc_dapm_free - free dapm resources * @dapm: DAPM context