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
a1cb98ac
Commit
a1cb98ac
authored
Aug 04, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/component' into asoc-next
parents
7c081528
0f2780ad
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1125 additions
and
749 deletions
+1125
-749
include/sound/soc-dai.h
include/sound/soc-dai.h
+4
-1
include/sound/soc-dapm.h
include/sound/soc-dapm.h
+5
-3
include/sound/soc.h
include/sound/soc.h
+57
-21
include/trace/events/asoc.h
include/trace/events/asoc.h
+3
-3
sound/soc/codecs/ac97.c
sound/soc/codecs/ac97.c
+2
-2
sound/soc/codecs/cx20442.c
sound/soc/codecs/cx20442.c
+3
-3
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tlv320dac33.c
+1
-1
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda134x.c
+1
-1
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8960.c
+1
-1
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.c
+2
-2
sound/soc/omap/ams-delta.c
sound/soc/omap/ams-delta.c
+1
-1
sound/soc/soc-cache.c
sound/soc/soc-cache.c
+3
-4
sound/soc/soc-compress.c
sound/soc/soc-compress.c
+10
-3
sound/soc/soc-core.c
sound/soc/soc-core.c
+462
-384
sound/soc/soc-dapm.c
sound/soc/soc-dapm.c
+158
-121
sound/soc/soc-jack.c
sound/soc/soc-jack.c
+2
-2
sound/soc/soc-pcm.c
sound/soc/soc-pcm.c
+400
-180
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_alc5632.c
+2
-3
sound/soc/tegra/tegra_max98090.c
sound/soc/tegra/tegra_max98090.c
+2
-3
sound/soc/tegra/tegra_rt5640.c
sound/soc/tegra/tegra_rt5640.c
+2
-3
sound/soc/tegra/tegra_wm8753.c
sound/soc/tegra/tegra_wm8753.c
+1
-2
sound/soc/tegra/tegra_wm8903.c
sound/soc/tegra/tegra_wm8903.c
+2
-3
sound/soc/tegra/trimslice.c
sound/soc/tegra/trimslice.c
+1
-2
No files found.
include/sound/soc-dai.h
View file @
a1cb98ac
...
...
@@ -257,7 +257,6 @@ struct snd_soc_dai {
struct
snd_soc_dapm_widget
*
playback_widget
;
struct
snd_soc_dapm_widget
*
capture_widget
;
struct
snd_soc_dapm_context
dapm
;
/* DAI DMA data */
void
*
playback_dma_data
;
...
...
@@ -273,6 +272,10 @@ struct snd_soc_dai {
struct
snd_soc_codec
*
codec
;
struct
snd_soc_component
*
component
;
/* CODEC TDM slot masks and params (for fixup) */
unsigned
int
tx_mask
;
unsigned
int
rx_mask
;
struct
snd_soc_card
*
card
;
struct
list_head
list
;
...
...
include/sound/soc-dapm.h
View file @
a1cb98ac
...
...
@@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const
char
*
pin
);
int
snd_soc_dapm_ignore_suspend
(
struct
snd_soc_dapm_context
*
dapm
,
const
char
*
pin
);
void
snd_soc_dapm_auto_nc_
codec_pins
(
struct
snd_soc_codec
*
codec
);
void
snd_soc_dapm_auto_nc_
pins
(
struct
snd_soc_card
*
card
);
/* Mostly internal - should not normally be used */
void
dapm_mark_io_dirty
(
struct
snd_soc_dapm_context
*
dapm
);
...
...
@@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
struct
snd_soc_dapm_widget_list
**
list
);
struct
snd_soc_codec
*
snd_soc_dapm_kcontrol_codec
(
struct
snd_kcontrol
*
kcontrol
);
struct
snd_soc_dapm_context
*
snd_soc_dapm_kcontrol_dapm
(
struct
snd_kcontrol
*
kcontrol
);
/* dapm widget types */
enum
snd_soc_dapm_type
{
...
...
@@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
const
char
*
name
;
/* widget name */
const
char
*
sname
;
/* stream name */
struct
snd_soc_codec
*
codec
;
struct
snd_soc_platform
*
platform
;
struct
list_head
list
;
struct
snd_soc_dapm_context
*
dapm
;
...
...
@@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
struct
device
*
dev
;
/* from parent - for debug */
struct
snd_soc_component
*
component
;
/* parent component */
struct
snd_soc_codec
*
codec
;
/* parent codec */
struct
snd_soc_platform
*
platform
;
/* parent platform */
struct
snd_soc_card
*
card
;
/* parent card */
/* used during DAPM updates */
...
...
@@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
struct
list_head
list
;
int
(
*
stream_event
)(
struct
snd_soc_dapm_context
*
dapm
,
int
event
);
int
(
*
set_bias_level
)(
struct
snd_soc_dapm_context
*
dapm
,
enum
snd_soc_bias_level
level
);
#ifdef CONFIG_DEBUG_FS
struct
dentry
*
debugfs_dapm
;
...
...
include/sound/soc.h
View file @
a1cb98ac
...
...
@@ -436,6 +436,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
int
snd_soc_platform_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_platform
*
platform
);
int
soc_dai_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
);
/* Jack reporting */
int
snd_soc_jack_new
(
struct
snd_soc_codec
*
codec
,
const
char
*
id
,
int
type
,
struct
snd_soc_jack
*
jack
);
...
...
@@ -503,10 +507,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
const
char
*
prefix
);
struct
snd_kcontrol
*
snd_soc_card_get_kcontrol
(
struct
snd_soc_card
*
soc_card
,
const
char
*
name
);
int
snd_soc_add_component_controls
(
struct
snd_soc_component
*
component
,
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
);
int
snd_soc_add_codec_controls
(
struct
snd_soc_codec
*
codec
,
const
struct
snd_kcontrol_new
*
controls
,
int
num_controls
);
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
);
int
snd_soc_add_platform_controls
(
struct
snd_soc_platform
*
platform
,
const
struct
snd_kcontrol_new
*
controls
,
int
num_controls
);
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
);
int
snd_soc_add_card_controls
(
struct
snd_soc_card
*
soc_card
,
const
struct
snd_kcontrol_new
*
controls
,
int
num_controls
);
int
snd_soc_add_dai_controls
(
struct
snd_soc_dai
*
dai
,
...
...
@@ -677,12 +683,17 @@ struct snd_soc_component_driver {
int
(
*
of_xlate_dai_name
)(
struct
snd_soc_component
*
component
,
struct
of_phandle_args
*
args
,
const
char
**
dai_name
);
void
(
*
seq_notifier
)(
struct
snd_soc_component
*
,
enum
snd_soc_dapm_type
,
int
subseq
);
int
(
*
stream_event
)(
struct
snd_soc_component
*
,
int
event
);
};
struct
snd_soc_component
{
const
char
*
name
;
int
id
;
const
char
*
name_prefix
;
struct
device
*
dev
;
struct
snd_soc_card
*
card
;
unsigned
int
active
;
...
...
@@ -705,18 +716,18 @@ struct snd_soc_component {
int
val_bytes
;
struct
mutex
io_mutex
;
/* Don't use these, use snd_soc_component_get_dapm() */
struct
snd_soc_dapm_context
dapm
;
struct
snd_soc_dapm_context
*
dapm_ptr
;
};
/* SoC Audio Codec device */
struct
snd_soc_codec
{
const
char
*
name
;
const
char
*
name_prefix
;
int
id
;
struct
device
*
dev
;
const
struct
snd_soc_codec_driver
*
driver
;
struct
mutex
mutex
;
struct
snd_soc_card
*
card
;
struct
list_head
list
;
struct
list_head
card_list
;
...
...
@@ -790,9 +801,6 @@ struct snd_soc_codec_driver {
void
(
*
seq_notifier
)(
struct
snd_soc_dapm_context
*
,
enum
snd_soc_dapm_type
,
int
);
/* codec stream completion event */
int
(
*
stream_event
)(
struct
snd_soc_dapm_context
*
dapm
,
int
event
);
bool
ignore_pmdown_time
;
/* Doesn't benefit from pmdown delay */
/* probe ordering - for components with runtime dependencies */
...
...
@@ -834,9 +842,6 @@ struct snd_soc_platform_driver {
/* platform stream compress ops */
const
struct
snd_compr_ops
*
compr_ops
;
/* platform stream completion event */
int
(
*
stream_event
)(
struct
snd_soc_dapm_context
*
dapm
,
int
event
);
/* probe ordering - for components with runtime dependencies */
int
probe_order
;
int
remove_order
;
...
...
@@ -847,23 +852,23 @@ struct snd_soc_platform_driver {
int
(
*
bespoke_trigger
)(
struct
snd_pcm_substream
*
,
int
);
};
struct
snd_soc_
platform
{
struct
snd_soc_
dai_link_component
{
const
char
*
name
;
int
id
;
const
struct
device_node
*
of_node
;
const
char
*
dai_name
;
};
struct
snd_soc_platform
{
struct
device
*
dev
;
const
struct
snd_soc_platform_driver
*
driver
;
unsigned
int
suspended
:
1
;
/* platform is suspended */
unsigned
int
probed
:
1
;
struct
snd_soc_card
*
card
;
struct
list_head
list
;
struct
list_head
card_list
;
struct
snd_soc_component
component
;
struct
snd_soc_dapm_context
dapm
;
#ifdef CONFIG_DEBUG_FS
struct
dentry
*
debugfs_platform_root
;
#endif
...
...
@@ -896,6 +901,10 @@ struct snd_soc_dai_link {
const
struct
device_node
*
codec_of_node
;
/* You MUST specify the DAI name within the codec */
const
char
*
codec_dai_name
;
struct
snd_soc_dai_link_component
*
codecs
;
unsigned
int
num_codecs
;
/*
* You MAY specify the link's platform/PCM/DMA driver, either by
* device name, or by DT/OF node, but not both. Some forms of link
...
...
@@ -1047,7 +1056,6 @@ struct snd_soc_card {
/* lists of probed devices belonging to this card */
struct
list_head
codec_dev_list
;
struct
list_head
platform_dev_list
;
struct
list_head
widgets
;
struct
list_head
paths
;
...
...
@@ -1094,6 +1102,9 @@ struct snd_soc_pcm_runtime {
struct
snd_soc_dai
*
codec_dai
;
struct
snd_soc_dai
*
cpu_dai
;
struct
snd_soc_dai
**
codec_dais
;
unsigned
int
num_codecs
;
struct
delayed_work
delayed_work
;
#ifdef CONFIG_DEBUG_FS
struct
dentry
*
debugfs_dpcm_root
;
...
...
@@ -1164,6 +1175,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
return
container_of
(
component
,
struct
snd_soc_platform
,
component
);
}
/**
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
* embedded in
* @dapm: The DAPM context to cast to the component
*
* This function must only be used on DAPM contexts that are known to be part of
* a component (e.g. in a component driver). Otherwise the behavior is
* undefined.
*/
static
inline
struct
snd_soc_component
*
snd_soc_dapm_to_component
(
struct
snd_soc_dapm_context
*
dapm
)
{
return
container_of
(
dapm
,
struct
snd_soc_component
,
dapm
);
}
/**
* snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
* @dapm: The DAPM context to cast to the CODEC
...
...
@@ -1188,7 +1214,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
static
inline
struct
snd_soc_platform
*
snd_soc_dapm_to_platform
(
struct
snd_soc_dapm_context
*
dapm
)
{
return
container_of
(
dapm
,
struct
snd_soc_platform
,
dapm
);
return
snd_soc_component_to_platform
(
snd_soc_dapm_to_component
(
dapm
));
}
/**
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
* component
* @component: The component for which to get the DAPM context
*/
static
inline
struct
snd_soc_dapm_context
*
snd_soc_component_get_dapm
(
struct
snd_soc_component
*
component
)
{
return
component
->
dapm_ptr
;
}
/* codec IO */
...
...
@@ -1261,7 +1298,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
static
inline
void
snd_soc_initialize_card_lists
(
struct
snd_soc_card
*
card
)
{
INIT_LIST_HEAD
(
&
card
->
codec_dev_list
);
INIT_LIST_HEAD
(
&
card
->
platform_dev_list
);
INIT_LIST_HEAD
(
&
card
->
widgets
);
INIT_LIST_HEAD
(
&
card
->
paths
);
INIT_LIST_HEAD
(
&
card
->
dapm_list
);
...
...
include/trace/events/asoc.h
View file @
a1cb98ac
...
...
@@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
TP_ARGS
(
codec
,
type
,
status
),
TP_STRUCT__entry
(
__string
(
name
,
codec
->
name
)
__string
(
name
,
codec
->
component
.
name
)
__string
(
status
,
status
)
__string
(
type
,
type
)
__field
(
int
,
id
)
),
TP_fast_assign
(
__assign_str
(
name
,
codec
->
name
);
__assign_str
(
name
,
codec
->
component
.
name
);
__assign_str
(
status
,
status
);
__assign_str
(
type
,
type
);
__entry
->
id
=
codec
->
id
;
__entry
->
id
=
codec
->
component
.
id
;
),
TP_printk
(
"codec=%s.%d type=%s status=%s"
,
__get_str
(
name
),
...
...
sound/soc/codecs/ac97.c
View file @
a1cb98ac
...
...
@@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
int
ret
;
/* add codec as bus device for standard ac97 */
ret
=
snd_ac97_bus
(
codec
->
c
ard
->
snd_card
,
0
,
soc_ac97_ops
,
NULL
,
&
ac97_bus
);
ret
=
snd_ac97_bus
(
codec
->
c
omponent
.
card
->
snd_card
,
0
,
soc_ac97_ops
,
NULL
,
&
ac97_bus
);
if
(
ret
<
0
)
return
ret
;
...
...
sound/soc/codecs/cx20442.c
View file @
a1cb98ac
...
...
@@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty)
/* Prevent the codec driver from further accessing the modem */
codec
->
hw_write
=
NULL
;
cx20442
->
control_data
=
NULL
;
codec
->
card
->
pop_time
=
0
;
codec
->
c
omponent
.
c
ard
->
pop_time
=
0
;
}
/* Line discipline .hangup() */
...
...
@@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty,
/* Set up codec driver access to modem controls */
cx20442
->
control_data
=
tty
;
codec
->
hw_write
=
(
hw_write_t
)
tty
->
ops
->
write
;
codec
->
card
->
pop_time
=
1
;
codec
->
c
omponent
.
c
ard
->
pop_time
=
1
;
}
}
...
...
@@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_drvdata
(
codec
,
cx20442
);
codec
->
hw_write
=
NULL
;
codec
->
card
->
pop_time
=
0
;
codec
->
c
omponent
.
c
ard
->
pop_time
=
0
;
return
0
;
}
...
...
sound/soc/codecs/tlv320dac33.c
View file @
a1cb98ac
...
...
@@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
if
(
dac33
->
irq
>=
0
)
{
ret
=
request_irq
(
dac33
->
irq
,
dac33_interrupt_handler
,
IRQF_TRIGGER_RISING
,
codec
->
name
,
codec
);
codec
->
component
.
name
,
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Could not request IRQ%d (%d)
\n
"
,
dac33
->
irq
,
ret
);
...
...
sound/soc/codecs/uda134x.c
View file @
a1cb98ac
...
...
@@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = {
static
int
uda134x_soc_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
uda134x_priv
*
uda134x
;
struct
uda134x_platform_data
*
pd
=
codec
->
card
->
dev
->
platform_data
;
struct
uda134x_platform_data
*
pd
=
codec
->
c
omponent
.
c
ard
->
dev
->
platform_data
;
const
struct
snd_soc_dapm_widget
*
widgets
;
unsigned
num_widgets
;
...
...
sound/soc/codecs/wm8960.c
View file @
a1cb98ac
...
...
@@ -472,7 +472,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
* list each time to find the desired power state do so now
* and save the result.
*/
list_for_each_entry
(
w
,
&
codec
->
card
->
widgets
,
list
)
{
list_for_each_entry
(
w
,
&
codec
->
c
omponent
.
c
ard
->
widgets
,
list
)
{
if
(
w
->
dapm
!=
&
codec
->
dapm
)
continue
;
if
(
strcmp
(
w
->
name
,
"LOUT1 PGA"
)
==
0
)
...
...
sound/soc/codecs/wm_adsp.c
View file @
a1cb98ac
...
...
@@ -1382,7 +1382,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
int
ret
;
int
val
;
dsp
->
card
=
codec
->
card
;
dsp
->
card
=
codec
->
c
omponent
.
c
ard
;
switch
(
event
)
{
case
SND_SOC_DAPM_POST_PMU
:
...
...
@@ -1617,7 +1617,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
struct
wm_adsp
*
dsps
=
snd_soc_codec_get_drvdata
(
codec
);
struct
wm_adsp
*
dsp
=
&
dsps
[
w
->
shift
];
dsp
->
card
=
codec
->
card
;
dsp
->
card
=
codec
->
c
omponent
.
c
ard
;
switch
(
event
)
{
case
SND_SOC_DAPM_PRE_PMU
:
...
...
sound/soc/omap/ams-delta.c
View file @
a1cb98ac
...
...
@@ -301,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty)
static
void
cx81801_close
(
struct
tty_struct
*
tty
)
{
struct
snd_soc_codec
*
codec
=
tty
->
disc_data
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
card
->
dapm
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
c
omponent
.
c
ard
->
dapm
;
del_timer_sync
(
&
cx81801_timer
);
...
...
sound/soc/soc-cache.c
View file @
a1cb98ac
...
...
@@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
mutex_init
(
&
codec
->
cache_rw_mutex
);
dev_dbg
(
codec
->
dev
,
"ASoC: Initializing cache for %s codec
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
if
(
codec_drv
->
reg_cache_default
)
codec
->
reg_cache
=
kmemdup
(
codec_drv
->
reg_cache_default
,
...
...
@@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
int
snd_soc_cache_exit
(
struct
snd_soc_codec
*
codec
)
{
dev_dbg
(
codec
->
dev
,
"ASoC: Destroying cache for %s codec
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
kfree
(
codec
->
reg_cache
);
codec
->
reg_cache
=
NULL
;
return
0
;
...
...
@@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
return
0
;
dev_dbg
(
codec
->
dev
,
"ASoC: Syncing cache for %s codec
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
trace_snd_soc_cache_sync
(
codec
,
name
,
"start"
);
ret
=
snd_soc_flat_cache_sync
(
codec
);
if
(
!
ret
)
...
...
sound/soc/soc-compress.c
View file @
a1cb98ac
...
...
@@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
if
(
platform
->
driver
->
compr_ops
&&
platform
->
driver
->
compr_ops
->
open
)
{
ret
=
platform
->
driver
->
compr_ops
->
open
(
cstream
);
if
(
ret
<
0
)
{
pr_err
(
"compress asoc: can't open platform %s
\n
"
,
platform
->
name
);
pr_err
(
"compress asoc: can't open platform %s
\n
"
,
platform
->
component
.
name
);
goto
out
;
}
}
...
...
@@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
if
(
platform
->
driver
->
compr_ops
&&
platform
->
driver
->
compr_ops
->
open
)
{
ret
=
platform
->
driver
->
compr_ops
->
open
(
cstream
);
if
(
ret
<
0
)
{
pr_err
(
"compress asoc: can't open platform %s
\n
"
,
platform
->
name
);
pr_err
(
"compress asoc: can't open platform %s
\n
"
,
platform
->
component
.
name
);
goto
out
;
}
}
...
...
@@ -627,6 +629,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
char
new_name
[
64
];
int
ret
=
0
,
direction
=
0
;
if
(
rtd
->
num_codecs
>
1
)
{
dev_err
(
rtd
->
card
->
dev
,
"Multicodec not supported for compressed stream
\n
"
);
return
-
EINVAL
;
}
/* check client and interface hw capabilities */
snprintf
(
new_name
,
sizeof
(
new_name
),
"%s %s-%d"
,
rtd
->
dai_link
->
stream_name
,
codec_dai
->
name
,
num
);
...
...
@@ -680,7 +687,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
ret
=
snd_compress_new
(
rtd
->
card
->
snd_card
,
num
,
direction
,
compr
);
if
(
ret
<
0
)
{
pr_err
(
"compress asoc: can't create compress for codec %s
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
goto
compr_err
;
}
...
...
sound/soc/soc-core.c
View file @
a1cb98ac
...
...
@@ -292,10 +292,11 @@ static struct dentry *soc_debugfs_create_dir(struct dentry *parent,
static
void
soc_init_codec_debugfs
(
struct
snd_soc_codec
*
codec
)
{
struct
dentry
*
debugfs_card_root
=
codec
->
card
->
debugfs_card_root
;
struct
dentry
*
debugfs_card_root
=
codec
->
c
omponent
.
c
ard
->
debugfs_card_root
;
codec
->
debugfs_codec_root
=
soc_debugfs_create_dir
(
debugfs_card_root
,
"codec:%s"
,
codec
->
name
);
"codec:%s"
,
codec
->
component
.
name
);
if
(
!
codec
->
debugfs_codec_root
)
{
dev_warn
(
codec
->
dev
,
"ASoC: Failed to create codec debugfs directory
\n
"
);
...
...
@@ -324,17 +325,18 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
static
void
soc_init_platform_debugfs
(
struct
snd_soc_platform
*
platform
)
{
struct
dentry
*
debugfs_card_root
=
platform
->
card
->
debugfs_card_root
;
struct
dentry
*
debugfs_card_root
=
platform
->
c
omponent
.
c
ard
->
debugfs_card_root
;
platform
->
debugfs_platform_root
=
soc_debugfs_create_dir
(
debugfs_card_root
,
"platform:%s"
,
platform
->
name
);
"platform:%s"
,
platform
->
component
.
name
);
if
(
!
platform
->
debugfs_platform_root
)
{
dev_warn
(
platform
->
dev
,
"ASoC: Failed to create platform debugfs directory
\n
"
);
return
;
}
snd_soc_dapm_debugfs_init
(
&
platform
->
dapm
,
snd_soc_dapm_debugfs_init
(
&
platform
->
component
.
dapm
,
platform
->
debugfs_platform_root
);
}
...
...
@@ -355,7 +357,7 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
list_for_each_entry
(
codec
,
&
codec_list
,
list
)
{
len
=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
"%s
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
if
(
len
>=
0
)
ret
+=
len
;
if
(
ret
>
PAGE_SIZE
)
{
...
...
@@ -426,7 +428,7 @@ static ssize_t platform_list_read_file(struct file *file,
list_for_each_entry
(
platform
,
&
platform_list
,
list
)
{
len
=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
"%s
\n
"
,
platform
->
name
);
platform
->
component
.
name
);
if
(
len
>=
0
)
ret
+=
len
;
if
(
ret
>
PAGE_SIZE
)
{
...
...
@@ -544,11 +546,12 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
int
err
;
codec
->
ac97
->
dev
.
bus
=
&
ac97_bus_type
;
codec
->
ac97
->
dev
.
parent
=
codec
->
card
->
dev
;
codec
->
ac97
->
dev
.
parent
=
codec
->
c
omponent
.
c
ard
->
dev
;
codec
->
ac97
->
dev
.
release
=
soc_ac97_device_release
;
dev_set_name
(
&
codec
->
ac97
->
dev
,
"%d-%d:%s"
,
codec
->
card
->
snd_card
->
number
,
0
,
codec
->
name
);
codec
->
component
.
card
->
snd_card
->
number
,
0
,
codec
->
component
.
name
);
err
=
device_register
(
&
codec
->
ac97
->
dev
);
if
(
err
<
0
)
{
dev_err
(
codec
->
dev
,
"ASoC: Can't register ac97 bus
\n
"
);
...
...
@@ -574,7 +577,7 @@ int snd_soc_suspend(struct device *dev)
{
struct
snd_soc_card
*
card
=
dev_get_drvdata
(
dev
);
struct
snd_soc_codec
*
codec
;
int
i
;
int
i
,
j
;
/* If the initialization of this soc device failed, there is no codec
* associated with it. Just bail out in this case.
...
...
@@ -594,15 +597,18 @@ int snd_soc_suspend(struct device *dev)
/* mute any active DACs */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
dai
=
card
->
rtd
[
i
].
codec_dai
;
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
if
(
card
->
rtd
[
i
].
dai_link
->
ignore_suspend
)
continue
;
for
(
j
=
0
;
j
<
card
->
rtd
[
i
].
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
dai
=
card
->
rtd
[
i
].
codec_dais
[
j
];
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
if
(
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
1
);
}
}
/* suspend all pcms */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
...
...
@@ -632,8 +638,12 @@ int snd_soc_suspend(struct device *dev)
/* close any waiting streams and save state */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
**
codec_dais
=
card
->
rtd
[
i
].
codec_dais
;
flush_delayed_work
(
&
card
->
rtd
[
i
].
delayed_work
);
card
->
rtd
[
i
].
codec
->
dapm
.
suspend_bias_level
=
card
->
rtd
[
i
].
codec
->
dapm
.
bias_level
;
for
(
j
=
0
;
j
<
card
->
rtd
[
i
].
num_codecs
;
j
++
)
{
codec_dais
[
j
]
->
codec
->
dapm
.
suspend_bias_level
=
codec_dais
[
j
]
->
codec
->
dapm
.
bias_level
;
}
}
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
...
...
@@ -717,7 +727,7 @@ static void soc_resume_deferred(struct work_struct *work)
struct
snd_soc_card
*
card
=
container_of
(
work
,
struct
snd_soc_card
,
deferred_resume_work
);
struct
snd_soc_codec
*
codec
;
int
i
;
int
i
,
j
;
/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
* so userspace apps are blocked from touching us
...
...
@@ -778,15 +788,18 @@ static void soc_resume_deferred(struct work_struct *work)
/* unmute any active DACs */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
dai
=
card
->
rtd
[
i
].
codec_dai
;
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
if
(
card
->
rtd
[
i
].
dai_link
->
ignore_suspend
)
continue
;
for
(
j
=
0
;
j
<
card
->
rtd
[
i
].
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
dai
=
card
->
rtd
[
i
].
codec_dais
[
j
];
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
if
(
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
0
);
}
}
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
cpu_dai
=
card
->
rtd
[
i
].
cpu_dai
;
...
...
@@ -830,13 +843,20 @@ int snd_soc_resume(struct device *dev)
/* activate pins from sleep state */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
cpu_dai
=
card
->
rtd
[
i
].
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
card
->
rtd
[
i
].
codec_dai
;
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
i
];
struct
snd_soc_dai
**
codec_dais
=
rtd
->
codec_dais
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
int
j
;
if
(
cpu_dai
->
active
)
pinctrl_pm_select_default_state
(
cpu_dai
->
dev
);
for
(
j
=
0
;
j
<
rtd
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
codec_dai
=
codec_dais
[
j
];
if
(
codec_dai
->
active
)
pinctrl_pm_select_default_state
(
codec_dai
->
dev
);
}
}
/* AC97 devices might have other drivers hanging off them so
* need to resume immediately. Other drivers don't have that
...
...
@@ -867,7 +887,8 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
static
const
struct
snd_soc_dai_ops
null_dai_ops
=
{
};
static
struct
snd_soc_codec
*
soc_find_codec
(
const
struct
device_node
*
codec_of_node
,
static
struct
snd_soc_codec
*
soc_find_codec
(
const
struct
device_node
*
codec_of_node
,
const
char
*
codec_name
)
{
struct
snd_soc_codec
*
codec
;
...
...
@@ -877,7 +898,7 @@ static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_n
if
(
codec
->
dev
->
of_node
!=
codec_of_node
)
continue
;
}
else
{
if
(
strcmp
(
codec
->
name
,
codec_name
))
if
(
strcmp
(
codec
->
component
.
name
,
codec_name
))
continue
;
}
...
...
@@ -906,9 +927,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
struct
snd_soc_dai_link
*
dai_link
=
&
card
->
dai_link
[
num
];
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
struct
snd_soc_component
*
component
;
struct
snd_soc_dai_link_component
*
codecs
=
dai_link
->
codecs
;
struct
snd_soc_dai
**
codec_dais
=
rtd
->
codec_dais
;
struct
snd_soc_platform
*
platform
;
struct
snd_soc_dai
*
cpu_dai
;
const
char
*
platform_name
;
int
i
;
dev_dbg
(
card
->
dev
,
"ASoC: binding %s at idx %d
\n
"
,
dai_link
->
name
,
num
);
...
...
@@ -935,23 +959,29 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
return
-
EPROBE_DEFER
;
}
/* Find CODEC from registered list */
rtd
->
codec
=
soc_find_codec
(
dai_link
->
codec_of_node
,
dai_link
->
codec_name
);
if
(
!
rtd
->
codec
)
{
rtd
->
num_codecs
=
dai_link
->
num_codecs
;
/* Find CODEC from registered CODECs */
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
struct
snd_soc_codec
*
codec
;
codec
=
soc_find_codec
(
codecs
[
i
].
of_node
,
codecs
[
i
].
name
);
if
(
!
codec
)
{
dev_err
(
card
->
dev
,
"ASoC: CODEC %s not registered
\n
"
,
dai_link
->
codec_
name
);
codecs
[
i
].
name
);
return
-
EPROBE_DEFER
;
}
/* Find CODEC DAI from registered list */
rtd
->
codec_dai
=
soc_find_codec_dai
(
rtd
->
codec
,
dai_link
->
codec_dai_name
);
if
(
!
rtd
->
codec_dai
)
{
codec_dais
[
i
]
=
soc_find_codec_dai
(
codec
,
codecs
[
i
].
dai_name
);
if
(
!
codec_dais
[
i
])
{
dev_err
(
card
->
dev
,
"ASoC: CODEC DAI %s not registered
\n
"
,
dai_link
->
codec_
dai_name
);
codecs
[
i
].
dai_name
);
return
-
EPROBE_DEFER
;
}
}
/* Single codec links expect codec and codec_dai in runtime data */
rtd
->
codec_dai
=
codec_dais
[
0
];
rtd
->
codec
=
rtd
->
codec_dai
->
codec
;
/* if there's no platform we match on the empty platform */
platform_name
=
dai_link
->
platform_name
;
...
...
@@ -965,7 +995,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
dai_link
->
platform_of_node
)
continue
;
}
else
{
if
(
strcmp
(
platform
->
name
,
platform_name
))
if
(
strcmp
(
platform
->
component
.
name
,
platform_name
))
continue
;
}
...
...
@@ -994,11 +1024,10 @@ static int soc_remove_platform(struct snd_soc_platform *platform)
}
/* Make sure all DAPM widgets are freed */
snd_soc_dapm_free
(
&
platform
->
dapm
);
snd_soc_dapm_free
(
&
platform
->
component
.
dapm
);
soc_cleanup_platform_debugfs
(
platform
);
platform
->
probed
=
0
;
list_del
(
&
platform
->
card_list
);
module_put
(
platform
->
dev
->
driver
->
owner
);
return
0
;
...
...
@@ -1043,8 +1072,8 @@ static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order)
static
void
soc_remove_link_dais
(
struct
snd_soc_card
*
card
,
int
num
,
int
order
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
struct
snd_soc_dai
*
c
odec_dai
=
rtd
->
codec_dai
,
*
c
pu_dai
=
rtd
->
cpu_dai
;
int
err
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
int
i
,
err
;
/* unregister the rtd device */
if
(
rtd
->
dev_registered
)
{
...
...
@@ -1055,7 +1084,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
}
/* remove the CODEC DAI */
soc_remove_codec_dai
(
codec_dai
,
order
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
soc_remove_codec_dai
(
rtd
->
codec_dais
[
i
],
order
);
/* remove the cpu_dai */
if
(
cpu_dai
&&
cpu_dai
->
probed
&&
...
...
@@ -1068,12 +1098,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
cpu_dai
->
name
,
err
);
}
cpu_dai
->
probed
=
0
;
if
(
!
cpu_dai
->
codec
)
{
snd_soc_dapm_free
(
&
cpu_dai
->
dapm
);
if
(
!
cpu_dai
->
codec
)
module_put
(
cpu_dai
->
dev
->
driver
->
owner
);
}
}
}
static
void
soc_remove_link_components
(
struct
snd_soc_card
*
card
,
int
num
,
...
...
@@ -1081,9 +1108,9 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num,
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_codec
*
codec
;
int
i
;
/* remove the platform */
if
(
platform
&&
platform
->
probed
&&
...
...
@@ -1092,8 +1119,8 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num,
}
/* remove the CODEC-side CODEC */
if
(
codec_dai
)
{
codec
=
codec_dai
->
codec
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec
=
rtd
->
codec_dais
[
i
]
->
codec
;
if
(
codec
&&
codec
->
probed
&&
codec
->
driver
->
remove_order
==
order
)
soc_remove_codec
(
codec
);
...
...
@@ -1128,7 +1155,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
}
static
void
soc_set_name_prefix
(
struct
snd_soc_card
*
card
,
struct
snd_soc_co
dec
*
codec
)
struct
snd_soc_co
mponent
*
component
)
{
int
i
;
...
...
@@ -1137,11 +1164,11 @@ static void soc_set_name_prefix(struct snd_soc_card *card,
for
(
i
=
0
;
i
<
card
->
num_configs
;
i
++
)
{
struct
snd_soc_codec_conf
*
map
=
&
card
->
codec_conf
[
i
];
if
(
map
->
of_node
&&
co
dec
->
dev
->
of_node
!=
map
->
of_node
)
if
(
map
->
of_node
&&
co
mponent
->
dev
->
of_node
!=
map
->
of_node
)
continue
;
if
(
map
->
dev_name
&&
strcmp
(
co
dec
->
name
,
map
->
dev_name
))
if
(
map
->
dev_name
&&
strcmp
(
co
mponent
->
name
,
map
->
dev_name
))
continue
;
co
dec
->
name_prefix
=
map
->
name_prefix
;
co
mponent
->
name_prefix
=
map
->
name_prefix
;
break
;
}
}
...
...
@@ -1153,9 +1180,9 @@ static int soc_probe_codec(struct snd_soc_card *card,
const
struct
snd_soc_codec_driver
*
driver
=
codec
->
driver
;
struct
snd_soc_dai
*
dai
;
codec
->
card
=
card
;
codec
->
c
omponent
.
c
ard
=
card
;
codec
->
dapm
.
card
=
card
;
soc_set_name_prefix
(
card
,
codec
);
soc_set_name_prefix
(
card
,
&
codec
->
component
);
if
(
!
try_module_get
(
codec
->
dev
->
driver
->
owner
))
return
-
ENODEV
;
...
...
@@ -1197,7 +1224,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
WARN
(
codec
->
dapm
.
idle_bias_off
&&
codec
->
dapm
.
bias_level
!=
SND_SOC_BIAS_OFF
,
"codec %s can not start from non-off bias with idle_bias_off==1
\n
"
,
codec
->
name
);
codec
->
component
.
name
);
}
if
(
driver
->
controls
)
...
...
@@ -1229,8 +1256,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
struct
snd_soc_component
*
component
;
struct
snd_soc_dai
*
dai
;
platform
->
card
=
card
;
platform
->
dapm
.
card
=
card
;
platform
->
c
omponent
.
c
ard
=
card
;
platform
->
component
.
dapm
.
card
=
card
;
if
(
!
try_module_get
(
platform
->
dev
->
driver
->
owner
))
return
-
ENODEV
;
...
...
@@ -1238,7 +1265,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
soc_init_platform_debugfs
(
platform
);
if
(
driver
->
dapm_widgets
)
snd_soc_dapm_new_controls
(
&
platform
->
dapm
,
snd_soc_dapm_new_controls
(
&
platform
->
component
.
dapm
,
driver
->
dapm_widgets
,
driver
->
num_dapm_widgets
);
/* Create DAPM widgets for each DAI stream */
...
...
@@ -1246,10 +1273,11 @@ static int soc_probe_platform(struct snd_soc_card *card,
if
(
component
->
dev
!=
platform
->
dev
)
continue
;
list_for_each_entry
(
dai
,
&
component
->
dai_list
,
list
)
snd_soc_dapm_new_dai_widgets
(
&
platform
->
dapm
,
dai
);
snd_soc_dapm_new_dai_widgets
(
&
platform
->
component
.
dapm
,
dai
);
}
platform
->
dapm
.
idle_bias_off
=
1
;
platform
->
component
.
dapm
.
idle_bias_off
=
1
;
if
(
driver
->
probe
)
{
ret
=
driver
->
probe
(
platform
);
...
...
@@ -1264,13 +1292,12 @@ static int soc_probe_platform(struct snd_soc_card *card,
snd_soc_add_platform_controls
(
platform
,
driver
->
controls
,
driver
->
num_controls
);
if
(
driver
->
dapm_routes
)
snd_soc_dapm_add_routes
(
&
platform
->
dapm
,
driver
->
dapm_routes
,
driver
->
num_dapm_routes
);
snd_soc_dapm_add_routes
(
&
platform
->
component
.
dapm
,
driver
->
dapm_routes
,
driver
->
num_dapm_routes
);
/* mark platform as probed and add to card platform list */
platform
->
probed
=
1
;
list_add
(
&
platform
->
card_list
,
&
card
->
platform_dev_list
);
list_add
(
&
platform
->
dapm
.
list
,
&
card
->
dapm_list
);
list_add
(
&
platform
->
component
.
dapm
.
list
,
&
card
->
dapm_list
);
return
0
;
...
...
@@ -1286,83 +1313,17 @@ static void rtd_release(struct device *dev)
kfree
(
dev
);
}
static
int
soc_aux_dev_init
(
struct
snd_soc_card
*
card
,
struct
snd_soc_codec
*
codec
,
int
num
)
{
struct
snd_soc_aux_dev
*
aux_dev
=
&
card
->
aux_dev
[
num
];
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd_aux
[
num
];
int
ret
;
rtd
->
card
=
card
;
/* do machine specific initialization */
if
(
aux_dev
->
init
)
{
ret
=
aux_dev
->
init
(
&
codec
->
dapm
);
if
(
ret
<
0
)
return
ret
;
}
rtd
->
codec
=
codec
;
return
0
;
}
static
int
soc_dai_link_init
(
struct
snd_soc_card
*
card
,
struct
snd_soc_codec
*
codec
,
int
num
)
{
struct
snd_soc_dai_link
*
dai_link
=
&
card
->
dai_link
[
num
];
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
int
ret
;
rtd
->
card
=
card
;
/* do machine specific initialization */
if
(
dai_link
->
init
)
{
ret
=
dai_link
->
init
(
rtd
);
if
(
ret
<
0
)
return
ret
;
}
rtd
->
codec
=
codec
;
return
0
;
}
static
int
soc_post_component_init
(
struct
snd_soc_card
*
card
,
struct
snd_soc_codec
*
codec
,
int
num
,
int
dailess
)
static
int
soc_post_component_init
(
struct
snd_soc_pcm_runtime
*
rtd
,
const
char
*
name
)
{
struct
snd_soc_dai_link
*
dai_link
=
NULL
;
struct
snd_soc_aux_dev
*
aux_dev
=
NULL
;
struct
snd_soc_pcm_runtime
*
rtd
;
const
char
*
name
;
int
ret
=
0
;
if
(
!
dailess
)
{
dai_link
=
&
card
->
dai_link
[
num
];
rtd
=
&
card
->
rtd
[
num
];
name
=
dai_link
->
name
;
ret
=
soc_dai_link_init
(
card
,
codec
,
num
);
}
else
{
aux_dev
=
&
card
->
aux_dev
[
num
];
rtd
=
&
card
->
rtd_aux
[
num
];
name
=
aux_dev
->
name
;
ret
=
soc_aux_dev_init
(
card
,
codec
,
num
);
}
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init %s: %d
\n
"
,
name
,
ret
);
return
ret
;
}
/* register the rtd device */
rtd
->
dev
=
kzalloc
(
sizeof
(
struct
device
),
GFP_KERNEL
);
if
(
!
rtd
->
dev
)
return
-
ENOMEM
;
device_initialize
(
rtd
->
dev
);
rtd
->
dev
->
parent
=
card
->
dev
;
rtd
->
dev
->
parent
=
rtd
->
card
->
dev
;
rtd
->
dev
->
release
=
rtd_release
;
rtd
->
dev
->
init_name
=
name
;
dev_set_drvdata
(
rtd
->
dev
,
rtd
);
...
...
@@ -1375,7 +1336,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
if
(
ret
<
0
)
{
/* calling put_device() here to free the rtd->dev */
put_device
(
rtd
->
dev
);
dev_err
(
card
->
dev
,
dev_err
(
rtd
->
card
->
dev
,
"ASoC: failed to register runtime device: %d
\n
"
,
ret
);
return
ret
;
}
...
...
@@ -1384,26 +1345,15 @@ static int soc_post_component_init(struct snd_soc_card *card,
/* add DAPM sysfs entries for this codec */
ret
=
snd_soc_dapm_sys_add
(
rtd
->
dev
);
if
(
ret
<
0
)
dev_err
(
codec
->
dev
,
dev_err
(
rtd
->
dev
,
"ASoC: failed to add codec dapm sysfs entries: %d
\n
"
,
ret
);
/* add codec sysfs entries */
ret
=
device_create_file
(
rtd
->
dev
,
&
dev_attr_codec_reg
);
if
(
ret
<
0
)
dev_err
(
codec
->
dev
,
dev_err
(
rtd
->
dev
,
"ASoC: failed to add codec sysfs files: %d
\n
"
,
ret
);
#ifdef CONFIG_DEBUG_FS
/* add DPCM sysfs entries */
if
(
!
dailess
&&
!
dai_link
->
dynamic
)
goto
out
;
ret
=
soc_dpcm_debugfs_add
(
rtd
);
if
(
ret
<
0
)
dev_err
(
rtd
->
dev
,
"ASoC: failed to add dpcm sysfs entries: %d
\n
"
,
ret
);
out:
#endif
return
0
;
}
...
...
@@ -1412,9 +1362,8 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num,
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
int
ret
;
int
i
,
ret
;
/* probe the CPU-side component, if it is a CODEC */
if
(
cpu_dai
->
codec
&&
...
...
@@ -1425,13 +1374,15 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num,
return
ret
;
}
/* probe the CODEC-side component */
if
(
!
codec_dai
->
codec
->
probed
&&
codec_dai
->
codec
->
driver
->
probe_order
==
order
)
{
ret
=
soc_probe_codec
(
card
,
codec_dai
->
codec
);
/* probe the CODEC-side components */
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
(
!
rtd
->
codec_dais
[
i
]
->
codec
->
probed
&&
rtd
->
codec_dais
[
i
]
->
codec
->
driver
->
probe_order
==
order
)
{
ret
=
soc_probe_codec
(
card
,
rtd
->
codec_dais
[
i
]
->
codec
);
if
(
ret
<
0
)
return
ret
;
}
}
/* probe the platform */
if
(
!
platform
->
probed
&&
...
...
@@ -1470,12 +1421,16 @@ static int soc_probe_codec_dai(struct snd_soc_card *card,
static
int
soc_link_dai_widgets
(
struct
snd_soc_card
*
card
,
struct
snd_soc_dai_link
*
dai_link
,
struct
snd_soc_dai
*
cpu_dai
,
struct
snd_soc_dai
*
codec_dai
)
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dapm_widget
*
play_w
,
*
capture_w
;
int
ret
;
if
(
rtd
->
num_codecs
>
1
)
dev_warn
(
card
->
dev
,
"ASoC: Multiple codecs not supported yet
\n
"
);
/* link the DAI widgets */
play_w
=
codec_dai
->
playback_widget
;
capture_w
=
cpu_dai
->
capture_widget
;
...
...
@@ -1508,19 +1463,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
{
struct
snd_soc_dai_link
*
dai_link
=
&
card
->
dai_link
[
num
];
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
num
];
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
int
ret
;
int
i
,
ret
;
dev_dbg
(
card
->
dev
,
"ASoC: probe %s dai link %d late %d
\n
"
,
card
->
name
,
num
,
order
);
/* config components */
cpu_dai
->
platform
=
platform
;
codec_dai
->
card
=
card
;
cpu_dai
->
card
=
card
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
rtd
->
codec_dais
[
i
]
->
card
=
card
;
/* set default power off timeout */
rtd
->
pmdown_time
=
pmdown_time
;
...
...
@@ -1529,11 +1483,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
if
(
!
cpu_dai
->
probed
&&
cpu_dai
->
driver
->
probe_order
==
order
)
{
if
(
!
cpu_dai
->
codec
)
{
cpu_dai
->
dapm
.
card
=
card
;
if
(
!
try_module_get
(
cpu_dai
->
dev
->
driver
->
owner
))
return
-
ENODEV
;
list_add
(
&
cpu_dai
->
dapm
.
list
,
&
card
->
dapm_list
);
}
if
(
cpu_dai
->
driver
->
probe
)
{
...
...
@@ -1550,18 +1501,43 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
}
/* probe the CODEC DAI */
ret
=
soc_probe_codec_dai
(
card
,
codec_dai
,
order
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
ret
=
soc_probe_codec_dai
(
card
,
rtd
->
codec_dais
[
i
],
order
);
if
(
ret
)
return
ret
;
}
/* complete DAI probe during last probe */
if
(
order
!=
SND_SOC_COMP_ORDER_LAST
)
return
0
;
ret
=
soc_post_component_init
(
card
,
codec
,
num
,
0
);
/* do machine specific initialization */
if
(
dai_link
->
init
)
{
ret
=
dai_link
->
init
(
rtd
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init %s: %d
\n
"
,
dai_link
->
name
,
ret
);
return
ret
;
}
}
ret
=
soc_post_component_init
(
rtd
,
dai_link
->
name
);
if
(
ret
)
return
ret
;
#ifdef CONFIG_DEBUG_FS
/* add DPCM sysfs entries */
if
(
dai_link
->
dynamic
)
{
ret
=
soc_dpcm_debugfs_add
(
rtd
);
if
(
ret
<
0
)
{
dev_err
(
rtd
->
dev
,
"ASoC: failed to add dpcm sysfs entries: %d
\n
"
,
ret
);
return
ret
;
}
}
#endif
ret
=
device_create_file
(
rtd
->
dev
,
&
dev_attr_pmdown_time
);
if
(
ret
<
0
)
dev_warn
(
rtd
->
dev
,
"ASoC: failed to add pmdown_time sysfs: %d
\n
"
,
...
...
@@ -1590,16 +1566,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
codec2codec_close_delayed_work
);
/* link the DAI widgets */
ret
=
soc_link_dai_widgets
(
card
,
dai_link
,
cpu_dai
,
codec_dai
);
ret
=
soc_link_dai_widgets
(
card
,
dai_link
,
rtd
);
if
(
ret
)
return
ret
;
}
}
/* add platform data for AC97 devices */
if
(
rtd
->
codec_dai
->
driver
->
ac97_control
)
snd_ac97_dev_add_pdata
(
codec
->
ac97
,
rtd
->
cpu_dai
->
ac97_pdata
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
(
rtd
->
codec_dais
[
i
]
->
driver
->
ac97_control
)
snd_ac97_dev_add_pdata
(
rtd
->
codec_dais
[
i
]
->
codec
->
ac97
,
rtd
->
cpu_dai
->
ac97_pdata
);
}
return
0
;
}
...
...
@@ -1637,11 +1615,6 @@ static int soc_register_ac97_codec(struct snd_soc_codec *codec,
return
0
;
}
static
int
soc_register_ac97_dai_link
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
return
soc_register_ac97_codec
(
rtd
->
codec
,
rtd
->
codec_dai
);
}
static
void
soc_unregister_ac97_codec
(
struct
snd_soc_codec
*
codec
)
{
if
(
codec
->
ac97_registered
)
{
...
...
@@ -1650,74 +1623,77 @@ static void soc_unregister_ac97_codec(struct snd_soc_codec *codec)
}
}
static
void
soc_un
register_ac97_dai_link
(
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
soc_
register_ac97_dai_link
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
soc_unregister_ac97_codec
(
rtd
->
codec
);
}
#endif
int
i
,
ret
;
static
struct
snd_soc_codec
*
soc_find_matching_codec
(
struct
snd_soc_card
*
card
,
int
num
)
{
struct
snd_soc_aux_dev
*
aux_dev
=
&
card
->
aux_dev
[
num
];
struct
snd_soc_codec
*
codec
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
i
];
/* find CODEC from registered CODECs */
list_for_each_entry
(
codec
,
&
codec_list
,
list
)
{
if
(
aux_dev
->
codec_of_node
&&
(
codec
->
dev
->
of_node
!=
aux_dev
->
codec_of_node
))
continue
;
if
(
aux_dev
->
codec_name
&&
strcmp
(
codec
->
name
,
aux_dev
->
codec_name
))
continue
;
return
codec
;
ret
=
soc_register_ac97_codec
(
codec_dai
->
codec
,
codec_dai
);
if
(
ret
)
{
while
(
--
i
>=
0
)
soc_unregister_ac97_codec
(
codec_dai
->
codec
);
return
ret
;
}
}
return
NULL
;
return
0
;
}
static
void
soc_unregister_ac97_dai_link
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
int
i
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
soc_unregister_ac97_codec
(
rtd
->
codec_dais
[
i
]
->
codec
);
}
#endif
static
int
soc_
check
_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
static
int
soc_
bind
_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd_aux
[
num
];
struct
snd_soc_aux_dev
*
aux_dev
=
&
card
->
aux_dev
[
num
];
const
char
*
codecname
=
aux_dev
->
codec_name
;
struct
snd_soc_codec
*
codec
=
soc_find_matching_codec
(
card
,
num
);
if
(
codec
)
return
0
;
rtd
->
codec
=
soc_find_codec
(
aux_dev
->
codec_of_node
,
codecname
);
if
(
!
rtd
->
codec
)
{
if
(
aux_dev
->
codec_of_node
)
codecname
=
of_node_full_name
(
aux_dev
->
codec_of_node
);
dev_err
(
card
->
dev
,
"ASoC: %s not registered
\n
"
,
codecname
);
return
-
EPROBE_DEFER
;
}
return
0
;
}
static
int
soc_probe_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd_aux
[
num
];
struct
snd_soc_aux_dev
*
aux_dev
=
&
card
->
aux_dev
[
num
];
const
char
*
codecname
=
aux_dev
->
codec_name
;
int
ret
=
-
ENODEV
;
struct
snd_soc_codec
*
codec
=
soc_find_matching_codec
(
card
,
num
);
if
(
!
codec
)
{
if
(
aux_dev
->
codec_of_node
)
codecname
=
of_node_full_name
(
aux_dev
->
codec_of_node
);
/* codec not found */
dev_err
(
card
->
dev
,
"ASoC: codec %s not found"
,
codecname
);
return
-
EPROBE_DEFER
;
}
int
ret
;
if
(
codec
->
probed
)
{
dev_err
(
codec
->
dev
,
"ASoC: codec already probed
"
);
if
(
rtd
->
codec
->
probed
)
{
dev_err
(
rtd
->
codec
->
dev
,
"ASoC: codec already probed
\n
"
);
return
-
EBUSY
;
}
ret
=
soc_probe_codec
(
card
,
codec
);
ret
=
soc_probe_codec
(
card
,
rtd
->
codec
);
if
(
ret
<
0
)
return
ret
;
ret
=
soc_post_component_init
(
card
,
codec
,
num
,
1
);
/* do machine specific initialization */
if
(
aux_dev
->
init
)
{
ret
=
aux_dev
->
init
(
&
rtd
->
codec
->
dapm
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init %s: %d
\n
"
,
aux_dev
->
name
,
ret
);
return
ret
;
}
}
return
soc_post_component_init
(
rtd
,
aux_dev
->
name
);
}
static
void
soc_remove_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
...
...
@@ -1769,9 +1745,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
goto
base_error
;
}
/*
check
aux_devs too */
/*
bind
aux_devs too */
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
{
ret
=
soc_
check
_aux_dev
(
card
,
i
);
ret
=
soc_
bind
_aux_dev
(
card
,
i
);
if
(
ret
!=
0
)
goto
base_error
;
}
...
...
@@ -1869,17 +1845,24 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
card
->
num_dapm_routes
);
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
i
];
dai_link
=
&
card
->
dai_link
[
i
];
dai_fmt
=
dai_link
->
dai_fmt
;
if
(
dai_fmt
)
{
ret
=
snd_soc_dai_set_fmt
(
card
->
rtd
[
i
].
codec_dai
,
dai_fmt
);
struct
snd_soc_dai
**
codec_dais
=
rtd
->
codec_dais
;
int
j
;
for
(
j
=
0
;
j
<
rtd
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
codec_dai
=
codec_dais
[
j
];
ret
=
snd_soc_dai_set_fmt
(
codec_dai
,
dai_fmt
);
if
(
ret
!=
0
&&
ret
!=
-
ENOTSUPP
)
dev_warn
(
card
->
rtd
[
i
].
codec_dai
->
dev
,
dev_warn
(
codec_dai
->
dev
,
"ASoC: Failed to set DAI format: %d
\n
"
,
ret
);
}
}
/* If this is a regular CPU link there will be a platform */
if
(
dai_fmt
&&
...
...
@@ -1947,8 +1930,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
if
(
card
->
fully_routed
)
list_for_each_entry
(
codec
,
&
card
->
codec_dev_list
,
card_list
)
snd_soc_dapm_auto_nc_codec_pins
(
codec
);
snd_soc_dapm_auto_nc_pins
(
card
);
snd_soc_dapm_new_widgets
(
card
);
...
...
@@ -2078,10 +2060,15 @@ int snd_soc_poweroff(struct device *dev)
/* deactivate pins to sleep state */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
cpu_dai
=
card
->
rtd
[
i
].
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
card
->
rtd
[
i
].
codec_dai
;
pinctrl_pm_select_sleep_state
(
codec_dai
->
dev
);
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
i
];
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
int
j
;
pinctrl_pm_select_sleep_state
(
cpu_dai
->
dev
);
for
(
j
=
0
;
j
<
rtd
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
j
];
pinctrl_pm_select_sleep_state
(
codec_dai
->
dev
);
}
}
return
0
;
...
...
@@ -2406,6 +2393,25 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
}
EXPORT_SYMBOL_GPL
(
snd_soc_card_get_kcontrol
);
/**
* snd_soc_add_component_controls - Add an array of controls to a component.
*
* @component: Component to add controls to
* @controls: Array of controls to add
* @num_controls: Number of elements in the array
*
* Return: 0 for success, else error.
*/
int
snd_soc_add_component_controls
(
struct
snd_soc_component
*
component
,
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
)
{
struct
snd_card
*
card
=
component
->
card
->
snd_card
;
return
snd_soc_add_controls
(
card
,
component
->
dev
,
controls
,
num_controls
,
component
->
name_prefix
,
component
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_add_component_controls
);
/**
* snd_soc_add_codec_controls - add an array of controls to a codec.
* Convenience function to add a list of controls. Many codecs were
...
...
@@ -2418,12 +2424,10 @@ EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
* Return 0 for success, else error.
*/
int
snd_soc_add_codec_controls
(
struct
snd_soc_codec
*
codec
,
const
struct
snd_kcontrol_new
*
controls
,
int
num_controls
)
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
)
{
struct
snd_card
*
card
=
codec
->
card
->
snd_card
;
return
snd_soc_add_controls
(
card
,
codec
->
dev
,
controls
,
num_controls
,
codec
->
name_prefix
,
&
codec
->
component
);
return
snd_soc_add_component_controls
(
&
codec
->
component
,
controls
,
num_controls
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_add_codec_controls
);
...
...
@@ -2438,12 +2442,10 @@ EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
* Return 0 for success, else error.
*/
int
snd_soc_add_platform_controls
(
struct
snd_soc_platform
*
platform
,
const
struct
snd_kcontrol_new
*
controls
,
int
num_controls
)
const
struct
snd_kcontrol_new
*
controls
,
unsigned
int
num_controls
)
{
struct
snd_card
*
card
=
platform
->
card
->
snd_card
;
return
snd_soc_add_controls
(
card
,
platform
->
dev
,
controls
,
num_controls
,
NULL
,
&
platform
->
component
);
return
snd_soc_add_component_controls
(
&
platform
->
component
,
controls
,
num_controls
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_add_platform_controls
);
...
...
@@ -3115,7 +3117,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
int
snd_soc_limit_volume
(
struct
snd_soc_codec
*
codec
,
const
char
*
name
,
int
max
)
{
struct
snd_card
*
card
=
codec
->
card
->
snd_card
;
struct
snd_card
*
card
=
codec
->
c
omponent
.
c
ard
->
snd_card
;
struct
snd_kcontrol
*
kctl
;
struct
soc_mixer_control
*
mc
;
int
found
=
0
;
...
...
@@ -3661,6 +3663,9 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
else
snd_soc_xlate_tdm_slot_mask
(
slots
,
&
tx_mask
,
&
rx_mask
);
dai
->
tx_mask
=
tx_mask
;
dai
->
rx_mask
=
rx_mask
;
if
(
dai
->
driver
&&
dai
->
driver
->
ops
->
set_tdm_slot
)
return
dai
->
driver
->
ops
->
set_tdm_slot
(
dai
,
tx_mask
,
rx_mask
,
slots
,
slot_width
);
...
...
@@ -3733,6 +3738,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
}
EXPORT_SYMBOL_GPL
(
snd_soc_dai_digital_mute
);
static
int
snd_soc_init_multicodec
(
struct
snd_soc_card
*
card
,
struct
snd_soc_dai_link
*
dai_link
)
{
/* Legacy codec/codec_dai link is a single entry in multicodec */
if
(
dai_link
->
codec_name
||
dai_link
->
codec_of_node
||
dai_link
->
codec_dai_name
)
{
dai_link
->
num_codecs
=
1
;
dai_link
->
codecs
=
devm_kzalloc
(
card
->
dev
,
sizeof
(
struct
snd_soc_dai_link_component
),
GFP_KERNEL
);
if
(
!
dai_link
->
codecs
)
return
-
ENOMEM
;
dai_link
->
codecs
[
0
].
name
=
dai_link
->
codec_name
;
dai_link
->
codecs
[
0
].
of_node
=
dai_link
->
codec_of_node
;
dai_link
->
codecs
[
0
].
dai_name
=
dai_link
->
codec_dai_name
;
}
if
(
!
dai_link
->
codecs
)
{
dev_err
(
card
->
dev
,
"ASoC: DAI link has no CODECs
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
/**
* snd_soc_register_card - Register a card with the ASoC core
*
...
...
@@ -3741,7 +3773,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
*/
int
snd_soc_register_card
(
struct
snd_soc_card
*
card
)
{
int
i
,
ret
;
int
i
,
j
,
ret
;
if
(
!
card
->
name
||
!
card
->
dev
)
return
-
EINVAL
;
...
...
@@ -3749,23 +3781,30 @@ int snd_soc_register_card(struct snd_soc_card *card)
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
{
struct
snd_soc_dai_link
*
link
=
&
card
->
dai_link
[
i
];
ret
=
snd_soc_init_multicodec
(
card
,
link
);
if
(
ret
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init multicodec
\n
"
);
return
ret
;
}
for
(
j
=
0
;
j
<
link
->
num_codecs
;
j
++
)
{
/*
* Codec must be specified by 1 of name or OF node,
* not both or neither.
*/
if
(
!!
link
->
codec_name
==
!!
link
->
codec_of_node
)
{
dev_err
(
card
->
dev
,
"ASoC: Neither/both codec name/of_node are set for %s
\n
"
,
if
(
!!
link
->
codecs
[
j
].
name
==
!!
link
->
codecs
[
j
].
of_node
)
{
dev_err
(
card
->
dev
,
"ASoC: Neither/both codec name/of_node are set for %s
\n
"
,
link
->
name
);
return
-
EINVAL
;
}
/* Codec DAI name must be specified */
if
(
!
link
->
codec_dai_name
)
{
dev_err
(
card
->
dev
,
"ASoC: codec_dai_name not set for %s
\n
"
,
if
(
!
link
->
codecs
[
j
].
dai_name
)
{
dev_err
(
card
->
dev
,
"ASoC: codec_dai_name not set for %s
\n
"
,
link
->
name
);
return
-
EINVAL
;
}
}
/*
* Platform may be specified by either name or OF node, but
...
...
@@ -3817,8 +3856,19 @@ int snd_soc_register_card(struct snd_soc_card *card)
card
->
num_rtd
=
0
;
card
->
rtd_aux
=
&
card
->
rtd
[
card
->
num_links
];
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
{
card
->
rtd
[
i
].
card
=
card
;
card
->
rtd
[
i
].
dai_link
=
&
card
->
dai_link
[
i
];
card
->
rtd
[
i
].
codec_dais
=
devm_kzalloc
(
card
->
dev
,
sizeof
(
struct
snd_soc_dai
*
)
*
(
card
->
rtd
[
i
].
dai_link
->
num_codecs
),
GFP_KERNEL
);
if
(
card
->
rtd
[
i
].
codec_dais
==
NULL
)
return
-
ENOMEM
;
}
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
card
->
rtd_aux
[
i
].
card
=
card
;
INIT_LIST_HEAD
(
&
card
->
dapm_dirty
);
card
->
instantiated
=
0
;
...
...
@@ -3831,10 +3881,16 @@ int snd_soc_register_card(struct snd_soc_card *card)
/* deactivate pins to sleep state */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dai
*
cpu_dai
=
card
->
rtd
[
i
].
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
card
->
rtd
[
i
].
codec_dai
;
struct
snd_soc_pcm_runtime
*
rtd
=
&
card
->
rtd
[
i
];
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
int
j
;
for
(
j
=
0
;
j
<
rtd
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
j
];
if
(
!
codec_dai
->
active
)
pinctrl_pm_select_sleep_state
(
codec_dai
->
dev
);
}
if
(
!
cpu_dai
->
active
)
pinctrl_pm_select_sleep_state
(
cpu_dai
->
dev
);
}
...
...
@@ -3941,16 +3997,14 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
* snd_soc_register_dais - Register a DAI with the ASoC core
*
* @component: The component the DAIs are registered for
* @codec: The CODEC that the DAIs are registered for, NULL if the component is
* not a CODEC.
* @dai_drv: DAI driver to use for the DAIs
* @count: Number of DAIs
* @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the
* parent's name.
*/
static
int
snd_soc_register_dais
(
struct
snd_soc_component
*
component
,
struct
snd_soc_
codec
*
codec
,
struct
snd_soc_dai_driver
*
dai_drv
,
size_t
count
,
bool
legacy_dai_naming
)
struct
snd_soc_
dai_driver
*
dai_drv
,
size_t
count
,
bool
legacy_dai_naming
)
{
struct
device
*
dev
=
component
->
dev
;
struct
snd_soc_dai
*
dai
;
...
...
@@ -3959,6 +4013,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
dev_dbg
(
dev
,
"ASoC: dai register %s #%Zu
\n
"
,
dev_name
(
dev
),
count
);
component
->
dai_drv
=
dai_drv
;
component
->
num_dai
=
count
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
dai
=
kzalloc
(
sizeof
(
struct
snd_soc_dai
),
GFP_KERNEL
);
...
...
@@ -3991,16 +4048,11 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
}
dai
->
component
=
component
;
dai
->
codec
=
codec
;
dai
->
dev
=
dev
;
dai
->
driver
=
&
dai_drv
[
i
];
dai
->
dapm
.
dev
=
dev
;
if
(
!
dai
->
driver
->
ops
)
dai
->
driver
->
ops
=
&
null_dai_ops
;
if
(
!
dai
->
codec
)
dai
->
dapm
.
idle_bias_off
=
1
;
list_add
(
&
dai
->
list
,
&
component
->
dai_list
);
dev_dbg
(
dev
,
"ASoC: Registered DAI '%s'
\n
"
,
dai
->
name
);
...
...
@@ -4014,60 +4066,82 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
return
ret
;
}
/**
* snd_soc_register_component - Register a component with the ASoC core
*
*/
static
int
__snd_soc_register_component
(
struct
device
*
dev
,
struct
snd_soc_component
*
cmpnt
,
const
struct
snd_soc_component_driver
*
cmpnt_drv
,
struct
snd_soc_codec
*
codec
,
struct
snd_soc_dai_driver
*
dai_drv
,
int
num_dai
,
bool
allow_single_dai
)
static
void
snd_soc_component_seq_notifier
(
struct
snd_soc_dapm_context
*
dapm
,
enum
snd_soc_dapm_type
type
,
int
subseq
)
{
int
re
t
;
struct
snd_soc_component
*
component
=
dapm
->
componen
t
;
dev_dbg
(
dev
,
"component register %s
\n
"
,
dev_name
(
dev
));
component
->
driver
->
seq_notifier
(
component
,
type
,
subseq
);
}
if
(
!
cmpnt
)
{
dev_err
(
dev
,
"ASoC: Failed to connecting component
\n
"
);
return
-
ENOMEM
;
}
static
int
snd_soc_component_stream_event
(
struct
snd_soc_dapm_context
*
dapm
,
int
event
)
{
struct
snd_soc_component
*
component
=
dapm
->
component
;
return
component
->
driver
->
stream_event
(
component
,
event
);
}
mutex_init
(
&
cmpnt
->
io_mutex
);
static
int
snd_soc_component_initialize
(
struct
snd_soc_component
*
component
,
const
struct
snd_soc_component_driver
*
driver
,
struct
device
*
dev
)
{
struct
snd_soc_dapm_context
*
dapm
;
c
mpnt
->
name
=
fmt_single_name
(
dev
,
&
cmp
nt
->
id
);
if
(
!
c
mp
nt
->
name
)
{
dev_err
(
dev
,
"ASoC: Failed to
simplifying
name
\n
"
);
c
omponent
->
name
=
fmt_single_name
(
dev
,
&
compone
nt
->
id
);
if
(
!
c
ompone
nt
->
name
)
{
dev_err
(
dev
,
"ASoC: Failed to
allocate
name
\n
"
);
return
-
ENOMEM
;
}
cmpnt
->
dev
=
dev
;
cmpnt
->
driver
=
cmpnt_drv
;
cmpnt
->
dai_drv
=
dai_drv
;
cmpnt
->
num_dai
=
num_dai
;
INIT_LIST_HEAD
(
&
cmpnt
->
dai_list
);
component
->
dev
=
dev
;
component
->
driver
=
driver
;
ret
=
snd_soc_register_dais
(
cmpnt
,
codec
,
dai_drv
,
num_dai
,
allow_single_dai
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"ASoC: Failed to regster DAIs: %d
\n
"
,
ret
);
goto
error_component_name
;
}
if
(
!
component
->
dapm_ptr
)
component
->
dapm_ptr
=
&
component
->
dapm
;
dapm
=
component
->
dapm_ptr
;
dapm
->
dev
=
dev
;
dapm
->
component
=
component
;
dapm
->
bias_level
=
SND_SOC_BIAS_OFF
;
if
(
driver
->
seq_notifier
)
dapm
->
seq_notifier
=
snd_soc_component_seq_notifier
;
if
(
driver
->
stream_event
)
dapm
->
stream_event
=
snd_soc_component_stream_event
;
INIT_LIST_HEAD
(
&
component
->
dai_list
);
mutex_init
(
&
component
->
io_mutex
);
return
0
;
}
static
void
snd_soc_component_add_unlocked
(
struct
snd_soc_component
*
component
)
{
list_add
(
&
component
->
list
,
&
component_list
);
}
static
void
snd_soc_component_add
(
struct
snd_soc_component
*
component
)
{
mutex_lock
(
&
client_mutex
);
list_add
(
&
cmpnt
->
list
,
&
component_lis
t
);
snd_soc_component_add_unlocked
(
componen
t
);
mutex_unlock
(
&
client_mutex
);
}
dev_dbg
(
cmpnt
->
dev
,
"ASoC: Registered component '%s'
\n
"
,
cmpnt
->
name
);
return
ret
;
static
void
snd_soc_component_cleanup
(
struct
snd_soc_component
*
component
)
{
snd_soc_unregister_dais
(
component
);
kfree
(
component
->
name
);
}
error_component_name:
kfree
(
cmpnt
->
name
);
static
void
snd_soc_component_del_unlocked
(
struct
snd_soc_component
*
component
)
{
list_del
(
&
component
->
list
);
}
return
ret
;
static
void
snd_soc_component_del
(
struct
snd_soc_component
*
component
)
{
mutex_lock
(
&
client_mutex
);
snd_soc_component_del_unlocked
(
component
);
mutex_unlock
(
&
client_mutex
);
}
int
snd_soc_register_component
(
struct
device
*
dev
,
...
...
@@ -4076,32 +4150,38 @@ int snd_soc_register_component(struct device *dev,
int
num_dai
)
{
struct
snd_soc_component
*
cmpnt
;
int
ret
;
cmpnt
=
devm_kzalloc
(
dev
,
sizeof
(
*
cmpnt
),
GFP_KERNEL
);
cmpnt
=
kzalloc
(
sizeof
(
*
cmpnt
),
GFP_KERNEL
);
if
(
!
cmpnt
)
{
dev_err
(
dev
,
"ASoC: Failed to allocate memory
\n
"
);
return
-
ENOMEM
;
}
ret
=
snd_soc_component_initialize
(
cmpnt
,
cmpnt_drv
,
dev
);
if
(
ret
)
goto
err_free
;
cmpnt
->
ignore_pmdown_time
=
true
;
cmpnt
->
registered_as_component
=
true
;
return
__snd_soc_register_component
(
dev
,
cmpnt
,
cmpnt_drv
,
NULL
,
dai_drv
,
num_dai
,
true
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_register_component
);
ret
=
snd_soc_register_dais
(
cmpnt
,
dai_drv
,
num_dai
,
true
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"ASoC: Failed to regster DAIs: %d
\n
"
,
ret
);
goto
err_cleanup
;
}
static
void
__snd_soc_unregister_component
(
struct
snd_soc_component
*
cmpnt
)
{
snd_soc_unregister_dais
(
cmpnt
);
snd_soc_component_add
(
cmpnt
);
mutex_lock
(
&
client_mutex
);
list_del
(
&
cmpnt
->
list
);
mutex_unlock
(
&
client_mutex
);
return
0
;
dev_dbg
(
cmpnt
->
dev
,
"ASoC: Unregistered component '%s'
\n
"
,
cmpnt
->
name
);
kfree
(
cmpnt
->
name
);
err_cleanup:
snd_soc_component_cleanup
(
cmpnt
);
err_free:
kfree
(
cmpnt
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_register_component
);
/**
* snd_soc_unregister_component - Unregister a component from the ASoC core
...
...
@@ -4118,7 +4198,9 @@ void snd_soc_unregister_component(struct device *dev)
return
;
found:
__snd_soc_unregister_component
(
cmpnt
);
snd_soc_component_del
(
cmpnt
);
snd_soc_component_cleanup
(
cmpnt
);
kfree
(
cmpnt
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_unregister_component
);
...
...
@@ -4151,37 +4233,25 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
{
int
ret
;
/* create platform component name */
platform
->
name
=
fmt_single_name
(
dev
,
&
platform
->
id
);
if
(
platform
->
name
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_component_initialize
(
&
platform
->
component
,
&
platform_drv
->
component_driver
,
dev
);
if
(
ret
)
return
ret
;
platform
->
dev
=
dev
;
platform
->
driver
=
platform_drv
;
platform
->
dapm
.
dev
=
dev
;
platform
->
dapm
.
platform
=
platform
;
platform
->
dapm
.
component
=
&
platform
->
component
;
platform
->
dapm
.
stream_event
=
platform_drv
->
stream_event
;
if
(
platform_drv
->
write
)
platform
->
component
.
write
=
snd_soc_platform_drv_write
;
if
(
platform_drv
->
read
)
platform
->
component
.
read
=
snd_soc_platform_drv_read
;
/* register component */
ret
=
__snd_soc_register_component
(
dev
,
&
platform
->
component
,
&
platform_drv
->
component_driver
,
NULL
,
NULL
,
0
,
false
);
if
(
ret
<
0
)
{
dev_err
(
platform
->
component
.
dev
,
"ASoC: Failed to register component: %d
\n
"
,
ret
);
return
ret
;
}
mutex_lock
(
&
client_mutex
);
snd_soc_component_add_unlocked
(
&
platform
->
component
);
list_add
(
&
platform
->
list
,
&
platform_list
);
mutex_unlock
(
&
client_mutex
);
dev_dbg
(
dev
,
"ASoC: Registered platform '%s'
\n
"
,
platform
->
name
);
dev_dbg
(
dev
,
"ASoC: Registered platform '%s'
\n
"
,
platform
->
component
.
name
);
return
0
;
}
...
...
@@ -4218,15 +4288,16 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
*/
void
snd_soc_remove_platform
(
struct
snd_soc_platform
*
platform
)
{
__snd_soc_unregister_component
(
&
platform
->
component
);
mutex_lock
(
&
client_mutex
);
list_del
(
&
platform
->
list
);
snd_soc_component_del_unlocked
(
&
platform
->
component
);
mutex_unlock
(
&
client_mutex
);
snd_soc_component_cleanup
(
&
platform
->
component
);
dev_dbg
(
platform
->
dev
,
"ASoC: Unregistered platform '%s'
\n
"
,
platform
->
name
);
kfree
(
platform
->
name
);
platform
->
component
.
name
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_remove_platform
);
...
...
@@ -4312,6 +4383,14 @@ static int snd_soc_codec_drv_read(struct snd_soc_component *component,
return
0
;
}
static
int
snd_soc_codec_set_bias_level
(
struct
snd_soc_dapm_context
*
dapm
,
enum
snd_soc_bias_level
level
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
dapm
);
return
codec
->
driver
->
set_bias_level
(
codec
,
level
);
}
/**
* snd_soc_register_codec - Register a codec with the ASoC core
*
...
...
@@ -4323,6 +4402,7 @@ int snd_soc_register_codec(struct device *dev,
int
num_dai
)
{
struct
snd_soc_codec
*
codec
;
struct
snd_soc_dai
*
dai
;
struct
regmap
*
regmap
;
int
ret
,
i
;
...
...
@@ -4332,24 +4412,23 @@ int snd_soc_register_codec(struct device *dev,
if
(
codec
==
NULL
)
return
-
ENOMEM
;
/* create CODEC component name */
codec
->
name
=
fmt_single_name
(
dev
,
&
codec
->
id
);
if
(
codec
->
name
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
fail_codec
;
}
codec
->
component
.
dapm_ptr
=
&
codec
->
dapm
;
ret
=
snd_soc_component_initialize
(
&
codec
->
component
,
&
codec_drv
->
component_driver
,
dev
)
;
if
(
ret
)
goto
err_free
;
if
(
codec_drv
->
write
)
codec
->
component
.
write
=
snd_soc_codec_drv_write
;
if
(
codec_drv
->
read
)
codec
->
component
.
read
=
snd_soc_codec_drv_read
;
codec
->
component
.
ignore_pmdown_time
=
codec_drv
->
ignore_pmdown_time
;
codec
->
dapm
.
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
dapm
.
dev
=
dev
;
codec
->
dapm
.
codec
=
codec
;
codec
->
dapm
.
component
=
&
codec
->
component
;
if
(
codec_drv
->
seq_notifier
)
codec
->
dapm
.
seq_notifier
=
codec_drv
->
seq_notifier
;
codec
->
dapm
.
stream_event
=
codec_drv
->
stream_event
;
if
(
codec_drv
->
set_bias_level
)
codec
->
dapm
.
set_bias_level
=
snd_soc_codec_set_bias_level
;
codec
->
dev
=
dev
;
codec
->
driver
=
codec_drv
;
codec
->
component
.
val_bytes
=
codec_drv
->
reg_word_size
;
...
...
@@ -4368,7 +4447,7 @@ int snd_soc_register_codec(struct device *dev,
dev_err
(
codec
->
dev
,
"Failed to set cache I/O:%d
\n
"
,
ret
);
return
ret
;
goto
err_cleanup
;
}
}
}
...
...
@@ -4378,29 +4457,27 @@ int snd_soc_register_codec(struct device *dev,
fixup_codec_formats
(
&
dai_drv
[
i
].
capture
);
}
mutex_lock
(
&
client_mutex
);
list_add
(
&
codec
->
list
,
&
codec_list
);
mutex_unlock
(
&
client_mutex
);
/* register component */
ret
=
__snd_soc_register_component
(
dev
,
&
codec
->
component
,
&
codec_drv
->
component_driver
,
codec
,
dai_drv
,
num_dai
,
false
);
ret
=
snd_soc_register_dais
(
&
codec
->
component
,
dai_drv
,
num_dai
,
false
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"ASoC: Failed to regster component
: %d
\n
"
,
ret
);
goto
fail_codec_name
;
dev_err
(
dev
,
"ASoC: Failed to regster DAIs
: %d
\n
"
,
ret
);
goto
err_cleanup
;
}
dev_dbg
(
codec
->
dev
,
"ASoC: Registered codec '%s'
\n
"
,
codec
->
name
);
return
0
;
list_for_each_entry
(
dai
,
&
codec
->
component
.
dai_list
,
list
)
dai
->
codec
=
codec
;
fail_codec_name:
mutex_lock
(
&
client_mutex
);
list_del
(
&
codec
->
list
);
snd_soc_component_add_unlocked
(
&
codec
->
component
);
list_add
(
&
codec
->
list
,
&
codec_list
);
mutex_unlock
(
&
client_mutex
);
kfree
(
codec
->
name
);
fail_codec:
dev_dbg
(
codec
->
dev
,
"ASoC: Registered codec '%s'
\n
"
,
codec
->
component
.
name
);
return
0
;
err_cleanup:
snd_soc_component_cleanup
(
&
codec
->
component
);
err_free:
kfree
(
codec
);
return
ret
;
}
...
...
@@ -4422,16 +4499,17 @@ void snd_soc_unregister_codec(struct device *dev)
return
;
found:
__snd_soc_unregister_component
(
&
codec
->
component
);
mutex_lock
(
&
client_mutex
);
list_del
(
&
codec
->
list
);
snd_soc_component_del_unlocked
(
&
codec
->
component
);
mutex_unlock
(
&
client_mutex
);
dev_dbg
(
codec
->
dev
,
"ASoC: Unregistered codec '%s'
\n
"
,
codec
->
name
);
dev_dbg
(
codec
->
dev
,
"ASoC: Unregistered codec '%s'
\n
"
,
codec
->
component
.
name
);
snd_soc_component_cleanup
(
&
codec
->
component
);
snd_soc_cache_exit
(
codec
);
kfree
(
codec
->
name
);
kfree
(
codec
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_unregister_codec
);
...
...
sound/soc/soc-dapm.c
View file @
a1cb98ac
...
...
@@ -349,13 +349,28 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
return
true
;
}
/**
* snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
* kcontrol
* @kcontrol: The kcontrol
*
* Note: This function must only be used on kcontrols that are known to have
* been registered for a CODEC. Otherwise the behaviour is undefined.
*/
struct
snd_soc_dapm_context
*
snd_soc_dapm_kcontrol_dapm
(
struct
snd_kcontrol
*
kcontrol
)
{
return
dapm_kcontrol_get_wlist
(
kcontrol
)
->
widgets
[
0
]
->
dapm
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_kcontrol_dapm
);
/**
* snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
* @kcontrol: The kcontrol
*/
struct
snd_soc_codec
*
snd_soc_dapm_kcontrol_codec
(
struct
snd_kcontrol
*
kcontrol
)
{
return
dapm_kcontrol_get_wlist
(
kcontrol
)
->
widgets
[
0
]
->
codec
;
return
snd_soc_dapm_to_codec
(
snd_soc_dapm_kcontrol_dapm
(
kcontrol
))
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_kcontrol_codec
);
...
...
@@ -375,23 +390,38 @@ static void dapm_reset(struct snd_soc_card *card)
}
}
static
int
soc_widget_read
(
struct
snd_soc_dapm_widget
*
w
,
int
reg
,
static
const
char
*
soc_dapm_prefix
(
struct
snd_soc_dapm_context
*
dapm
)
{
if
(
!
dapm
->
component
)
return
NULL
;
return
dapm
->
component
->
name_prefix
;
}
static
int
soc_dapm_read
(
struct
snd_soc_dapm_context
*
dapm
,
int
reg
,
unsigned
int
*
value
)
{
if
(
!
w
->
dapm
->
component
)
if
(
!
dapm
->
component
)
return
-
EIO
;
return
snd_soc_component_read
(
w
->
dapm
->
component
,
reg
,
value
);
return
snd_soc_component_read
(
dapm
->
component
,
reg
,
value
);
}
static
int
soc_
widget_update_bits
(
struct
snd_soc_dapm_widget
*
w
,
static
int
soc_
dapm_update_bits
(
struct
snd_soc_dapm_context
*
dapm
,
int
reg
,
unsigned
int
mask
,
unsigned
int
value
)
{
if
(
!
w
->
dapm
->
component
)
if
(
!
dapm
->
component
)
return
-
EIO
;
return
snd_soc_component_update_bits_async
(
w
->
dapm
->
component
,
reg
,
return
snd_soc_component_update_bits_async
(
dapm
->
component
,
reg
,
mask
,
value
);
}
static
int
soc_dapm_test_bits
(
struct
snd_soc_dapm_context
*
dapm
,
int
reg
,
unsigned
int
mask
,
unsigned
int
value
)
{
if
(
!
dapm
->
component
)
return
-
EIO
;
return
snd_soc_component_test_bits
(
dapm
->
component
,
reg
,
mask
,
value
);
}
static
void
soc_dapm_async_complete
(
struct
snd_soc_dapm_context
*
dapm
)
{
if
(
dapm
->
component
)
...
...
@@ -420,15 +450,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
if
(
ret
!=
0
)
goto
out
;
if
(
dapm
->
codec
)
{
if
(
dapm
->
codec
->
driver
->
set_bias_level
)
ret
=
dapm
->
codec
->
driver
->
set_bias_level
(
dapm
->
codec
,
level
);
else
dapm
->
bias_level
=
level
;
}
else
if
(
!
card
||
dapm
!=
&
card
->
dapm
)
{
if
(
dapm
->
set_bias_level
)
ret
=
dapm
->
set_bias_level
(
dapm
,
level
);
else
if
(
!
card
||
dapm
!=
&
card
->
dapm
)
dapm
->
bias_level
=
level
;
}
if
(
ret
!=
0
)
goto
out
;
...
...
@@ -452,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
int
i
;
if
(
e
->
reg
!=
SND_SOC_NOPM
)
{
soc_
widget_read
(
dest
,
e
->
reg
,
&
val
);
soc_
dapm_read
(
dapm
,
e
->
reg
,
&
val
);
val
=
(
val
>>
e
->
shift_l
)
&
e
->
mask
;
item
=
snd_soc_enum_val_to_item
(
e
,
val
);
}
else
{
...
...
@@ -496,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w,
unsigned
int
val
;
if
(
reg
!=
SND_SOC_NOPM
)
{
soc_
widget_read
(
w
,
reg
,
&
val
);
soc_
dapm_read
(
w
->
dapm
,
reg
,
&
val
);
val
=
(
val
>>
shift
)
&
mask
;
if
(
invert
)
val
=
max
-
val
;
...
...
@@ -570,11 +595,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
const
char
*
name
;
int
ret
;
if
(
dapm
->
codec
)
prefix
=
dapm
->
codec
->
name_prefix
;
else
prefix
=
NULL
;
prefix
=
soc_dapm_prefix
(
dapm
);
if
(
prefix
)
prefix_len
=
strlen
(
prefix
)
+
1
;
else
...
...
@@ -1308,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
static
void
dapm_seq_run_coalesced
(
struct
snd_soc_card
*
card
,
struct
list_head
*
pending
)
{
struct
snd_soc_dapm_context
*
dapm
;
struct
snd_soc_dapm_widget
*
w
;
int
reg
;
unsigned
int
value
=
0
;
unsigned
int
mask
=
0
;
reg
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
)
->
reg
;
w
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
);
reg
=
w
->
reg
;
dapm
=
w
->
dapm
;
list_for_each_entry
(
w
,
pending
,
power_list
)
{
WARN_ON
(
reg
!=
w
->
reg
);
WARN_ON
(
reg
!=
w
->
reg
||
dapm
!=
w
->
dapm
);
w
->
power
=
w
->
new_power
;
mask
|=
w
->
mask
<<
w
->
shift
;
...
...
@@ -1326,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
else
value
|=
w
->
off_val
<<
w
->
shift
;
pop_dbg
(
w
->
dapm
->
dev
,
card
->
pop_time
,
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x
\n
"
,
w
->
name
,
reg
,
value
,
mask
);
...
...
@@ -1339,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
/* Any widget will do, they should all be updating the
* same register.
*/
w
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
);
pop_dbg
(
w
->
dapm
->
dev
,
card
->
pop_time
,
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
"pop test : Applying 0x%x/0x%x to %x in %dms
\n
"
,
value
,
mask
,
reg
,
card
->
pop_time
);
pop_wait
(
card
->
pop_time
);
soc_
widget_update_bits
(
w
,
reg
,
mask
,
value
);
soc_
dapm_update_bits
(
dapm
,
reg
,
mask
,
value
);
}
list_for_each_entry
(
w
,
pending
,
power_list
)
{
...
...
@@ -1492,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card)
if
(
!
w
)
return
;
ret
=
soc_widget_update_bits
(
w
,
update
->
reg
,
update
->
mask
,
update
->
val
);
ret
=
soc_dapm_update_bits
(
w
->
dapm
,
update
->
reg
,
update
->
mask
,
update
->
val
);
if
(
ret
<
0
)
dev_err
(
w
->
dapm
->
dev
,
"ASoC: %s DAPM update failed: %d
\n
"
,
w
->
name
,
ret
);
...
...
@@ -2062,17 +2084,13 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_mixer_update_power
);
/* show dapm widget status in sys fs */
static
ssize_t
dapm_widget_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
ssize_t
dapm_widget_show_codec
(
struct
snd_soc_codec
*
codec
,
char
*
buf
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
dev_get_drvdata
(
dev
);
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
snd_soc_dapm_widget
*
w
;
int
count
=
0
;
char
*
state
=
"not set"
;
list_for_each_entry
(
w
,
&
codec
->
card
->
widgets
,
list
)
{
list_for_each_entry
(
w
,
&
codec
->
c
omponent
.
c
ard
->
widgets
,
list
)
{
if
(
w
->
dapm
!=
&
codec
->
dapm
)
continue
;
...
...
@@ -2120,6 +2138,21 @@ static ssize_t dapm_widget_show(struct device *dev,
return
count
;
}
/* show dapm widget status in sys fs */
static
ssize_t
dapm_widget_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
dev_get_drvdata
(
dev
);
int
i
,
count
=
0
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
struct
snd_soc_codec
*
codec
=
rtd
->
codec_dais
[
i
]
->
codec
;
count
+=
dapm_widget_show_codec
(
codec
,
buf
+
count
);
}
return
count
;
}
static
DEVICE_ATTR
(
dapm_widget
,
0444
,
dapm_widget_show
,
NULL
);
int
snd_soc_dapm_sys_add
(
struct
device
*
dev
)
...
...
@@ -2371,14 +2404,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
const
char
*
source
;
char
prefixed_sink
[
80
];
char
prefixed_source
[
80
];
const
char
*
prefix
;
int
ret
;
if
(
dapm
->
codec
&&
dapm
->
codec
->
name_prefix
)
{
prefix
=
soc_dapm_prefix
(
dapm
);
if
(
prefix
)
{
snprintf
(
prefixed_sink
,
sizeof
(
prefixed_sink
),
"%s %s"
,
dapm
->
codec
->
name_
prefix
,
route
->
sink
);
prefix
,
route
->
sink
);
sink
=
prefixed_sink
;
snprintf
(
prefixed_source
,
sizeof
(
prefixed_source
),
"%s %s"
,
dapm
->
codec
->
name_
prefix
,
route
->
source
);
prefix
,
route
->
source
);
source
=
prefixed_source
;
}
else
{
sink
=
route
->
sink
;
...
...
@@ -2439,6 +2474,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
const
char
*
source
;
char
prefixed_sink
[
80
];
char
prefixed_source
[
80
];
const
char
*
prefix
;
if
(
route
->
control
)
{
dev_err
(
dapm
->
dev
,
...
...
@@ -2446,12 +2482,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
return
-
EINVAL
;
}
if
(
dapm
->
codec
&&
dapm
->
codec
->
name_prefix
)
{
prefix
=
soc_dapm_prefix
(
dapm
);
if
(
prefix
)
{
snprintf
(
prefixed_sink
,
sizeof
(
prefixed_sink
),
"%s %s"
,
dapm
->
codec
->
name_
prefix
,
route
->
sink
);
prefix
,
route
->
sink
);
sink
=
prefixed_sink
;
snprintf
(
prefixed_source
,
sizeof
(
prefixed_source
),
"%s %s"
,
dapm
->
codec
->
name_
prefix
,
route
->
source
);
prefix
,
route
->
source
);
source
=
prefixed_source
;
}
else
{
sink
=
route
->
sink
;
...
...
@@ -2670,7 +2707,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
/* Read the initial power state from the device */
if
(
w
->
reg
>=
0
)
{
soc_
widget_read
(
w
,
w
->
reg
,
&
val
);
soc_
dapm_read
(
w
->
dapm
,
w
->
reg
,
&
val
);
val
=
val
>>
w
->
shift
;
val
&=
w
->
mask
;
if
(
val
==
w
->
on_val
)
...
...
@@ -2701,8 +2738,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
int
snd_soc_dapm_get_volsw
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_
codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_
dapm_context
*
dapm
=
snd_soc_dapm_kcontrol_dapm
(
kcontrol
);
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
int
reg
=
mc
->
reg
;
...
...
@@ -2711,17 +2748,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
unsigned
int
mask
=
(
1
<<
fls
(
max
))
-
1
;
unsigned
int
invert
=
mc
->
invert
;
unsigned
int
val
;
int
ret
=
0
;
if
(
snd_soc_volsw_is_stereo
(
mc
))
dev_warn
(
codec
->
dapm
.
dev
,
dev_warn
(
dapm
->
dev
,
"ASoC: Control '%s' is stereo, which is not supported
\n
"
,
kcontrol
->
id
.
name
);
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
if
(
dapm_kcontrol_is_powered
(
kcontrol
)
&&
reg
!=
SND_SOC_NOPM
)
val
=
(
snd_soc_read
(
codec
,
reg
)
>>
shift
)
&
mask
;
else
if
(
dapm_kcontrol_is_powered
(
kcontrol
)
&&
reg
!=
SND_SOC_NOPM
)
{
ret
=
soc_dapm_read
(
dapm
,
reg
,
&
val
);
val
=
(
val
>>
shift
)
&
mask
;
}
else
{
val
=
dapm_kcontrol_get_value
(
kcontrol
);
}
mutex_unlock
(
&
card
->
dapm_mutex
);
if
(
invert
)
...
...
@@ -2729,7 +2769,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
else
ucontrol
->
value
.
integer
.
value
[
0
]
=
val
;
return
0
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_get_volsw
);
...
...
@@ -2745,8 +2785,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
int
snd_soc_dapm_put_volsw
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_
codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_
dapm_context
*
dapm
=
snd_soc_dapm_kcontrol_dapm
(
kcontrol
);
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
int
reg
=
mc
->
reg
;
...
...
@@ -2760,7 +2800,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
int
ret
=
0
;
if
(
snd_soc_volsw_is_stereo
(
mc
))
dev_warn
(
codec
->
dapm
.
dev
,
dev_warn
(
dapm
->
dev
,
"ASoC: Control '%s' is stereo, which is not supported
\n
"
,
kcontrol
->
id
.
name
);
...
...
@@ -2778,7 +2818,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
mask
=
mask
<<
shift
;
val
=
val
<<
shift
;
reg_change
=
s
nd_soc_test_bits
(
codec
,
reg
,
mask
,
val
);
reg_change
=
s
oc_dapm_test_bits
(
dapm
,
reg
,
mask
,
val
);
}
if
(
change
||
reg_change
)
{
...
...
@@ -2817,12 +2857,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
int
snd_soc_dapm_get_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_
codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_
dapm_context
*
dapm
=
snd_soc_dapm_kcontrol_dapm
(
kcontrol
);
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
reg_val
,
val
;
int
ret
=
0
;
if
(
e
->
reg
!=
SND_SOC_NOPM
)
re
g_val
=
snd_soc_read
(
codec
,
e
->
reg
);
re
t
=
soc_dapm_read
(
dapm
,
e
->
reg
,
&
reg_val
);
else
reg_val
=
dapm_kcontrol_get_value
(
kcontrol
);
...
...
@@ -2834,7 +2875,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
ucontrol
->
value
.
enumerated
.
item
[
1
]
=
val
;
}
return
0
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_get_enum_double
);
...
...
@@ -2850,8 +2891,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
int
snd_soc_dapm_put_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_
codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_
dapm_context
*
dapm
=
snd_soc_dapm_kcontrol_dapm
(
kcontrol
);
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
*
item
=
ucontrol
->
value
.
enumerated
.
item
;
unsigned
int
val
,
change
;
...
...
@@ -2874,7 +2915,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
if
(
e
->
reg
!=
SND_SOC_NOPM
)
change
=
s
nd_soc_test_bits
(
codec
,
e
->
reg
,
mask
,
val
);
change
=
s
oc_dapm_test_bits
(
dapm
,
e
->
reg
,
mask
,
val
);
else
change
=
dapm_kcontrol_set_value
(
kcontrol
,
val
);
...
...
@@ -2971,6 +3012,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
const
struct
snd_soc_dapm_widget
*
widget
)
{
struct
snd_soc_dapm_widget
*
w
;
const
char
*
prefix
;
int
ret
;
if
((
w
=
dapm_cnew_widget
(
widget
))
==
NULL
)
...
...
@@ -3011,9 +3053,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
break
;
}
if
(
dapm
->
codec
&&
dapm
->
codec
->
name_prefix
)
w
->
name
=
kasprintf
(
GFP_KERNEL
,
"%s %s"
,
dapm
->
codec
->
name_
prefix
,
widget
->
name
);
prefix
=
soc_dapm_prefix
(
dapm
);
if
(
prefix
)
w
->
name
=
kasprintf
(
GFP_KERNEL
,
"%s %s"
,
prefix
,
widget
->
name
);
else
w
->
name
=
kasprintf
(
GFP_KERNEL
,
"%s"
,
widget
->
name
);
...
...
@@ -3066,7 +3108,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w
->
dapm
=
dapm
;
w
->
codec
=
dapm
->
codec
;
w
->
platform
=
dapm
->
platform
;
INIT_LIST_HEAD
(
&
w
->
sources
);
INIT_LIST_HEAD
(
&
w
->
sinks
);
INIT_LIST_HEAD
(
&
w
->
list
);
...
...
@@ -3173,27 +3214,15 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
switch
(
event
)
{
case
SND_SOC_DAPM_PRE_PMU
:
if
(
source
->
driver
->
ops
&&
source
->
driver
->
ops
->
hw_params
)
{
substream
.
stream
=
SNDRV_PCM_STREAM_CAPTURE
;
ret
=
source
->
driver
->
ops
->
hw_params
(
&
substream
,
params
,
source
);
if
(
ret
!=
0
)
{
dev_err
(
source
->
dev
,
"ASoC: hw_params() failed: %d
\n
"
,
ret
);
ret
=
soc_dai_hw_params
(
&
substream
,
params
,
source
);
if
(
ret
<
0
)
goto
out
;
}
}
if
(
sink
->
driver
->
ops
&&
sink
->
driver
->
ops
->
hw_params
)
{
substream
.
stream
=
SNDRV_PCM_STREAM_PLAYBACK
;
ret
=
sink
->
driver
->
ops
->
hw_params
(
&
substream
,
params
,
sink
);
if
(
ret
!=
0
)
{
dev_err
(
sink
->
dev
,
"ASoC: hw_params() failed: %d
\n
"
,
ret
);
ret
=
soc_dai_hw_params
(
&
substream
,
params
,
sink
);
if
(
ret
<
0
)
goto
out
;
}
}
break
;
case
SND_SOC_DAPM_POST_PMU
:
...
...
@@ -3365,25 +3394,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
return
0
;
}
void
snd_soc_dapm_connect_dai_link_widgets
(
struct
snd_soc_card
*
card
)
static
void
dapm_connect_dai_link_widgets
(
struct
snd_soc_card
*
card
,
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_
pcm_runtime
*
rtd
=
card
->
rtd
;
struct
snd_soc_
dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dapm_widget
*
sink
,
*
source
;
struct
snd_soc_dai
*
cpu_dai
,
*
codec_dai
;
int
i
;
/* for each BE DAI link... */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
rtd
=
&
card
->
rtd
[
i
];
cpu_dai
=
rtd
->
cpu_dai
;
codec_dai
=
rtd
->
codec_dai
;
/*
* dynamic FE links have no fixed DAI mapping.
* CODEC<->CODEC links have no direct connection.
*/
if
(
rtd
->
dai_link
->
dynamic
||
rtd
->
dai_link
->
params
)
continue
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
i
];
/* there is no point in connecting BE DAI links with dummies */
if
(
snd_soc_dai_is_dummy
(
codec_dai
)
||
...
...
@@ -3395,8 +3414,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
source
=
cpu_dai
->
playback_widget
;
sink
=
codec_dai
->
playback_widget
;
dev_dbg
(
rtd
->
dev
,
"connected DAI link %s:%s -> %s:%s
\n
"
,
cpu_dai
->
co
dec
->
name
,
source
->
name
,
codec_dai
->
platform
->
name
,
sink
->
name
);
cpu_dai
->
co
mponent
->
name
,
source
->
name
,
codec_dai
->
component
->
name
,
sink
->
name
);
snd_soc_dapm_add_path
(
&
card
->
dapm
,
source
,
sink
,
NULL
,
NULL
);
...
...
@@ -3407,8 +3426,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
source
=
codec_dai
->
capture_widget
;
sink
=
cpu_dai
->
capture_widget
;
dev_dbg
(
rtd
->
dev
,
"connected DAI link %s:%s -> %s:%s
\n
"
,
codec_dai
->
co
dec
->
name
,
source
->
name
,
cpu_dai
->
platform
->
name
,
sink
->
name
);
codec_dai
->
co
mponent
->
name
,
source
->
name
,
cpu_dai
->
component
->
name
,
sink
->
name
);
snd_soc_dapm_add_path
(
&
card
->
dapm
,
source
,
sink
,
NULL
,
NULL
);
...
...
@@ -3445,11 +3464,34 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
}
}
void
snd_soc_dapm_connect_dai_link_widgets
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
card
->
rtd
;
int
i
;
/* for each BE DAI link... */
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
rtd
=
&
card
->
rtd
[
i
];
/*
* dynamic FE links have no fixed DAI mapping.
* CODEC<->CODEC links have no direct connection.
*/
if
(
rtd
->
dai_link
->
dynamic
||
rtd
->
dai_link
->
params
)
continue
;
dapm_connect_dai_link_widgets
(
card
,
rtd
);
}
}
static
void
soc_dapm_stream_event
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
stream
,
int
event
)
{
int
i
;
soc_dapm_dai_stream_event
(
rtd
->
cpu_dai
,
stream
,
event
);
soc_dapm_dai_stream_event
(
rtd
->
codec_dai
,
stream
,
event
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
soc_dapm_dai_stream_event
(
rtd
->
codec_dais
[
i
],
stream
,
event
);
dapm_power_widgets
(
rtd
->
card
,
event
);
}
...
...
@@ -3758,36 +3800,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
}
/**
* snd_soc_dapm_auto_nc_
codec_
pins - call snd_soc_dapm_nc_pin for unused pins
* @c
odec: The codec
whose pins should be processed
* snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins
* @c
ard: The card
whose pins should be processed
*
* Automatically call snd_soc_dapm_nc_pin() for any external pins in the c
odec
* which are unused. Pins are used if they are connected externally to
the
* co
dec
, whether that be to some other device, or a loop-back connection to
* the co
dec
itself.
* Automatically call snd_soc_dapm_nc_pin() for any external pins in the c
ard
* which are unused. Pins are used if they are connected externally to
a
* co
mponent
, whether that be to some other device, or a loop-back connection to
* the co
mponent
itself.
*/
void
snd_soc_dapm_auto_nc_
codec_pins
(
struct
snd_soc_codec
*
codec
)
void
snd_soc_dapm_auto_nc_
pins
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
dapm
;
struct
snd_soc_dapm_widget
*
w
;
dev_dbg
(
codec
->
dev
,
"ASoC: Auto NC: DAPMs: card:%p codec:%p
\n
"
,
&
card
->
dapm
,
&
codec
->
dapm
);
dev_dbg
(
card
->
dev
,
"ASoC: Auto NC: DAPMs: card:%p
\n
"
,
&
card
->
dapm
);
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
if
(
w
->
dapm
!=
dapm
)
continue
;
switch
(
w
->
id
)
{
case
snd_soc_dapm_input
:
case
snd_soc_dapm_output
:
case
snd_soc_dapm_micbias
:
dev_dbg
(
c
odec
->
dev
,
"ASoC: Auto NC: Checking widget %s
\n
"
,
dev_dbg
(
c
ard
->
dev
,
"ASoC: Auto NC: Checking widget %s
\n
"
,
w
->
name
);
if
(
!
snd_soc_dapm_widget_in_card_paths
(
card
,
w
))
{
dev_dbg
(
c
odec
->
dev
,
dev_dbg
(
c
ard
->
dev
,
"... Not in map; disabling
\n
"
);
snd_soc_dapm_nc_pin
(
dapm
,
w
->
name
);
snd_soc_dapm_nc_pin
(
w
->
dapm
,
w
->
name
);
}
break
;
default:
...
...
sound/soc/soc-jack.c
View file @
a1cb98ac
...
...
@@ -43,7 +43,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
INIT_LIST_HEAD
(
&
jack
->
jack_zones
);
BLOCKING_INIT_NOTIFIER_HEAD
(
&
jack
->
notifier
);
return
snd_jack_new
(
codec
->
card
->
snd_card
,
id
,
type
,
&
jack
->
jack
);
return
snd_jack_new
(
codec
->
c
omponent
.
c
ard
->
snd_card
,
id
,
type
,
&
jack
->
jack
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_jack_new
);
...
...
@@ -260,7 +260,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
static
irqreturn_t
gpio_handler
(
int
irq
,
void
*
data
)
{
struct
snd_soc_jack_gpio
*
gpio
=
data
;
struct
device
*
dev
=
gpio
->
jack
->
codec
->
card
->
dev
;
struct
device
*
dev
=
gpio
->
jack
->
codec
->
c
omponent
.
c
ard
->
dev
;
trace_snd_soc_jack_irq
(
gpio
->
name
);
...
...
sound/soc/soc-pcm.c
View file @
a1cb98ac
...
...
@@ -47,22 +47,26 @@
void
snd_soc_runtime_activate
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
stream
)
{
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_da
i
;
int
i
;
lockdep_assert_held
(
&
rtd
->
pcm_mutex
);
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
cpu_dai
->
playback_active
++
;
codec_dai
->
playback_active
++
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
rtd
->
codec_dais
[
i
]
->
playback_active
++
;
}
else
{
cpu_dai
->
capture_active
++
;
codec_dai
->
capture_active
++
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
rtd
->
codec_dais
[
i
]
->
capture_active
++
;
}
cpu_dai
->
active
++
;
codec_dai
->
active
++
;
cpu_dai
->
component
->
active
++
;
codec_dai
->
component
->
active
++
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
rtd
->
codec_dais
[
i
]
->
active
++
;
rtd
->
codec_dais
[
i
]
->
component
->
active
++
;
}
}
/**
...
...
@@ -78,22 +82,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
void
snd_soc_runtime_deactivate
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
stream
)
{
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_da
i
;
int
i
;
lockdep_assert_held
(
&
rtd
->
pcm_mutex
);
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
cpu_dai
->
playback_active
--
;
codec_dai
->
playback_active
--
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
rtd
->
codec_dais
[
i
]
->
playback_active
--
;
}
else
{
cpu_dai
->
capture_active
--
;
codec_dai
->
capture_active
--
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
rtd
->
codec_dais
[
i
]
->
capture_active
--
;
}
cpu_dai
->
active
--
;
codec_dai
->
active
--
;
cpu_dai
->
component
->
active
--
;
codec_dai
->
component
->
active
--
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
rtd
->
codec_dais
[
i
]
->
component
->
active
--
;
rtd
->
codec_dais
[
i
]
->
active
--
;
}
}
/**
...
...
@@ -107,11 +115,16 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
*/
bool
snd_soc_runtime_ignore_pmdown_time
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
int
i
;
bool
ignore
=
true
;
if
(
!
rtd
->
pmdown_time
||
rtd
->
dai_link
->
ignore_pmdown_time
)
return
true
;
return
rtd
->
cpu_dai
->
component
->
ignore_pmdown_time
&&
rtd
->
codec_dai
->
component
->
ignore_pmdown_time
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
ignore
&=
rtd
->
codec_dais
[
i
]
->
component
->
ignore_pmdown_time
;
return
rtd
->
cpu_dai
->
component
->
ignore_pmdown_time
&&
ignore
;
}
/**
...
...
@@ -222,8 +235,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
unsigned
int
rate
,
channels
,
sample_bits
,
symmetry
;
unsigned
int
rate
,
channels
,
sample_bits
,
symmetry
,
i
;
rate
=
params_rate
(
params
);
channels
=
params_channels
(
params
);
...
...
@@ -231,8 +243,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
/* reject unmatched parameters when applying symmetry */
symmetry
=
cpu_dai
->
driver
->
symmetric_rates
||
codec_dai
->
driver
->
symmetric_rates
||
rtd
->
dai_link
->
symmetric_rates
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
symmetry
|=
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_rates
;
if
(
symmetry
&&
cpu_dai
->
rate
&&
cpu_dai
->
rate
!=
rate
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched rate symmetry: %d - %d
\n
"
,
cpu_dai
->
rate
,
rate
);
...
...
@@ -240,8 +255,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
}
symmetry
=
cpu_dai
->
driver
->
symmetric_channels
||
codec_dai
->
driver
->
symmetric_channels
||
rtd
->
dai_link
->
symmetric_channels
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
symmetry
|=
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_channels
;
if
(
symmetry
&&
cpu_dai
->
channels
&&
cpu_dai
->
channels
!=
channels
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched channel symmetry: %d - %d
\n
"
,
cpu_dai
->
channels
,
channels
);
...
...
@@ -249,8 +267,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
}
symmetry
=
cpu_dai
->
driver
->
symmetric_samplebits
||
codec_dai
->
driver
->
symmetric_samplebits
||
rtd
->
dai_link
->
symmetric_samplebits
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
symmetry
|=
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_samplebits
;
if
(
symmetry
&&
cpu_dai
->
sample_bits
&&
cpu_dai
->
sample_bits
!=
sample_bits
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched sample bits symmetry: %d - %d
\n
"
,
cpu_dai
->
sample_bits
,
sample_bits
);
...
...
@@ -264,15 +285,20 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai_driver
*
cpu_driver
=
rtd
->
cpu_dai
->
driver
;
struct
snd_soc_dai_driver
*
codec_driver
=
rtd
->
codec_dai
->
driver
;
struct
snd_soc_dai_link
*
link
=
rtd
->
dai_link
;
unsigned
int
symmetry
,
i
;
return
cpu_driver
->
symmetric_rates
||
codec_driver
->
symmetric_rates
||
link
->
symmetric_rates
||
cpu_driver
->
symmetric_channels
||
codec_driver
->
symmetric_channels
||
link
->
symmetric_channels
||
cpu_driver
->
symmetric_samplebits
||
codec_driver
->
symmetric_samplebits
||
link
->
symmetric_samplebits
;
symmetry
=
cpu_driver
->
symmetric_rates
||
link
->
symmetric_rates
||
cpu_driver
->
symmetric_channels
||
link
->
symmetric_channels
||
cpu_driver
->
symmetric_samplebits
||
link
->
symmetric_samplebits
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
symmetry
=
symmetry
||
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_rates
||
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_channels
||
rtd
->
codec_dais
[
i
]
->
driver
->
symmetric_samplebits
;
return
symmetry
;
}
/*
...
...
@@ -284,15 +310,10 @@ static int sample_sizes[] = {
24
,
32
,
};
static
void
soc_pcm_apply_msb
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
static
void
soc_pcm_set_msb
(
struct
snd_pcm_substream
*
substream
,
int
bits
)
{
int
ret
,
i
,
bits
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
bits
=
dai
->
driver
->
playback
.
sig_bits
;
else
bits
=
dai
->
driver
->
capture
.
sig_bits
;
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
int
ret
,
i
;
if
(
!
bits
)
return
;
...
...
@@ -304,38 +325,105 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
ret
=
snd_pcm_hw_constraint_msbits
(
substream
->
runtime
,
0
,
sample_sizes
[
i
],
bits
);
if
(
ret
!=
0
)
dev_warn
(
dai
->
dev
,
dev_warn
(
rtd
->
dev
,
"ASoC: Failed to set MSB %d/%d: %d
\n
"
,
bits
,
sample_sizes
[
i
],
ret
);
}
}
static
void
soc_pcm_init_runtime_hw
(
struct
snd_pcm_runtime
*
runtime
,
struct
snd_soc_pcm_stream
*
codec_stream
,
struct
snd_soc_pcm_stream
*
cpu_stream
)
static
void
soc_pcm_apply_msb
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
;
int
i
;
unsigned
int
bits
=
0
,
cpu_bits
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
playback
.
sig_bits
==
0
)
{
bits
=
0
;
break
;
}
bits
=
max
(
codec_dai
->
driver
->
playback
.
sig_bits
,
bits
);
}
cpu_bits
=
cpu_dai
->
driver
->
playback
.
sig_bits
;
}
else
{
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
playback
.
sig_bits
==
0
)
{
bits
=
0
;
break
;
}
bits
=
max
(
codec_dai
->
driver
->
capture
.
sig_bits
,
bits
);
}
cpu_bits
=
cpu_dai
->
driver
->
capture
.
sig_bits
;
}
soc_pcm_set_msb
(
substream
,
bits
);
soc_pcm_set_msb
(
substream
,
cpu_bits
);
}
static
void
soc_pcm_init_runtime_hw
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_pcm_hardware
*
hw
=
&
runtime
->
hw
;
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai_driver
*
cpu_dai_drv
=
rtd
->
cpu_dai
->
driver
;
struct
snd_soc_dai_driver
*
codec_dai_drv
;
struct
snd_soc_pcm_stream
*
codec_stream
;
struct
snd_soc_pcm_stream
*
cpu_stream
;
unsigned
int
chan_min
=
0
,
chan_max
=
UINT_MAX
;
unsigned
int
rate_min
=
0
,
rate_max
=
UINT_MAX
;
unsigned
int
rates
=
UINT_MAX
;
u64
formats
=
ULLONG_MAX
;
int
i
;
hw
->
channels_min
=
max
(
codec_stream
->
channels_min
,
cpu_stream
->
channels_min
);
hw
->
channels_max
=
min
(
codec_stream
->
channels_max
,
cpu_stream
->
channels_max
);
if
(
hw
->
formats
)
hw
->
formats
&=
codec_stream
->
formats
&
cpu_stream
->
formats
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
cpu_stream
=
&
cpu_dai_drv
->
playback
;
else
hw
->
formats
=
codec_stream
->
formats
&
cpu_stream
->
formats
;
hw
->
rates
=
snd_pcm_rate_mask_intersect
(
codec_stream
->
rates
,
cpu_stream
->
rates
);
cpu_stream
=
&
cpu_dai_drv
->
capture
;
hw
->
rate_min
=
0
;
hw
->
rate_max
=
UINT_MAX
;
/* first calculate min/max only for CODECs in the DAI link */
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai_drv
=
rtd
->
codec_dais
[
i
]
->
driver
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
codec_stream
=
&
codec_dai_drv
->
playback
;
else
codec_stream
=
&
codec_dai_drv
->
capture
;
chan_min
=
max
(
chan_min
,
codec_stream
->
channels_min
);
chan_max
=
min
(
chan_max
,
codec_stream
->
channels_max
);
rate_min
=
max
(
rate_min
,
codec_stream
->
rate_min
);
rate_max
=
min_not_zero
(
rate_max
,
codec_stream
->
rate_max
);
formats
&=
codec_stream
->
formats
;
rates
=
snd_pcm_rate_mask_intersect
(
codec_stream
->
rates
,
rates
);
}
/*
* chan min/max cannot be enforced if there are multiple CODEC DAIs
* connected to a single CPU DAI, use CPU DAI's directly and let
* channel allocation be fixed up later
*/
if
(
rtd
->
num_codecs
>
1
)
{
chan_min
=
cpu_stream
->
channels_min
;
chan_max
=
cpu_stream
->
channels_max
;
}
hw
->
channels_min
=
max
(
chan_min
,
cpu_stream
->
channels_min
);
hw
->
channels_max
=
min
(
chan_max
,
cpu_stream
->
channels_max
);
if
(
hw
->
formats
)
hw
->
formats
&=
formats
&
cpu_stream
->
formats
;
else
hw
->
formats
=
formats
&
cpu_stream
->
formats
;
hw
->
rates
=
snd_pcm_rate_mask_intersect
(
rates
,
cpu_stream
->
rates
);
snd_pcm_limit_hw_rates
(
runtime
);
hw
->
rate_min
=
max
(
hw
->
rate_min
,
cpu_stream
->
rate_min
);
hw
->
rate_min
=
max
(
hw
->
rate_min
,
codec_stream
->
rate_min
);
hw
->
rate_min
=
max
(
hw
->
rate_min
,
rate_min
);
hw
->
rate_max
=
min_not_zero
(
hw
->
rate_max
,
cpu_stream
->
rate_max
);
hw
->
rate_max
=
min_not_zero
(
hw
->
rate_max
,
codec_stream
->
rate_max
);
hw
->
rate_max
=
min_not_zero
(
hw
->
rate_max
,
rate_max
);
}
/*
...
...
@@ -349,15 +437,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai_driver
*
cpu_dai_drv
=
cpu_dai
->
driver
;
struct
snd_soc_dai_driver
*
codec_dai_drv
=
codec_dai
->
driver
;
int
ret
=
0
;
struct
snd_soc_dai
*
codec_dai
;
const
char
*
codec_dai_name
=
"multicodec"
;
int
i
,
ret
=
0
;
pinctrl_pm_select_default_state
(
cpu_dai
->
dev
);
pinctrl_pm_select_default_state
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
pinctrl_pm_select_default_state
(
rtd
->
codec_dais
[
i
]
->
dev
);
pm_runtime_get_sync
(
cpu_dai
->
dev
);
pm_runtime_get_sync
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
pm_runtime_get_sync
(
rtd
->
codec_dais
[
i
]
->
dev
);
pm_runtime_get_sync
(
platform
->
dev
);
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -376,20 +465,30 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
ret
=
platform
->
driver
->
ops
->
open
(
substream
);
if
(
ret
<
0
)
{
dev_err
(
platform
->
dev
,
"ASoC: can't open platform"
" %s: %d
\n
"
,
platform
->
name
,
ret
);
" %s: %d
\n
"
,
platform
->
component
.
name
,
ret
);
goto
platform_err
;
}
}
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
startup
)
{
ret
=
codec_dai
->
driver
->
ops
->
startup
(
substream
,
codec_dai
);
ret
=
codec_dai
->
driver
->
ops
->
startup
(
substream
,
codec_dai
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"ASoC: can't open codec"
" %s: %d
\n
"
,
codec_dai
->
name
,
ret
);
dev_err
(
codec_dai
->
dev
,
"ASoC: can't open codec %s: %d
\n
"
,
codec_dai
->
name
,
ret
);
goto
codec_dai_err
;
}
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
codec_dai
->
tx_mask
=
0
;
else
codec_dai
->
rx_mask
=
0
;
}
if
(
rtd
->
dai_link
->
ops
&&
rtd
->
dai_link
->
ops
->
startup
)
{
ret
=
rtd
->
dai_link
->
ops
->
startup
(
substream
);
if
(
ret
<
0
)
{
...
...
@@ -404,13 +503,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto
dynamic
;
/* Check that the codec and cpu DAIs are compatible */
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
soc_pcm_init_runtime_hw
(
runtime
,
&
codec_dai_drv
->
playback
,
&
cpu_dai_drv
->
playback
);
}
else
{
soc_pcm_init_runtime_hw
(
runtime
,
&
codec_dai_drv
->
capture
,
&
cpu_dai_drv
->
capture
);
}
soc_pcm_init_runtime_hw
(
substream
);
if
(
rtd
->
num_codecs
==
1
)
codec_dai_name
=
rtd
->
codec_dai
->
name
;
if
(
soc_pcm_has_symmetry
(
substream
))
runtime
->
hw
.
info
|=
SNDRV_PCM_INFO_JOINT_DUPLEX
;
...
...
@@ -418,23 +514,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
ret
=
-
EINVAL
;
if
(
!
runtime
->
hw
.
rates
)
{
printk
(
KERN_ERR
"ASoC: %s <-> %s No matching rates
\n
"
,
codec_dai
->
name
,
cpu_dai
->
name
);
codec_dai
_
name
,
cpu_dai
->
name
);
goto
config_err
;
}
if
(
!
runtime
->
hw
.
formats
)
{
printk
(
KERN_ERR
"ASoC: %s <-> %s No matching formats
\n
"
,
codec_dai
->
name
,
cpu_dai
->
name
);
codec_dai
_
name
,
cpu_dai
->
name
);
goto
config_err
;
}
if
(
!
runtime
->
hw
.
channels_min
||
!
runtime
->
hw
.
channels_max
||
runtime
->
hw
.
channels_min
>
runtime
->
hw
.
channels_max
)
{
printk
(
KERN_ERR
"ASoC: %s <-> %s No matching channels
\n
"
,
codec_dai
->
name
,
cpu_dai
->
name
);
codec_dai
_
name
,
cpu_dai
->
name
);
goto
config_err
;
}
soc_pcm_apply_msb
(
substream
,
codec_dai
);
soc_pcm_apply_msb
(
substream
,
cpu_dai
);
soc_pcm_apply_msb
(
substream
);
/* Symmetry only applies if we've already got an active stream. */
if
(
cpu_dai
->
active
)
{
...
...
@@ -443,14 +538,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto
config_err
;
}
if
(
codec_dai
->
active
)
{
ret
=
soc_pcm_apply_symmetry
(
substream
,
codec_dai
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
(
rtd
->
codec_dais
[
i
]
->
active
)
{
ret
=
soc_pcm_apply_symmetry
(
substream
,
rtd
->
codec_dais
[
i
]);
if
(
ret
!=
0
)
goto
config_err
;
}
}
pr_debug
(
"ASoC: %s <-> %s info:
\n
"
,
codec_dai
->
name
,
cpu_dai
->
name
);
codec_dai
_
name
,
cpu_dai
->
name
);
pr_debug
(
"ASoC: rate mask 0x%x
\n
"
,
runtime
->
hw
.
rates
);
pr_debug
(
"ASoC: min ch %d max ch %d
\n
"
,
runtime
->
hw
.
channels_min
,
runtime
->
hw
.
channels_max
);
...
...
@@ -469,10 +567,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
rtd
->
dai_link
->
ops
->
shutdown
(
substream
);
machine_err:
i
=
rtd
->
num_codecs
;
codec_dai_err:
while
(
--
i
>=
0
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
->
shutdown
)
codec_dai
->
driver
->
ops
->
shutdown
(
substream
,
codec_dai
);
}
codec_dai_err:
if
(
platform
->
driver
->
ops
&&
platform
->
driver
->
ops
->
close
)
platform
->
driver
->
ops
->
close
(
substream
);
...
...
@@ -483,10 +586,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock
(
&
rtd
->
pcm_mutex
);
pm_runtime_put
(
platform
->
dev
);
pm_runtime_put
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
pm_runtime_put
(
rtd
->
codec_dais
[
i
]
->
dev
);
pm_runtime_put
(
cpu_dai
->
dev
);
if
(
!
codec_dai
->
active
)
pinctrl_pm_select_sleep_state
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
(
!
rtd
->
codec_dais
[
i
]
->
active
)
pinctrl_pm_select_sleep_state
(
rtd
->
codec_dais
[
i
]
->
dev
);
}
if
(
!
cpu_dai
->
active
)
pinctrl_pm_select_sleep_state
(
cpu_dai
->
dev
);
...
...
@@ -502,7 +608,7 @@ static void close_delayed_work(struct work_struct *work)
{
struct
snd_soc_pcm_runtime
*
rtd
=
container_of
(
work
,
struct
snd_soc_pcm_runtime
,
delayed_work
.
work
);
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
s
[
0
]
;
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -531,7 +637,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
codec_dai
;
int
i
;
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -541,14 +648,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
if
(
!
cpu_dai
->
active
)
cpu_dai
->
rate
=
0
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
!
codec_dai
->
active
)
codec_dai
->
rate
=
0
;
}
if
(
cpu_dai
->
driver
->
ops
->
shutdown
)
cpu_dai
->
driver
->
ops
->
shutdown
(
substream
,
cpu_dai
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
->
shutdown
)
codec_dai
->
driver
->
ops
->
shutdown
(
substream
,
codec_dai
);
}
if
(
rtd
->
dai_link
->
ops
&&
rtd
->
dai_link
->
ops
->
shutdown
)
rtd
->
dai_link
->
ops
->
shutdown
(
substream
);
...
...
@@ -578,10 +691,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
mutex_unlock
(
&
rtd
->
pcm_mutex
);
pm_runtime_put
(
platform
->
dev
);
pm_runtime_put
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
pm_runtime_put
(
rtd
->
codec_dais
[
i
]
->
dev
);
pm_runtime_put
(
cpu_dai
->
dev
);
if
(
!
codec_dai
->
active
)
pinctrl_pm_select_sleep_state
(
codec_dai
->
dev
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
(
!
rtd
->
codec_dais
[
i
]
->
active
)
pinctrl_pm_select_sleep_state
(
rtd
->
codec_dais
[
i
]
->
dev
);
}
if
(
!
cpu_dai
->
active
)
pinctrl_pm_select_sleep_state
(
cpu_dai
->
dev
);
...
...
@@ -598,8 +714,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
=
0
;
struct
snd_soc_dai
*
codec_dai
;
int
i
,
ret
=
0
;
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -621,14 +737,18 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
}
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
prepare
)
{
ret
=
codec_dai
->
driver
->
ops
->
prepare
(
substream
,
codec_dai
);
ret
=
codec_dai
->
driver
->
ops
->
prepare
(
substream
,
codec_dai
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"ASoC: DAI prepare error: %d
\n
"
,
ret
);
dev_err
(
codec_dai
->
dev
,
"ASoC: DAI prepare error: %d
\n
"
,
ret
);
goto
out
;
}
}
}
if
(
cpu_dai
->
driver
->
ops
&&
cpu_dai
->
driver
->
ops
->
prepare
)
{
ret
=
cpu_dai
->
driver
->
ops
->
prepare
(
substream
,
cpu_dai
);
...
...
@@ -649,13 +769,44 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
snd_soc_dapm_stream_event
(
rtd
,
substream
->
stream
,
SND_SOC_DAPM_STREAM_START
);
snd_soc_dai_digital_mute
(
codec_dai
,
0
,
substream
->
stream
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
snd_soc_dai_digital_mute
(
rtd
->
codec_dais
[
i
],
0
,
substream
->
stream
);
out:
mutex_unlock
(
&
rtd
->
pcm_mutex
);
return
ret
;
}
static
void
soc_pcm_codec_params_fixup
(
struct
snd_pcm_hw_params
*
params
,
unsigned
int
mask
)
{
struct
snd_interval
*
interval
;
int
channels
=
hweight_long
(
mask
);
interval
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
interval
->
min
=
channels
;
interval
->
max
=
channels
;
}
int
soc_dai_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
int
ret
;
if
(
dai
->
driver
->
ops
&&
dai
->
driver
->
ops
->
hw_params
)
{
ret
=
dai
->
driver
->
ops
->
hw_params
(
substream
,
params
,
dai
);
if
(
ret
<
0
)
{
dev_err
(
dai
->
dev
,
"ASoC: can't set %s hw params: %d
\n
"
,
dai
->
name
,
ret
);
return
ret
;
}
}
return
0
;
}
/*
* Called by ALSA when the hardware params are set by application. This
* function can also be called multiple times and can allocate buffers
...
...
@@ -667,8 +818,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
=
0
;
int
i
,
ret
=
0
;
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -685,29 +835,40 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
hw_params
)
{
ret
=
codec_dai
->
driver
->
ops
->
hw_params
(
substream
,
params
,
codec_dai
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"ASoC: can't set %s hw params:"
" %d
\n
"
,
codec_dai
->
name
,
ret
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
i
];
struct
snd_pcm_hw_params
codec_params
;
/* copy params for each codec */
codec_params
=
*
params
;
/* fixup params based on TDM slot masks */
if
(
codec_dai
->
tx_mask
)
soc_pcm_codec_params_fixup
(
&
codec_params
,
codec_dai
->
tx_mask
);
if
(
codec_dai
->
rx_mask
)
soc_pcm_codec_params_fixup
(
&
codec_params
,
codec_dai
->
rx_mask
);
ret
=
soc_dai_hw_params
(
substream
,
&
codec_params
,
codec_dai
);
if
(
ret
<
0
)
goto
codec_err
;
}
codec_dai
->
rate
=
params_rate
(
&
codec_params
);
codec_dai
->
channels
=
params_channels
(
&
codec_params
);
codec_dai
->
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
&
codec_params
));
}
if
(
cpu_dai
->
driver
->
ops
&&
cpu_dai
->
driver
->
ops
->
hw_params
)
{
ret
=
cpu_dai
->
driver
->
ops
->
hw_params
(
substream
,
params
,
cpu_dai
);
if
(
ret
<
0
)
{
dev_err
(
cpu_dai
->
dev
,
"ASoC: %s hw params failed: %d
\n
"
,
cpu_dai
->
name
,
ret
);
ret
=
soc_dai_hw_params
(
substream
,
params
,
cpu_dai
);
if
(
ret
<
0
)
goto
interface_err
;
}
}
if
(
platform
->
driver
->
ops
&&
platform
->
driver
->
ops
->
hw_params
)
{
ret
=
platform
->
driver
->
ops
->
hw_params
(
substream
,
params
);
if
(
ret
<
0
)
{
dev_err
(
platform
->
dev
,
"ASoC: %s hw params failed: %d
\n
"
,
platform
->
name
,
ret
);
platform
->
component
.
name
,
ret
);
goto
platform_err
;
}
}
...
...
@@ -718,11 +879,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
cpu_dai
->
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
params
));
codec_dai
->
rate
=
params_rate
(
params
);
codec_dai
->
channels
=
params_channels
(
params
);
codec_dai
->
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
params
));
out:
mutex_unlock
(
&
rtd
->
pcm_mutex
);
return
ret
;
...
...
@@ -732,10 +888,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
cpu_dai
->
driver
->
ops
->
hw_free
(
substream
,
cpu_dai
);
interface_err:
i
=
rtd
->
num_codecs
;
codec_err:
while
(
--
i
>=
0
)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
hw_free
)
codec_dai
->
driver
->
ops
->
hw_free
(
substream
,
codec_dai
);
codec_dai
->
rate
=
0
;
}
codec_err:
if
(
rtd
->
dai_link
->
ops
&&
rtd
->
dai_link
->
ops
->
hw_free
)
rtd
->
dai_link
->
ops
->
hw_free
(
substream
);
...
...
@@ -751,8 +913,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
codec_dai
;
bool
playback
=
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
;
int
i
;
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
...
...
@@ -763,16 +926,22 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
cpu_dai
->
sample_bits
=
0
;
}
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
active
==
1
)
{
codec_dai
->
rate
=
0
;
codec_dai
->
channels
=
0
;
codec_dai
->
sample_bits
=
0
;
}
}
/* apply codec digital mute */
if
((
playback
&&
codec_dai
->
playback_active
==
1
)
||
(
!
playback
&&
codec_dai
->
capture_active
==
1
))
snd_soc_dai_digital_mute
(
codec_dai
,
1
,
substream
->
stream
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
if
((
playback
&&
rtd
->
codec_dais
[
i
]
->
playback_active
==
1
)
||
(
!
playback
&&
rtd
->
codec_dais
[
i
]
->
capture_active
==
1
))
snd_soc_dai_digital_mute
(
rtd
->
codec_dais
[
i
],
1
,
substream
->
stream
);
}
/* free any machine hw params */
if
(
rtd
->
dai_link
->
ops
&&
rtd
->
dai_link
->
ops
->
hw_free
)
...
...
@@ -783,8 +952,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
platform
->
driver
->
ops
->
hw_free
(
substream
);
/* now free hw params for the DAIs */
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
hw_free
)
codec_dai
->
driver
->
ops
->
hw_free
(
substream
,
codec_dai
);
}
if
(
cpu_dai
->
driver
->
ops
&&
cpu_dai
->
driver
->
ops
->
hw_free
)
cpu_dai
->
driver
->
ops
->
hw_free
(
substream
,
cpu_dai
);
...
...
@@ -798,14 +970,18 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
;
struct
snd_soc_dai
*
codec_dai
;
int
i
,
ret
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
trigger
)
{
ret
=
codec_dai
->
driver
->
ops
->
trigger
(
substream
,
cmd
,
codec_dai
);
ret
=
codec_dai
->
driver
->
ops
->
trigger
(
substream
,
cmd
,
codec_dai
);
if
(
ret
<
0
)
return
ret
;
}
}
if
(
platform
->
driver
->
ops
&&
platform
->
driver
->
ops
->
trigger
)
{
ret
=
platform
->
driver
->
ops
->
trigger
(
substream
,
cmd
);
...
...
@@ -834,15 +1010,19 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
;
struct
snd_soc_dai
*
codec_dai
;
int
i
,
ret
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
bespoke_trigger
)
{
ret
=
codec_dai
->
driver
->
ops
->
bespoke_trigger
(
substream
,
cmd
,
codec_dai
);
ret
=
codec_dai
->
driver
->
ops
->
bespoke_trigger
(
substream
,
cmd
,
codec_dai
);
if
(
ret
<
0
)
return
ret
;
}
}
if
(
platform
->
driver
->
bespoke_trigger
)
{
ret
=
platform
->
driver
->
bespoke_trigger
(
substream
,
cmd
);
...
...
@@ -867,10 +1047,12 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
codec_dai
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
snd_pcm_uframes_t
offset
=
0
;
snd_pcm_sframes_t
delay
=
0
;
snd_pcm_sframes_t
codec_delay
=
0
;
int
i
;
if
(
platform
->
driver
->
ops
&&
platform
->
driver
->
ops
->
pointer
)
offset
=
platform
->
driver
->
ops
->
pointer
(
substream
);
...
...
@@ -878,11 +1060,21 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
if
(
cpu_dai
->
driver
->
ops
&&
cpu_dai
->
driver
->
ops
->
delay
)
delay
+=
cpu_dai
->
driver
->
ops
->
delay
(
substream
,
cpu_dai
);
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
delay
)
delay
+=
codec_dai
->
driver
->
ops
->
delay
(
substream
,
codec_dai
);
codec_delay
=
max
(
codec_delay
,
codec_dai
->
driver
->
ops
->
delay
(
substream
,
codec_dai
));
}
delay
+=
codec_delay
;
/*
* None of the existing platform drivers implement delay(), so
* for now the codec_dai of first multicodec entry is used
*/
if
(
platform
->
driver
->
delay
)
delay
+=
platform
->
driver
->
delay
(
substream
,
codec_dai
);
delay
+=
platform
->
driver
->
delay
(
substream
,
rtd
->
codec_dais
[
0
]
);
runtime
->
delay
=
delay
;
...
...
@@ -985,7 +1177,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
struct
snd_soc_dapm_widget
*
widget
,
int
stream
)
{
struct
snd_soc_pcm_runtime
*
be
;
int
i
;
int
i
,
j
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
{
...
...
@@ -994,10 +1186,15 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
if
(
!
be
->
dai_link
->
no_pcm
)
continue
;
if
(
be
->
cpu_dai
->
playback_widget
==
widget
||
be
->
codec_dai
->
playback_widget
==
widget
)
if
(
be
->
cpu_dai
->
playback_widget
==
widget
)
return
be
;
for
(
j
=
0
;
j
<
be
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
dai
=
be
->
codec_dais
[
j
];
if
(
dai
->
playback_widget
==
widget
)
return
be
;
}
}
}
else
{
for
(
i
=
0
;
i
<
card
->
num_links
;
i
++
)
{
...
...
@@ -1006,11 +1203,16 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
if
(
!
be
->
dai_link
->
no_pcm
)
continue
;
if
(
be
->
cpu_dai
->
capture_widget
==
widget
||
be
->
codec_dai
->
capture_widget
==
widget
)
if
(
be
->
cpu_dai
->
capture_widget
==
widget
)
return
be
;
for
(
j
=
0
;
j
<
be
->
num_codecs
;
j
++
)
{
struct
snd_soc_dai
*
dai
=
be
->
codec_dais
[
j
];
if
(
dai
->
capture_widget
==
widget
)
return
be
;
}
}
}
dev_err
(
card
->
dev
,
"ASoC: can't get %s BE for %s
\n
"
,
stream
?
"capture"
:
"playback"
,
widget
->
name
);
...
...
@@ -1071,6 +1273,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* Destroy any old FE <--> BE connections */
list_for_each_entry
(
dpcm
,
&
fe
->
dpcm
[
stream
].
be_clients
,
list_be
)
{
unsigned
int
i
;
/* is there a valid CPU DAI widget for this BE */
widget
=
dai_get_widget
(
dpcm
->
be
->
cpu_dai
,
stream
);
...
...
@@ -1080,11 +1283,14 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
continue
;
/* is there a valid CODEC DAI widget for this BE */
widget
=
dai_get_widget
(
dpcm
->
be
->
codec_dai
,
stream
);
for
(
i
=
0
;
i
<
dpcm
->
be
->
num_codecs
;
i
++
)
{
struct
snd_soc_dai
*
dai
=
dpcm
->
be
->
codec_dais
[
i
];
widget
=
dai_get_widget
(
dai
,
stream
);
/* prune the BE if it's no longer in our active list */
if
(
widget
&&
widget_in_list
(
list
,
widget
))
continue
;
}
dev_dbg
(
fe
->
dev
,
"ASoC: pruning %s BE %s for %s
\n
"
,
stream
?
"capture"
:
"playback"
,
...
...
@@ -2114,17 +2320,23 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
list_for_each_entry
(
dpcm
,
clients
,
list_be
)
{
struct
snd_soc_pcm_runtime
*
be
=
dpcm
->
be
;
struct
snd_soc_dai
*
dai
=
be
->
codec_dai
;
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
int
i
;
if
(
be
->
dai_link
->
ignore_suspend
)
continue
;
dev_dbg
(
be
->
dev
,
"ASoC: BE digital mute %s
\n
"
,
be
->
dai_link
->
name
);
for
(
i
=
0
;
i
<
be
->
num_codecs
;
i
++
)
{
struct
snd_soc_dai
*
dai
=
be
->
codec_dais
[
i
];
struct
snd_soc_dai_driver
*
drv
=
dai
->
driver
;
dev_dbg
(
be
->
dev
,
"ASoC: BE digital mute %s
\n
"
,
be
->
dai_link
->
name
);
if
(
drv
->
ops
&&
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
if
(
drv
->
ops
&&
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
mute
);
}
}
return
0
;
}
...
...
@@ -2188,24 +2400,29 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
int
soc_new_pcm
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
num
)
{
struct
snd_soc_platform
*
platform
=
rtd
->
platform
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_dai
*
codec_dai
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_pcm
*
pcm
;
char
new_name
[
64
];
int
ret
=
0
,
playback
=
0
,
capture
=
0
;
int
i
;
if
(
rtd
->
dai_link
->
dynamic
||
rtd
->
dai_link
->
no_pcm
)
{
playback
=
rtd
->
dai_link
->
dpcm_playback
;
capture
=
rtd
->
dai_link
->
dpcm_capture
;
}
else
{
if
(
codec_dai
->
driver
->
playback
.
channels_min
&&
cpu_dai
->
driver
->
playback
.
channels_min
)
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
{
codec_dai
=
rtd
->
codec_dais
[
i
];
if
(
codec_dai
->
driver
->
playback
.
channels_min
)
playback
=
1
;
if
(
codec_dai
->
driver
->
capture
.
channels_min
&&
cpu_dai
->
driver
->
capture
.
channels_min
)
if
(
codec_dai
->
driver
->
capture
.
channels_min
)
capture
=
1
;
}
capture
=
capture
&&
cpu_dai
->
driver
->
capture
.
channels_min
;
playback
=
playback
&&
cpu_dai
->
driver
->
playback
.
channels_min
;
}
if
(
rtd
->
dai_link
->
playback_only
)
{
playback
=
1
;
capture
=
0
;
...
...
@@ -2229,7 +2446,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd
->
dai_link
->
stream_name
);
else
snprintf
(
new_name
,
sizeof
(
new_name
),
"%s %s-%d"
,
rtd
->
dai_link
->
stream_name
,
codec_dai
->
name
,
num
);
rtd
->
dai_link
->
stream_name
,
(
rtd
->
num_codecs
>
1
)
?
"multicodec"
:
rtd
->
codec_dai
->
name
,
num
);
ret
=
snd_pcm_new
(
rtd
->
card
->
snd_card
,
new_name
,
num
,
playback
,
capture
,
&
pcm
);
...
...
@@ -2302,7 +2521,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
pcm
->
private_free
=
platform
->
driver
->
pcm_free
;
out:
dev_info
(
rtd
->
card
->
dev
,
"%s <-> %s mapping ok
\n
"
,
codec_dai
->
name
,
dev_info
(
rtd
->
card
->
dev
,
"%s <-> %s mapping ok
\n
"
,
(
rtd
->
num_codecs
>
1
)
?
"multicodec"
:
rtd
->
codec_dai
->
name
,
cpu_dai
->
name
);
return
ret
;
}
...
...
sound/soc/tegra/tegra_alc5632.c
View file @
a1cb98ac
...
...
@@ -41,8 +41,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_alc5632
*
alc5632
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
@@ -105,7 +104,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
dapm
;
struct
tegra_alc5632
*
machine
=
snd_soc_card_get_drvdata
(
codec
->
card
);
struct
tegra_alc5632
*
machine
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
snd_soc_jack_new
(
codec
,
"Headset Jack"
,
SND_JACK_HEADSET
,
&
tegra_alc5632_hs_jack
);
...
...
sound/soc/tegra/tegra_max98090.c
View file @
a1cb98ac
...
...
@@ -49,8 +49,7 @@ static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_max98090
*
machine
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
@@ -127,7 +126,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
tegra_max98090
*
machine
=
snd_soc_card_get_drvdata
(
codec
->
card
);
struct
tegra_max98090
*
machine
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
if
(
gpio_is_valid
(
machine
->
gpio_hp_det
))
{
snd_soc_jack_new
(
codec
,
"Headphones"
,
SND_JACK_HEADPHONE
,
...
...
sound/soc/tegra/tegra_rt5640.c
View file @
a1cb98ac
...
...
@@ -51,8 +51,7 @@ static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_rt5640
*
machine
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
@@ -110,7 +109,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
tegra_rt5640
*
machine
=
snd_soc_card_get_drvdata
(
codec
->
card
);
struct
tegra_rt5640
*
machine
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
snd_soc_jack_new
(
codec
,
"Headphones"
,
SND_JACK_HEADPHONE
,
&
tegra_rt5640_hp_jack
);
...
...
sound/soc/tegra/tegra_wm8753.c
View file @
a1cb98ac
...
...
@@ -55,8 +55,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_wm8753
*
machine
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
sound/soc/tegra/tegra_wm8903.c
View file @
a1cb98ac
...
...
@@ -60,8 +60,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_wm8903
*
machine
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
@@ -173,7 +172,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_dapm_context
*
dapm
=
&
codec
->
dapm
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_wm8903
*
machine
=
snd_soc_card_get_drvdata
(
card
);
if
(
gpio_is_valid
(
machine
->
gpio_hp_det
))
{
...
...
sound/soc/tegra/trimslice.c
View file @
a1cb98ac
...
...
@@ -50,8 +50,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
tegra_trimslice
*
trimslice
=
snd_soc_card_get_drvdata
(
card
);
int
srate
,
mclk
;
int
err
;
...
...
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