Commit 4253f3a8 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/dapm' into asoc-next

parents 24ecc23c 6e588a0d
...@@ -397,6 +397,7 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, ...@@ -397,6 +397,7 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num); const struct snd_soc_dapm_route *route, int num);
int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num); const struct snd_soc_dapm_route *route, int num);
void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w);
/* dapm events */ /* dapm events */
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
...@@ -511,9 +512,18 @@ struct snd_soc_dapm_route { ...@@ -511,9 +512,18 @@ struct snd_soc_dapm_route {
struct snd_soc_dapm_path { struct snd_soc_dapm_path {
const char *name; const char *name;
/* source (input) and sink (output) widgets */ /*
struct snd_soc_dapm_widget *source; * source (input) and sink (output) widgets
struct snd_soc_dapm_widget *sink; * The union is for convience, since it is a lot nicer to type
* p->source, rather than p->node[SND_SOC_DAPM_DIR_IN]
*/
union {
struct {
struct snd_soc_dapm_widget *source;
struct snd_soc_dapm_widget *sink;
};
struct snd_soc_dapm_widget *node[2];
};
/* status */ /* status */
u32 connect:1; /* source and sink widgets are connected */ u32 connect:1; /* source and sink widgets are connected */
...@@ -524,8 +534,7 @@ struct snd_soc_dapm_path { ...@@ -524,8 +534,7 @@ struct snd_soc_dapm_path {
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);
struct list_head list_source; struct list_head list_node[2];
struct list_head list_sink;
struct list_head list_kcontrol; struct list_head list_kcontrol;
struct list_head list; struct list_head list;
}; };
...@@ -559,8 +568,7 @@ struct snd_soc_dapm_widget { ...@@ -559,8 +568,7 @@ struct snd_soc_dapm_widget {
unsigned char new_power:1; /* power from this run */ unsigned char new_power:1; /* power from this run */
unsigned char power_checked:1; /* power checked this run */ unsigned char power_checked:1; /* power checked this run */
unsigned char is_supply:1; /* Widget is a supply type widget */ unsigned char is_supply:1; /* Widget is a supply type widget */
unsigned char is_sink:1; /* Widget is a sink type widget */ unsigned char is_ep:2; /* Widget is a endpoint type widget */
unsigned char is_source:1; /* Widget is a source type widget */
int subseq; /* sort within widget type */ int subseq; /* sort within widget type */
int (*power_check)(struct snd_soc_dapm_widget *w); int (*power_check)(struct snd_soc_dapm_widget *w);
...@@ -575,16 +583,14 @@ struct snd_soc_dapm_widget { ...@@ -575,16 +583,14 @@ struct snd_soc_dapm_widget {
struct snd_kcontrol **kcontrols; struct snd_kcontrol **kcontrols;
struct snd_soc_dobj dobj; struct snd_soc_dobj dobj;
/* widget input and outputs */ /* widget input and output edges */
struct list_head sources; struct list_head edges[2];
struct list_head sinks;
/* used during DAPM updates */ /* used during DAPM updates */
struct list_head work_list; struct list_head work_list;
struct list_head power_list; struct list_head power_list;
struct list_head dirty; struct list_head dirty;
int inputs; int endpoints[2];
int outputs;
struct clk *clk; struct clk *clk;
}; };
...@@ -672,4 +678,58 @@ static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level( ...@@ -672,4 +678,58 @@ static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level(
return dapm->bias_level; return dapm->bias_level;
} }
enum snd_soc_dapm_direction {
SND_SOC_DAPM_DIR_IN,
SND_SOC_DAPM_DIR_OUT
};
#define SND_SOC_DAPM_DIR_TO_EP(x) BIT(x)
#define SND_SOC_DAPM_EP_SOURCE SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_IN)
#define SND_SOC_DAPM_EP_SINK SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_OUT)
/**
* snd_soc_dapm_widget_for_each_sink_path - Iterates over all paths in the
* specified direction of a widget
* @w: The widget
* @dir: Whether to iterate over the paths where the specified widget is the
* incoming or outgoing widgets
* @p: The path iterator variable
*/
#define snd_soc_dapm_widget_for_each_path(w, dir, p) \
list_for_each_entry(p, &w->edges[dir], list_node[dir])
/**
* snd_soc_dapm_widget_for_each_sink_path_safe - Iterates over all paths in the
* specified direction of a widget
* @w: The widget
* @dir: Whether to iterate over the paths where the specified widget is the
* incoming or outgoing widgets
* @p: The path iterator variable
* @next_p: Temporary storage for the next path
*
* This function works like snd_soc_dapm_widget_for_each_sink_path, expect that
* it is safe to remove the current path from the list while iterating
*/
#define snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p) \
list_for_each_entry_safe(p, next_p, &w->edges[dir], list_node[dir])
/**
* snd_soc_dapm_widget_for_each_sink_path - Iterates over all paths leaving a
* widget
* @w: The widget
* @p: The path iterator variable
*/
#define snd_soc_dapm_widget_for_each_sink_path(w, p) \
snd_soc_dapm_widget_for_each_path(w, SND_SOC_DAPM_DIR_IN, p)
/**
* snd_soc_dapm_widget_for_each_source_path - Iterates over all paths leading to
* a widget
* @w: The widget
* @p: The path iterator variable
*/
#define snd_soc_dapm_widget_for_each_source_path(w, p) \
snd_soc_dapm_widget_for_each_path(w, SND_SOC_DAPM_DIR_OUT, p)
#endif #endif
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#define DAPM_DIRECT "(direct)" #define DAPM_DIRECT "(direct)"
#define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
struct snd_soc_jack; struct snd_soc_jack;
struct snd_soc_codec; struct snd_soc_codec;
...@@ -152,62 +153,38 @@ TRACE_EVENT(snd_soc_dapm_walk_done, ...@@ -152,62 +153,38 @@ TRACE_EVENT(snd_soc_dapm_walk_done,
(int)__entry->path_checks, (int)__entry->neighbour_checks) (int)__entry->path_checks, (int)__entry->neighbour_checks)
); );
TRACE_EVENT(snd_soc_dapm_output_path, TRACE_EVENT(snd_soc_dapm_path,
TP_PROTO(struct snd_soc_dapm_widget *widget, TP_PROTO(struct snd_soc_dapm_widget *widget,
enum snd_soc_dapm_direction dir,
struct snd_soc_dapm_path *path), struct snd_soc_dapm_path *path),
TP_ARGS(widget, path), TP_ARGS(widget, dir, path),
TP_STRUCT__entry( TP_STRUCT__entry(
__string( wname, widget->name ) __string( wname, widget->name )
__string( pname, path->name ? path->name : DAPM_DIRECT) __string( pname, path->name ? path->name : DAPM_DIRECT)
__string( psname, path->sink->name ) __string( pnname, path->node[dir]->name )
__field( int, path_sink ) __field( int, path_node )
__field( int, path_connect ) __field( int, path_connect )
__field( int, path_dir )
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(wname, widget->name); __assign_str(wname, widget->name);
__assign_str(pname, path->name ? path->name : DAPM_DIRECT); __assign_str(pname, path->name ? path->name : DAPM_DIRECT);
__assign_str(psname, path->sink->name); __assign_str(pnname, path->node[dir]->name);
__entry->path_connect = path->connect; __entry->path_connect = path->connect;
__entry->path_sink = (long)path->sink; __entry->path_node = (long)path->node[dir];
__entry->path_dir = dir;
), ),
TP_printk("%c%s -> %s -> %s", TP_printk("%c%s %s %s %s %s",
(int) __entry->path_sink && (int) __entry->path_node &&
(int) __entry->path_connect ? '*' : ' ', (int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname)) __get_str(wname), DAPM_ARROW(__entry->path_dir),
); __get_str(pname), DAPM_ARROW(__entry->path_dir),
__get_str(pnname))
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 = (long)path->source;
),
TP_printk("%c%s <- %s <- %s",
(int) __entry->path_source &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
); );
TRACE_EVENT(snd_soc_dapm_connected, TRACE_EVENT(snd_soc_dapm_connected,
......
...@@ -1298,7 +1298,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) ...@@ -1298,7 +1298,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute)
dev_dbg(dai->dev, "Stream name=%s\n", dev_dbg(dai->dev, "Stream name=%s\n",
dai->playback_widget->name); dai->playback_widget->name);
w = dai->playback_widget; w = dai->playback_widget;
list_for_each_entry(p, &w->sinks, list_source) { snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (p->connected && !p->connected(w, p->sink)) if (p->connected && !p->connected(w, p->sink))
continue; continue;
...@@ -1317,7 +1317,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) ...@@ -1317,7 +1317,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute)
dev_dbg(dai->dev, "Stream name=%s\n", dev_dbg(dai->dev, "Stream name=%s\n",
dai->capture_widget->name); dai->capture_widget->name);
w = dai->capture_widget; w = dai->capture_widget;
list_for_each_entry(p, &w->sources, list_sink) { snd_soc_dapm_widget_for_each_source_path(w, p) {
if (p->connected && !p->connected(w, p->sink)) if (p->connected && !p->connected(w, p->sink))
continue; continue;
......
This diff is collapsed.
...@@ -1231,24 +1231,17 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list, ...@@ -1231,24 +1231,17 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list,
} }
int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
int stream, struct snd_soc_dapm_widget_list **list_) int stream, struct snd_soc_dapm_widget_list **list)
{ {
struct snd_soc_dai *cpu_dai = fe->cpu_dai; struct snd_soc_dai *cpu_dai = fe->cpu_dai;
struct snd_soc_dapm_widget_list *list;
int paths; int paths;
list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
if (list == NULL)
return -ENOMEM;
/* get number of valid DAI paths and their widgets */ /* get number of valid DAI paths and their widgets */
paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list); paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list);
dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
stream ? "capture" : "playback"); stream ? "capture" : "playback");
*list_ = list;
return paths; return paths;
} }
......
...@@ -1758,7 +1758,6 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, ...@@ -1758,7 +1758,6 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
u32 index) u32 index)
{ {
struct snd_soc_dapm_widget *w, *next_w; struct snd_soc_dapm_widget *w, *next_w;
struct snd_soc_dapm_path *p, *next_p;
list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
...@@ -1770,31 +1769,9 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, ...@@ -1770,31 +1769,9 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
if (w->dobj.index != index && if (w->dobj.index != index &&
w->dobj.index != SND_SOC_TPLG_INDEX_ALL) w->dobj.index != SND_SOC_TPLG_INDEX_ALL)
continue; continue;
list_del(&w->list);
/*
* remove source and sink paths associated to this widget.
* While removing the path, remove reference to it from both
* source and sink widgets so that path is removed only once.
*/
list_for_each_entry_safe(p, next_p, &w->sources, list_sink) {
list_del(&p->list_sink);
list_del(&p->list_source);
list_del(&p->list);
kfree(p);
}
list_for_each_entry_safe(p, next_p, &w->sinks, list_source) {
list_del(&p->list_sink);
list_del(&p->list_source);
list_del(&p->list);
kfree(p);
}
/* check and free and dynamic widget kcontrols */ /* check and free and dynamic widget kcontrols */
snd_soc_tplg_widget_remove(w); snd_soc_tplg_widget_remove(w);
kfree(w->kcontrols); snd_soc_dapm_free_widget(w);
kfree(w->name);
kfree(w);
} }
} }
EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment