summaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c189
1 files changed, 82 insertions, 107 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 879cf1be67a9..f61c8633e7eb 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -71,9 +71,9 @@ static int dapm_up_seq[] = {
[snd_soc_dapm_pinctrl] = 2,
[snd_soc_dapm_clock_supply] = 2,
[snd_soc_dapm_supply] = 3,
+ [snd_soc_dapm_dai_link] = 3,
[snd_soc_dapm_micbias] = 4,
[snd_soc_dapm_vmid] = 4,
- [snd_soc_dapm_dai_link] = 3,
[snd_soc_dapm_dai_in] = 5,
[snd_soc_dapm_dai_out] = 5,
[snd_soc_dapm_aif_in] = 5,
@@ -652,10 +652,8 @@ static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
}
static struct snd_soc_dapm_widget *
-dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
+dapm_wcache_lookup(struct snd_soc_dapm_widget *w, const char *name)
{
- struct snd_soc_dapm_widget *w = wcache->widget;
-
if (w) {
struct list_head *wlist = &w->dapm->card->widgets;
const int depth = 2;
@@ -673,12 +671,6 @@ dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
return NULL;
}
-static inline void dapm_wcache_update(struct snd_soc_dapm_wcache *wcache,
- struct snd_soc_dapm_widget *w)
-{
- wcache->widget = w;
-}
-
/**
* snd_soc_dapm_force_bias_level() - Sets the DAPM bias level
* @dapm: The DAPM context for which to set the level
@@ -1881,58 +1873,52 @@ static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
dapm_mark_dirty(peer, "peer state change");
}
-static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
+static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
struct list_head *up_list,
struct list_head *down_list)
{
struct snd_soc_dapm_path *path;
+ int power;
+
+ switch (w->id) {
+ case snd_soc_dapm_pre:
+ power = 0;
+ goto end;
+ case snd_soc_dapm_post:
+ power = 1;
+ goto end;
+ default:
+ break;
+ }
+
+ power = dapm_widget_power_check(w);
if (w->power == power)
return;
trace_snd_soc_dapm_widget_power(w, power);
- /* If we changed our power state perhaps our neigbours changed
- * also.
+ /*
+ * If we changed our power state perhaps our neigbours
+ * changed also.
*/
snd_soc_dapm_widget_for_each_source_path(w, path)
dapm_widget_set_peer_power(path->source, power, path->connect);
- /* Supplies can't affect their outputs, only their inputs */
- if (!w->is_supply) {
+ /*
+ * Supplies can't affect their outputs, only their inputs
+ */
+ if (!w->is_supply)
snd_soc_dapm_widget_for_each_sink_path(w, path)
- dapm_widget_set_peer_power(path->sink, power,
- path->connect);
- }
+ dapm_widget_set_peer_power(path->sink, power, path->connect);
+end:
if (power)
dapm_seq_insert(w, up_list, true);
else
dapm_seq_insert(w, down_list, false);
}
-static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
- struct list_head *up_list,
- struct list_head *down_list)
-{
- int power;
-
- switch (w->id) {
- case snd_soc_dapm_pre:
- dapm_seq_insert(w, down_list, false);
- break;
- case snd_soc_dapm_post:
- dapm_seq_insert(w, up_list, true);
- break;
-
- default:
- power = dapm_widget_power_check(w);
-
- dapm_widget_set_power(w, power, up_list, down_list);
- break;
- }
-}
-
static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
{
if (dapm->idle_bias_off)
@@ -2497,6 +2483,9 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
struct snd_soc_dapm_path *p, *next_p;
enum snd_soc_dapm_direction dir;
+ if (!w)
+ return;
+
list_del(&w->list);
list_del(&w->dirty);
/*
@@ -2516,12 +2505,6 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_free_widget);
-void snd_soc_dapm_reset_cache(struct snd_soc_dapm_context *dapm)
-{
- dapm->path_sink_cache.widget = NULL;
- dapm->path_source_cache.widget = NULL;
-}
-
/* free all dapm widgets and resources */
static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
{
@@ -2532,7 +2515,9 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
continue;
snd_soc_dapm_free_widget(w);
}
- snd_soc_dapm_reset_cache(dapm);
+
+ dapm->wcache_sink = NULL;
+ dapm->wcache_source = NULL;
}
static struct snd_soc_dapm_widget *dapm_find_widget(
@@ -2838,7 +2823,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
int (*connected)(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink))
{
- struct snd_soc_dapm_widget *widgets[2];
enum snd_soc_dapm_direction dir;
struct snd_soc_dapm_path *path;
int ret;
@@ -2874,8 +2858,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
path->node[SND_SOC_DAPM_DIR_IN] = wsource;
path->node[SND_SOC_DAPM_DIR_OUT] = wsink;
- widgets[SND_SOC_DAPM_DIR_IN] = wsource;
- widgets[SND_SOC_DAPM_DIR_OUT] = wsink;
path->connected = connected;
INIT_LIST_HEAD(&path->list);
@@ -2917,12 +2899,13 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
}
list_add(&path->list, &dapm->card->paths);
+
snd_soc_dapm_for_each_direction(dir)
- list_add(&path->list_node[dir], &widgets[dir]->edges[dir]);
+ list_add(&path->list_node[dir], &path->node[dir]->edges[dir]);
snd_soc_dapm_for_each_direction(dir) {
- dapm_update_widget_flags(widgets[dir]);
- dapm_mark_dirty(widgets[dir], "Route added");
+ dapm_update_widget_flags(path->node[dir]);
+ dapm_mark_dirty(path->node[dir], "Route added");
}
if (dapm->card->instantiated && path->connect)
@@ -2961,8 +2944,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
source = route->source;
}
- wsource = dapm_wcache_lookup(&dapm->path_source_cache, source);
- wsink = dapm_wcache_lookup(&dapm->path_sink_cache, sink);
+ wsource = dapm_wcache_lookup(dapm->wcache_source, source);
+ wsink = dapm_wcache_lookup(dapm->wcache_sink, sink);
if (wsink && wsource)
goto skip_search;
@@ -3006,30 +2989,27 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
if (!wsource)
wsource = wtsource;
- if (wsource == NULL) {
- dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
- route->source);
- return -ENODEV;
- }
- if (wsink == NULL) {
- dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
- route->sink);
- return -ENODEV;
- }
+ ret = -ENODEV;
+ if (!wsource)
+ goto err;
+ if (!wsink)
+ goto err;
skip_search:
- dapm_wcache_update(&dapm->path_sink_cache, wsink);
- dapm_wcache_update(&dapm->path_source_cache, wsource);
+ /* update cache */
+ dapm->wcache_sink = wsink;
+ dapm->wcache_source = wsource;
ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
route->connected);
- if (ret)
- goto err;
-
- return 0;
err:
- dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
- source, route->control, sink);
+ if (ret)
+ dev_err(dapm->dev, "ASoC: Failed to add route %s%s -%s%s%s> %s%s\n",
+ source, !wsource ? "(*)" : "",
+ !route->control ? "" : "> [",
+ !route->control ? "" : route->control,
+ !route->control ? "" : "] -",
+ sink, !wsink ? "(*)" : "");
return ret;
}
@@ -3115,13 +3095,8 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
for (i = 0; i < num; i++) {
int 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,
- route->control ? route->control : "direct",
- route->sink);
+ if (r < 0)
ret = r;
- }
route++;
}
mutex_unlock(&dapm->card->dapm_mutex);
@@ -4157,56 +4132,53 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
+ const struct snd_kcontrol_new *kcontrol_news;
+ int num_kcontrols;
const char **w_param_text;
unsigned long private_value = 0;
char *link_name;
- int ret;
+ int ret = -ENOMEM;
link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
rtd->dai_link->name, id);
if (!link_name)
- return ERR_PTR(-ENOMEM);
-
- memset(&template, 0, sizeof(template));
- template.reg = SND_SOC_NOPM;
- template.id = snd_soc_dapm_dai_link;
- template.name = link_name;
- template.event = snd_soc_dai_link_event;
- template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD;
- template.kcontrol_news = NULL;
+ goto name_fail;
/* allocate memory for control, only in case of multiple configs */
+ w_param_text = NULL;
+ kcontrol_news = NULL;
+ num_kcontrols = 0;
if (rtd->dai_link->num_params > 1) {
w_param_text = devm_kcalloc(card->dev,
rtd->dai_link->num_params,
sizeof(char *), GFP_KERNEL);
- if (!w_param_text) {
- ret = -ENOMEM;
+ if (!w_param_text)
goto param_fail;
- }
- template.num_kcontrols = 1;
- template.kcontrol_news =
- snd_soc_dapm_alloc_kcontrol(card,
- link_name,
- rtd->dai_link->params,
- rtd->dai_link->num_params,
- w_param_text, &private_value);
- if (!template.kcontrol_news) {
- ret = -ENOMEM;
+ num_kcontrols = 1;
+ kcontrol_news = snd_soc_dapm_alloc_kcontrol(card, link_name,
+ rtd->dai_link->params,
+ rtd->dai_link->num_params,
+ w_param_text, &private_value);
+ if (!kcontrol_news)
goto param_fail;
- }
- } else {
- w_param_text = NULL;
}
+
+ memset(&template, 0, sizeof(template));
+ template.reg = SND_SOC_NOPM;
+ template.id = snd_soc_dapm_dai_link;
+ template.name = link_name;
+ template.event = snd_soc_dai_link_event;
+ template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD;
+ template.kcontrol_news = kcontrol_news;
+ template.num_kcontrols = num_kcontrols;
+
dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
if (IS_ERR(w)) {
ret = PTR_ERR(w);
- dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
- link_name, ret);
goto outfree_kcontrol_news;
}
@@ -4220,6 +4192,9 @@ outfree_kcontrol_news:
rtd->dai_link->num_params, w_param_text);
param_fail:
devm_kfree(card->dev, link_name);
+name_fail:
+ dev_err(rtd->dev, "ASoC: Failed to create %s-%s widget: %d\n",
+ rtd->dai_link->name, id, ret);
return ERR_PTR(ret);
}