ASoC: dapm: Add a flag to mark paths connected to supply widgets

Supply widgets do not count towards the input and output widgets of their
neighbors and for supply widgets themselves we do not care for the number
of input or output paths. This means that a path that connects to a supply
widget effectively behaves the same as a path that as the weak property set.
This patch adds a new path flag that gets set to true when the path is
connected to at least one supply widget. If a path with the flag set is
encountered in is_connected_{input,output}_ep() is is skipped in the same
way that weak paths are skipped. This slightly brings down the number of
path checks.

Since both the weak and the supply flag are implemented as bitfields which
are stored in the same word there is no runtime overhead due to checking
both rather than just one and also the size of the path struct is not
increased by this patch. Another advantage is that we do not have to handle
supply widgets in is_connected_{input,output}_ep() anymore since it will
never be called for supply widgets. The only exception is from
dapm_widget_power_read_file() where a check is added to special case supply
widgets.

Testing with the ADAU1761, which has a handful of supply widgets, shows the
following changes in the DAPM stats for a playback stream start.

         Power  Path  Neighbour
Before:  34     78    117
After:   34     48    117

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Lars-Peter Clausen 2014-10-25 17:42:00 +02:00 committed by Mark Brown
parent 6dd98b0a3e
commit c1862c8bae
2 changed files with 14 additions and 10 deletions

View File

@ -510,6 +510,7 @@ struct snd_soc_dapm_path {
u32 connect:1; /* source and sink widgets are connected */ u32 connect:1; /* source and sink widgets are connected */
u32 walking:1; /* path is in the process of being walked */ u32 walking:1; /* path is in the process of being walked */
u32 weak:1; /* path ignored for power management */ u32 weak:1; /* path ignored for power management */
u32 is_supply:1; /* At least one of the connected widgets is a supply */
int (*connected)(struct snd_soc_dapm_widget *source, int (*connected)(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink); struct snd_soc_dapm_widget *sink);

View File

@ -821,9 +821,6 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
DAPM_UPDATE_STAT(widget, path_checks); DAPM_UPDATE_STAT(widget, path_checks);
if (widget->is_supply)
return 0;
if (widget->is_sink && widget->connected) { if (widget->is_sink && widget->connected) {
widget->outputs = snd_soc_dapm_suspend_check(widget); widget->outputs = snd_soc_dapm_suspend_check(widget);
return widget->outputs; return widget->outputs;
@ -832,7 +829,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
list_for_each_entry(path, &widget->sinks, list_source) { list_for_each_entry(path, &widget->sinks, list_source) {
DAPM_UPDATE_STAT(widget, neighbour_checks); DAPM_UPDATE_STAT(widget, neighbour_checks);
if (path->weak) if (path->weak || path->is_supply)
continue; continue;
if (path->walking) if (path->walking)
@ -882,9 +879,6 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
DAPM_UPDATE_STAT(widget, path_checks); DAPM_UPDATE_STAT(widget, path_checks);
if (widget->is_supply)
return 0;
if (widget->is_source && widget->connected) { if (widget->is_source && widget->connected) {
widget->inputs = snd_soc_dapm_suspend_check(widget); widget->inputs = snd_soc_dapm_suspend_check(widget);
return widget->inputs; return widget->inputs;
@ -893,7 +887,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
list_for_each_entry(path, &widget->sources, list_sink) { list_for_each_entry(path, &widget->sources, list_sink) {
DAPM_UPDATE_STAT(widget, neighbour_checks); DAPM_UPDATE_STAT(widget, neighbour_checks);
if (path->weak) if (path->weak || path->is_supply)
continue; continue;
if (path->walking) if (path->walking)
@ -1691,8 +1685,14 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
in = is_connected_input_ep(w, NULL); /* Supply widgets are not handled by is_connected_{input,output}_ep() */
out = is_connected_output_ep(w, NULL); if (w->is_supply) {
in = 0;
out = 0;
} else {
in = is_connected_input_ep(w, NULL);
out = is_connected_output_ep(w, NULL);
}
ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
w->name, w->power ? "On" : "Off", w->name, w->power ? "On" : "Off",
@ -2213,6 +2213,9 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
INIT_LIST_HEAD(&path->list_source); INIT_LIST_HEAD(&path->list_source);
INIT_LIST_HEAD(&path->list_sink); INIT_LIST_HEAD(&path->list_sink);
if (wsource->is_supply || wsink->is_supply)
path->is_supply = 1;
/* connect static paths */ /* connect static paths */
if (control == NULL) { if (control == NULL) {
path->connect = 1; path->connect = 1;