Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
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
Hide 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,14 +597,17 @@ 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
;
if
(
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
1
);
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 */
...
...
@@ -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,14 +788,17 @@ 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
;
if
(
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
0
);
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
++
)
{
...
...
@@ -830,12 +843,19 @@ 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
);
if
(
codec_dai
->
active
)
pinctrl_pm_select_default_state
(
codec_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
...
...
@@ -867,8 +887,9 @@ 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
,
const
char
*
codec_name
)
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,24 +959,30 @@ 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
)
{
dev_err
(
card
->
dev
,
"ASoC: CODEC %s not registered
\n
"
,
dai_link
->
codec_name
);
return
-
EPROBE_DEFER
;
}
rtd
->
num_codecs
=
dai_link
->
num_codecs
;
/* Find CODEC DAI from registered list */
rtd
->
codec_dai
=
soc_find_codec_dai
(
rtd
->
codec
,
dai_link
->
codec_dai_name
);
if
(
!
rtd
->
codec_dai
)
{
dev_err
(
card
->
dev
,
"ASoC: CODEC DAI %s not registered
\n
"
,
dai_link
->
codec_dai_name
);
return
-
EPROBE_DEFER
;
/* 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
"
,
codecs
[
i
].
name
);
return
-
EPROBE_DEFER
;
}
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
"
,
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
;
if
(
!
platform_name
&&
!
dai_link
->
platform_of_node
)
...
...
@@ -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,11 +1098,8 @@ 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
);
}
}
}
...
...
@@ -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
)
static
int
soc_post_component_init
(
struct
snd_soc_pcm_runtime
*
rtd
,
const
char
*
name
)
{
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
)
{
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,12 +1374,14 @@ 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
);
if
(
ret
<
0
)
return
ret
;
/* 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 */
...
...
@@ -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
);
if
(
ret
)
return
ret
;
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
int
soc_check_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
static
void
soc_unregister_ac97_dai_link
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
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
;
if
(
aux_dev
->
codec_of_node
)
codecname
=
of_node_full_name
(
aux_dev
->
codec_of_node
);
int
i
;
dev_err
(
card
->
dev
,
"ASoC: %s not registered
\n
"
,
codecname
);
return
-
EPROBE_DEFER
;
for
(
i
=
0
;
i
<
rtd
->
num_codecs
;
i
++
)
soc_unregister_ac97_codec
(
rtd
->
codec_dais
[
i
]
->
codec
)
;
}
#endif
static
int
soc_
probe
_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
;
int
ret
=
-
ENODEV
;
struct
snd_soc_codec
*
codec
=
soc_find_matching_codec
(
card
,
num
);
if
(
!
codec
)
{
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
);
/* codec not found */
dev_err
(
card
->
dev
,
"ASoC: codec %s not found"
,
codecname
);
dev_err
(
card
->
dev
,
"ASoC: %s not registered
\n
"
,
codecname
);
return
-
EPROBE_DEFER
;
}
if
(
codec
->
probed
)
{
dev_err
(
codec
->
dev
,
"ASoC: codec already probed"
);
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
];
int
ret
;
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
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,16 +1845,23 @@ 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
);
if
(
ret
!=
0
&&
ret
!=
-
ENOTSUPP
)
dev_warn
(
card
->
rtd
[
i
].
codec_dai
->
dev
,
"ASoC: Failed to set DAI format: %d
\n
"
,
ret
);
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
(
codec_dai
->
dev
,
"ASoC: Failed to set DAI format: %d
\n
"
,
ret
);
}
}
/* If this is a regular CPU link there will be a platform */
...
...
@@ -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,22 +3781,29 @@ 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
];
/*
* 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
"
,
link
->
name
);
return
-
EINVAL
;
ret
=
snd_soc_init_multicodec
(
card
,
link
);
if
(
ret
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init multicodec
\n
"
);
return
ret
;
}
/* Codec DAI name must be specified */
if
(
!
link
->
codec_dai_name
)
{
dev_err
(
card
->
dev
,
"ASoC: codec_dai_name not set for %s
\n
"
,
link
->
name
);
return
-
EINVAL
;
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
->
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
->
codecs
[
j
].
dai_name
)
{
dev_err
(
card
->
dev
,
"ASoC: codec_dai_name not set for %s
\n
"
,
link
->
name
);
return
-
EINVAL
;
}
}
/*
...
...
@@ -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
;
if
(
!
codec_dai
->
active
)
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
;
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
;
mutex_init
(
&
cmpnt
->
io_mutex
);
return
component
->
driver
->
stream_event
(
component
,
event
);
}
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
;
codec
->
dapm
.
seq_notifier
=
codec_drv
->
seq_notifier
;
codec
->
dapm
.
stream_event
=
codec_drv
->
stream_event
;
if
(
codec_drv
->
seq_notifier
)
codec
->
dapm
.
seq_notifier
=
codec_drv
->
seq_notifier
;
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
);
goto
out
;
}
}
substream
.
stream
=
SNDRV_PCM_STREAM_CAPTURE
;
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
);
goto
out
;
}
}
substream
.
stream
=
SNDRV_PCM_STREAM_PLAYBACK
;
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
...
...
@@ -7,7 +7,7 @@
* Copyright (C) 2010 Texas Instruments Inc.
*
* Authors: Liam Girdwood <lrg@ti.com>
* Mark Brown <broonie@opensource.wolfsonmicro.com>
* Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
...
...
@@ -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,18 +465,28 @@ 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
;
}
}
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
startup
)
{
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
);
goto
codec_dai_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
);
if
(
ret
<
0
)
{
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
)
{
...
...
@@ -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
);
if
(
ret
!=
0
)
goto
config_err
;
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:
if
(
codec_dai
->
driver
->
ops
->
shutdown
)
codec_dai
->
driver
->
ops
->
shutdown
(
substream
,
codec_dai
);
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
);
}
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
;
if
(
!
codec_dai
->
active
)
codec_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
);
if
(
codec_dai
->
driver
->
ops
->
shutdown
)
codec_dai
->
driver
->
ops
->
shutdown
(
substream
,
codec_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,12 +737,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
}
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
prepare
)
{
ret
=
codec_dai
->
driver
->
ops
->
prepare
(
substream
,
codec_dai
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"ASoC: DAI prepare error: %d
\n
"
,
ret
);
goto
out
;
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
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"ASoC: DAI prepare error: %d
\n
"
,
ret
);
goto
out
;
}
}
}
...
...
@@ -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
;
}
}
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
);
goto
interface_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
));
}
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:
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
hw_free
)
codec_dai
->
driver
->
ops
->
hw_free
(
substream
,
codec_dai
);
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
;
}
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
;
}
if
(
codec_dai
->
active
==
1
)
{
codec_dai
->
rate
=
0
;
codec_dai
->
channels
=
0
;
codec_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 */
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
hw_free
)
codec_dai
->
driver
->
ops
->
hw_free
(
substream
,
codec_dai
);
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,13 +970,17 @@ 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
;
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
trigger
)
{
ret
=
codec_dai
->
driver
->
ops
->
trigger
(
substream
,
cmd
,
codec_dai
);
if
(
ret
<
0
)
return
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
);
if
(
ret
<
0
)
return
ret
;
}
}
if
(
platform
->
driver
->
ops
&&
platform
->
driver
->
ops
->
trigger
)
{
...
...
@@ -834,14 +1010,18 @@ 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
;
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
bespoke_trigger
)
{
ret
=
codec_dai
->
driver
->
ops
->
bespoke_trigger
(
substream
,
cmd
,
codec_dai
);
if
(
ret
<
0
)
return
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
);
if
(
ret
<
0
)
return
ret
;
}
}
if
(
platform
->
driver
->
bespoke_trigger
)
{
...
...
@@ -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
);
if
(
codec_dai
->
driver
->
ops
&&
codec_dai
->
driver
->
ops
->
delay
)
delay
+=
codec_dai
->
driver
->
ops
->
delay
(
substream
,
codec_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
)
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,9 +1186,14 @@ 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
{
...
...
@@ -1006,9 +1203,14 @@ 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
;
}
}
}
...
...
@@ -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
;
/* 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,16 +2320,22 @@ 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
)
drv
->
ops
->
digital_mute
(
dai
,
mute
);
if
(
drv
->
ops
&&
drv
->
ops
->
digital_mute
&&
dai
->
playback_active
)
drv
->
ops
->
digital_mute
(
dai
,
mute
);
}
}
return
0
;
...
...
@@ -2188,22 +2400,27 @@ 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
)
playback
=
1
;
if
(
codec_dai
->
driver
->
capture
.
channels_min
&&
cpu_dai
->
driver
->
capture
.
channels_min
)
capture
=
1
;
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
)
capture
=
1
;
}
capture
=
capture
&&
cpu_dai
->
driver
->
capture
.
channels_min
;
playback
=
playback
&&
cpu_dai
->
driver
->
playback
.
channels_min
;
}
if
(
rtd
->
dai_link
->
playback_only
)
{
...
...
@@ -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,8 +2521,9 @@ 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
,
cpu_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