Skip to content

Commit

Permalink
ASoC: Add weak routes for sidetone style paths
Browse files Browse the repository at this point in the history
Normally DAPM will power up any connected audio path. This is not ideal
for sidetone paths as with sidetone paths the audio path is not wanted in
itself, it is only desired if the two paths it provides a sidetone between
are both active. If the sidetone path causes a power up then it can be
hard to minimise pops as we first power up either the sidetone or the main
output path and then power the other, with the second power up potentially
introducing a DC offset.

Address this by introducing the concept of a weak path. If a path is marked
as weak then DAPM will ignore that path when walking the graph, though all
the relevant controls are still available to the application layer to allow
these paths to be configured.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
  • Loading branch information
Mark Brown committed Jun 13, 2011
1 parent 5bef44f commit bf3a9e1
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/sound/soc-dapm.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);
int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);

/* dapm events */
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
Expand Down
87 changes: 87 additions & 0 deletions sound/soc/soc-dapm.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
}

list_for_each_entry(path, &widget->sinks, list_source) {
if (path->weak)
continue;

if (path->walked)
continue;

Expand Down Expand Up @@ -643,6 +646,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
}

list_for_each_entry(path, &widget->sources, list_sink) {
if (path->weak)
continue;

if (path->walked)
continue;

Expand Down Expand Up @@ -724,6 +730,9 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)

/* Check if one of our outputs is connected */
list_for_each_entry(path, &w->sinks, list_source) {
if (path->weak)
continue;

if (path->connected &&
!path->connected(path->source, path->sink))
continue;
Expand Down Expand Up @@ -1806,6 +1815,84 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);

static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route)
{
struct snd_soc_dapm_widget *source = dapm_find_widget(dapm,
route->source,
true);
struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm,
route->sink,
true);
struct snd_soc_dapm_path *path;
int count = 0;

if (!source) {
dev_err(dapm->dev, "Unable to find source %s for weak route\n",
route->source);
return -ENODEV;
}

if (!sink) {
dev_err(dapm->dev, "Unable to find sink %s for weak route\n",
route->sink);
return -ENODEV;
}

if (route->control || route->connected)
dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n",
route->source, route->sink);

list_for_each_entry(path, &source->sinks, list_source) {
if (path->sink == sink) {
path->weak = 1;
count++;
}
}

if (count == 0)
dev_err(dapm->dev, "No path found for weak route %s->%s\n",
route->source, route->sink);
if (count > 1)
dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n",
count, route->source, route->sink);

return 0;
}

/**
* snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak
* @dapm: DAPM context
* @route: audio routes
* @num: number of routes
*
* Mark existing routes matching those specified in the passed array
* as being weak, meaning that they are ignored for the purpose of
* power decisions. The main intended use case is for sidetone paths
* which couple audio between other independent paths if they are both
* active in order to make the combination work better at the user
* level but which aren't intended to be "used".
*
* Note that CODEC drivers should not use this as sidetone type paths
* can frequently also be used as bypass paths.
*/
int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num)
{
int i, err;
int ret = 0;

for (i = 0; i < num; i++) {
err = snd_soc_dapm_weak_route(dapm, route);
if (err)
ret = err;
route++;
}

return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);

/**
* snd_soc_dapm_new_widgets - add new dapm widgets
* @dapm: DAPM context
Expand Down

0 comments on commit bf3a9e1

Please sign in to comment.