aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jhnikula@gmail.com>2010-12-14 05:18:31 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-12-15 13:01:01 -0500
commit97c866defc0fc6e18b49603ac19f732f53e79c46 (patch)
tree66ba8412fad0974ebf9a30c45ad5d81f26607e6e
parent8ddab3f5107c3955e70e87a632d4d179ddba1189 (diff)
ASoC: Move widgets from DAPM context to snd_soc_card
Decoupling widgets from DAPM context is required when extending the ASoC core to cross-device paths. Even the list of widgets are now kept in struct snd_soc_card, the widget listing in sysfs and debugs remain sorted per device. This patch makes possible to build cross-device paths but does not extend yet the DAPM to handle codec bias and widget power changes of an another device. Cross-device paths are registered by listing the widgets from device A in a map for device B. In case of conflicting widget names between the devices, a uniform name prefix is needed to separate them. See commit ead9b91 "ASoC: Add optional name_prefix for kcontrol, widget and route names" for help. An example below shows a path that connects MONO out of A into Line In of B: static const struct snd_soc_dapm_route mapA[] = { {"MONO", NULL, "DAC"}, }; static const struct snd_soc_dapm_route mapB[] = { {"Line In", NULL, "MONO"}, }; 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-dapm.h2
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/codecs/wm8960.c4
-rw-r--r--sound/soc/soc-core.c2
-rw-r--r--sound/soc/soc-dapm.c69
5 files changed, 55 insertions, 23 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 2c1e0eed43d5..c0e7c47469fc 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -462,7 +462,7 @@ struct snd_soc_dapm_widget {
462 462
463/* DAPM context */ 463/* DAPM context */
464struct snd_soc_dapm_context { 464struct snd_soc_dapm_context {
465 struct list_head widgets; 465 int n_widgets; /* number of widgets in this context */
466 enum snd_soc_bias_level bias_level; 466 enum snd_soc_bias_level bias_level;
467 enum snd_soc_bias_level suspend_bias_level; 467 enum snd_soc_bias_level suspend_bias_level;
468 struct delayed_work delayed_work; 468 struct delayed_work delayed_work;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 466895b627b5..d5fb8618fdba 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -661,6 +661,7 @@ struct snd_soc_card {
661 struct list_head platform_dev_list; 661 struct list_head platform_dev_list;
662 struct list_head dai_dev_list; 662 struct list_head dai_dev_list;
663 663
664 struct list_head widgets;
664 struct list_head paths; 665 struct list_head paths;
665 666
666#ifdef CONFIG_DEBUG_FS 667#ifdef CONFIG_DEBUG_FS
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 2c5712dce1d5..054f5737319c 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -418,7 +418,9 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
418 * list each time to find the desired power state do so now 418 * list each time to find the desired power state do so now
419 * and save the result. 419 * and save the result.
420 */ 420 */
421 list_for_each_entry(w, &codec->dapm.widgets, list) { 421 list_for_each_entry(w, &codec->card->widgets, list) {
422 if (w->dapm != &codec->dapm)
423 continue;
422 if (strcmp(w->name, "LOUT1 PGA") == 0) 424 if (strcmp(w->name, "LOUT1 PGA") == 0)
423 wm8960->lout1 = w; 425 wm8960->lout1 = w;
424 if (strcmp(w->name, "ROUT1 PGA") == 0) 426 if (strcmp(w->name, "ROUT1 PGA") == 0)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index bdb2ca9da58b..bd183a7ed696 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1879,6 +1879,7 @@ static int soc_probe(struct platform_device *pdev)
1879 INIT_LIST_HEAD(&card->dai_dev_list); 1879 INIT_LIST_HEAD(&card->dai_dev_list);
1880 INIT_LIST_HEAD(&card->codec_dev_list); 1880 INIT_LIST_HEAD(&card->codec_dev_list);
1881 INIT_LIST_HEAD(&card->platform_dev_list); 1881 INIT_LIST_HEAD(&card->platform_dev_list);
1882 INIT_LIST_HEAD(&card->widgets);
1882 INIT_LIST_HEAD(&card->paths); 1883 INIT_LIST_HEAD(&card->paths);
1883 1884
1884 soc_init_card_debugfs(card); 1885 soc_init_card_debugfs(card);
@@ -3481,7 +3482,6 @@ int snd_soc_register_codec(struct device *dev,
3481 else 3482 else
3482 codec->compress_type = SND_SOC_FLAT_COMPRESSION; 3483 codec->compress_type = SND_SOC_FLAT_COMPRESSION;
3483 3484
3484 INIT_LIST_HEAD(&codec->dapm.widgets);
3485 codec->write = codec_drv->write; 3485 codec->write = codec_drv->write;
3486 codec->read = codec_drv->read; 3486 codec->read = codec_drv->read;
3487 codec->dapm.bias_level = SND_SOC_BIAS_OFF; 3487 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 5d9ec4a3a9f1..8731e89646ae 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -940,7 +940,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
940 /* Check which widgets we need to power and store them in 940 /* Check which widgets we need to power and store them in
941 * lists indicating if they should be powered up or down. 941 * lists indicating if they should be powered up or down.
942 */ 942 */
943 list_for_each_entry(w, &dapm->widgets, list) { 943 list_for_each_entry(w, &card->widgets, list) {
944 if (w->dapm != dapm)
945 continue;
944 switch (w->id) { 946 switch (w->id) {
945 case snd_soc_dapm_pre: 947 case snd_soc_dapm_pre:
946 dapm_seq_insert(w, &down_list, dapm_down_seq); 948 dapm_seq_insert(w, &down_list, dapm_down_seq);
@@ -978,7 +980,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
978 /* If there are no DAPM widgets then try to figure out power from the 980 /* If there are no DAPM widgets then try to figure out power from the
979 * event type. 981 * event type.
980 */ 982 */
981 if (list_empty(&dapm->widgets)) { 983 if (!dapm->n_widgets) {
982 switch (event) { 984 switch (event) {
983 case SND_SOC_DAPM_STREAM_START: 985 case SND_SOC_DAPM_STREAM_START:
984 case SND_SOC_DAPM_STREAM_RESUME: 986 case SND_SOC_DAPM_STREAM_RESUME:
@@ -1145,8 +1147,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm)
1145 if (!dapm->debugfs_dapm) 1147 if (!dapm->debugfs_dapm)
1146 return; 1148 return;
1147 1149
1148 list_for_each_entry(w, &dapm->widgets, list) { 1150 list_for_each_entry(w, &dapm->card->widgets, list) {
1149 if (!w->name) 1151 if (!w->name || w->dapm != dapm)
1150 continue; 1152 continue;
1151 1153
1152 d = debugfs_create_file(w->name, 0444, 1154 d = debugfs_create_file(w->name, 0444,
@@ -1241,7 +1243,9 @@ static ssize_t dapm_widget_show(struct device *dev,
1241 int count = 0; 1243 int count = 0;
1242 char *state = "not set"; 1244 char *state = "not set";
1243 1245
1244 list_for_each_entry(w, &codec->dapm.widgets, list) { 1246 list_for_each_entry(w, &codec->card->widgets, list) {
1247 if (w->dapm != &codec->dapm)
1248 continue;
1245 1249
1246 /* only display widgets that burnm power */ 1250 /* only display widgets that burnm power */
1247 switch (w->id) { 1251 switch (w->id) {
@@ -1303,7 +1307,9 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
1303 struct snd_soc_dapm_widget *w, *next_w; 1307 struct snd_soc_dapm_widget *w, *next_w;
1304 struct snd_soc_dapm_path *p, *next_p; 1308 struct snd_soc_dapm_path *p, *next_p;
1305 1309
1306 list_for_each_entry_safe(w, next_w, &dapm->widgets, list) { 1310 list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
1311 if (w->dapm != dapm)
1312 continue;
1307 list_del(&w->list); 1313 list_del(&w->list);
1308 /* 1314 /*
1309 * remove source and sink paths associated to this widget. 1315 * remove source and sink paths associated to this widget.
@@ -1334,7 +1340,9 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
1334{ 1340{
1335 struct snd_soc_dapm_widget *w; 1341 struct snd_soc_dapm_widget *w;
1336 1342
1337 list_for_each_entry(w, &dapm->widgets, list) { 1343 list_for_each_entry(w, &dapm->card->widgets, list) {
1344 if (w->dapm != dapm)
1345 continue;
1338 if (!strcmp(w->name, pin)) { 1346 if (!strcmp(w->name, pin)) {
1339 dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n", 1347 dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n",
1340 pin, status); 1348 pin, status);
@@ -1370,6 +1378,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
1370{ 1378{
1371 struct snd_soc_dapm_path *path; 1379 struct snd_soc_dapm_path *path;
1372 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1380 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1381 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
1373 const char *sink; 1382 const char *sink;
1374 const char *control = route->control; 1383 const char *control = route->control;
1375 const char *source; 1384 const char *source;
@@ -1389,17 +1398,28 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
1389 source = route->source; 1398 source = route->source;
1390 } 1399 }
1391 1400
1392 /* find src and dest widgets */ 1401 /*
1393 list_for_each_entry(w, &dapm->widgets, list) { 1402 * find src and dest widgets over all widgets but favor a widget from
1394 1403 * current DAPM context
1404 */
1405 list_for_each_entry(w, &dapm->card->widgets, list) {
1395 if (!wsink && !(strcmp(w->name, sink))) { 1406 if (!wsink && !(strcmp(w->name, sink))) {
1396 wsink = w; 1407 wtsink = w;
1408 if (w->dapm == dapm)
1409 wsink = w;
1397 continue; 1410 continue;
1398 } 1411 }
1399 if (!wsource && !(strcmp(w->name, source))) { 1412 if (!wsource && !(strcmp(w->name, source))) {
1400 wsource = w; 1413 wtsource = w;
1414 if (w->dapm == dapm)
1415 wsource = w;
1401 } 1416 }
1402 } 1417 }
1418 /* use widget from another DAPM context if not found from this */
1419 if (!wsink)
1420 wsink = wtsink;
1421 if (!wsource)
1422 wsource = wtsource;
1403 1423
1404 if (wsource == NULL || wsink == NULL) 1424 if (wsource == NULL || wsink == NULL)
1405 return -ENODEV; 1425 return -ENODEV;
@@ -1537,7 +1557,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
1537{ 1557{
1538 struct snd_soc_dapm_widget *w; 1558 struct snd_soc_dapm_widget *w;
1539 1559
1540 list_for_each_entry(w, &dapm->widgets, list) 1560 list_for_each_entry(w, &dapm->card->widgets, list)
1541 { 1561 {
1542 if (w->new) 1562 if (w->new)
1543 continue; 1563 continue;
@@ -2037,12 +2057,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2037 else 2057 else
2038 snprintf(w->name, name_len, "%s", widget->name); 2058 snprintf(w->name, name_len, "%s", widget->name);
2039 2059
2060 dapm->n_widgets++;
2040 w->dapm = dapm; 2061 w->dapm = dapm;
2041 w->codec = dapm->codec; 2062 w->codec = dapm->codec;
2042 INIT_LIST_HEAD(&w->sources); 2063 INIT_LIST_HEAD(&w->sources);
2043 INIT_LIST_HEAD(&w->sinks); 2064 INIT_LIST_HEAD(&w->sinks);
2044 INIT_LIST_HEAD(&w->list); 2065 INIT_LIST_HEAD(&w->list);
2045 list_add(&w->list, &dapm->widgets); 2066 list_add(&w->list, &dapm->card->widgets);
2046 2067
2047 /* machine layer set ups unconnected pins and insertions */ 2068 /* machine layer set ups unconnected pins and insertions */
2048 w->connected = 1; 2069 w->connected = 1;
@@ -2085,9 +2106,9 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
2085{ 2106{
2086 struct snd_soc_dapm_widget *w; 2107 struct snd_soc_dapm_widget *w;
2087 2108
2088 list_for_each_entry(w, &dapm->widgets, list) 2109 list_for_each_entry(w, &dapm->card->widgets, list)
2089 { 2110 {
2090 if (!w->sname) 2111 if (!w->sname || w->dapm != dapm)
2091 continue; 2112 continue;
2092 dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", 2113 dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
2093 w->name, w->sname, stream, event); 2114 w->name, w->sname, stream, event);
@@ -2170,7 +2191,9 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
2170{ 2191{
2171 struct snd_soc_dapm_widget *w; 2192 struct snd_soc_dapm_widget *w;
2172 2193
2173 list_for_each_entry(w, &dapm->widgets, list) { 2194 list_for_each_entry(w, &dapm->card->widgets, list) {
2195 if (w->dapm != dapm)
2196 continue;
2174 if (!strcmp(w->name, pin)) { 2197 if (!strcmp(w->name, pin)) {
2175 dev_dbg(w->dapm->dev, 2198 dev_dbg(w->dapm->dev,
2176 "dapm: force enable pin %s\n", pin); 2199 "dapm: force enable pin %s\n", pin);
@@ -2235,7 +2258,9 @@ int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
2235{ 2258{
2236 struct snd_soc_dapm_widget *w; 2259 struct snd_soc_dapm_widget *w;
2237 2260
2238 list_for_each_entry(w, &dapm->widgets, list) { 2261 list_for_each_entry(w, &dapm->card->widgets, list) {
2262 if (w->dapm != dapm)
2263 continue;
2239 if (!strcmp(w->name, pin)) 2264 if (!strcmp(w->name, pin))
2240 return w->connected; 2265 return w->connected;
2241 } 2266 }
@@ -2260,7 +2285,9 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
2260{ 2285{
2261 struct snd_soc_dapm_widget *w; 2286 struct snd_soc_dapm_widget *w;
2262 2287
2263 list_for_each_entry(w, &dapm->widgets, list) { 2288 list_for_each_entry(w, &dapm->card->widgets, list) {
2289 if (w->dapm != dapm)
2290 continue;
2264 if (!strcmp(w->name, pin)) { 2291 if (!strcmp(w->name, pin)) {
2265 w->ignore_suspend = 1; 2292 w->ignore_suspend = 1;
2266 return 0; 2293 return 0;
@@ -2291,7 +2318,9 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
2291 LIST_HEAD(down_list); 2318 LIST_HEAD(down_list);
2292 int powerdown = 0; 2319 int powerdown = 0;
2293 2320
2294 list_for_each_entry(w, &dapm->widgets, list) { 2321 list_for_each_entry(w, &dapm->card->widgets, list) {
2322 if (w->dapm != dapm)
2323 continue;
2295 if (w->power) { 2324 if (w->power) {
2296 dapm_seq_insert(w, &down_list, dapm_down_seq); 2325 dapm_seq_insert(w, &down_list, dapm_down_seq);
2297 w->power = 0; 2326 w->power = 0;