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