diff --git a/include/sound/soc.h b/include/sound/soc.h index b9ee22018352..c9ae1271281e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -931,7 +931,12 @@ struct snd_soc_dai_link { }; struct snd_soc_codec_conf { + /* + * specify device either by device name, or by + * DT/OF node, but not both. + */ const char *dev_name; + const struct device_node *of_node; /* * optional map of kcontrol, widget and path name prefixes that are @@ -942,7 +947,13 @@ struct snd_soc_codec_conf { struct snd_soc_aux_dev { const char *name; /* Codec name */ - const char *codec_name; /* for multi-codec */ + + /* + * specify multi-codec either by device name, or by + * DT/OF node, but not both. + */ + const char *codec_name; + const struct device_node *codec_of_node; /* codec/machine specific init - e.g. add machine controls */ int (*init)(struct snd_soc_dapm_context *dapm); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a675eec64756..a53698266d57 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1117,10 +1117,12 @@ static void soc_set_name_prefix(struct snd_soc_card *card, for (i = 0; i < card->num_configs; i++) { struct snd_soc_codec_conf *map = &card->codec_conf[i]; - if (map->dev_name && !strcmp(codec->name, map->dev_name)) { - codec->name_prefix = map->name_prefix; - break; - } + if (map->of_node && codec->dev->of_node != map->of_node) + continue; + if (map->dev_name && strcmp(codec->name, map->dev_name)) + continue; + codec->name_prefix = map->name_prefix; + break; } } @@ -1596,52 +1598,67 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) } #endif -static int soc_check_aux_dev(struct snd_soc_card *card, int num) +static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card, + int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_codec *codec; - /* find CODEC from registered CODECs*/ + /* find CODEC from registered CODECs */ list_for_each_entry(codec, &codec_list, list) { - if (!strcmp(codec->name, aux_dev->codec_name)) - return 0; + if (aux_dev->codec_of_node && + (codec->dev->of_node != aux_dev->codec_of_node)) + continue; + if (aux_dev->codec_name && strcmp(codec->name, aux_dev->codec_name)) + continue; + return codec; } - dev_err(card->dev, "ASoC: %s not registered\n", aux_dev->codec_name); + return NULL; +} +static int soc_check_aux_dev(struct snd_soc_card *card, int num) +{ + struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; + const char *codecname = aux_dev->codec_name; + struct snd_soc_codec *codec = soc_find_matching_codec(card, num); + + if (codec) + return 0; + if (aux_dev->codec_of_node) + codecname = of_node_full_name(aux_dev->codec_of_node); + + dev_err(card->dev, "ASoC: %s not registered\n", codecname); return -EPROBE_DEFER; } static int soc_probe_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; - struct snd_soc_codec *codec; + const char *codecname = aux_dev->codec_name; int ret = -ENODEV; + struct snd_soc_codec *codec = soc_find_matching_codec(card, num); - /* find CODEC from registered CODECs*/ - list_for_each_entry(codec, &codec_list, list) { - if (!strcmp(codec->name, aux_dev->codec_name)) { - if (codec->probed) { - dev_err(codec->dev, - "ASoC: codec already probed"); - ret = -EBUSY; - goto out; - } - goto found; - } + if (!codec) { + if (aux_dev->codec_of_node) + codecname = of_node_full_name(aux_dev->codec_of_node); + + /* codec not found */ + dev_err(card->dev, "ASoC: codec %s not found", codecname); + return -EPROBE_DEFER; + } + + if (codec->probed) { + dev_err(codec->dev, "ASoC: codec already probed"); + return -EBUSY; } - /* codec not found */ - dev_err(card->dev, "ASoC: codec %s not found", aux_dev->codec_name); - return -EPROBE_DEFER; -found: ret = soc_probe_codec(card, codec); if (ret < 0) return ret; ret = soc_post_component_init(card, codec, num, 1); -out: return ret; }