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
Kirill Smelkov
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