Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305647
b: refs/heads/master
c: ec2e303
h: refs/heads/master
i:
  305645: b39e81a
  305643: 8afee46
  305639: 457e9ac
  305631: 06dd040
v: v3
  • Loading branch information
Liam Girdwood authored and Mark Brown committed Apr 18, 2012
1 parent a61b536 commit 8d4e7d6
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0cbe4b36b075e80f3149a91ef640bc7930aa94c7
refs/heads/master: ec2e3031b65f23f66840b5c89c4b83076831a435
5 changes: 5 additions & 0 deletions trunk/include/sound/soc-dapm.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ struct snd_soc_dapm_pin;
struct snd_soc_dapm_route;
struct snd_soc_dapm_context;
struct regulator;
struct snd_soc_dapm_widget_list;

int dapm_reg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
Expand Down Expand Up @@ -403,6 +404,10 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
/* Mostly internal - should not normally be used */
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);

/* dapm path query */
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
struct snd_soc_dapm_widget_list **list);

/* dapm widget types */
enum snd_soc_dapm_type {
snd_soc_dapm_input = 0, /* input pin */
Expand Down
80 changes: 80 additions & 0 deletions trunk/include/trace/events/asoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <linux/ktime.h>
#include <linux/tracepoint.h>

#define DAPM_DIRECT "(direct)"

struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_platform;
Expand Down Expand Up @@ -241,6 +243,84 @@ TRACE_EVENT(snd_soc_dapm_walk_done,
(int)__entry->path_checks, (int)__entry->neighbour_checks)
);

TRACE_EVENT(snd_soc_dapm_output_path,

TP_PROTO(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_path *path),

TP_ARGS(widget, path),

TP_STRUCT__entry(
__string( wname, widget->name )
__string( pname, path->name ? path->name : DAPM_DIRECT)
__string( psname, path->sink->name )
__field( int, path_sink )
__field( int, path_connect )
),

TP_fast_assign(
__assign_str(wname, widget->name);
__assign_str(pname, path->name ? path->name : DAPM_DIRECT);
__assign_str(psname, path->sink->name);
__entry->path_connect = path->connect;
__entry->path_sink = (int)path->sink;
),

TP_printk("%c%s -> %s -> %s\n",
(int) __entry->path_sink &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
);

TRACE_EVENT(snd_soc_dapm_input_path,

TP_PROTO(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_path *path),

TP_ARGS(widget, path),

TP_STRUCT__entry(
__string( wname, widget->name )
__string( pname, path->name ? path->name : DAPM_DIRECT)
__string( psname, path->source->name )
__field( int, path_source )
__field( int, path_connect )
),

TP_fast_assign(
__assign_str(wname, widget->name);
__assign_str(pname, path->name ? path->name : DAPM_DIRECT);
__assign_str(psname, path->source->name);
__entry->path_connect = path->connect;
__entry->path_source = (int)path->source;
),

TP_printk("%c%s <- %s <- %s\n",
(int) __entry->path_source &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
);

TRACE_EVENT(snd_soc_dapm_connected,

TP_PROTO(int paths, int stream),

TP_ARGS(paths, stream),

TP_STRUCT__entry(
__field( int, paths )
__field( int, stream )
),

TP_fast_assign(
__entry->paths = paths;
__entry->stream = stream;
),

TP_printk("%s: found %d paths\n",
__entry->stream ? "capture" : "playback", __entry->paths)
);

TRACE_EVENT(snd_soc_jack_irq,

TP_PROTO(const char *name),
Expand Down
122 changes: 112 additions & 10 deletions trunk/sound/soc/soc-dapm.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,11 +705,51 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
}
}

/* add widget to list if it's not already in the list */
static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_widget_list *wlist;
int wlistsize, wlistentries, i;

if (*list == NULL)
return -EINVAL;

wlist = *list;

/* is this widget already in the list */
for (i = 0; i < wlist->num_widgets; i++) {
if (wlist->widgets[i] == w)
return 0;
}

/* allocate some new space */
wlistentries = wlist->num_widgets + 1;
wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
wlistentries * sizeof(struct snd_soc_dapm_widget *);
*list = krealloc(wlist, wlistsize, GFP_KERNEL);
if (*list == NULL) {
dev_err(w->dapm->dev, "can't allocate widget list for %s\n",
w->name);
return -ENOMEM;
}
wlist = *list;

/* insert the widget */
dev_dbg(w->dapm->dev, "added %s in widget list pos %d\n",
w->name, wlist->num_widgets);

wlist->widgets[wlist->num_widgets] = w;
wlist->num_widgets++;
return 1;
}

/*
* Recursively check for a completed path to an active or physically connected
* output widget. Returns number of complete paths.
*/
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_widget_list **list)
{
struct snd_soc_dapm_path *path;
int con = 0;
Expand Down Expand Up @@ -765,9 +805,23 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
if (path->walked)
continue;

trace_snd_soc_dapm_output_path(widget, path);

if (path->sink && path->connect) {
path->walked = 1;
con += is_connected_output_ep(path->sink);

/* do we need to add this widget to the list ? */
if (list) {
int err;
err = dapm_list_add_widget(list, path->sink);
if (err < 0) {
dev_err(widget->dapm->dev, "could not add widget %s\n",
widget->name);
return con;
}
}

con += is_connected_output_ep(path->sink, list);
}
}

Expand All @@ -780,7 +834,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
* Recursively check for a completed path to an active or physically connected
* input widget. Returns number of complete paths.
*/
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_widget_list **list)
{
struct snd_soc_dapm_path *path;
int con = 0;
Expand Down Expand Up @@ -848,9 +903,23 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
if (path->walked)
continue;

trace_snd_soc_dapm_input_path(widget, path);

if (path->source && path->connect) {
path->walked = 1;
con += is_connected_input_ep(path->source);

/* do we need to add this widget to the list ? */
if (list) {
int err;
err = dapm_list_add_widget(list, path->sink);
if (err < 0) {
dev_err(widget->dapm->dev, "could not add widget %s\n",
widget->name);
return con;
}
}

con += is_connected_input_ep(path->source, list);
}
}

Expand All @@ -859,6 +928,39 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
return con;
}

/**
* snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
* @dai: the soc DAI.
* @stream: stream direction.
* @list: list of active widgets for this stream.
*
* Queries DAPM graph as to whether an valid audio stream path exists for
* the initial stream specified by name. This takes into account
* current mixer and mux kcontrol settings. Creates list of valid widgets.
*
* Returns the number of valid paths or negative error.
*/
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
struct snd_soc_dapm_widget_list **list)
{
struct snd_soc_card *card = dai->card;
int paths;

mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
dapm_reset(card);

if (stream == SNDRV_PCM_STREAM_PLAYBACK)
paths = is_connected_output_ep(dai->playback_widget, list);
else
paths = is_connected_input_ep(dai->playback_widget, list);

trace_snd_soc_dapm_connected(paths, stream);
dapm_clear_walk(&card->dapm);
mutex_unlock(&card->dapm_mutex);

return paths;
}

/*
* Handler for generic register modifier widget.
*/
Expand Down Expand Up @@ -915,9 +1017,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)

DAPM_UPDATE_STAT(w, power_checks);

in = is_connected_input_ep(w);
in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
out = is_connected_output_ep(w);
out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);
return out != 0 && in != 0;
}
Expand All @@ -940,7 +1042,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT(w, power_checks);

if (w->active) {
in = is_connected_input_ep(w);
in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
return in != 0;
} else {
Expand All @@ -956,7 +1058,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT(w, power_checks);

if (w->active) {
out = is_connected_output_ep(w);
out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);
return out != 0;
} else {
Expand Down Expand Up @@ -1558,9 +1660,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
if (!buf)
return -ENOMEM;

in = is_connected_input_ep(w);
in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
out = is_connected_output_ep(w);
out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);

ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
Expand Down

0 comments on commit 8d4e7d6

Please sign in to comment.