Skip to content

Commit

Permalink
ASoC: dt: Allow Aux Codecs to be specified using DT
Browse files Browse the repository at this point in the history
This patch adds support for specifying auxiliary codecs and
codec configuration via device tree phandles.

This change adds new fields to snd_soc_aux_dev and snd_soc_codec_conf
and adds support for the changes to SoC core methods.

Signed-off-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
  • Loading branch information
Sebastian Reichel authored and Mark Brown committed May 1, 2014
1 parent c9eaa44 commit 3ca041e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 27 deletions.
13 changes: 12 additions & 1 deletion include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
68 changes: 42 additions & 26 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,10 +1104,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;
}
}

Expand Down Expand Up @@ -1541,52 +1543,66 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
}
#endif

static int soc_check_aux_dev(struct snd_soc_card *card, int num)
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;
}

Expand Down

0 comments on commit 3ca041e

Please sign in to comment.