Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
0e09b67e
Commit
0e09b67e
authored
Jun 11, 2009
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dapm' into for-2.6.32
parents
fa44c077
291f3bbc
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
227 additions
and
77 deletions
+227
-77
include/sound/soc.h
include/sound/soc.h
+0
-2
sound/soc/soc-dapm.c
sound/soc/soc-dapm.c
+227
-75
No files found.
include/sound/soc.h
View file @
0e09b67e
...
...
@@ -369,8 +369,6 @@ struct snd_soc_codec {
enum
snd_soc_bias_level
bias_level
;
enum
snd_soc_bias_level
suspend_bias_level
;
struct
delayed_work
delayed_work
;
struct
list_head
up_list
;
struct
list_head
down_list
;
/* codec DAI's */
struct
snd_soc_dai
*
dai
;
...
...
sound/soc/soc-dapm.c
View file @
0e09b67e
...
...
@@ -52,19 +52,37 @@
/* dapm power sequences - make this per codec in the future */
static
int
dapm_up_seq
[]
=
{
snd_soc_dapm_pre
,
snd_soc_dapm_supply
,
snd_soc_dapm_micbias
,
snd_soc_dapm_mic
,
snd_soc_dapm_mux
,
snd_soc_dapm_value_mux
,
snd_soc_dapm_dac
,
snd_soc_dapm_mixer
,
snd_soc_dapm_mixer_named_ctl
,
snd_soc_dapm_pga
,
snd_soc_dapm_adc
,
snd_soc_dapm_hp
,
snd_soc_dapm_spk
,
snd_soc_dapm_post
[
snd_soc_dapm_pre
]
=
0
,
[
snd_soc_dapm_supply
]
=
1
,
[
snd_soc_dapm_micbias
]
=
2
,
[
snd_soc_dapm_mic
]
=
3
,
[
snd_soc_dapm_mux
]
=
4
,
[
snd_soc_dapm_value_mux
]
=
4
,
[
snd_soc_dapm_dac
]
=
5
,
[
snd_soc_dapm_mixer
]
=
6
,
[
snd_soc_dapm_mixer_named_ctl
]
=
6
,
[
snd_soc_dapm_pga
]
=
7
,
[
snd_soc_dapm_adc
]
=
8
,
[
snd_soc_dapm_hp
]
=
9
,
[
snd_soc_dapm_spk
]
=
10
,
[
snd_soc_dapm_post
]
=
11
,
};
static
int
dapm_down_seq
[]
=
{
snd_soc_dapm_pre
,
snd_soc_dapm_adc
,
snd_soc_dapm_hp
,
snd_soc_dapm_spk
,
snd_soc_dapm_pga
,
snd_soc_dapm_mixer_named_ctl
,
snd_soc_dapm_mixer
,
snd_soc_dapm_dac
,
snd_soc_dapm_mic
,
snd_soc_dapm_micbias
,
snd_soc_dapm_mux
,
snd_soc_dapm_value_mux
,
snd_soc_dapm_supply
,
snd_soc_dapm_post
[
snd_soc_dapm_pre
]
=
0
,
[
snd_soc_dapm_adc
]
=
1
,
[
snd_soc_dapm_hp
]
=
2
,
[
snd_soc_dapm_spk
]
=
3
,
[
snd_soc_dapm_pga
]
=
4
,
[
snd_soc_dapm_mixer_named_ctl
]
=
5
,
[
snd_soc_dapm_mixer
]
=
5
,
[
snd_soc_dapm_dac
]
=
6
,
[
snd_soc_dapm_mic
]
=
7
,
[
snd_soc_dapm_micbias
]
=
8
,
[
snd_soc_dapm_mux
]
=
9
,
[
snd_soc_dapm_value_mux
]
=
9
,
[
snd_soc_dapm_supply
]
=
10
,
[
snd_soc_dapm_post
]
=
11
,
};
static
void
pop_wait
(
u32
pop_time
)
...
...
@@ -689,53 +707,211 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
return
power
;
}
/*
* Scan a single DAPM widget for a complete audio path and update the
* power status appropriately.
static
int
dapm_seq_compare
(
struct
snd_soc_dapm_widget
*
a
,
struct
snd_soc_dapm_widget
*
b
,
int
sort
[])
{
if
(
sort
[
a
->
id
]
!=
sort
[
b
->
id
])
return
sort
[
a
->
id
]
-
sort
[
b
->
id
];
if
(
a
->
reg
!=
b
->
reg
)
return
a
->
reg
-
b
->
reg
;
return
0
;
}
/* Insert a widget in order into a DAPM power sequence. */
static
void
dapm_seq_insert
(
struct
snd_soc_dapm_widget
*
new_widget
,
struct
list_head
*
list
,
int
sort
[])
{
struct
snd_soc_dapm_widget
*
w
;
list_for_each_entry
(
w
,
list
,
power_list
)
if
(
dapm_seq_compare
(
new_widget
,
w
,
sort
)
<
0
)
{
list_add_tail
(
&
new_widget
->
power_list
,
&
w
->
power_list
);
return
;
}
list_add_tail
(
&
new_widget
->
power_list
,
list
);
}
/* Apply the coalesced changes from a DAPM sequence */
static
void
dapm_seq_run_coalesced
(
struct
snd_soc_codec
*
codec
,
struct
list_head
*
pending
)
{
struct
snd_soc_dapm_widget
*
w
;
int
reg
,
power
,
ret
;
unsigned
int
value
=
0
;
unsigned
int
mask
=
0
;
unsigned
int
cur_mask
;
reg
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
)
->
reg
;
list_for_each_entry
(
w
,
pending
,
power_list
)
{
cur_mask
=
1
<<
w
->
shift
;
BUG_ON
(
reg
!=
w
->
reg
);
if
(
w
->
invert
)
power
=
!
w
->
power
;
else
power
=
w
->
power
;
mask
|=
cur_mask
;
if
(
power
)
value
|=
cur_mask
;
pop_dbg
(
codec
->
pop_time
,
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x
\n
"
,
w
->
name
,
reg
,
value
,
mask
);
/* power up pre event */
if
(
w
->
power
&&
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_PRE_PMU
))
{
pop_dbg
(
codec
->
pop_time
,
"pop test : %s PRE_PMU
\n
"
,
w
->
name
);
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_PRE_PMU
);
if
(
ret
<
0
)
pr_err
(
"%s: pre event failed: %d
\n
"
,
w
->
name
,
ret
);
}
/* power down pre event */
if
(
!
w
->
power
&&
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_PRE_PMD
))
{
pop_dbg
(
codec
->
pop_time
,
"pop test : %s PRE_PMD
\n
"
,
w
->
name
);
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_PRE_PMD
);
if
(
ret
<
0
)
pr_err
(
"%s: pre event failed: %d
\n
"
,
w
->
name
,
ret
);
}
/* Lower PGA volume to reduce pops */
if
(
w
->
id
==
snd_soc_dapm_pga
&&
!
w
->
power
)
dapm_set_pga
(
w
,
w
->
power
);
}
if
(
reg
>=
0
)
{
pop_dbg
(
codec
->
pop_time
,
"pop test : Applying 0x%x/0x%x to %x in %dms
\n
"
,
value
,
mask
,
reg
,
codec
->
pop_time
);
pop_wait
(
codec
->
pop_time
);
snd_soc_update_bits
(
codec
,
reg
,
mask
,
value
);
}
list_for_each_entry
(
w
,
pending
,
power_list
)
{
/* Raise PGA volume to reduce pops */
if
(
w
->
id
==
snd_soc_dapm_pga
&&
w
->
power
)
dapm_set_pga
(
w
,
w
->
power
);
/* power up post event */
if
(
w
->
power
&&
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_POST_PMU
))
{
pop_dbg
(
codec
->
pop_time
,
"pop test : %s POST_PMU
\n
"
,
w
->
name
);
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_POST_PMU
);
if
(
ret
<
0
)
pr_err
(
"%s: post event failed: %d
\n
"
,
w
->
name
,
ret
);
}
/* power down post event */
if
(
!
w
->
power
&&
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_POST_PMD
))
{
pop_dbg
(
codec
->
pop_time
,
"pop test : %s POST_PMD
\n
"
,
w
->
name
);
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_POST_PMD
);
if
(
ret
<
0
)
pr_err
(
"%s: post event failed: %d
\n
"
,
w
->
name
,
ret
);
}
}
}
/* Apply a DAPM power sequence.
*
* We walk over a pre-sorted list of widgets to apply power to. In
* order to minimise the number of writes to the device required
* multiple widgets will be updated in a single write where possible.
* Currently anything that requires more than a single write is not
* handled.
*/
static
int
dapm_power_widget
(
struct
snd_soc_codec
*
codec
,
int
even
t
,
struct
snd_soc_dapm_widget
*
w
)
static
void
dapm_seq_run
(
struct
snd_soc_codec
*
codec
,
struct
list_head
*
lis
t
,
int
event
,
int
sort
[]
)
{
struct
snd_soc_dapm_widget
*
w
,
*
n
;
LIST_HEAD
(
pending
);
int
cur_sort
=
-
1
;
int
cur_reg
=
SND_SOC_NOPM
;
int
ret
;
list_for_each_entry_safe
(
w
,
n
,
list
,
power_list
)
{
ret
=
0
;
/* Do we need to apply any queued changes? */
if
(
sort
[
w
->
id
]
!=
cur_sort
||
w
->
reg
!=
cur_reg
)
{
if
(
!
list_empty
(
&
pending
))
dapm_seq_run_coalesced
(
codec
,
&
pending
);
INIT_LIST_HEAD
(
&
pending
);
cur_sort
=
-
1
;
cur_reg
=
SND_SOC_NOPM
;
}
switch
(
w
->
id
)
{
case
snd_soc_dapm_pre
:
if
(
!
w
->
event
)
return
0
;
list_for_each_entry_safe_continue
(
w
,
n
,
list
,
power_list
);
if
(
event
==
SND_SOC_DAPM_STREAM_START
)
{
if
(
event
==
SND_SOC_DAPM_STREAM_START
)
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_PRE_PMU
);
if
(
ret
<
0
)
return
ret
;
}
else
if
(
event
==
SND_SOC_DAPM_STREAM_STOP
)
{
else
if
(
event
==
SND_SOC_DAPM_STREAM_STOP
)
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_PRE_PMD
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
break
;
case
snd_soc_dapm_post
:
if
(
!
w
->
event
)
return
0
;
list_for_each_entry_safe_continue
(
w
,
n
,
list
,
power_list
);
if
(
event
==
SND_SOC_DAPM_STREAM_START
)
{
if
(
event
==
SND_SOC_DAPM_STREAM_START
)
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_POST_PMU
);
if
(
ret
<
0
)
return
ret
;
}
else
if
(
event
==
SND_SOC_DAPM_STREAM_STOP
)
{
else
if
(
event
==
SND_SOC_DAPM_STREAM_STOP
)
ret
=
w
->
event
(
w
,
NULL
,
SND_SOC_DAPM_POST_PMD
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
break
;
case
snd_soc_dapm_input
:
case
snd_soc_dapm_output
:
case
snd_soc_dapm_hp
:
case
snd_soc_dapm_mic
:
case
snd_soc_dapm_line
:
case
snd_soc_dapm_spk
:
/* No register support currently */
ret
=
dapm_generic_apply_power
(
w
);
break
;
default:
return
dapm_generic_apply_power
(
w
);
/* Queue it up for application */
cur_sort
=
sort
[
w
->
id
];
cur_reg
=
w
->
reg
;
list_move
(
&
w
->
power_list
,
&
pending
);
break
;
}
if
(
ret
<
0
)
pr_err
(
"Failed to apply widget power: %d
\n
"
,
ret
);
}
if
(
!
list_empty
(
&
pending
))
dapm_seq_run_coalesced
(
codec
,
&
pending
);
}
/*
...
...
@@ -751,23 +927,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
{
struct
snd_soc_device
*
socdev
=
codec
->
socdev
;
struct
snd_soc_dapm_widget
*
w
;
LIST_HEAD
(
up_list
);
LIST_HEAD
(
down_list
);
int
ret
=
0
;
int
i
,
power
;
int
power
;
int
sys_power
=
0
;
INIT_LIST_HEAD
(
&
codec
->
up_list
);
INIT_LIST_HEAD
(
&
codec
->
down_list
);
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down.
*/
list_for_each_entry
(
w
,
&
codec
->
dapm_widgets
,
list
)
{
switch
(
w
->
id
)
{
case
snd_soc_dapm_pre
:
list_add_tail
(
&
codec
->
down_list
,
&
w
->
power_list
);
dapm_seq_insert
(
w
,
&
down_list
,
dapm_down_seq
);
break
;
case
snd_soc_dapm_post
:
list_add_tail
(
&
codec
->
up_list
,
&
w
->
power_list
);
dapm_seq_insert
(
w
,
&
up_list
,
dapm_up_seq
);
break
;
default:
...
...
@@ -782,10 +957,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
continue
;
if
(
power
)
list_add_tail
(
&
w
->
power_list
,
&
codec
->
up_list
);
dapm_seq_insert
(
w
,
&
up_list
,
dapm_up_seq
);
else
list_add_tail
(
&
w
->
power_list
,
&
codec
->
down_list
);
dapm_seq_insert
(
w
,
&
down_list
,
dapm_down_seq
);
w
->
power
=
power
;
break
;
...
...
@@ -802,32 +976,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
}
/* Power down widgets first; try to avoid amplifying pops. */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dapm_down_seq
);
i
++
)
{
list_for_each_entry
(
w
,
&
codec
->
down_list
,
power_list
)
{
/* is widget in stream order */
if
(
w
->
id
!=
dapm_down_seq
[
i
])
continue
;
ret
=
dapm_power_widget
(
codec
,
event
,
w
);
if
(
ret
!=
0
)
pr_err
(
"Failed to power down %s: %d
\n
"
,
w
->
name
,
ret
);
}
}
dapm_seq_run
(
codec
,
&
down_list
,
event
,
dapm_down_seq
);
/* Now power up. */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dapm_up_seq
);
i
++
)
{
list_for_each_entry
(
w
,
&
codec
->
up_list
,
power_list
)
{
/* is widget in stream order */
if
(
w
->
id
!=
dapm_up_seq
[
i
])
continue
;
ret
=
dapm_power_widget
(
codec
,
event
,
w
);
if
(
ret
!=
0
)
pr_err
(
"Failed to power up %s: %d
\n
"
,
w
->
name
,
ret
);
}
}
dapm_seq_run
(
codec
,
&
up_list
,
event
,
dapm_up_seq
);
/* If we just powered the last thing off drop to standby bias */
if
(
codec
->
bias_level
==
SND_SOC_BIAS_PREPARE
&&
!
sys_power
)
{
...
...
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