From c471fdd1b6f41a8e4efc8ca684e47005e7ebbb61 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 29 Apr 2014 14:51:22 +0200 Subject: [PATCH 1/7] ASoC: dapm: Factor out duplicated code in soc_dapm_stream_event() In soc_dapm_stream_event() we have the same code twice, once for the codec_dai and once for the cpu_dai. This patch factors the duplicated code out into a separate function. This will make it easier to modify the implementation (since there is only one place that needs to be updated) and also easier to add support for more than two DAIs per DAI link. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 81 +++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f4ba7b40a6ab..9e7209c06358 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3510,59 +3510,40 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) } } +static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, + int event) +{ + struct snd_soc_dapm_widget *w; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + w = dai->playback_widget; + else + w = dai->capture_widget; + + if (w) { + dapm_mark_dirty(w, "stream event"); + + switch (event) { + case SND_SOC_DAPM_STREAM_START: + w->active = 1; + break; + case SND_SOC_DAPM_STREAM_STOP: + w->active = 0; + break; + case SND_SOC_DAPM_STREAM_SUSPEND: + case SND_SOC_DAPM_STREAM_RESUME: + case SND_SOC_DAPM_STREAM_PAUSE_PUSH: + case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: + break; + } + } +} + static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event) { - - struct snd_soc_dapm_widget *w_cpu, *w_codec; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - w_cpu = cpu_dai->playback_widget; - w_codec = codec_dai->playback_widget; - } else { - w_cpu = cpu_dai->capture_widget; - w_codec = codec_dai->capture_widget; - } - - if (w_cpu) { - - dapm_mark_dirty(w_cpu, "stream event"); - - switch (event) { - case SND_SOC_DAPM_STREAM_START: - w_cpu->active = 1; - break; - case SND_SOC_DAPM_STREAM_STOP: - w_cpu->active = 0; - break; - case SND_SOC_DAPM_STREAM_SUSPEND: - case SND_SOC_DAPM_STREAM_RESUME: - case SND_SOC_DAPM_STREAM_PAUSE_PUSH: - case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: - break; - } - } - - if (w_codec) { - - dapm_mark_dirty(w_codec, "stream event"); - - switch (event) { - case SND_SOC_DAPM_STREAM_START: - w_codec->active = 1; - break; - case SND_SOC_DAPM_STREAM_STOP: - w_codec->active = 0; - break; - case SND_SOC_DAPM_STREAM_SUSPEND: - case SND_SOC_DAPM_STREAM_RESUME: - case SND_SOC_DAPM_STREAM_PAUSE_PUSH: - case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: - break; - } - } + soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); + soc_dapm_dai_stream_event(rtd->codec_dai, stream, event); dapm_power_widgets(rtd->card, event); } From c9e065c27fe9b81e5d6e7681d77a24f7b9616675 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 4 May 2014 19:17:05 +0200 Subject: [PATCH 2/7] ASoC: dapm: Make sure to always update the DAPM graph in _put_volsw() When using auto-muted controls it may happen that the register value will not change when changing a control from enabled to disabled (since the control might be physically disabled due to the auto-muting). We have to make sure to still update the DAPM graph and disconnect the mixer input. Fixes: commit 5729507 ("ASoC: dapm: Implement mixer input auto-disable") Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1e171bd31f2a..fb6c7b793459 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2792,22 +2792,19 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); change = dapm_kcontrol_set_value(kcontrol, val); - - if (reg != SND_SOC_NOPM) { - mask = mask << shift; - val = val << shift; - - change = snd_soc_test_bits(codec, reg, mask, val); - } - if (change) { if (reg != SND_SOC_NOPM) { - update.kcontrol = kcontrol; - update.reg = reg; - update.mask = mask; - update.val = val; + mask = mask << shift; + val = val << shift; + + if (snd_soc_test_bits(codec, reg, mask, val)) { + update.kcontrol = kcontrol; + update.reg = reg; + update.mask = mask; + update.val = val; + card->update = &update; + } - card->update = &update; } ret = soc_dapm_mixer_update_power(card, kcontrol, connect); From a4e9154c429abde956fad10f7c7e7e50d6a1da9f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 May 2014 16:20:25 +0200 Subject: [PATCH 3/7] ASoC: dapm: Revert "ASoC: dapm: Fix double prefix addition" This reverts commit bd23c5b661858446267f4d6b2fb4edd8eb710dda. The patch claims that the patch is necessary to avoid double prefix addition when calling snd_soc_dapm_add_route() from snd_soc_dapm_connect_dai_link_widgets(). But snd_soc_dapm_add_route() is called with the card's DAPM context, which does not have a prefix, which means there is no prefix that could be added a second time. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fb6c7b793459..10ed22f457b8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2381,8 +2381,7 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, } static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_route *route, - unsigned int is_prefixed) + const struct snd_soc_dapm_route *route) { struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; @@ -2392,7 +2391,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, char prefixed_source[80]; int ret; - if (dapm->codec && dapm->codec->name_prefix && !is_prefixed) { + if (dapm->codec && dapm->codec->name_prefix) { snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", dapm->codec->name_prefix, route->sink); sink = prefixed_sink; @@ -2520,7 +2519,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { - r = snd_soc_dapm_add_route(dapm, route, false); + r = snd_soc_dapm_add_route(dapm, route); if (r < 0) { dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n", route->source, @@ -3427,7 +3426,7 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) cpu_dai->codec->name, r.source, codec_dai->platform->name, r.sink); - snd_soc_dapm_add_route(&card->dapm, &r, true); + snd_soc_dapm_add_route(&card->dapm, &r); } /* connect BE DAI capture if widgets are valid */ @@ -3438,7 +3437,7 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) codec_dai->codec->name, r.source, cpu_dai->platform->name, r.sink); - snd_soc_dapm_add_route(&card->dapm, &r, true); + snd_soc_dapm_add_route(&card->dapm, &r); } } From 9887c20b9fea415ade824fddd9f9ceaf3a3e72bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 May 2014 16:20:26 +0200 Subject: [PATCH 4/7] ASoC: dapm: Use snd_soc_dapm_add_path() in connect_dai_link_widgets() We already know which two widgets should be connected, so use snd_soc_dapm_add_path() instead of snd_soc_dapm_add_route() in snd_soc_dapm_connect_dai_link_widgets(). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 10ed22f457b8..ac8897ecd72e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3397,12 +3397,10 @@ 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) { struct snd_soc_pcm_runtime *rtd = card->rtd; + struct snd_soc_dapm_widget *sink, *source; struct snd_soc_dai *cpu_dai, *codec_dai; - struct snd_soc_dapm_route r; int i; - memset(&r, 0, sizeof(r)); - /* for each BE DAI link... */ for (i = 0; i < card->num_rtd; i++) { rtd = &card->rtd[i]; @@ -3420,26 +3418,27 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) /* connect BE DAI playback if widgets are valid */ if (codec_dai->playback_widget && cpu_dai->playback_widget) { - r.source = cpu_dai->playback_widget->name; - r.sink = codec_dai->playback_widget->name; + source = cpu_dai->playback_widget; + sink = codec_dai->playback_widget; dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - cpu_dai->codec->name, r.source, - codec_dai->platform->name, r.sink); + cpu_dai->codec->name, source->name, + codec_dai->platform->name, sink->name); - snd_soc_dapm_add_route(&card->dapm, &r); + snd_soc_dapm_add_path(&card->dapm, source, sink, + NULL, NULL); } /* connect BE DAI capture if widgets are valid */ if (codec_dai->capture_widget && cpu_dai->capture_widget) { - r.source = codec_dai->capture_widget->name; - r.sink = cpu_dai->capture_widget->name; + source = codec_dai->capture_widget; + sink = cpu_dai->capture_widget; dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - codec_dai->codec->name, r.source, - cpu_dai->platform->name, r.sink); + codec_dai->codec->name, source->name, + cpu_dai->platform->name, sink->name); - snd_soc_dapm_add_route(&card->dapm, &r); + snd_soc_dapm_add_path(&card->dapm, source, sink, + NULL, NULL); } - } } From fe83897fc5b519b085f545d5cee2b722ed4f6d85 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 May 2014 16:20:27 +0200 Subject: [PATCH 5/7] ASoC: dapm: Use snd_soc_dapm_add_path() in snd_soc_dapm_new_pcm() We already know the widgets we want to connect, so use snd_soc_dapm_add_path() instead of snd_soc_dapm_add_route() in snd_soc_dapm_new_pcm(). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ac8897ecd72e..21ecf9a37d00 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3242,11 +3242,11 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink) { - struct snd_soc_dapm_route routes[2]; struct snd_soc_dapm_widget template; struct snd_soc_dapm_widget *w; size_t len; char *link_name; + int ret; len = strlen(source->name) + strlen(sink->name) + 2; link_name = devm_kzalloc(card->dev, len, GFP_KERNEL); @@ -3273,15 +3273,10 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, w->params = params; - memset(&routes, 0, sizeof(routes)); - - routes[0].source = source->name; - routes[0].sink = link_name; - routes[1].source = link_name; - routes[1].sink = sink->name; - - return snd_soc_dapm_add_routes(&card->dapm, routes, - ARRAY_SIZE(routes)); + ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL); + if (ret) + return ret; + return snd_soc_dapm_add_path(&card->dapm, w, sink, NULL, NULL); } int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, From 0f9bd7b19467b9454a8e3729406f4cdcaaa32814 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 May 2014 16:20:28 +0200 Subject: [PATCH 6/7] ASoC: dapm: Simplify snd_soc_dapm_link_dai_widgets() If we find a widget who's stream name matches the name of a DAI widget then thats the one it should be connected to. Based on the widget id we can say in which direction the path should be. No need to go back to the DAI and check the stream names. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 21ecf9a37d00..d0c61c120ac1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3334,6 +3334,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) { struct snd_soc_dapm_widget *dai_w, *w; + struct snd_soc_dapm_widget *src, *sink; struct snd_soc_dai *dai; /* For each DAI widget... */ @@ -3364,25 +3365,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) if (!w->sname || !strstr(w->sname, dai_w->name)) continue; - if (dai->driver->playback.stream_name && - strstr(w->sname, - dai->driver->playback.stream_name)) { - dev_dbg(dai->dev, "%s -> %s\n", - dai->playback_widget->name, w->name); - - snd_soc_dapm_add_path(w->dapm, - dai->playback_widget, w, NULL, NULL); - } - - if (dai->driver->capture.stream_name && - strstr(w->sname, - dai->driver->capture.stream_name)) { - dev_dbg(dai->dev, "%s -> %s\n", - w->name, dai->capture_widget->name); - - snd_soc_dapm_add_path(w->dapm, w, - dai->capture_widget, NULL, NULL); + if (dai_w->id == snd_soc_dapm_dai_in) { + src = dai_w; + sink = w; + } else { + src = w; + sink = dai_w; } + dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name); + snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL); } } From 94986198f5e1f949b2b78373b8a4da803cdcc7f3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 11 May 2014 19:27:47 +0200 Subject: [PATCH 7/7] ASoC: dapm: Handle SND_SOC_DAPM_REG() generically Commit commit de9ba98b6d ("ASoC: dapm: Make widget power register settings more flexible") added generic support for on_val/off_val in the DAPM core. With this in place there is no need anymore for having a special event callback for SND_SOC_DAPM_REG() widgets. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 7 ++----- sound/soc/soc-dapm.c | 20 -------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 75020f52acdd..5932d66fd654 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -256,9 +256,8 @@ struct device; /* generic widgets */ #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ { .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ - .reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \ - .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} + .reg = wreg, .shift = wshift, .mask = wmask, \ + .on_val = won_val, .off_val = woff_val, } #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ { .id = snd_soc_dapm_supply, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ @@ -362,8 +361,6 @@ struct regulator; struct snd_soc_dapm_widget_list; struct snd_soc_dapm_update; -int dapm_reg_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event); int dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int dapm_clock_event(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d0c61c120ac1..98e20de50e2d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1058,26 +1058,6 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, return paths; } -/* - * Handler for generic register modifier widget. - */ -int dapm_reg_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - unsigned int val; - - if (SND_SOC_DAPM_EVENT_ON(event)) - val = w->on_val; - else - val = w->off_val; - - soc_widget_update_bits(w, -(w->reg + 1), - w->mask << w->shift, val << w->shift); - - return 0; -} -EXPORT_SYMBOL_GPL(dapm_reg_event); - /* * Handler for regulator supply widget. */