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
7b451962
Commit
7b451962
authored
Apr 12, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-next
parents
69976189
1059ecfa
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
171 additions
and
148 deletions
+171
-148
sound/soc/soc-dapm.c
sound/soc/soc-dapm.c
+171
-148
No files found.
sound/soc/soc-dapm.c
View file @
7b451962
...
...
@@ -504,17 +504,27 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
return
0
;
}
/* create new dapm mixer control */
static
int
dapm_new_mixer
(
struct
snd_soc_dapm_widget
*
w
)
/*
* Determine if a kcontrol is shared. If it is, look it up. If it isn't,
* create it. Either way, add the widget into the control's widget list
*/
static
int
dapm_create_or_share_mixmux_kcontrol
(
struct
snd_soc_dapm_widget
*
w
,
int
kci
,
struct
snd_soc_dapm_path
*
path
)
{
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
int
i
,
ret
=
0
;
size_t
name_len
,
prefix_len
;
struct
snd_soc_dapm_path
*
path
;
struct
snd_card
*
card
=
dapm
->
card
->
snd_card
;
const
char
*
prefix
;
size_t
prefix_len
;
int
shared
;
struct
snd_kcontrol
*
kcontrol
;
struct
snd_soc_dapm_widget_list
*
wlist
;
int
wlistentries
;
size_t
wlistsize
;
bool
wname_in_long_name
,
kcname_in_long_name
;
size_t
name_len
;
char
*
long_name
;
const
char
*
name
;
int
ret
;
if
(
dapm
->
codec
)
prefix
=
dapm
->
codec
->
name_prefix
;
...
...
@@ -526,103 +536,141 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
else
prefix_len
=
0
;
/* add kcontrol */
for
(
i
=
0
;
i
<
w
->
num_kcontrols
;
i
++
)
{
shared
=
dapm_is_shared_kcontrol
(
dapm
,
w
,
&
w
->
kcontrol_news
[
kci
],
&
kcontrol
);
/* match name */
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
{
if
(
kcontrol
)
{
wlist
=
kcontrol
->
private_data
;
wlistentries
=
wlist
->
num_widgets
+
1
;
}
else
{
wlist
=
NULL
;
wlistentries
=
1
;
}
/* mixer/mux paths name must match control name */
if
(
path
->
name
!=
(
char
*
)
w
->
kcontrol_news
[
i
].
name
)
continue
;
wlistsize
=
sizeof
(
struct
snd_soc_dapm_widget_list
)
+
wlistentries
*
sizeof
(
struct
snd_soc_dapm_widget
*
);
wlist
=
krealloc
(
wlist
,
wlistsize
,
GFP_KERNEL
);
if
(
wlist
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: can't allocate widget list for %s
\n
"
,
w
->
name
);
return
-
ENOMEM
;
}
wlist
->
num_widgets
=
wlistentries
;
wlist
->
widgets
[
wlistentries
-
1
]
=
w
;
if
(
w
->
kcontrols
[
i
])
{
path
->
kcontrol
=
w
->
kcontrols
[
i
];
continue
;
if
(
!
kcontrol
)
{
if
(
shared
)
{
wname_in_long_name
=
false
;
kcname_in_long_name
=
true
;
}
else
{
switch
(
w
->
id
)
{
case
snd_soc_dapm_switch
:
case
snd_soc_dapm_mixer
:
wname_in_long_name
=
true
;
kcname_in_long_name
=
true
;
break
;
case
snd_soc_dapm_mixer_named_ctl
:
wname_in_long_name
=
false
;
kcname_in_long_name
=
true
;
break
;
case
snd_soc_dapm_mux
:
case
snd_soc_dapm_virt_mux
:
case
snd_soc_dapm_value_mux
:
wname_in_long_name
=
true
;
kcname_in_long_name
=
false
;
break
;
default:
kfree
(
wlist
);
return
-
EINVAL
;
}
}
if
(
wname_in_long_name
&&
kcname_in_long_name
)
{
name_len
=
strlen
(
w
->
name
)
-
prefix_len
+
1
+
strlen
(
w
->
kcontrol_news
[
kci
].
name
)
+
1
;
wlistsize
=
sizeof
(
struct
snd_soc_dapm_widget_list
)
+
sizeof
(
struct
snd_soc_dapm_widget
*
),
wlist
=
kzalloc
(
wlistsize
,
GFP_KERNEL
);
if
(
wlist
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: can't allocate widget list for %s
\n
"
,
w
->
name
);
long_name
=
kmalloc
(
name_len
,
GFP_KERNEL
);
if
(
long_name
==
NULL
)
{
kfree
(
wlist
);
return
-
ENOMEM
;
}
wlist
->
num_widgets
=
1
;
wlist
->
widgets
[
0
]
=
w
;
/* add dapm control with long name.
* for dapm_mixer this is the concatenation of the
* mixer and kcontrol name.
* for dapm_mixer_named_ctl this is simply the
* kcontrol name.
/*
* The control will get a prefix from the control
* creation process but we're also using the same
* prefix for widgets so cut the prefix off the
* front of the widget name.
*/
name_len
=
strlen
(
w
->
kcontrol_news
[
i
].
name
)
+
1
;
if
(
w
->
id
!=
snd_soc_dapm_mixer_named_ctl
)
name_len
+=
1
+
strlen
(
w
->
name
);
snprintf
(
long_name
,
name_len
,
"%s %s"
,
w
->
name
+
prefix_len
,
w
->
kcontrol_news
[
kci
].
name
);
long_name
[
name_len
-
1
]
=
'\0'
;
name
=
long_name
;
}
else
if
(
wname_in_long_name
)
{
long_name
=
NULL
;
name
=
w
->
name
+
prefix_len
;
}
else
{
long_name
=
NULL
;
name
=
w
->
kcontrol_news
[
kci
].
name
;
}
path
->
long_name
=
kmalloc
(
name_len
,
GFP_KERNEL
);
kcontrol
=
snd_soc_cnew
(
&
w
->
kcontrol_news
[
kci
],
wlist
,
name
,
prefix
);
ret
=
snd_ctl_add
(
card
,
kcontrol
);
if
(
ret
<
0
)
{
dev_err
(
dapm
->
dev
,
"ASoC: failed to add widget %s dapm kcontrol %s: %d
\n
"
,
w
->
name
,
name
,
ret
);
kfree
(
wlist
);
kfree
(
long_name
);
return
ret
;
}
if
(
path
->
long_name
==
NULL
)
{
kfree
(
wlist
);
return
-
ENOMEM
;
}
path
->
long_name
=
long_name
;
}
switch
(
w
->
id
)
{
default:
/* The control will get a prefix from
* the control creation process but
* we're also using the same prefix
* for widgets so cut the prefix off
* the front of the widget name.
*/
snprintf
((
char
*
)
path
->
long_name
,
name_len
,
"%s %s"
,
w
->
name
+
prefix_len
,
w
->
kcontrol_news
[
i
].
name
);
break
;
case
snd_soc_dapm_mixer_named_ctl
:
snprintf
((
char
*
)
path
->
long_name
,
name_len
,
"%s"
,
w
->
kcontrol_news
[
i
].
name
);
break
;
}
kcontrol
->
private_data
=
wlist
;
w
->
kcontrols
[
kci
]
=
kcontrol
;
path
->
kcontrol
=
kcontrol
;
((
char
*
)
path
->
long_name
)[
name_len
-
1
]
=
'\0'
;
return
0
;
}
path
->
kcontrol
=
snd_soc_cnew
(
&
w
->
kcontrol_news
[
i
],
wlist
,
path
->
long_name
,
prefix
);
ret
=
snd_ctl_add
(
card
,
path
->
kcontrol
);
if
(
ret
<
0
)
{
dev_err
(
dapm
->
dev
,
"ASoC: failed to add widget"
" %s dapm kcontrol %s: %d
\n
"
,
w
->
name
,
path
->
long_name
,
ret
);
kfree
(
wlist
);
kfree
(
path
->
long_name
);
path
->
long_name
=
NULL
;
return
ret
;
/* create new dapm mixer control */
static
int
dapm_new_mixer
(
struct
snd_soc_dapm_widget
*
w
)
{
int
i
,
ret
;
struct
snd_soc_dapm_path
*
path
;
/* add kcontrol */
for
(
i
=
0
;
i
<
w
->
num_kcontrols
;
i
++
)
{
/* match name */
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
{
/* mixer/mux paths name must match control name */
if
(
path
->
name
!=
(
char
*
)
w
->
kcontrol_news
[
i
].
name
)
continue
;
if
(
w
->
kcontrols
[
i
])
{
path
->
kcontrol
=
w
->
kcontrols
[
i
];
continue
;
}
w
->
kcontrols
[
i
]
=
path
->
kcontrol
;
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
i
,
path
);
if
(
ret
<
0
)
return
ret
;
}
}
return
ret
;
return
0
;
}
/* create new dapm mux control */
static
int
dapm_new_mux
(
struct
snd_soc_dapm_widget
*
w
)
{
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
struct
snd_soc_dapm_path
*
path
=
NULL
;
struct
snd_kcontrol
*
kcontrol
;
struct
snd_card
*
card
=
dapm
->
card
->
snd_card
;
const
char
*
prefix
;
size_t
prefix_len
;
struct
snd_soc_dapm_path
*
path
;
int
ret
;
struct
snd_soc_dapm_widget_list
*
wlist
;
int
shared
,
wlistentries
;
size_t
wlistsize
;
const
char
*
name
;
if
(
w
->
num_kcontrols
!=
1
)
{
dev_err
(
dapm
->
dev
,
...
...
@@ -631,65 +679,19 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
return
-
EINVAL
;
}
shared
=
dapm_is_shared_kcontrol
(
dapm
,
w
,
&
w
->
kcontrol_news
[
0
],
&
kcontrol
);
if
(
kcontrol
)
{
wlist
=
kcontrol
->
private_data
;
wlistentries
=
wlist
->
num_widgets
+
1
;
}
else
{
wlist
=
NULL
;
wlistentries
=
1
;
}
wlistsize
=
sizeof
(
struct
snd_soc_dapm_widget_list
)
+
wlistentries
*
sizeof
(
struct
snd_soc_dapm_widget
*
),
wlist
=
krealloc
(
wlist
,
wlistsize
,
GFP_KERNEL
);
if
(
wlist
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: can't allocate widget list for %s
\n
"
,
w
->
name
);
return
-
ENOMEM
;
}
wlist
->
num_widgets
=
wlistentries
;
wlist
->
widgets
[
wlistentries
-
1
]
=
w
;
if
(
!
kcontrol
)
{
if
(
dapm
->
codec
)
prefix
=
dapm
->
codec
->
name_prefix
;
else
prefix
=
NULL
;
if
(
shared
)
{
name
=
w
->
kcontrol_news
[
0
].
name
;
prefix_len
=
0
;
}
else
{
name
=
w
->
name
;
if
(
prefix
)
prefix_len
=
strlen
(
prefix
)
+
1
;
else
prefix_len
=
0
;
}
/*
* The control will get a prefix from the control creation
* process but we're also using the same prefix for widgets so
* cut the prefix off the front of the widget name.
*/
kcontrol
=
snd_soc_cnew
(
&
w
->
kcontrol_news
[
0
],
wlist
,
name
+
prefix_len
,
prefix
);
ret
=
snd_ctl_add
(
card
,
kcontrol
);
if
(
ret
<
0
)
{
dev_err
(
dapm
->
dev
,
"ASoC: failed to add kcontrol %s: %d
\n
"
,
w
->
name
,
ret
);
kfree
(
wlist
);
return
ret
;
}
path
=
list_first_entry
(
&
w
->
sources
,
struct
snd_soc_dapm_path
,
list_sink
);
if
(
!
path
)
{
dev_err
(
dapm
->
dev
,
"ASoC: mux %s has no paths
\n
"
,
w
->
name
);
return
-
EINVAL
;
}
kcontrol
->
private_data
=
wlist
;
w
->
kcontrols
[
0
]
=
kcontrol
;
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
0
,
path
)
;
if
(
ret
<
0
)
return
ret
;
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
path
->
kcontrol
=
kcontrol
;
path
->
kcontrol
=
w
->
kcontrols
[
0
]
;
return
0
;
}
...
...
@@ -705,14 +707,33 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
}
/* reset 'walked' bit for each dapm path */
static
inline
void
dapm_clear_walk
(
struct
snd_soc_dapm_context
*
dapm
)
static
void
dapm_clear_walk_output
(
struct
snd_soc_dapm_context
*
dapm
,
struct
list_head
*
sink
)
{
struct
snd_soc_dapm_path
*
p
;
list_for_each_entry
(
p
,
&
dapm
->
card
->
paths
,
list
)
p
->
walked
=
0
;
list_for_each_entry
(
p
,
sink
,
list_source
)
{
if
(
p
->
walked
)
{
p
->
walked
=
0
;
dapm_clear_walk_output
(
dapm
,
&
p
->
sink
->
sinks
);
}
}
}
static
void
dapm_clear_walk_input
(
struct
snd_soc_dapm_context
*
dapm
,
struct
list_head
*
source
)
{
struct
snd_soc_dapm_path
*
p
;
list_for_each_entry
(
p
,
source
,
list_sink
)
{
if
(
p
->
walked
)
{
p
->
walked
=
0
;
dapm_clear_walk_input
(
dapm
,
&
p
->
source
->
sources
);
}
}
}
/* We implement power down on suspend by checking the power state of
* the ALSA card - when we are suspending the ALSA state for the card
* is set to D3.
...
...
@@ -995,13 +1016,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
dapm_reset
(
card
);
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
paths
=
is_connected_output_ep
(
dai
->
playback_widget
,
list
);
else
dapm_clear_walk_output
(
&
card
->
dapm
,
&
dai
->
playback_widget
->
sinks
);
}
else
{
paths
=
is_connected_input_ep
(
dai
->
capture_widget
,
list
);
dapm_clear_walk_input
(
&
card
->
dapm
,
&
dai
->
capture_widget
->
sources
);
}
trace_snd_soc_dapm_connected
(
paths
,
stream
);
dapm_clear_walk
(
&
card
->
dapm
);
mutex_unlock
(
&
card
->
dapm_mutex
);
return
paths
;
...
...
@@ -1104,9 +1129,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
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_input
(
w
->
dapm
,
&
w
->
sources
);
out
=
is_connected_output_ep
(
w
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_output
(
w
->
dapm
,
&
w
->
sinks
);
return
out
!=
0
&&
in
!=
0
;
}
...
...
@@ -1129,7 +1154,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
if
(
w
->
active
)
{
in
=
is_connected_input_ep
(
w
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_input
(
w
->
dapm
,
&
w
->
sources
);
return
in
!=
0
;
}
else
{
return
dapm_generic_check_power
(
w
);
...
...
@@ -1145,7 +1170,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
if
(
w
->
active
)
{
out
=
is_connected_output_ep
(
w
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_output
(
w
->
dapm
,
&
w
->
sinks
);
return
out
!=
0
;
}
else
{
return
dapm_generic_check_power
(
w
);
...
...
@@ -1177,8 +1202,6 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
return
1
;
}
dapm_clear_walk
(
w
->
dapm
);
return
0
;
}
...
...
@@ -1759,9 +1782,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
return
-
ENOMEM
;
in
=
is_connected_input_ep
(
w
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_input
(
w
->
dapm
,
&
w
->
sources
);
out
=
is_connected_output_ep
(
w
,
NULL
);
dapm_clear_walk
(
w
->
dapm
);
dapm_clear_walk
_output
(
w
->
dapm
,
&
w
->
sinks
);
ret
=
snprintf
(
buf
,
PAGE_SIZE
,
"%s: %s%s in %d out %d"
,
w
->
name
,
w
->
power
?
"On"
:
"Off"
,
...
...
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