ASoC: simple-card: Move dai-link level properties away from dai subnodes

The properties like format, bitclock-master, frame-master,
bitclock-inversion, and frame-inversion should be common to the dais
connected with a dai-link. For bitclock-master and frame-master
properties to be unambiguous they need to indicate the mastering dai
node with a phandle.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Acked-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Jyri Sarha
2014-03-24 12:15:25 +02:00
committed by Mark Brown
父節點 389cb8348c
當前提交 b3ca11ff59
共有 2 個文件被更改,包括 192 次插入139 次删除

查看文件

@@ -88,7 +88,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
static int
asoc_simple_card_sub_parse_of(struct device_node *np,
unsigned int daifmt,
struct asoc_simple_dai *dai,
const struct device_node **p_node,
const char **name)
@@ -116,14 +115,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
if (ret)
return ret;
/*
* bitclock-inversion, frame-inversion
* bitclock-master, frame-master
* and specific "format" if it has
*/
dai->fmt = snd_soc_of_parse_daifmt(np, NULL, NULL, NULL);
dai->fmt |= daifmt;
/*
* dai->sysclk come from
* "clocks = <&xxx>" (if system has common clock)
@@ -151,37 +142,135 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
return 0;
}
static int simple_card_cpu_codec_of(struct device_node *node,
int daifmt,
struct snd_soc_dai_link *dai_link,
struct simple_dai_props *dai_props)
static int simple_card_dai_link_of(struct device_node *node,
struct device *dev,
struct snd_soc_dai_link *dai_link,
struct simple_dai_props *dai_props)
{
struct device_node *np;
struct device_node *np = NULL;
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
char *name;
char prop[128];
char *prefix = "";
int ret;
/* CPU sub-node */
ret = -EINVAL;
np = of_get_child_by_name(node, "simple-audio-card,cpu");
if (np) {
ret = asoc_simple_card_sub_parse_of(np, daifmt,
&dai_props->cpu_dai,
&dai_link->cpu_of_node,
&dai_link->cpu_dai_name);
of_node_put(np);
}
if (ret < 0)
return ret;
if (!strcmp("sound", node->name))
prefix = "simple-audio-card,";
/* CODEC sub-node */
ret = -EINVAL;
np = of_get_child_by_name(node, "simple-audio-card,codec");
if (np) {
ret = asoc_simple_card_sub_parse_of(np, daifmt,
&dai_props->codec_dai,
&dai_link->codec_of_node,
&dai_link->codec_dai_name);
of_node_put(np);
daifmt = snd_soc_of_parse_daifmt(node, prefix,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
snprintf(prop, sizeof(prop), "%scpu", prefix);
np = of_get_child_by_name(node, prop);
if (!np) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find simple-audio-card,cpu DT node\n",
__func__);
goto dai_link_of_err;
}
ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai,
&dai_link->cpu_of_node,
&dai_link->cpu_dai_name);
if (ret < 0)
goto dai_link_of_err;
dai_props->cpu_dai.fmt = daifmt;
switch (((np == bitclkmaster)<<4)|(np == framemaster)) {
case 0x11:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
break;
case 0x10:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
break;
case 0x01:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
break;
default:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
break;
}
of_node_put(np);
snprintf(prop, sizeof(prop), "%scodec", prefix);
np = of_get_child_by_name(node, prop);
if (!np) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find simple-audio-card,codec DT node\n",
__func__);
goto dai_link_of_err;
}
ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai,
&dai_link->codec_of_node,
&dai_link->codec_dai_name);
if (ret < 0)
goto dai_link_of_err;
if (strlen(prefix) && !bitclkmaster && !framemaster) {
/* No dai-link level and master setting was not found from
sound node level, revert back to legacy DT parsing and
take the settings from codec node. */
dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n",
__func__);
dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt =
snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) |
(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
} else {
dai_props->codec_dai.fmt = daifmt;
switch (((np == bitclkmaster)<<4)|(np == framemaster)) {
case 0x11:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
break;
case 0x10:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
break;
case 0x01:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
break;
default:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
break;
}
}
if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
ret = -EINVAL;
goto dai_link_of_err;
}
/* simple-card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node;
/* Link name is created from CPU/CODEC dai name */
name = devm_kzalloc(dev,
strlen(dai_link->cpu_dai_name) +
strlen(dai_link->codec_dai_name) + 2,
GFP_KERNEL);
sprintf(name, "%s-%s", dai_link->cpu_dai_name,
dai_link->codec_dai_name);
dai_link->name = dai_link->stream_name = name;
dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
dev_dbg(dev, "\tcpu : %s / %04x / %d\n",
dai_link->cpu_dai_name,
dai_props->cpu_dai.fmt,
dai_props->cpu_dai.sysclk);
dev_dbg(dev, "\tcodec : %s / %04x / %d\n",
dai_link->codec_dai_name,
dai_props->codec_dai.fmt,
dai_props->codec_dai.sysclk);
dai_link_of_err:
if (np)
of_node_put(np);
if (bitclkmaster)
of_node_put(bitclkmaster);
if (framemaster)
of_node_put(framemaster);
return ret;
}
@@ -192,19 +281,11 @@ static int asoc_simple_card_parse_of(struct device_node *node,
{
struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
struct simple_dai_props *dai_props = priv->dai_props;
struct device_node *np;
char *name;
unsigned int daifmt;
int ret;
/* parsing the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name");
/* get CPU/CODEC common format via simple-audio-card,format */
daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,", NULL,
NULL) &
(SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK);
/* off-codec widgets */
if (of_property_read_bool(node, "simple-audio-card,widgets")) {
ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
@@ -221,71 +302,31 @@ static int asoc_simple_card_parse_of(struct device_node *node,
return ret;
}
/* loop on the DAI links */
np = NULL;
for (;;) {
if (multi) {
np = of_get_next_child(node, np);
if (!np)
break;
}
dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ?
priv->snd_card.name : "");
ret = simple_card_cpu_codec_of(multi ? np : node,
daifmt, dai_link, dai_props);
if (multi) {
struct device_node *np = NULL;
int i;
for (i = 0; (np = of_get_next_child(node, np)); i++) {
dev_dbg(dev, "\tlink %d:\n", i);
ret = simple_card_dai_link_of(np, dev, dai_link + i,
dai_props + i);
if (ret < 0) {
of_node_put(np);
return ret;
}
}
} else {
ret = simple_card_dai_link_of(node, dev, dai_link, dai_props);
if (ret < 0)
goto err;
/*
* overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC
* while the other bits should be identical unless buggy SW/HW design.
*/
dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt;
if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
ret = -EINVAL;
goto err;
}
/* simple-card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node;
name = devm_kzalloc(dev,
strlen(dai_link->cpu_dai_name) +
strlen(dai_link->codec_dai_name) + 2,
GFP_KERNEL);
sprintf(name, "%s-%s", dai_link->cpu_dai_name,
dai_link->codec_dai_name);
dai_link->name = dai_link->stream_name = name;
if (!multi)
break;
dai_link++;
dai_props++;
return ret;
}
/* card name is created from CPU/CODEC dai name */
dai_link = priv->snd_card.dai_link;
if (!priv->snd_card.name)
priv->snd_card.name = dai_link->name;
dev_dbg(dev, "card-name : %s\n", priv->snd_card.name);
dev_dbg(dev, "platform : %04x\n", daifmt);
dai_props = priv->dai_props;
dev_dbg(dev, "cpu : %s / %04x / %d\n",
dai_link->cpu_dai_name,
dai_props->cpu_dai.fmt,
dai_props->cpu_dai.sysclk);
dev_dbg(dev, "codec : %s / %04x / %d\n",
dai_link->codec_dai_name,
dai_props->codec_dai.fmt,
dai_props->codec_dai.sysclk);
priv->snd_card.name = priv->snd_card.dai_link->name;
return 0;
err:
of_node_put(np);
return ret;
}
/* update the reference count of the devices nodes at end of probe */