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
a1916ff3
Commit
a1916ff3
authored
Jan 11, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/pcm-list' into asoc-next
parents
2dd49f8e
f2ed6b07
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
180 additions
and
106 deletions
+180
-106
include/sound/soc-dai.h
include/sound/soc-dai.h
+1
-0
include/sound/soc.h
include/sound/soc.h
+9
-2
sound/soc/soc-core.c
sound/soc/soc-core.c
+170
-104
No files found.
include/sound/soc-dai.h
View file @
a1916ff3
...
...
@@ -222,6 +222,7 @@ struct snd_soc_dai_driver {
const
char
*
name
;
unsigned
int
id
;
unsigned
int
base
;
struct
snd_soc_dobj
dobj
;
/* DAI driver callbacks */
int
(
*
probe
)(
struct
snd_soc_dai
*
dai
);
...
...
include/sound/soc.h
View file @
a1916ff3
...
...
@@ -798,6 +798,7 @@ struct snd_soc_component {
unsigned
int
registered_as_component
:
1
;
struct
list_head
list
;
struct
list_head
list_aux
;
/* for auxiliary component of the card */
struct
snd_soc_dai_driver
*
dai_drv
;
int
num_dai
;
...
...
@@ -841,6 +842,9 @@ struct snd_soc_component {
int
(
*
probe
)(
struct
snd_soc_component
*
);
void
(
*
remove
)(
struct
snd_soc_component
*
);
/* machine specific init */
int
(
*
init
)(
struct
snd_soc_component
*
component
);
#ifdef CONFIG_DEBUG_FS
void
(
*
init_debugfs
)(
struct
snd_soc_component
*
component
);
const
char
*
debugfs_prefix
;
...
...
@@ -1141,8 +1145,7 @@ struct snd_soc_card {
*/
struct
snd_soc_aux_dev
*
aux_dev
;
int
num_aux_devs
;
struct
snd_soc_pcm_runtime
*
rtd_aux
;
int
num_aux_rtd
;
struct
list_head
aux_comp_list
;
const
struct
snd_kcontrol_new
*
controls
;
int
num_controls
;
...
...
@@ -1550,6 +1553,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
INIT_LIST_HEAD
(
&
card
->
widgets
);
INIT_LIST_HEAD
(
&
card
->
paths
);
INIT_LIST_HEAD
(
&
card
->
dapm_list
);
INIT_LIST_HEAD
(
&
card
->
aux_comp_list
);
}
static
inline
bool
snd_soc_volsw_is_stereo
(
struct
soc_mixer_control
*
mc
)
...
...
@@ -1676,6 +1680,9 @@ int snd_soc_add_dai_link(struct snd_soc_card *card,
void
snd_soc_remove_dai_link
(
struct
snd_soc_card
*
card
,
struct
snd_soc_dai_link
*
dai_link
);
int
snd_soc_register_dai
(
struct
snd_soc_component
*
component
,
struct
snd_soc_dai_driver
*
dai_drv
);
#include <sound/soc-dai.h>
#ifdef CONFIG_DEBUG_FS
...
...
sound/soc/soc-core.c
View file @
a1916ff3
...
...
@@ -1413,6 +1413,16 @@ static int soc_probe_component(struct snd_soc_card *card,
component
->
name
);
}
/* machine specific init */
if
(
component
->
init
)
{
ret
=
component
->
init
(
component
);
if
(
ret
<
0
)
{
dev_err
(
component
->
dev
,
"Failed to do machine specific init %d
\n
"
,
ret
);
goto
err_probe
;
}
}
if
(
component
->
controls
)
snd_soc_add_component_controls
(
component
,
component
->
controls
,
component
->
num_controls
);
...
...
@@ -1657,65 +1667,81 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
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
*
name
=
aux_dev
->
codec_name
;
rtd
->
component
=
soc_find_component
(
aux_dev
->
codec_of_node
,
name
);
if
(
!
rtd
->
component
)
{
if
(
aux_dev
->
codec_of_node
)
name
=
of_node_full_name
(
aux_dev
->
codec_of_node
);
dev_err
(
card
->
dev
,
"ASoC: %s not registered
\n
"
,
name
);
return
-
EPROBE_DEFER
;
struct
snd_soc_component
*
component
;
const
char
*
name
;
struct
device_node
*
codec_of_node
;
if
(
aux_dev
->
codec_of_node
||
aux_dev
->
codec_name
)
{
/* codecs, usually analog devices */
name
=
aux_dev
->
codec_name
;
codec_of_node
=
aux_dev
->
codec_of_node
;
component
=
soc_find_component
(
codec_of_node
,
name
);
if
(
!
component
)
{
if
(
codec_of_node
)
name
=
of_node_full_name
(
codec_of_node
);
goto
err_defer
;
}
}
else
if
(
aux_dev
->
name
)
{
/* generic components */
name
=
aux_dev
->
name
;
component
=
soc_find_component
(
NULL
,
name
);
if
(
!
component
)
goto
err_defer
;
}
else
{
dev_err
(
card
->
dev
,
"ASoC: Invalid auxiliary device
\n
"
);
return
-
EINVAL
;
}
/*
* Some places still reference rtd->codec, so we have to keep that
* initialized if the component is a CODEC. Once all those references
* have been removed, this code can be removed as well.
*/
rtd
->
codec
=
rtd
->
component
->
codec
;
component
->
init
=
aux_dev
->
init
;
list_add
(
&
component
->
list_aux
,
&
card
->
aux_comp_list
);
return
0
;
err_defer:
dev_err
(
card
->
dev
,
"ASoC: %s not registered
\n
"
,
name
);
return
-
EPROBE_DEFER
;
}
static
int
soc_probe_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
static
int
soc_probe_aux_dev
ices
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_
pcm_runtime
*
rtd
=
&
card
->
rtd_aux
[
num
]
;
struct
snd_soc_aux_dev
*
aux_dev
=
&
card
->
aux_dev
[
num
]
;
struct
snd_soc_
component
*
comp
;
int
order
;
int
ret
;
ret
=
soc_probe_component
(
card
,
rtd
->
component
);
if
(
ret
<
0
)
return
ret
;
/* do machine specific initialization */
if
(
aux_dev
->
init
)
{
ret
=
aux_dev
->
init
(
rtd
->
component
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to init %s: %d
\n
"
,
aux_dev
->
name
,
ret
);
return
ret
;
for
(
order
=
SND_SOC_COMP_ORDER_FIRST
;
order
<=
SND_SOC_COMP_ORDER_LAST
;
order
++
)
{
list_for_each_entry
(
comp
,
&
card
->
aux_comp_list
,
list_aux
)
{
if
(
comp
->
driver
->
probe_order
==
order
)
{
ret
=
soc_probe_component
(
card
,
comp
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to probe aux component %s %d
\n
"
,
comp
->
name
,
ret
);
return
ret
;
}
}
}
}
return
soc_post_component_init
(
rtd
,
aux_dev
->
name
)
;
return
0
;
}
static
void
soc_remove_aux_dev
(
struct
snd_soc_card
*
card
,
int
num
)
static
void
soc_remove_aux_dev
ices
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_
pcm_runtime
*
rtd
=
&
card
->
rtd_aux
[
num
]
;
struct
snd_soc_component
*
component
=
rtd
->
component
;
struct
snd_soc_
component
*
comp
,
*
_comp
;
int
order
;
/* unregister the rtd device */
if
(
rtd
->
dev_registered
)
{
device_unregister
(
rtd
->
dev
);
rtd
->
dev_registered
=
0
;
for
(
order
=
SND_SOC_COMP_ORDER_FIRST
;
order
<=
SND_SOC_COMP_ORDER_LAST
;
order
++
)
{
list_for_each_entry_safe
(
comp
,
_comp
,
&
card
->
aux_comp_list
,
list_aux
)
{
if
(
comp
->
driver
->
remove_order
==
order
)
{
soc_remove_component
(
comp
);
/* remove it from the card's aux_comp_list */
list_del
(
&
comp
->
list_aux
);
}
}
}
if
(
component
)
soc_remove_component
(
component
);
}
static
int
snd_soc_init_codec_cache
(
struct
snd_soc_codec
*
codec
)
...
...
@@ -1894,6 +1920,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
/* probe auxiliary components */
ret
=
soc_probe_aux_devices
(
card
);
if
(
ret
<
0
)
goto
probe_dai_err
;
/* Find new DAI links added during probing components and bind them.
* Components with topology may bring new DAIs and DAI links.
*/
...
...
@@ -1923,16 +1954,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
{
ret
=
soc_probe_aux_dev
(
card
,
i
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"ASoC: failed to add auxiliary devices %d
\n
"
,
ret
);
goto
probe_aux_dev_err
;
}
}
snd_soc_dapm_link_dai_widgets
(
card
);
snd_soc_dapm_connect_dai_link_widgets
(
card
);
...
...
@@ -1992,8 +2013,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
return
0
;
probe_aux_dev_err:
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
soc_remove_aux_dev
(
card
,
i
);
soc_remove_aux_devices
(
card
);
probe_dai_err:
soc_remove_dai_links
(
card
);
...
...
@@ -2039,20 +2059,18 @@ static int soc_probe(struct platform_device *pdev)
static
int
soc_cleanup_card_resources
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_pcm_runtime
*
rtd
;
int
i
;
/* make sure any delayed work runs */
list_for_each_entry
(
rtd
,
&
card
->
rtd_list
,
list
)
flush_delayed_work
(
&
rtd
->
delayed_work
);
/* remove auxiliary devices */
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
soc_remove_aux_dev
(
card
,
i
);
/* remove and free each DAI */
soc_remove_dai_links
(
card
);
soc_remove_pcm_runtimes
(
card
);
/* remove auxiliary devices */
soc_remove_aux_devices
(
card
);
soc_cleanup_card_debugfs
(
card
);
/* remove the card */
...
...
@@ -2608,16 +2626,6 @@ int snd_soc_register_card(struct snd_soc_card *card)
INIT_LIST_HEAD
(
&
card
->
rtd_list
);
card
->
num_rtd
=
0
;
card
->
rtd_aux
=
devm_kzalloc
(
card
->
dev
,
sizeof
(
struct
snd_soc_pcm_runtime
)
*
card
->
num_aux_devs
,
GFP_KERNEL
);
if
(
card
->
rtd_aux
==
NULL
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
card
->
num_aux_devs
;
i
++
)
card
->
rtd_aux
[
i
].
card
=
card
;
INIT_LIST_HEAD
(
&
card
->
dapm_dirty
);
INIT_LIST_HEAD
(
&
card
->
dobj_list
);
card
->
instantiated
=
0
;
...
...
@@ -2744,6 +2752,56 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
}
}
/* Create a DAI and add it to the component's DAI list */
static
struct
snd_soc_dai
*
soc_add_dai
(
struct
snd_soc_component
*
component
,
struct
snd_soc_dai_driver
*
dai_drv
,
bool
legacy_dai_naming
)
{
struct
device
*
dev
=
component
->
dev
;
struct
snd_soc_dai
*
dai
;
dev_dbg
(
dev
,
"ASoC: dynamically register DAI %s
\n
"
,
dev_name
(
dev
));
dai
=
kzalloc
(
sizeof
(
struct
snd_soc_dai
),
GFP_KERNEL
);
if
(
dai
==
NULL
)
return
NULL
;
/*
* Back in the old days when we still had component-less DAIs,
* instead of having a static name, component-less DAIs would
* inherit the name of the parent device so it is possible to
* register multiple instances of the DAI. We still need to keep
* the same naming style even though those DAIs are not
* component-less anymore.
*/
if
(
legacy_dai_naming
&&
(
dai_drv
->
id
==
0
||
dai_drv
->
name
==
NULL
))
{
dai
->
name
=
fmt_single_name
(
dev
,
&
dai
->
id
);
}
else
{
dai
->
name
=
fmt_multiple_name
(
dev
,
dai_drv
);
if
(
dai_drv
->
id
)
dai
->
id
=
dai_drv
->
id
;
else
dai
->
id
=
component
->
num_dai
;
}
if
(
dai
->
name
==
NULL
)
{
kfree
(
dai
);
return
NULL
;
}
dai
->
component
=
component
;
dai
->
dev
=
dev
;
dai
->
driver
=
dai_drv
;
if
(
!
dai
->
driver
->
ops
)
dai
->
driver
->
ops
=
&
null_dai_ops
;
list_add
(
&
dai
->
list
,
&
component
->
dai_list
);
component
->
num_dai
++
;
dev_dbg
(
dev
,
"ASoC: Registered DAI '%s'
\n
"
,
dai
->
name
);
return
dai
;
}
/**
* snd_soc_register_dais - Register a DAI with the ASoC core
*
...
...
@@ -2765,58 +2823,66 @@ 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
);
dai
=
soc_add_dai
(
component
,
dai_drv
+
i
,
count
==
1
&&
legacy_dai_naming
);
if
(
dai
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
err
;
}
}
/*
* Back in the old days when we still had component-less DAIs,
* instead of having a static name, component-less DAIs would
* inherit the name of the parent device so it is possible to
* register multiple instances of the DAI. We still need to keep
* the same naming style even though those DAIs are not
* component-less anymore.
*/
if
(
count
==
1
&&
legacy_dai_naming
&&
(
dai_drv
[
i
].
id
==
0
||
dai_drv
[
i
].
name
==
NULL
))
{
dai
->
name
=
fmt_single_name
(
dev
,
&
dai
->
id
);
}
else
{
dai
->
name
=
fmt_multiple_name
(
dev
,
&
dai_drv
[
i
]);
if
(
dai_drv
[
i
].
id
)
dai
->
id
=
dai_drv
[
i
].
id
;
else
dai
->
id
=
i
;
}
if
(
dai
->
name
==
NULL
)
{
kfree
(
dai
);
ret
=
-
ENOMEM
;
goto
err
;
}
return
0
;
dai
->
component
=
component
;
dai
->
dev
=
dev
;
dai
->
driver
=
&
dai_drv
[
i
];
if
(
!
dai
->
driver
->
ops
)
dai
->
driver
->
ops
=
&
null_dai_ops
;
err:
snd_soc_unregister_dais
(
component
);
list_add
(
&
dai
->
list
,
&
component
->
dai_list
);
return
ret
;
}
dev_dbg
(
dev
,
"ASoC: Registered DAI '%s'
\n
"
,
dai
->
name
);
/**
* snd_soc_register_dai - Register a DAI dynamically & create its widgets
*
* @component: The component the DAIs are registered for
* @dai_drv: DAI driver to use for the DAI
*
* Topology can use this API to register DAIs when probing a component.
* These DAIs's widgets will be freed in the card cleanup and the DAIs
* will be freed in the component cleanup.
*/
int
snd_soc_register_dai
(
struct
snd_soc_component
*
component
,
struct
snd_soc_dai_driver
*
dai_drv
)
{
struct
snd_soc_dapm_context
*
dapm
=
snd_soc_component_get_dapm
(
component
);
struct
snd_soc_dai
*
dai
;
int
ret
;
if
(
dai_drv
->
dobj
.
type
!=
SND_SOC_DOBJ_PCM
)
{
dev_err
(
component
->
dev
,
"Invalid dai type %d
\n
"
,
dai_drv
->
dobj
.
type
);
return
-
EINVAL
;
}
return
0
;
lockdep_assert_held
(
&
client_mutex
);
dai
=
soc_add_dai
(
component
,
dai_drv
,
false
);
if
(
!
dai
)
return
-
ENOMEM
;
err:
snd_soc_unregister_dais
(
component
);
/* Create the DAI widgets here. After adding DAIs, topology may
* also add routes that need these widgets as source or sink.
*/
ret
=
snd_soc_dapm_new_dai_widgets
(
dapm
,
dai
);
if
(
ret
!=
0
)
{
dev_err
(
component
->
dev
,
"Failed to create DAI widgets %d
\n
"
,
ret
);
}
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_register_dai
);
static
void
snd_soc_component_seq_notifier
(
struct
snd_soc_dapm_context
*
dapm
,
enum
snd_soc_dapm_type
type
,
int
subseq
)
...
...
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