Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
4253f3a8
Commit
4253f3a8
authored
Aug 30, 2015
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-next
parents
24ecc23c
6e588a0d
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
311 additions
and
347 deletions
+311
-347
include/sound/soc-dapm.h
include/sound/soc-dapm.h
+72
-12
include/trace/events/asoc.h
include/trace/events/asoc.h
+15
-38
sound/soc/intel/atom/sst-atom-controls.c
sound/soc/intel/atom/sst-atom-controls.c
+2
-2
sound/soc/soc-dapm.c
sound/soc/soc-dapm.c
+219
-262
sound/soc/soc-pcm.c
sound/soc/soc-pcm.c
+2
-9
sound/soc/soc-topology.c
sound/soc/soc-topology.c
+1
-24
No files found.
include/sound/soc-dapm.h
View file @
4253f3a8
...
...
@@ -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
);
int
snd_soc_dapm_weak_routes
(
struct
snd_soc_dapm_context
*
dapm
,
const
struct
snd_soc_dapm_route
*
route
,
int
num
);
void
snd_soc_dapm_free_widget
(
struct
snd_soc_dapm_widget
*
w
);
/* dapm events */
void
snd_soc_dapm_stream_event
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
stream
,
...
...
@@ -511,9 +512,18 @@ struct snd_soc_dapm_route {
struct
snd_soc_dapm_path
{
const
char
*
name
;
/* source (input) and sink (output) widgets */
/*
* source (input) and sink (output) widgets
* 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 */
u32
connect
:
1
;
/* source and sink widgets are connected */
...
...
@@ -524,8 +534,7 @@ struct snd_soc_dapm_path {
int
(
*
connected
)(
struct
snd_soc_dapm_widget
*
source
,
struct
snd_soc_dapm_widget
*
sink
);
struct
list_head
list_source
;
struct
list_head
list_sink
;
struct
list_head
list_node
[
2
];
struct
list_head
list_kcontrol
;
struct
list_head
list
;
};
...
...
@@ -559,8 +568,7 @@ struct snd_soc_dapm_widget {
unsigned
char
new_power
:
1
;
/* power from 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_sink
:
1
;
/* Widget is a sink type widget */
unsigned
char
is_source
:
1
;
/* Widget is a source type widget */
unsigned
char
is_ep
:
2
;
/* Widget is a endpoint type widget */
int
subseq
;
/* sort within widget type */
int
(
*
power_check
)(
struct
snd_soc_dapm_widget
*
w
);
...
...
@@ -575,16 +583,14 @@ struct snd_soc_dapm_widget {
struct
snd_kcontrol
**
kcontrols
;
struct
snd_soc_dobj
dobj
;
/* widget input and outputs */
struct
list_head
sources
;
struct
list_head
sinks
;
/* widget input and output edges */
struct
list_head
edges
[
2
];
/* used during DAPM updates */
struct
list_head
work_list
;
struct
list_head
power_list
;
struct
list_head
dirty
;
int
inputs
;
int
outputs
;
int
endpoints
[
2
];
struct
clk
*
clk
;
};
...
...
@@ -672,4 +678,58 @@ static inline enum snd_soc_bias_level snd_soc_dapm_get_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
include/trace/events/asoc.h
View file @
4253f3a8
...
...
@@ -8,6 +8,7 @@
#include <linux/tracepoint.h>
#define DAPM_DIRECT "(direct)"
#define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
struct
snd_soc_jack
;
struct
snd_soc_codec
;
...
...
@@ -152,62 +153,38 @@ TRACE_EVENT(snd_soc_dapm_walk_done,
(
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
,
enum
snd_soc_dapm_direction
dir
,
struct
snd_soc_dapm_path
*
path
),
TP_ARGS
(
widget
,
path
),
TP_ARGS
(
widget
,
dir
,
path
),
TP_STRUCT__entry
(
__string
(
wname
,
widget
->
name
)
__string
(
pname
,
path
->
name
?
path
->
name
:
DAPM_DIRECT
)
__string
(
p
sname
,
path
->
sink
->
name
)
__field
(
int
,
path_
sink
)
__string
(
p
nname
,
path
->
node
[
dir
]
->
name
)
__field
(
int
,
path_
node
)
__field
(
int
,
path_connect
)
__field
(
int
,
path_dir
)
),
TP_fast_assign
(
__assign_str
(
wname
,
widget
->
name
);
__assign_str
(
pname
,
path
->
name
?
path
->
name
:
DAPM_DIRECT
);
__assign_str
(
p
sname
,
path
->
sink
->
name
);
__assign_str
(
p
nname
,
path
->
node
[
dir
]
->
name
);
__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"
,
(
int
)
__entry
->
path_
sink
&&
TP_printk
(
"%c%s
%s %s %s
%s"
,
(
int
)
__entry
->
path_
node
&&
(
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
=
(
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
))
__get_str
(
wname
),
DAPM_ARROW
(
__entry
->
path_dir
),
__get_str
(
pname
),
DAPM_ARROW
(
__entry
->
path_dir
),
__get_str
(
pnname
))
);
TRACE_EVENT
(
snd_soc_dapm_connected
,
...
...
sound/soc/intel/atom/sst-atom-controls.c
View file @
4253f3a8
...
...
@@ -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
"
,
dai
->
playback_widget
->
name
);
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
))
continue
;
...
...
@@ -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
"
,
dai
->
capture_widget
->
name
);
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
))
continue
;
...
...
sound/soc/soc-dapm.c
View file @
4253f3a8
...
...
@@ -47,6 +47,13 @@
#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
#define SND_SOC_DAPM_DIR_REVERSE(x) ((x == SND_SOC_DAPM_DIR_IN) ? \
SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN)
#define snd_soc_dapm_for_each_direction(dir) \
for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \
(dir)++)
static
int
snd_soc_dapm_add_path
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_soc_dapm_widget
*
wsource
,
struct
snd_soc_dapm_widget
*
wsink
,
const
char
*
control
,
...
...
@@ -167,44 +174,58 @@ static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
}
/*
* dapm_widget_invalidate_input_paths() - Invalidate the cached number of input
* paths
* @w: The widget for which to invalidate the cached number of input paths
*
* The function resets the cached number of inputs for the specified widget and
* all widgets that can be reached via outgoing paths from the widget.
*
* This function must be called if the number of input paths for a widget might
* have changed. E.g. if the source state of a widget changes or a path is added
* or activated with the widget as the sink.
* Common implementation for dapm_widget_invalidate_input_paths() and
* dapm_widget_invalidate_output_paths(). The function is inlined since the
* combined size of the two specialized functions is only marginally larger then
* the size of the generic function and at the same time the fast path of the
* specialized functions is significantly smaller than the generic function.
*/
static
void
dapm_widget_invalidate_input_paths
(
struct
snd_soc_dapm_widget
*
w
)
static
__always_inline
void
dapm_widget_invalidate_paths
(
struct
snd_soc_dapm_widget
*
w
,
enum
snd_soc_dapm_direction
dir
)
{
struct
snd_soc_dapm_widget
*
sink
;
enum
snd_soc_dapm_direction
rdir
=
SND_SOC_DAPM_DIR_REVERSE
(
dir
);
struct
snd_soc_dapm_widget
*
node
;
struct
snd_soc_dapm_path
*
p
;
LIST_HEAD
(
list
);
dapm_assert_locked
(
w
->
dapm
);
if
(
w
->
inputs
==
-
1
)
if
(
w
->
endpoints
[
dir
]
==
-
1
)
return
;
w
->
inputs
=
-
1
;
list_add_tail
(
&
w
->
work_list
,
&
list
);
w
->
endpoints
[
dir
]
=
-
1
;
list_for_each_entry
(
w
,
&
list
,
work_list
)
{
list_for_each_entry
(
p
,
&
w
->
sinks
,
list_source
)
{
snd_soc_dapm_widget_for_each_path
(
w
,
dir
,
p
)
{
if
(
p
->
is_supply
||
p
->
weak
||
!
p
->
connect
)
continue
;
sink
=
p
->
sink
;
if
(
sink
->
inputs
!=
-
1
)
{
sink
->
inputs
=
-
1
;
list_add_tail
(
&
sink
->
work_list
,
&
list
);
node
=
p
->
node
[
rdir
]
;
if
(
node
->
endpoints
[
dir
]
!=
-
1
)
{
node
->
endpoints
[
dir
]
=
-
1
;
list_add_tail
(
&
node
->
work_list
,
&
list
);
}
}
}
}
/*
* dapm_widget_invalidate_input_paths() - Invalidate the cached number of
* input paths
* @w: The widget for which to invalidate the cached number of input paths
*
* Resets the cached number of inputs for the specified widget and all widgets
* that can be reached via outcoming paths from the widget.
*
* This function must be called if the number of output paths for a widget might
* have changed. E.g. if the source state of a widget changes or a path is added
* or activated with the widget as the sink.
*/
static
void
dapm_widget_invalidate_input_paths
(
struct
snd_soc_dapm_widget
*
w
)
{
dapm_widget_invalidate_paths
(
w
,
SND_SOC_DAPM_DIR_IN
);
}
/*
* dapm_widget_invalidate_output_paths() - Invalidate the cached number of
* output paths
...
...
@@ -219,29 +240,7 @@ static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w)
*/
static
void
dapm_widget_invalidate_output_paths
(
struct
snd_soc_dapm_widget
*
w
)
{
struct
snd_soc_dapm_widget
*
source
;
struct
snd_soc_dapm_path
*
p
;
LIST_HEAD
(
list
);
dapm_assert_locked
(
w
->
dapm
);
if
(
w
->
outputs
==
-
1
)
return
;
w
->
outputs
=
-
1
;
list_add_tail
(
&
w
->
work_list
,
&
list
);
list_for_each_entry
(
w
,
&
list
,
work_list
)
{
list_for_each_entry
(
p
,
&
w
->
sources
,
list_sink
)
{
if
(
p
->
is_supply
||
p
->
weak
||
!
p
->
connect
)
continue
;
source
=
p
->
source
;
if
(
source
->
outputs
!=
-
1
)
{
source
->
outputs
=
-
1
;
list_add_tail
(
&
source
->
work_list
,
&
list
);
}
}
}
dapm_widget_invalidate_paths
(
w
,
SND_SOC_DAPM_DIR_OUT
);
}
/*
...
...
@@ -270,9 +269,9 @@ static void dapm_path_invalidate(struct snd_soc_dapm_path *p)
* endpoints is either connected or disconnected that sum won't change,
* so there is no need to re-check the path.
*/
if
(
p
->
source
->
inputs
!=
0
)
if
(
p
->
source
->
endpoints
[
SND_SOC_DAPM_DIR_IN
]
!=
0
)
dapm_widget_invalidate_input_paths
(
p
->
sink
);
if
(
p
->
sink
->
outputs
!=
0
)
if
(
p
->
sink
->
endpoints
[
SND_SOC_DAPM_DIR_OUT
]
!=
0
)
dapm_widget_invalidate_output_paths
(
p
->
source
);
}
...
...
@@ -283,11 +282,11 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card)
mutex_lock
(
&
card
->
dapm_mutex
);
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
if
(
w
->
is_
sink
||
w
->
is_source
)
{
if
(
w
->
is_
ep
)
{
dapm_mark_dirty
(
w
,
"Rechecking endpoints"
);
if
(
w
->
is_
sink
)
if
(
w
->
is_
ep
&
SND_SOC_DAPM_EP_SINK
)
dapm_widget_invalidate_output_paths
(
w
);
if
(
w
->
is_
source
)
if
(
w
->
is_
ep
&
SND_SOC_DAPM_EP_SOURCE
)
dapm_widget_invalidate_input_paths
(
w
);
}
}
...
...
@@ -894,7 +893,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
/* add kcontrol */
for
(
i
=
0
;
i
<
w
->
num_kcontrols
;
i
++
)
{
/* match name */
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
{
snd_soc_dapm_widget_for_each_source_path
(
w
,
path
)
{
/* mixer/mux paths name must match control name */
if
(
path
->
name
!=
(
char
*
)
w
->
kcontrol_news
[
i
].
name
)
continue
;
...
...
@@ -923,18 +922,18 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
static
int
dapm_new_mux
(
struct
snd_soc_dapm_widget
*
w
)
{
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
enum
snd_soc_dapm_direction
dir
;
struct
snd_soc_dapm_path
*
path
;
struct
list_head
*
paths
;
const
char
*
type
;
int
ret
;
switch
(
w
->
id
)
{
case
snd_soc_dapm_mux
:
paths
=
&
w
->
sources
;
dir
=
SND_SOC_DAPM_DIR_OUT
;
type
=
"mux"
;
break
;
case
snd_soc_dapm_demux
:
paths
=
&
w
->
sinks
;
dir
=
SND_SOC_DAPM_DIR_IN
;
type
=
"demux"
;
break
;
default:
...
...
@@ -948,7 +947,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
return
-
EINVAL
;
}
if
(
list_empty
(
paths
))
{
if
(
list_empty
(
&
w
->
edges
[
dir
]
))
{
dev_err
(
dapm
->
dev
,
"ASoC: %s %s has no paths
\n
"
,
type
,
w
->
name
);
return
-
EINVAL
;
}
...
...
@@ -957,17 +956,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
if
(
ret
<
0
)
return
ret
;
if
(
w
->
id
==
snd_soc_dapm_mux
)
{
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
{
if
(
path
->
name
)
dapm_kcontrol_add_path
(
w
->
kcontrols
[
0
],
path
);
}
}
else
{
list_for_each_entry
(
path
,
&
w
->
sinks
,
list_source
)
{
snd_soc_dapm_widget_for_each_path
(
w
,
dir
,
path
)
{
if
(
path
->
name
)
dapm_kcontrol_add_path
(
w
->
kcontrols
[
0
],
path
);
}
}
return
0
;
}
...
...
@@ -1032,66 +1024,59 @@ 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
)
static
int
dapm_widget_list_create
(
struct
snd_soc_dapm_widget_list
**
list
,
struct
list_head
*
widgets
)
{
struct
snd_soc_dapm_widget_list
*
wlist
;
int
wlistsize
,
wlistentries
,
i
;
if
(
*
list
==
NULL
)
return
-
EINVAL
;
struct
snd_soc_dapm_widget
*
w
;
struct
list_head
*
it
;
unsigned
int
size
=
0
;
unsigned
int
i
=
0
;
wlist
=
*
list
;
list_for_each
(
it
,
widgets
)
size
++
;
/* 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
,
"ASoC: can't allocate widget list for %s
\n
"
,
w
->
name
);
*
list
=
kzalloc
(
sizeof
(
**
list
)
+
size
*
sizeof
(
*
w
),
GFP_KERNEL
);
if
(
*
list
==
NULL
)
return
-
ENOMEM
;
}
wlist
=
*
list
;
/* insert the widget */
dev_dbg
(
w
->
dapm
->
dev
,
"ASoC: added %s in widget list pos %d
\n
"
,
w
->
name
,
wlist
->
num_widgets
);
list_for_each_entry
(
w
,
widgets
,
work_list
)
(
*
list
)
->
widgets
[
i
++
]
=
w
;
wlist
->
widgets
[
wlist
->
num_widgets
]
=
w
;
wlist
->
num_widgets
++
;
return
1
;
(
*
list
)
->
num_widgets
=
i
;
return
0
;
}
/*
* Recursively check for a completed path to an active or physically connected
* output widget. Returns number of complete paths.
* Common implementation for is_connected_output_ep() and
* is_connected_input_ep(). The function is inlined since the combined size of
* the two specialized functions is only marginally larger then the size of the
* generic function and at the same time the fast path of the specialized
* functions is significantly smaller than the generic function.
*/
static
int
is_connected_output_ep
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_soc_dapm_widget_list
**
list
)
static
__always_inline
int
is_connected_ep
(
struct
snd_soc_dapm_widget
*
widget
,
struct
list_head
*
list
,
enum
snd_soc_dapm_direction
dir
,
int
(
*
fn
)(
struct
snd_soc_dapm_widget
*
,
struct
list_head
*
))
{
enum
snd_soc_dapm_direction
rdir
=
SND_SOC_DAPM_DIR_REVERSE
(
dir
);
struct
snd_soc_dapm_path
*
path
;
int
con
=
0
;
if
(
widget
->
outputs
>=
0
)
return
widget
->
outputs
;
if
(
widget
->
endpoints
[
dir
]
>=
0
)
return
widget
->
endpoints
[
dir
]
;
DAPM_UPDATE_STAT
(
widget
,
path_checks
);
if
(
widget
->
is_sink
&&
widget
->
connected
)
{
widget
->
outputs
=
snd_soc_dapm_suspend_check
(
widget
);
return
widget
->
outputs
;
/* do we need to add this widget to the list ? */
if
(
list
)
list_add_tail
(
&
widget
->
work_list
,
list
);
if
((
widget
->
is_ep
&
SND_SOC_DAPM_DIR_TO_EP
(
dir
))
&&
widget
->
connected
)
{
widget
->
endpoints
[
dir
]
=
snd_soc_dapm_suspend_check
(
widget
);
return
widget
->
endpoints
[
dir
];
}
list_for_each_entry
(
path
,
&
widget
->
sinks
,
list_source
)
{
snd_soc_dapm_widget_for_each_path
(
widget
,
rdir
,
path
)
{
DAPM_UPDATE_STAT
(
widget
,
neighbour_checks
);
if
(
path
->
weak
||
path
->
is_supply
)
...
...
@@ -1100,91 +1085,40 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
if
(
path
->
walking
)
return
1
;
trace_snd_soc_dapm_
output_path
(
widget
,
path
);
trace_snd_soc_dapm_
path
(
widget
,
dir
,
path
);
if
(
path
->
connect
)
{
path
->
walking
=
1
;
/* 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
,
"ASoC: could not add widget %s
\n
"
,
widget
->
name
);
con
+=
fn
(
path
->
node
[
dir
],
list
);
path
->
walking
=
0
;
return
con
;
}
}
con
+=
is_connected_output_ep
(
path
->
sink
,
list
);
path
->
walking
=
0
;
}
}
widget
->
outputs
=
con
;
widget
->
endpoints
[
dir
]
=
con
;
return
con
;
}
/*
* 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
,
struct
list_head
*
list
)
{
return
is_connected_ep
(
widget
,
list
,
SND_SOC_DAPM_DIR_OUT
,
is_connected_output_ep
);
}
/*
* 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
,
struct
snd_soc_dapm_widget_list
*
*
list
)
struct
list_head
*
list
)
{
struct
snd_soc_dapm_path
*
path
;
int
con
=
0
;
if
(
widget
->
inputs
>=
0
)
return
widget
->
inputs
;
DAPM_UPDATE_STAT
(
widget
,
path_checks
);
if
(
widget
->
is_source
&&
widget
->
connected
)
{
widget
->
inputs
=
snd_soc_dapm_suspend_check
(
widget
);
return
widget
->
inputs
;
}
list_for_each_entry
(
path
,
&
widget
->
sources
,
list_sink
)
{
DAPM_UPDATE_STAT
(
widget
,
neighbour_checks
);
if
(
path
->
weak
||
path
->
is_supply
)
continue
;
if
(
path
->
walking
)
return
1
;
trace_snd_soc_dapm_input_path
(
widget
,
path
);
if
(
path
->
connect
)
{
path
->
walking
=
1
;
/* do we need to add this widget to the list ? */
if
(
list
)
{
int
err
;
err
=
dapm_list_add_widget
(
list
,
path
->
source
);
if
(
err
<
0
)
{
dev_err
(
widget
->
dapm
->
dev
,
"ASoC: could not add widget %s
\n
"
,
widget
->
name
);
path
->
walking
=
0
;
return
con
;
}
}
con
+=
is_connected_input_ep
(
path
->
source
,
list
);
path
->
walking
=
0
;
}
}
widget
->
inputs
=
con
;
return
con
;
return
is_connected_ep
(
widget
,
list
,
SND_SOC_DAPM_DIR_IN
,
is_connected_input_ep
);
}
/**
...
...
@@ -1204,7 +1138,9 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
{
struct
snd_soc_card
*
card
=
dai
->
component
->
card
;
struct
snd_soc_dapm_widget
*
w
;
LIST_HEAD
(
widgets
);
int
paths
;
int
ret
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
...
...
@@ -1213,14 +1149,21 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
* to reset the cached number of inputs and outputs.
*/
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
w
->
inputs
=
-
1
;
w
->
outputs
=
-
1
;
w
->
endpoints
[
SND_SOC_DAPM_DIR_IN
]
=
-
1
;
w
->
endpoints
[
SND_SOC_DAPM_DIR_OUT
]
=
-
1
;
}
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
paths
=
is_connected_output_ep
(
dai
->
playback_widget
,
list
);
paths
=
is_connected_output_ep
(
dai
->
playback_widget
,
&
widgets
);
else
paths
=
is_connected_input_ep
(
dai
->
capture_widget
,
list
);
paths
=
is_connected_input_ep
(
dai
->
capture_widget
,
&
widgets
);
/* Drop starting point */
list_del
(
widgets
.
next
);
ret
=
dapm_widget_list_create
(
list
,
&
widgets
);
if
(
ret
)
paths
=
ret
;
trace_snd_soc_dapm_connected
(
paths
,
stream
);
mutex_unlock
(
&
card
->
dapm_mutex
);
...
...
@@ -1321,7 +1264,7 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT
(
w
,
power_checks
);
/* Check if one of our outputs is connected */
list_for_each_entry
(
path
,
&
w
->
sinks
,
list_source
)
{
snd_soc_dapm_widget_for_each_sink_path
(
w
,
path
)
{
DAPM_UPDATE_STAT
(
w
,
neighbour_checks
);
if
(
path
->
weak
)
...
...
@@ -1745,12 +1688,12 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
/* If we changed our power state perhaps our neigbours changed
* also.
*/
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
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
)
{
list_for_each_entry
(
path
,
&
w
->
sinks
,
list_source
)
snd_soc_dapm_widget_for_each_sink_path
(
w
,
path
)
dapm_widget_set_peer_power
(
path
->
sink
,
power
,
path
->
connect
);
}
...
...
@@ -1951,6 +1894,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
{
struct
snd_soc_dapm_widget
*
w
=
file
->
private_data
;
struct
snd_soc_card
*
card
=
w
->
dapm
->
card
;
enum
snd_soc_dapm_direction
dir
,
rdir
;
char
*
buf
;
int
in
,
out
;
ssize_t
ret
;
...
...
@@ -1987,25 +1931,21 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
w
->
sname
,
w
->
active
?
"active"
:
"inactive"
);
list_for_each_entry
(
p
,
&
w
->
sources
,
list_sink
)
{
if
(
p
->
connected
&&
!
p
->
connected
(
w
,
p
->
source
))
snd_soc_dapm_for_each_direction
(
dir
)
{
rdir
=
SND_SOC_DAPM_DIR_REVERSE
(
dir
);
snd_soc_dapm_widget_for_each_path
(
w
,
dir
,
p
)
{
if
(
p
->
connected
&&
!
p
->
connected
(
w
,
p
->
node
[
rdir
]))
continue
;
if
(
p
->
connect
)
ret
+=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
" in
\"
%s
\"
\"
%s
\"\n
"
,
p
->
name
?
p
->
name
:
"static"
,
p
->
source
->
name
);
}
list_for_each_entry
(
p
,
&
w
->
sinks
,
list_source
)
{
if
(
p
->
connected
&&
!
p
->
connected
(
w
,
p
->
sink
))
if
(
!
p
->
connect
)
continue
;
if
(
p
->
connect
)
ret
+=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
" out
\"
%s
\"
\"
%s
\"\n
"
,
" %s
\"
%s
\"
\"
%s
\"\n
"
,
(
rdir
==
SND_SOC_DAPM_DIR_IN
)
?
"in"
:
"out"
,
p
->
name
?
p
->
name
:
"static"
,
p
->
sink
->
name
);
p
->
node
[
rdir
]
->
name
);
}
}
mutex_unlock
(
&
card
->
dapm_mutex
);
...
...
@@ -2305,37 +2245,43 @@ struct attribute *soc_dapm_dev_attrs[] = {
static
void
dapm_free_path
(
struct
snd_soc_dapm_path
*
path
)
{
list_del
(
&
path
->
list_
sink
);
list_del
(
&
path
->
list_
source
);
list_del
(
&
path
->
list_
node
[
SND_SOC_DAPM_DIR_IN
]
);
list_del
(
&
path
->
list_
node
[
SND_SOC_DAPM_DIR_OUT
]
);
list_del
(
&
path
->
list_kcontrol
);
list_del
(
&
path
->
list
);
kfree
(
path
);
}
/* free all dapm widgets and resources */
static
void
dapm_free_widgets
(
struct
snd_soc_dapm_context
*
dapm
)
void
snd_soc_dapm_free_widget
(
struct
snd_soc_dapm_widget
*
w
)
{
struct
snd_soc_dapm_widget
*
w
,
*
next_w
;
struct
snd_soc_dapm_path
*
p
,
*
next_p
;
enum
snd_soc_dapm_direction
dir
;
list_for_each_entry_safe
(
w
,
next_w
,
&
dapm
->
card
->
widgets
,
list
)
{
if
(
w
->
dapm
!=
dapm
)
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
)
dapm_free_path
(
p
);
list_for_each_entry_safe
(
p
,
next_p
,
&
w
->
sinks
,
list_source
)
snd_soc_dapm_for_each_direction
(
dir
)
{
snd_soc_dapm_widget_for_each_path_safe
(
w
,
dir
,
p
,
next_p
)
dapm_free_path
(
p
);
}
kfree
(
w
->
kcontrols
);
kfree
(
w
->
name
);
kfree_const
(
w
->
name
);
kfree
(
w
);
}
/* free all dapm widgets and resources */
static
void
dapm_free_widgets
(
struct
snd_soc_dapm_context
*
dapm
)
{
struct
snd_soc_dapm_widget
*
w
,
*
next_w
;
list_for_each_entry_safe
(
w
,
next_w
,
&
dapm
->
card
->
widgets
,
list
)
{
if
(
w
->
dapm
!=
dapm
)
continue
;
snd_soc_dapm_free_widget
(
w
);
}
}
...
...
@@ -2441,20 +2387,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
*/
static
void
dapm_update_widget_flags
(
struct
snd_soc_dapm_widget
*
w
)
{
enum
snd_soc_dapm_direction
dir
;
struct
snd_soc_dapm_path
*
p
;
unsigned
int
ep
;
switch
(
w
->
id
)
{
case
snd_soc_dapm_input
:
/* On a fully routed card a input is never a source */
if
(
w
->
dapm
->
card
->
fully_routed
)
break
;
w
->
is_source
=
1
;
list_for_each_entry
(
p
,
&
w
->
sources
,
list_sink
)
{
return
;
ep
=
SND_SOC_DAPM_EP_SOURCE
;
snd_soc_dapm_widget_for_each_source_path
(
w
,
p
)
{
if
(
p
->
source
->
id
==
snd_soc_dapm_micbias
||
p
->
source
->
id
==
snd_soc_dapm_mic
||
p
->
source
->
id
==
snd_soc_dapm_line
||
p
->
source
->
id
==
snd_soc_dapm_output
)
{
w
->
is_source
=
0
;
ep
=
0
;
break
;
}
}
...
...
@@ -2462,25 +2410,30 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)
case
snd_soc_dapm_output
:
/* On a fully routed card a output is never a sink */
if
(
w
->
dapm
->
card
->
fully_routed
)
break
;
w
->
is_sink
=
1
;
list_for_each_entry
(
p
,
&
w
->
sinks
,
list_source
)
{
return
;
ep
=
SND_SOC_DAPM_EP_SINK
;
snd_soc_dapm_widget_for_each_sink_path
(
w
,
p
)
{
if
(
p
->
sink
->
id
==
snd_soc_dapm_spk
||
p
->
sink
->
id
==
snd_soc_dapm_hp
||
p
->
sink
->
id
==
snd_soc_dapm_line
||
p
->
sink
->
id
==
snd_soc_dapm_input
)
{
w
->
is_sink
=
0
;
ep
=
0
;
break
;
}
}
break
;
case
snd_soc_dapm_line
:
w
->
is_sink
=
!
list_empty
(
&
w
->
sources
);
w
->
is_source
=
!
list_empty
(
&
w
->
sinks
);
ep
=
0
;
snd_soc_dapm_for_each_direction
(
dir
)
{
if
(
!
list_empty
(
&
w
->
edges
[
dir
]))
ep
|=
SND_SOC_DAPM_DIR_TO_EP
(
dir
);
}
break
;
default:
break
;
return
;
}
w
->
is_ep
=
ep
;
}
static
int
snd_soc_dapm_check_dynamic_path
(
struct
snd_soc_dapm_context
*
dapm
,
...
...
@@ -2533,6 +2486,8 @@ 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
;
...
...
@@ -2565,13 +2520,14 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
if
(
!
path
)
return
-
ENOMEM
;
path
->
source
=
wsource
;
path
->
sink
=
wsink
;
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
);
INIT_LIST_HEAD
(
&
path
->
list_kcontrol
);
INIT_LIST_HEAD
(
&
path
->
list_source
);
INIT_LIST_HEAD
(
&
path
->
list_sink
);
if
(
wsource
->
is_supply
||
wsink
->
is_supply
)
path
->
is_supply
=
1
;
...
...
@@ -2609,14 +2565,13 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
}
list_add
(
&
path
->
list
,
&
dapm
->
card
->
paths
);
list_add
(
&
path
->
list_sink
,
&
wsink
->
sources
);
list_add
(
&
path
->
list_source
,
&
wsource
->
sinks
);
dapm_update_widget_flags
(
wsource
);
dapm_update_widget_flags
(
wsink
);
snd_soc_dapm_for_each_direction
(
dir
)
list_add
(
&
path
->
list_node
[
dir
],
&
widgets
[
dir
]
->
edges
[
dir
]);
dapm_mark_dirty
(
wsource
,
"Route added"
);
dapm_mark_dirty
(
wsink
,
"Route added"
);
snd_soc_dapm_for_each_direction
(
dir
)
{
dapm_update_widget_flags
(
widgets
[
dir
]);
dapm_mark_dirty
(
widgets
[
dir
],
"Route added"
);
}
if
(
dapm
->
card
->
instantiated
&&
path
->
connect
)
dapm_path_invalidate
(
path
);
...
...
@@ -2864,7 +2819,7 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
dev_warn
(
dapm
->
dev
,
"ASoC: Ignoring control for weak route %s->%s
\n
"
,
route
->
source
,
route
->
sink
);
list_for_each_entry
(
path
,
&
source
->
sinks
,
list_source
)
{
snd_soc_dapm_widget_for_each_sink_path
(
source
,
path
)
{
if
(
path
->
sink
==
sink
)
{
path
->
weak
=
1
;
count
++
;
...
...
@@ -3298,6 +3253,7 @@ struct snd_soc_dapm_widget *
snd_soc_dapm_new_control_unlocked
(
struct
snd_soc_dapm_context
*
dapm
,
const
struct
snd_soc_dapm_widget
*
widget
)
{
enum
snd_soc_dapm_direction
dir
;
struct
snd_soc_dapm_widget
*
w
;
const
char
*
prefix
;
int
ret
;
...
...
@@ -3344,7 +3300,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
if
(
prefix
)
w
->
name
=
kasprintf
(
GFP_KERNEL
,
"%s %s"
,
prefix
,
widget
->
name
);
else
w
->
name
=
k
asprintf
(
GFP_KERNEL
,
"%s"
,
widget
->
name
);
w
->
name
=
k
strdup_const
(
widget
->
name
,
GFP_KERNEL
);
if
(
w
->
name
==
NULL
)
{
kfree
(
w
);
return
NULL
;
...
...
@@ -3352,27 +3308,27 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
switch
(
w
->
id
)
{
case
snd_soc_dapm_mic
:
w
->
is_
source
=
1
;
w
->
is_
ep
=
SND_SOC_DAPM_EP_SOURCE
;
w
->
power_check
=
dapm_generic_check_power
;
break
;
case
snd_soc_dapm_input
:
if
(
!
dapm
->
card
->
fully_routed
)
w
->
is_
source
=
1
;
w
->
is_
ep
=
SND_SOC_DAPM_EP_SOURCE
;
w
->
power_check
=
dapm_generic_check_power
;
break
;
case
snd_soc_dapm_spk
:
case
snd_soc_dapm_hp
:
w
->
is_
sink
=
1
;
w
->
is_
ep
=
SND_SOC_DAPM_EP_SINK
;
w
->
power_check
=
dapm_generic_check_power
;
break
;
case
snd_soc_dapm_output
:
if
(
!
dapm
->
card
->
fully_routed
)
w
->
is_
sink
=
1
;
w
->
is_
ep
=
SND_SOC_DAPM_EP_SINK
;
w
->
power_check
=
dapm_generic_check_power
;
break
;
case
snd_soc_dapm_vmid
:
case
snd_soc_dapm_siggen
:
w
->
is_
source
=
1
;
w
->
is_
ep
=
SND_SOC_DAPM_EP_SOURCE
;
w
->
power_check
=
dapm_always_on_check_power
;
break
;
case
snd_soc_dapm_mux
:
...
...
@@ -3406,14 +3362,14 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
}
w
->
dapm
=
dapm
;
INIT_LIST_HEAD
(
&
w
->
sources
);
INIT_LIST_HEAD
(
&
w
->
sinks
);
INIT_LIST_HEAD
(
&
w
->
list
);
INIT_LIST_HEAD
(
&
w
->
dirty
);
list_add_tail
(
&
w
->
list
,
&
dapm
->
card
->
widgets
);
w
->
inputs
=
-
1
;
w
->
outputs
=
-
1
;
snd_soc_dapm_for_each_direction
(
dir
)
{
INIT_LIST_HEAD
(
&
w
->
edges
[
dir
]);
w
->
endpoints
[
dir
]
=
-
1
;
}
/* machine layer set ups unconnected pins and insertions */
w
->
connected
=
1
;
...
...
@@ -3467,19 +3423,17 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
int
ret
;
if
(
WARN_ON
(
!
config
)
||
WARN_ON
(
list_empty
(
&
w
->
sources
)
||
list_empty
(
&
w
->
sinks
)))
WARN_ON
(
list_empty
(
&
w
->
edges
[
SND_SOC_DAPM_DIR_OUT
])
||
list_empty
(
&
w
->
edges
[
SND_SOC_DAPM_DIR_IN
])))
return
-
EINVAL
;
/* We only support a single source and sink, pick the first */
source_p
=
list_first_entry
(
&
w
->
sources
,
struct
snd_soc_dapm_path
,
list_sink
);
sink_p
=
list_first_entry
(
&
w
->
sinks
,
struct
snd_soc_dapm_path
,
list_source
);
if
(
WARN_ON
(
!
source_p
||
!
sink_p
)
||
WARN_ON
(
!
sink_p
->
source
||
!
source_p
->
sink
)
||
WARN_ON
(
!
source_p
->
source
||
!
sink_p
->
sink
))
return
-
EINVAL
;
source_p
=
list_first_entry
(
&
w
->
edges
[
SND_SOC_DAPM_DIR_OUT
],
struct
snd_soc_dapm_path
,
list_node
[
SND_SOC_DAPM_DIR_OUT
]);
sink_p
=
list_first_entry
(
&
w
->
edges
[
SND_SOC_DAPM_DIR_IN
],
struct
snd_soc_dapm_path
,
list_node
[
SND_SOC_DAPM_DIR_IN
]);
source
=
source_p
->
source
->
priv
;
sink
=
sink_p
->
sink
->
priv
;
...
...
@@ -3851,6 +3805,7 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
int
event
)
{
struct
snd_soc_dapm_widget
*
w
;
unsigned
int
ep
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
w
=
dai
->
playback_widget
;
...
...
@@ -3860,12 +3815,22 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
if
(
w
)
{
dapm_mark_dirty
(
w
,
"stream event"
);
if
(
w
->
id
==
snd_soc_dapm_dai_in
)
{
ep
=
SND_SOC_DAPM_EP_SOURCE
;
dapm_widget_invalidate_input_paths
(
w
);
}
else
{
ep
=
SND_SOC_DAPM_EP_SINK
;
dapm_widget_invalidate_output_paths
(
w
);
}
switch
(
event
)
{
case
SND_SOC_DAPM_STREAM_START
:
w
->
active
=
1
;
w
->
is_ep
=
ep
;
break
;
case
SND_SOC_DAPM_STREAM_STOP
:
w
->
active
=
0
;
w
->
is_ep
=
0
;
break
;
case
SND_SOC_DAPM_STREAM_SUSPEND
:
case
SND_SOC_DAPM_STREAM_RESUME
:
...
...
@@ -3873,14 +3838,6 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
case
SND_SOC_DAPM_STREAM_PAUSE_RELEASE
:
break
;
}
if
(
w
->
id
==
snd_soc_dapm_dai_in
)
{
w
->
is_source
=
w
->
active
;
dapm_widget_invalidate_input_paths
(
w
);
}
else
{
w
->
is_sink
=
w
->
active
;
dapm_widget_invalidate_output_paths
(
w
);
}
}
}
...
...
sound/soc/soc-pcm.c
View file @
4253f3a8
...
...
@@ -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
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_dapm_widget_list
*
list
;
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 */
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
,
stream
?
"capture"
:
"playback"
);
*
list_
=
list
;
return
paths
;
}
...
...
sound/soc/soc-topology.c
View file @
4253f3a8
...
...
@@ -1758,7 +1758,6 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
u32
index
)
{
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
)
{
...
...
@@ -1770,31 +1769,9 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
if
(
w
->
dobj
.
index
!=
index
&&
w
->
dobj
.
index
!=
SND_SOC_TPLG_INDEX_ALL
)
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 */
snd_soc_tplg_widget_remove
(
w
);
kfree
(
w
->
kcontrols
);
kfree
(
w
->
name
);
kfree
(
w
);
snd_soc_dapm_free_widget
(
w
);
}
}
EXPORT_SYMBOL_GPL
(
snd_soc_tplg_widget_remove_all
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment