ASoC: core: add multi-codec support in DT
This patch exports a core function which handles the DT description of multi-codec links (as: "sound-dai = <&hdmi 0>, <&spdif_codec>;") and creates a CODEC component array in the DAI link. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
f114040e3e
commit
93b0f3eeeb
2 changed files with 98 additions and 15 deletions
|
@ -1451,6 +1451,9 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||||
struct device_node **framemaster);
|
struct device_node **framemaster);
|
||||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||||
const char **dai_name);
|
const char **dai_name);
|
||||||
|
int snd_soc_of_get_dai_link_codecs(struct device *dev,
|
||||||
|
struct device_node *of_node,
|
||||||
|
struct snd_soc_dai_link *dai_link);
|
||||||
|
|
||||||
#include <sound/soc-dai.h>
|
#include <sound/soc-dai.h>
|
||||||
|
|
||||||
|
|
|
@ -4750,36 +4750,30 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
|
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
|
||||||
|
|
||||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
static int snd_soc_get_dai_name(struct of_phandle_args *args,
|
||||||
const char **dai_name)
|
const char **dai_name)
|
||||||
{
|
{
|
||||||
struct snd_soc_component *pos;
|
struct snd_soc_component *pos;
|
||||||
struct of_phandle_args args;
|
int ret = -EPROBE_DEFER;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = of_parse_phandle_with_args(of_node, "sound-dai",
|
|
||||||
"#sound-dai-cells", 0, &args);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = -EPROBE_DEFER;
|
|
||||||
|
|
||||||
mutex_lock(&client_mutex);
|
mutex_lock(&client_mutex);
|
||||||
list_for_each_entry(pos, &component_list, list) {
|
list_for_each_entry(pos, &component_list, list) {
|
||||||
if (pos->dev->of_node != args.np)
|
if (pos->dev->of_node != args->np)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pos->driver->of_xlate_dai_name) {
|
if (pos->driver->of_xlate_dai_name) {
|
||||||
ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
|
ret = pos->driver->of_xlate_dai_name(pos,
|
||||||
|
args,
|
||||||
|
dai_name);
|
||||||
} else {
|
} else {
|
||||||
int id = -1;
|
int id = -1;
|
||||||
|
|
||||||
switch (args.args_count) {
|
switch (args->args_count) {
|
||||||
case 0:
|
case 0:
|
||||||
id = 0; /* same as dai_drv[0] */
|
id = 0; /* same as dai_drv[0] */
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
id = args.args[0];
|
id = args->args[0];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* not supported */
|
/* not supported */
|
||||||
|
@ -4801,6 +4795,21 @@ int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&client_mutex);
|
mutex_unlock(&client_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||||
|
const char **dai_name)
|
||||||
|
{
|
||||||
|
struct of_phandle_args args;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = of_parse_phandle_with_args(of_node, "sound-dai",
|
||||||
|
"#sound-dai-cells", 0, &args);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = snd_soc_get_dai_name(&args, dai_name);
|
||||||
|
|
||||||
of_node_put(args.np);
|
of_node_put(args.np);
|
||||||
|
|
||||||
|
@ -4808,6 +4817,77 @@ int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
|
EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* snd_soc_of_get_dai_link_codecs - Parse a list of CODECs in the devicetree
|
||||||
|
* @dev: Card device
|
||||||
|
* @of_node: Device node
|
||||||
|
* @dai_link: DAI link
|
||||||
|
*
|
||||||
|
* Builds an array of CODEC DAI components from the DAI link property
|
||||||
|
* 'sound-dai'.
|
||||||
|
* The array is set in the DAI link and the number of DAIs is set accordingly.
|
||||||
|
* The device nodes in the array (of_node) must be dereferenced by the caller.
|
||||||
|
*
|
||||||
|
* Returns 0 for success
|
||||||
|
*/
|
||||||
|
int snd_soc_of_get_dai_link_codecs(struct device *dev,
|
||||||
|
struct device_node *of_node,
|
||||||
|
struct snd_soc_dai_link *dai_link)
|
||||||
|
{
|
||||||
|
struct of_phandle_args args;
|
||||||
|
struct snd_soc_dai_link_component *component;
|
||||||
|
char *name;
|
||||||
|
int index, num_codecs, ret;
|
||||||
|
|
||||||
|
/* Count the number of CODECs */
|
||||||
|
name = "sound-dai";
|
||||||
|
num_codecs = of_count_phandle_with_args(of_node, name,
|
||||||
|
"#sound-dai-cells");
|
||||||
|
if (num_codecs <= 0) {
|
||||||
|
if (num_codecs == -ENOENT)
|
||||||
|
dev_err(dev, "No 'sound-dai' property\n");
|
||||||
|
else
|
||||||
|
dev_err(dev, "Bad phandle in 'sound-dai'\n");
|
||||||
|
return num_codecs;
|
||||||
|
}
|
||||||
|
component = devm_kzalloc(dev,
|
||||||
|
sizeof *component * num_codecs,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!component)
|
||||||
|
return -ENOMEM;
|
||||||
|
dai_link->codecs = component;
|
||||||
|
dai_link->num_codecs = num_codecs;
|
||||||
|
|
||||||
|
/* Parse the list */
|
||||||
|
for (index = 0, component = dai_link->codecs;
|
||||||
|
index < dai_link->num_codecs;
|
||||||
|
index++, component++) {
|
||||||
|
ret = of_parse_phandle_with_args(of_node, name,
|
||||||
|
"#sound-dai-cells",
|
||||||
|
index, &args);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
component->of_node = args.np;
|
||||||
|
ret = snd_soc_get_dai_name(&args, &component->dai_name);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
for (index = 0, component = dai_link->codecs;
|
||||||
|
index < dai_link->num_codecs;
|
||||||
|
index++, component++) {
|
||||||
|
if (!component->of_node)
|
||||||
|
break;
|
||||||
|
of_node_put(component->of_node);
|
||||||
|
component->of_node = NULL;
|
||||||
|
}
|
||||||
|
dai_link->codecs = NULL;
|
||||||
|
dai_link->num_codecs = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_link_codecs);
|
||||||
|
|
||||||
static int __init snd_soc_init(void)
|
static int __init snd_soc_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
Loading…
Reference in a new issue