aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jhnikula@gmail.com>2010-11-13 13:40:44 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-11-15 10:24:58 -0500
commitead9b9199c09653dd9b889933c7af75f020c7286 (patch)
tree54ea7e4e8b8954236387f1131a9a09e305704c46
parent6ccd744123679c1f19fb6e414e3df717d9ed57f6 (diff)
ASoC: Add optional name_prefix for codec kcontrol, widget and route names
There is a need to prefix codec kcontrol, widget and internal route names in an ASoC machine that has multiple codecs with conflicting names. The name collision would occur when codec drivers try to registering kcontrols with the same name or when building audio paths. This patch introduces optional prefix_map into struct snd_soc_card. With it machine drivers can specify a unique name prefix to each codec that have conflicting names with anothers. Prefix to codec is matched with codec name. Following example illustrates a machine that has two same codec instances. Name collision from kcontrol registration is avoided by specifying a name prefix "foo" for the second codec. As the codec widget names are prefixed then second audio map for that codec shows a prefixed widget name. static const struct snd_soc_dapm_route map0[] = { {"Spk", NULL, "MONO"}, }; static const struct snd_soc_dapm_route map1[] = { {"Vibra", NULL, "foo MONO"}, }; static struct snd_soc_prefix_map codec_prefix[] = { { .dev_name = "codec.2", .name_prefix = "foo", }, }; static struct snd_soc_card card = { ... .prefix_map = codec_prefix, .num_prefixes = ARRAY_SIZE(codec_prefix), }; Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--include/sound/soc.h13
-rw-r--r--sound/soc/soc-core.c35
-rw-r--r--sound/soc/soc-dapm.c34
3 files changed, 78 insertions, 4 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index af23f4228869..3eb92ef6c83f 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -450,6 +450,7 @@ struct snd_soc_cache_ops {
450/* SoC Audio Codec device */ 450/* SoC Audio Codec device */
451struct snd_soc_codec { 451struct snd_soc_codec {
452 const char *name; 452 const char *name;
453 const char *name_prefix;
453 int id; 454 int id;
454 struct device *dev; 455 struct device *dev;
455 struct snd_soc_codec_driver *driver; 456 struct snd_soc_codec_driver *driver;
@@ -577,6 +578,11 @@ struct snd_soc_dai_link {
577 struct snd_soc_ops *ops; 578 struct snd_soc_ops *ops;
578}; 579};
579 580
581struct snd_soc_prefix_map {
582 const char *dev_name;
583 const char *name_prefix;
584};
585
580/* SoC card */ 586/* SoC card */
581struct snd_soc_card { 587struct snd_soc_card {
582 const char *name; 588 const char *name;
@@ -611,6 +617,13 @@ struct snd_soc_card {
611 struct snd_soc_pcm_runtime *rtd; 617 struct snd_soc_pcm_runtime *rtd;
612 int num_rtd; 618 int num_rtd;
613 619
620 /*
621 * optional map of kcontrol, widget and path name prefixes that are
622 * associated per device
623 */
624 struct snd_soc_prefix_map *prefix_map;
625 int num_prefixes;
626
614 struct work_struct deferred_resume_work; 627 struct work_struct deferred_resume_work;
615 628
616 /* lists of probed devices belonging to this card */ 629 /* lists of probed devices belonging to this card */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3d70ce58d03c..2540efd67ee7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1397,6 +1397,23 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
1397 } 1397 }
1398} 1398}
1399 1399
1400static void soc_set_name_prefix(struct snd_soc_card *card,
1401 struct snd_soc_codec *codec)
1402{
1403 int i;
1404
1405 if (card->prefix_map == NULL)
1406 return;
1407
1408 for (i = 0; i < card->num_prefixes; i++) {
1409 struct snd_soc_prefix_map *map = &card->prefix_map[i];
1410 if (map->dev_name && !strcmp(codec->name, map->dev_name)) {
1411 codec->name_prefix = map->name_prefix;
1412 break;
1413 }
1414 }
1415}
1416
1400static void rtd_release(struct device *dev) {} 1417static void rtd_release(struct device *dev) {}
1401 1418
1402static int soc_probe_dai_link(struct snd_soc_card *card, int num) 1419static int soc_probe_dai_link(struct snd_soc_card *card, int num)
@@ -1406,6 +1423,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
1406 struct snd_soc_codec *codec = rtd->codec; 1423 struct snd_soc_codec *codec = rtd->codec;
1407 struct snd_soc_platform *platform = rtd->platform; 1424 struct snd_soc_platform *platform = rtd->platform;
1408 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; 1425 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
1426 const char *temp;
1409 int ret; 1427 int ret;
1410 1428
1411 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); 1429 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
@@ -1440,6 +1458,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
1440 /* probe the CODEC */ 1458 /* probe the CODEC */
1441 if (!codec->probed) { 1459 if (!codec->probed) {
1442 codec->dapm.card = card; 1460 codec->dapm.card = card;
1461 soc_set_name_prefix(card, codec);
1443 if (codec->driver->probe) { 1462 if (codec->driver->probe) {
1444 ret = codec->driver->probe(codec); 1463 ret = codec->driver->probe(codec);
1445 if (ret < 0) { 1464 if (ret < 0) {
@@ -1492,11 +1511,15 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
1492 1511
1493 /* now that all clients have probed, initialise the DAI link */ 1512 /* now that all clients have probed, initialise the DAI link */
1494 if (dai_link->init) { 1513 if (dai_link->init) {
1514 /* machine controls, routes and widgets are not prefixed */
1515 temp = rtd->codec->name_prefix;
1516 rtd->codec->name_prefix = NULL;
1495 ret = dai_link->init(rtd); 1517 ret = dai_link->init(rtd);
1496 if (ret < 0) { 1518 if (ret < 0) {
1497 printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); 1519 printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name);
1498 return ret; 1520 return ret;
1499 } 1521 }
1522 rtd->codec->name_prefix = temp;
1500 } 1523 }
1501 1524
1502 /* Make sure all DAPM widgets are instantiated */ 1525 /* Make sure all DAPM widgets are instantiated */
@@ -2072,14 +2095,22 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
2072 const struct snd_kcontrol_new *controls, int num_controls) 2095 const struct snd_kcontrol_new *controls, int num_controls)
2073{ 2096{
2074 struct snd_card *card = codec->card->snd_card; 2097 struct snd_card *card = codec->card->snd_card;
2098 char prefixed_name[44], *name;
2075 int err, i; 2099 int err, i;
2076 2100
2077 for (i = 0; i < num_controls; i++) { 2101 for (i = 0; i < num_controls; i++) {
2078 const struct snd_kcontrol_new *control = &controls[i]; 2102 const struct snd_kcontrol_new *control = &controls[i];
2079 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); 2103 if (codec->name_prefix) {
2104 snprintf(prefixed_name, sizeof(prefixed_name), "%s %s",
2105 codec->name_prefix, control->name);
2106 name = prefixed_name;
2107 } else {
2108 name = control->name;
2109 }
2110 err = snd_ctl_add(card, snd_soc_cnew(control, codec, name));
2080 if (err < 0) { 2111 if (err < 0) {
2081 dev_err(codec->dev, "%s: Failed to add %s: %d\n", 2112 dev_err(codec->dev, "%s: Failed to add %s: %d\n",
2082 codec->name, control->name, err); 2113 codec->name, name, err);
2083 return err; 2114 return err;
2084 } 2115 }
2085 } 2116 }
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index bc2ec06943c0..60c8dec49480 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1295,6 +1295,7 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
1295 1295
1296 list_for_each_entry_safe(w, next_w, &dapm->widgets, list) { 1296 list_for_each_entry_safe(w, next_w, &dapm->widgets, list) {
1297 list_del(&w->list); 1297 list_del(&w->list);
1298 kfree(w->name);
1298 kfree(w); 1299 kfree(w);
1299 } 1300 }
1300 1301
@@ -1346,11 +1347,25 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
1346{ 1347{
1347 struct snd_soc_dapm_path *path; 1348 struct snd_soc_dapm_path *path;
1348 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1349 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1349 const char *sink = route->sink; 1350 const char *sink;
1350 const char *control = route->control; 1351 const char *control = route->control;
1351 const char *source = route->source; 1352 const char *source;
1353 char prefixed_sink[80];
1354 char prefixed_source[80];
1352 int ret = 0; 1355 int ret = 0;
1353 1356
1357 if (dapm->codec->name_prefix) {
1358 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
1359 dapm->codec->name_prefix, route->sink);
1360 sink = prefixed_sink;
1361 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
1362 dapm->codec->name_prefix, route->source);
1363 source = prefixed_source;
1364 } else {
1365 sink = route->sink;
1366 source = route->source;
1367 }
1368
1354 /* find src and dest widgets */ 1369 /* find src and dest widgets */
1355 list_for_each_entry(w, &dapm->widgets, list) { 1370 list_for_each_entry(w, &dapm->widgets, list) {
1356 1371
@@ -1978,10 +1993,25 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
1978 const struct snd_soc_dapm_widget *widget) 1993 const struct snd_soc_dapm_widget *widget)
1979{ 1994{
1980 struct snd_soc_dapm_widget *w; 1995 struct snd_soc_dapm_widget *w;
1996 size_t name_len;
1981 1997
1982 if ((w = dapm_cnew_widget(widget)) == NULL) 1998 if ((w = dapm_cnew_widget(widget)) == NULL)
1983 return -ENOMEM; 1999 return -ENOMEM;
1984 2000
2001 name_len = strlen(widget->name) + 1;
2002 if (dapm->codec->name_prefix)
2003 name_len += 1 + strlen(dapm->codec->name_prefix);
2004 w->name = kmalloc(name_len, GFP_KERNEL);
2005 if (w->name == NULL) {
2006 kfree(w);
2007 return -ENOMEM;
2008 }
2009 if (dapm->codec->name_prefix)
2010 snprintf(w->name, name_len, "%s %s",
2011 dapm->codec->name_prefix, widget->name);
2012 else
2013 snprintf(w->name, name_len, "%s", widget->name);
2014
1985 w->dapm = dapm; 2015 w->dapm = dapm;
1986 w->codec = dapm->codec; 2016 w->codec = dapm->codec;
1987 INIT_LIST_HEAD(&w->sources); 2017 INIT_LIST_HEAD(&w->sources);