2016-10-17 08:31:10

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 0/23] ASoC: add OF graph base simple-card


Hi Rob, Mark

These are OF graph base simple-card patch-set.
1) - 3) : simple-scu-card cleanup
4) - 10) : soc-core prepare for OF graph card
11) - 17) : OF graph new feature
18) - 23) : OF graph base simple-card

I posted 11) - 17) OF graph new feature patches before, and then Rob requested
about usecase. 18) - 23) can be usecase for it.
1) - 10) are independent (= Mark)
11) - 17) are independent (= Rob)
18) - 23) are depends on 1) - 10) and 11) - 17) (= Mark)

Kuninori Morimoto (23):
1) ASoC: simple-scu-card: code sync: follow to simple family style
2) ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv
3) ASoC: simple-scu-card: code sync: tidyup props/link naming
4) ASoC: soc-core: adjust for graph on snd_soc_of_parse_card_name
5) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_simple_widgets
6) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_routing
7) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_prefix
8) ASoC: soc-core: snd_soc_get_dai_name() become non static
9) ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check
10) ASoC: simple-card-utils: adjust for graph on asoc_simple_card_parse_card_name
11) Documentation: of: add type property
12) of_graph: add of_graph_get_remote_endpoint()
13) of_graph: add of_graph_port_type_is()
14) of_graph: add of_graph_get_port_parent()
15) of_graph: add of_graph_get_top_port()
16) of_graph: add for_each_of_port() / for_each_of_endpoint_in_port()
17) of_graph: add of_graph_get_endpoint_count()
18) ASoC: simple-card-utils: add asoc_simple_card_parse_graph_dai()
19) ASoC: simple-card-utils: add asoc_simple_card_try_to_probe_graph_card()
20) ASoC: add simple-graph-card document
21) ASoC: add simple-graph-card support
22) ASoC: add simple-graph-scu-card document
23) ASoC: add simple-graph-scu-card support

Documentation/devicetree/bindings/graph.txt | 21 +++++
Documentation/devicetree/bindings/sound/simple-graph-card.txt | 65 ++++++++++++++
Documentation/devicetree/bindings/sound/simple-graph-scu-card.txt | 66 ++++++++++++++
drivers/of/base.c | 166 +++++++++++++++++++++++++++++++---
include/linux/of_graph.h | 62 +++++++++++++
include/sound/simple_card_utils.h | 14 +++
include/sound/soc.h | 32 +++++--
sound/soc/generic/Kconfig | 15 ++++
sound/soc/generic/Makefile | 4 +
sound/soc/generic/simple-card-utils.c | 105 +++++++++++++++++++++-
sound/soc/generic/simple-card.c | 2 +-
sound/soc/generic/simple-graph-card.c | 461 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sound/soc/generic/simple-graph-scu-card.c | 437 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sound/soc/generic/simple-scu-card.c | 115 +++++++++++-------------
sound/soc/soc-core.c | 41 +++++----
15 files changed, 1505 insertions(+), 101 deletions(-)


2016-10-17 08:32:14

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 01/23] ASoC: simple-scu-card: code sync: follow to simple family style

From: Kuninori Morimoto <[email protected]>

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronized simple card style to other simple card family

Current simple-scu-card function naming is different from other simple card
family. And related to it, the necessary operation position is also
different. This patch synchronize these to other simple card family.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 99 ++++++++++++++++---------------------
1 file changed, 43 insertions(+), 56 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index b9973a5..b8d8437 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -101,7 +101,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}

-static int asoc_simple_card_parse_links(struct device_node *np,
+static int asoc_simple_card_dai_link_of(struct device_node *np,
struct asoc_simple_card_priv *priv,
unsigned int daifmt,
int idx, bool is_fe)
@@ -195,22 +195,35 @@ static int asoc_simple_card_parse_links(struct device_node *np,
return 0;
}

-static int asoc_simple_card_dai_link_of(struct device_node *node,
- struct asoc_simple_card_priv *priv)
+static int asoc_simple_card_parse_of(struct device_node *node,
+ struct asoc_simple_card_priv *priv)
+
{
struct device *dev = simple_priv_to_dev(priv);
struct device_node *np;
unsigned int daifmt = 0;
- int ret, i;
bool is_fe;
+ int ret, i;
+
+ if (!node)
+ return -EINVAL;
+
+ ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing");
+ if (ret < 0)
+ return ret;
+
+ /* sampling rate convert */
+ of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate);
+
+ /* channels transfer */
+ of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels);

/* find 1st codec */
np = of_get_child_by_name(node, PREFIX "codec");
if (!np)
return -ENODEV;

- ret = asoc_simple_card_parse_daifmt(dev, node, np,
- PREFIX, &daifmt);
+ ret = asoc_simple_card_parse_daifmt(dev, node, np, PREFIX, &daifmt);
if (ret < 0)
return ret;

@@ -220,58 +233,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
if (strcmp(np->name, PREFIX "cpu") == 0)
is_fe = true;

- ret = asoc_simple_card_parse_links(np, priv, daifmt, i, is_fe);
+ ret = asoc_simple_card_dai_link_of(np, priv, daifmt, i, is_fe);
if (ret < 0)
return ret;
i++;
}

- return 0;
-}
-
-static int asoc_simple_card_parse_of(struct device_node *node,
- struct asoc_simple_card_priv *priv,
- struct device *dev)
-{
- struct asoc_simple_dai *props;
- struct snd_soc_dai_link *links;
- int ret;
- int num;
-
- if (!node)
- return -EINVAL;
-
- num = of_get_child_count(node);
- props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
- links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
- if (!props || !links)
- return -ENOMEM;
-
- priv->dai_props = props;
- priv->dai_link = links;
-
- /* Init snd_soc_card */
- priv->snd_card.owner = THIS_MODULE;
- priv->snd_card.dev = dev;
- priv->snd_card.dai_link = priv->dai_link;
- priv->snd_card.num_links = num;
- priv->snd_card.codec_conf = &priv->codec_conf;
- priv->snd_card.num_configs = 1;
-
- ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing");
- if (ret < 0)
- return ret;
-
- /* sampling rate convert */
- of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate);
-
- /* channels transfer */
- of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels);
-
- ret = asoc_simple_card_dai_link_of(node, priv);
- if (ret < 0)
- return ret;
-
ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
if (ret < 0)
return ret;
@@ -287,16 +254,36 @@ static int asoc_simple_card_parse_of(struct device_node *node,
static int asoc_simple_card_probe(struct platform_device *pdev)
{
struct asoc_simple_card_priv *priv;
- struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_dai_link *links;
+ struct asoc_simple_dai *props;
struct device *dev = &pdev->dev;
- int ret;
+ struct device_node *np = pdev->dev.of_node;
+ int num, ret;

/* Allocate the private data */
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

- ret = asoc_simple_card_parse_of(np, priv, dev);
+ num = of_get_child_count(np);
+
+ props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
+ links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
+ if (!props || !links)
+ return -ENOMEM;
+
+ priv->dai_props = props;
+ priv->dai_link = links;
+
+ /* Init snd_soc_card */
+ priv->snd_card.owner = THIS_MODULE;
+ priv->snd_card.dev = dev;
+ priv->snd_card.dai_link = priv->dai_link;
+ priv->snd_card.num_links = num;
+ priv->snd_card.codec_conf = &priv->codec_conf;
+ priv->snd_card.num_configs = 1;
+
+ ret = asoc_simple_card_parse_of(np, priv);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret);
--
1.9.1

2016-10-17 08:32:34

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 02/23] ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv

From: Kuninori Morimoto <[email protected]>

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronized simple card style to other simple card family

This patch renames asoc_simple_card_priv to simple_card_data,
same as other simple card family.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index b8d8437..1704b18 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -22,7 +22,7 @@
#include <sound/soc-dai.h>
#include <sound/simple_card_utils.h>

-struct asoc_simple_card_priv {
+struct simple_card_data {
struct snd_soc_card snd_card;
struct snd_soc_codec_conf codec_conf;
struct asoc_simple_dai *dai_props;
@@ -42,7 +42,7 @@ struct asoc_simple_card_priv {
static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct asoc_simple_dai *dai_props =
simple_priv_to_props(priv, rtd->num);

@@ -52,7 +52,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct asoc_simple_dai *dai_props =
simple_priv_to_props(priv, rtd->num);

@@ -66,7 +66,7 @@ static struct snd_soc_ops asoc_simple_card_ops = {

static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dai_props;
@@ -84,7 +84,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
@@ -102,7 +102,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
}

static int asoc_simple_card_dai_link_of(struct device_node *np,
- struct asoc_simple_card_priv *priv,
+ struct simple_card_data *priv,
unsigned int daifmt,
int idx, bool is_fe)
{
@@ -196,7 +196,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
}

static int asoc_simple_card_parse_of(struct device_node *node,
- struct asoc_simple_card_priv *priv)
+ struct simple_card_data *priv)

{
struct device *dev = simple_priv_to_dev(priv);
@@ -253,7 +253,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,

static int asoc_simple_card_probe(struct platform_device *pdev)
{
- struct asoc_simple_card_priv *priv;
+ struct simple_card_data *priv;
struct snd_soc_dai_link *links;
struct asoc_simple_dai *props;
struct device *dev = &pdev->dev;
--
1.9.1

2016-10-17 08:33:02

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 03/23] ASoC: simple-scu-card: code sync: tidyup props/link naming

From: Kuninori Morimoto <[email protected]>

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronizes style to other simple card family so that be enable
to easy reviewing.

This patch uses dai_link/dai_props instead of links/props.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index 1704b18..348e9a7 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -254,8 +254,8 @@ static int asoc_simple_card_parse_of(struct device_node *node,
static int asoc_simple_card_probe(struct platform_device *pdev)
{
struct simple_card_data *priv;
- struct snd_soc_dai_link *links;
- struct asoc_simple_dai *props;
+ struct snd_soc_dai_link *dai_link;
+ struct asoc_simple_dai *dai_props;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
int num, ret;
@@ -267,13 +267,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)

num = of_get_child_count(np);

- props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
- links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
- if (!props || !links)
+ dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ if (!dai_props || !dai_link)
return -ENOMEM;

- priv->dai_props = props;
- priv->dai_link = links;
+ priv->dai_props = dai_props;
+ priv->dai_link = dai_link;

/* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE;
--
1.9.1

2016-10-17 08:33:22

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 04/23] ASoC: soc-core: adjust for graph on snd_soc_of_parse_card_name

From: Kuninori Morimoto <[email protected]>

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/soc.h | 7 +++++--
sound/soc/soc-core.c | 11 ++++++-----
2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 4f1c784..d100a33 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1642,8 +1642,11 @@ static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
int snd_soc_util_init(void);
void snd_soc_util_exit(void);

-int snd_soc_of_parse_card_name(struct snd_soc_card *card,
- const char *propname);
+#define snd_soc_of_parse_card_name(card, propname) \
+ snd_soc_of_parse_card_name_from_node(card, NULL, propname)
+int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_parse_tdm_slot(struct device_node *np,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0bbcd9..088a158 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3424,10 +3424,10 @@ found:
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);

/* Retrieve a card's name from device tree */
-int snd_soc_of_parse_card_name(struct snd_soc_card *card,
- const char *propname)
+int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname)
{
- struct device_node *np;
int ret;

if (!card->dev) {
@@ -3435,7 +3435,8 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
return -EINVAL;
}

- np = card->dev->of_node;
+ if (!np)
+ np = card->dev->of_node;

ret = of_property_read_string_index(np, propname, 0, &card->name);
/*
@@ -3452,7 +3453,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node);

static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_MIC("Microphone", NULL),
--
1.9.1

2016-10-17 08:33:51

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 05/23] ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_simple_widgets

From: Kuninori Morimoto <[email protected]>

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/soc.h | 8 ++++++--
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index d100a33..8130b73 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1647,8 +1647,12 @@ void snd_soc_util_exit(void);
int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
struct device_node *np,
const char *propname);
-int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
- const char *propname);
+#define snd_soc_of_parse_audio_simple_widgets(card, propname)\
+ snd_soc_of_parse_audio_simple_widgets_from_node(card, NULL, propname)
+int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
+
int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *tx_mask,
unsigned int *rx_mask,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 088a158..e56ea42 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3462,14 +3462,17 @@ static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};

-int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
+int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
+ struct device_node *np,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
struct snd_soc_dapm_widget *widgets;
const char *template, *wname;
int i, j, num_widgets, ret;

+ if (!np)
+ np = card->dev->of_node;
+
num_widgets = of_property_count_strings(np, propname);
if (num_widgets < 0) {
dev_err(card->dev,
@@ -3540,7 +3543,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node);

static int snd_soc_of_get_slot_mask(struct device_node *np,
const char *prop_name,
--
1.9.1

2016-10-17 08:34:07

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 06/23] ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_routing

From: Kuninori Morimoto <[email protected]>

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/soc.h | 9 +++++++--
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8130b73..3cb36d8 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1662,8 +1662,13 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname);
-int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
- const char *propname);
+
+#define snd_soc_of_parse_audio_routing(card, propname) \
+ snd_soc_of_parse_audio_routing_from_node(card, NULL, propname)
+int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
+
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e56ea42..79a1045 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3619,14 +3619,17 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);

-int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
+int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
+ struct device_node *np,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
int num_routes;
struct snd_soc_dapm_route *routes;
int i, ret;

+ if (!np)
+ np = card->dev->of_node;
+
num_routes = of_property_count_strings(np, propname);
if (num_routes < 0 || num_routes & 1) {
dev_err(card->dev,
@@ -3673,7 +3676,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node);

unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
--
1.9.1

2016-10-17 08:34:21

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 07/23] ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_prefix

From: Kuninori Morimoto <[email protected]>

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/soc.h | 6 +++++-
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 3cb36d8..fd63d23 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1658,7 +1658,11 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *rx_mask,
unsigned int *slots,
unsigned int *slot_width);
-void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
+#define snd_soc_of_parse_audio_prefix(card, codec_conf, of_node, propname) \
+ snd_soc_of_parse_audio_prefix_from_node(card, NULL, codec_conf, \
+ of_node, propname)
+void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
+ struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 79a1045..8371488 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3599,15 +3599,18 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);

-void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
+void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
+ struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
const char *str;
int ret;

+ if (!np)
+ np = card->dev->of_node;
+
ret = of_property_read_string(np, propname, &str);
if (ret < 0) {
/* no prefix is not error */
@@ -3617,7 +3620,7 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
codec_conf->of_node = of_node;
codec_conf->name_prefix = str;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node);

int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
struct device_node *np,
--
1.9.1

2016-10-17 08:34:41

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 08/23] ASoC: soc-core: snd_soc_get_dai_name() become non static

From: Kuninori Morimoto <[email protected]>

snd_soc_get_dai_name() is used from snd_soc_of_get_dai_name(),
and it is assuming that DT is using "sound-dai" / "#sound-dai-cells".
But graph base DT is using "remote-endpoint". This patch makes
snd_soc_get_dai_name() non static for graph support.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/soc.h | 2 ++
sound/soc/soc-core.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index fd63d23..77b01c4 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1677,6 +1677,8 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
struct device_node **framemaster);
+int snd_soc_get_dai_name(struct of_phandle_args *args,
+ const char **dai_name);
int snd_soc_of_get_dai_name(struct device_node *of_node,
const char **dai_name);
int snd_soc_of_get_dai_link_codecs(struct device *dev,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 8371488..6f911f4 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3794,7 +3794,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);

-static int snd_soc_get_dai_name(struct of_phandle_args *args,
+int snd_soc_get_dai_name(struct of_phandle_args *args,
const char **dai_name)
{
struct snd_soc_component *pos;
@@ -3846,6 +3846,7 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args,
mutex_unlock(&client_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(snd_soc_get_dai_name);

int snd_soc_of_get_dai_name(struct device_node *of_node,
const char **dai_name)
--
1.9.1

2016-10-17 08:34:58

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 09/23] ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check

From: Kuninori Morimoto <[email protected]>

Remove cpu/codec pointer check from asoc_simple_card_canonicalize_dailink()
This is verbose check, and will be issue if CPU name was created by
fmt_single_name() on simple-scu-card.c.
see also asoc_simple_card_canonicalize_cpu()

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/simple-card-utils.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 1cb3930..e5b80f5 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -195,9 +195,6 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);

int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
{
- if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name)
- return -EINVAL;
-
/* Assumes platform == cpu */
if (!dai_link->platform_of_node)
dai_link->platform_of_node = dai_link->cpu_of_node;
--
1.9.1

2016-10-17 08:35:31

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 10/23] ASoC: simple-card-utils: adjust for graph on asoc_simple_card_parse_card_name

From: Kuninori Morimoto <[email protected]>

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/simple_card_utils.h | 1 +
sound/soc/generic/simple-card-utils.c | 3 ++-
sound/soc/generic/simple-card.c | 2 +-
sound/soc/generic/simple-scu-card.c | 2 +-
4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index fd641255..09750ac 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -32,6 +32,7 @@ int asoc_simple_card_set_dailink_name(struct device *dev,
struct snd_soc_dai_link *dai_link,
const char *fmt, ...);
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
+ struct device_node *node,
char *prefix);

#define asoc_simple_card_parse_clk_cpu(node, dai_link, simple_dai) \
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index e5b80f5..6bc1510 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -79,6 +79,7 @@ int asoc_simple_card_set_dailink_name(struct device *dev,
EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);

int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
+ struct device_node *node,
char *prefix)
{
char prop[128];
@@ -87,7 +88,7 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
snprintf(prop, sizeof(prop), "%sname", prefix);

/* Parse the card name from DT */
- ret = snd_soc_of_parse_card_name(card, prop);
+ ret = snd_soc_of_parse_card_name_from_node(card, node, prop);
if (ret < 0)
return ret;

diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index f608f8d2..342ff53 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -401,7 +401,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
goto card_parse_end;
}

- ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
+ ret = asoc_simple_card_parse_card_name(&priv->snd_card, NULL, PREFIX);
if (ret < 0)
goto card_parse_end;

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index 348e9a7..a8164a2 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -239,7 +239,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
i++;
}

- ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
+ ret = asoc_simple_card_parse_card_name(&priv->snd_card, NULL, PREFIX);
if (ret < 0)
return ret;

--
1.9.1

2016-10-17 08:35:36

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 11/23] Documentation: of: add type property


From: Kuninori Morimoto <[email protected]>

OF graph indicates each devices connection. But it doesn't support type
of each port. For example HDMI case, it has video port and sound port
in one device node.
In this case, current driver can't handle each port correctly.
This patch enables to use type property on OF graph.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
Documentation/devicetree/bindings/graph.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/graph.txt b/Documentation/devicetree/bindings/graph.txt
index fcb1c6a..fe6c8ce 100644
--- a/Documentation/devicetree/bindings/graph.txt
+++ b/Documentation/devicetree/bindings/graph.txt
@@ -110,6 +110,27 @@ device-2 {
};
};

+port / endpoint type
+--------------------
+
+Each port can have its type if needed.
+For example HDMI case, it has video port and sound port.
+Below example indicates that port@0 is HDMI-video port,
+and port@1 is HDMI-sound port.
+
+HDMI {
+ port@0 {
+ type = "video";
+ endpoint {
+ };
+ };
+ port@1 {
+ type = "sound";
+ endpoint {
+ };
+ };
+};
+

Required properties
-------------------
--
1.9.1

2016-10-17 08:36:01

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 12/23] of_graph: add of_graph_get_remote_endpoint()


From: Kuninori Morimoto <[email protected]>

It should use same method to get same result.
To getting remote-endpoint node,
let's use of_graph_get_remote_endpoint()

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 18 ++++++++++++++++--
include/linux/of_graph.h | 8 ++++++++
2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ce6953..e3cdc5d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2356,6 +2356,20 @@ struct device_node *of_graph_get_endpoint_by_regs(
EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);

/**
+ * of_graph_get_remote_endpoint() - get remote endpoint node
+ * @node: pointer to a local endpoint device_node
+ *
+ * Return: Remote endpoint node associated with remote endpoint node linked
+ * to @node. Use of_node_put() on it when done.
+ */
+struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
+{
+ /* Get remote endpoint node. */
+ return of_parse_phandle(node, "remote-endpoint", 0);
+}
+EXPORT_SYMBOL(of_graph_get_remote_endpoint);
+
+/**
* of_graph_get_remote_port_parent() - get remote port's parent node
* @node: pointer to a local endpoint device_node
*
@@ -2369,7 +2383,7 @@ struct device_node *of_graph_get_remote_port_parent(
unsigned int depth;

/* Get remote endpoint node. */
- np = of_parse_phandle(node, "remote-endpoint", 0);
+ np = of_graph_get_remote_endpoint(node);

/* Walk 3 levels up only if there is 'ports' node. */
for (depth = 3; depth && np; depth--) {
@@ -2393,7 +2407,7 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
struct device_node *np;

/* Get remote endpoint node. */
- np = of_parse_phandle(node, "remote-endpoint", 0);
+ np = of_graph_get_remote_endpoint(node);
if (!np)
return NULL;
return of_get_next_parent(np);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index bb3a5a2..d9d6d9c 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -48,6 +48,8 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
struct device_node *of_graph_get_endpoint_by_regs(
const struct device_node *parent, int port_reg, int reg);
+struct device_node *of_graph_get_remote_endpoint(
+ const struct device_node *node);
struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
struct device_node *of_graph_get_remote_port(const struct device_node *node);
@@ -78,6 +80,12 @@ static inline struct device_node *of_graph_get_endpoint_by_regs(
return NULL;
}

+static inline struct device_node *of_graph_get_remote_endpoint(
+ const struct device_node *node)
+{
+ return NULL;
+}
+
static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
--
1.9.1

2016-10-17 08:36:32

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 13/23] of_graph: add of_graph_port_type_is()


From: Kuninori Morimoto <[email protected]>

OF graph indicates each devices connection. But it doesn't support type
of each port. For example HDMI case, it has video port and sound port
in one device node.
In this case, current driver can't handle each port correctly.

This patch adds of_graph_port_type_is() for it,
and adds of_graph_port_type_is_sound macro

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 14 ++++++++++++++
include/linux/of_graph.h | 8 ++++++++
2 files changed, 22 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index e3cdc5d..b035cff4 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2413,3 +2413,17 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
return of_get_next_parent(np);
}
EXPORT_SYMBOL(of_graph_get_remote_port);
+
+bool of_graph_port_type_is(struct device_node *port, char *type)
+{
+ const char *prop = NULL;
+
+ of_property_read_string(port, "type", &prop);
+
+ if (prop &&
+ strcmp(prop, type) == 0)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(of_graph_port_type_is);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index d9d6d9c..0a06441 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -40,9 +40,12 @@ struct of_endpoint {
for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \
child = of_graph_get_next_endpoint(parent, child))

+#define of_graph_port_type_is_sound(n) of_graph_port_type_is(n, "sound")
+
#ifdef CONFIG_OF
int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
+bool of_graph_port_type_is(struct device_node *port, char *type);
struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
@@ -61,6 +64,11 @@ static inline int of_graph_parse_endpoint(const struct device_node *node,
return -ENOSYS;
}

+static bool of_graph_port_type_is(struct device_node *port, char *type)
+{
+ return false;
+}
+
static inline struct device_node *of_graph_get_port_by_id(
struct device_node *node, u32 id)
{
--
1.9.1

2016-10-17 08:37:01

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 14/23] of_graph: add of_graph_get_port_parent()


From: Kuninori Morimoto <[email protected]>

Linux kernel already has of_graph_get_remote_port_parent(),
but, sometimes we want to get own port parent.
This patch adds of_graph_get_port_parent()

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 30 ++++++++++++++++++++++--------
include/linux/of_graph.h | 7 +++++++
2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index b035cff4..9d22391 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2370,6 +2370,27 @@ struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
EXPORT_SYMBOL(of_graph_get_remote_endpoint);

/**
+ * of_graph_get_port_parent() - get port's parent node
+ * @node: pointer to a local endpoint device_node
+ *
+ * Return: device node associated with endpoint node linked
+ * to @node. Use of_node_put() on it when done.
+ */
+struct device_node *of_graph_get_port_parent(struct device_node *node)
+{
+ unsigned int depth;
+
+ /* Walk 3 levels up only if there is 'ports' node. */
+ for (depth = 3; depth && node; depth--) {
+ node = of_get_next_parent(node);
+ if (depth == 2 && of_node_cmp(node->name, "ports"))
+ break;
+ }
+ return node;
+}
+EXPORT_SYMBOL(of_graph_get_port_parent);
+
+/**
* of_graph_get_remote_port_parent() - get remote port's parent node
* @node: pointer to a local endpoint device_node
*
@@ -2380,18 +2401,11 @@ struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
struct device_node *np;
- unsigned int depth;

/* Get remote endpoint node. */
np = of_graph_get_remote_endpoint(node);

- /* Walk 3 levels up only if there is 'ports' node. */
- for (depth = 3; depth && np; depth--) {
- np = of_get_next_parent(np);
- if (depth == 2 && of_node_cmp(np->name, "ports"))
- break;
- }
- return np;
+ return of_graph_get_port_parent(np);
}
EXPORT_SYMBOL(of_graph_get_remote_port_parent);

diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index 0a06441..0f362ed 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -53,6 +53,7 @@ struct device_node *of_graph_get_endpoint_by_regs(
const struct device_node *parent, int port_reg, int reg);
struct device_node *of_graph_get_remote_endpoint(
const struct device_node *node);
+struct device_node *of_graph_get_port_parent(struct device_node *node);
struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
struct device_node *of_graph_get_remote_port(const struct device_node *node);
@@ -94,6 +95,12 @@ static inline struct device_node *of_graph_get_remote_endpoint(
return NULL;
}

+static inline struct device_node *of_graph_get_port_parent(
+ struct device_node *node)
+{
+ return NULL;
+}
+
static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
--
1.9.1

2016-10-17 08:37:18

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 15/23] of_graph: add of_graph_get_top_port()


From: Kuninori Morimoto <[email protected]>

driver want to get top level of port[s] node. This patch adds
of_graph_get_top_port() for this purpose

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 24 ++++++++++++++++++++++++
include/linux/of_graph.h | 2 ++
2 files changed, 26 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 9d22391..07b9f68 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2261,6 +2261,30 @@ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
EXPORT_SYMBOL(of_graph_get_port_by_id);

/**
+ * of_graph_get_top_port() - get the top port node
+ * @dev: pointer to the device
+ *
+ * Return: A 'port' node pointer with refcount incremented. The caller
+ * has to use of_node_put() on it when done.
+ */
+struct device_node *of_graph_get_top_port(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct device_node *node;
+
+ node = of_get_child_by_name(np, "ports");
+ if (node)
+ return node;
+
+ node = of_get_child_by_name(np, "port");
+ if (node)
+ return node;
+
+ return NULL;
+}
+EXPORT_SYMBOL(of_graph_get_top_port);
+
+/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index 0f362ed..35e9a6e 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -14,6 +14,7 @@
#ifndef __LINUX_OF_GRAPH_H
#define __LINUX_OF_GRAPH_H

+#include <linux/device.h>
#include <linux/types.h>
#include <linux/errno.h>

@@ -47,6 +48,7 @@ int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
bool of_graph_port_type_is(struct device_node *port, char *type);
struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
+struct device_node *of_graph_get_top_port(struct device *dev);
struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
struct device_node *of_graph_get_endpoint_by_regs(
--
1.9.1

2016-10-17 08:37:28

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 16/23] of_graph: add for_each_of_port() / for_each_of_endpoint_in_port()

From: Kuninori Morimoto <[email protected]>

OF graph is used mainly from V4L2, but ALSA needs to use it. It already
has for_each_endpoint_of_node() which is for-loop for each endpoint.
But, ALSA needs for-loop for each port[s], and for-loop for each
endpoint of inside port[s]. This patch adds for_each_of_port()
and for_each_of_endpoint_in_port() for this purpose.

And it also adds for_each_of_endpoint() which is similar to
for_each_endpoint_of_node(). The difference is it can catch port
handle during for-loop.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/of_graph.h | 29 ++++++++++++++++++++++
2 files changed, 93 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 07b9f68..131f416 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2285,6 +2285,70 @@ struct device_node *of_graph_get_top_port(struct device *dev)
EXPORT_SYMBOL(of_graph_get_top_port);

/**
+ * of_graph_get_next_port() - get next port node
+ * @parent: pointer to the parent device node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_port(const struct device_node *parent,
+ struct device_node *prev)
+{
+ struct device_node *port;
+ struct device_node *node;
+
+ if (!parent)
+ return NULL;
+
+ node = of_get_child_by_name(parent, "ports");
+ if (node)
+ parent = node;
+
+ /*
+ * Start by locating the port node. If no previous endpoint is specified
+ * search for the first port node, otherwise get the previous endpoint
+ * parent port node.
+ */
+ if (!prev) {
+ port = of_get_child_by_name(parent, "port");
+ if (!port)
+ pr_err("%s(): no port node found in %s\n",
+ __func__, parent->full_name);
+ } else {
+ do {
+ port = of_get_next_child(parent, prev);
+ if (!port)
+ break;
+ } while (of_node_cmp(port->name, "port"));
+ }
+
+ of_node_put(node);
+
+ return port;
+}
+EXPORT_SYMBOL(of_graph_get_next_port);
+
+/**
+ * of_graph_get_next_endpoint_in_port() - get next endpoint node in port
+ * @parent: pointer to the parent device node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_endpoint_in_port(
+ const struct device_node *port,
+ struct device_node *prev)
+{
+ if (!port)
+ return NULL;
+
+ return of_get_next_child(port, prev);
+}
+EXPORT_SYMBOL(of_graph_get_next_endpoint_in_port);
+
+/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index 35e9a6e..eca1f3b 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -30,6 +30,16 @@ struct of_endpoint {
const struct device_node *local_node;
};

+#define for_each_of_port(parent, port) \
+ for (port = of_graph_get_next_port(parent, NULL); port != NULL; \
+ port = of_graph_get_next_port(parent, port))
+#define for_each_of_endpoint_in_port(port, ep) \
+ for (ep = of_graph_get_next_endpoint_in_port(port, NULL); ep != NULL; \
+ ep = of_graph_get_next_endpoint_in_port(port, ep))
+#define for_each_of_endpoint(parent, port, ep) \
+ for_each_of_port(parent, port) \
+ for_each_of_endpoint_in_port(port, ep)
+
/**
* for_each_endpoint_of_node - iterate over every endpoint in a device node
* @parent: parent device node containing ports and endpoints
@@ -49,6 +59,11 @@ int of_graph_parse_endpoint(const struct device_node *node,
bool of_graph_port_type_is(struct device_node *port, char *type);
struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
struct device_node *of_graph_get_top_port(struct device *dev);
+struct device_node *of_graph_get_next_port(const struct device_node *parent,
+ struct device_node *prev);
+struct device_node *of_graph_get_next_endpoint_in_port(
+ const struct device_node *port,
+ struct device_node *prev);
struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
struct device_node *previous);
struct device_node *of_graph_get_endpoint_by_regs(
@@ -78,6 +93,20 @@ static inline struct device_node *of_graph_get_port_by_id(
return NULL;
}

+static inline struct device_node *of_graph_get_next_port(
+ const struct device_node *parent,
+ struct device_node *prev)
+{
+ return NULL;
+}
+
+static inline struct device_node *of_graph_get_next_endpoint_in_port(
+ const struct device_node *port,
+ struct device_node *prev)
+{
+ return NULL;
+}
+
static inline struct device_node *of_graph_get_next_endpoint(
const struct device_node *parent,
struct device_node *previous)
--
1.9.1

2016-10-17 08:38:25

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 18/23] ASoC: simple-card-utils: add asoc_simple_card_parse_graph_dai()

From: Kuninori Morimoto <[email protected]>

simple-card already has asoc_simple_card_parse_dai(),
but graph base parsing needs graph specific version of it.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/simple_card_utils.h | 11 +++++++
sound/soc/generic/simple-card-utils.c | 57 +++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 09750ac..c79263a 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -60,6 +60,17 @@ int asoc_simple_card_parse_dai(struct device_node *node,
const char *cells_name,
int *is_single_links);

+#define asoc_simple_card_parse_graph_cpu(ep, dai_link, is_single_link) \
+ asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \
+ &dai_link->cpu_dai_name, is_single_link)
+#define asoc_simple_card_parse_graph_codec(ep, dai_link) \
+ asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \
+ &dai_link->codec_dai_name, NULL)
+int asoc_simple_card_parse_graph_dai(struct device_node *ep,
+ struct device_node **endpoint_np,
+ const char **dai_name,
+ int *is_single_link);
+
int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
struct asoc_simple_dai *simple_dai);

diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 6bc1510..47a73ee 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <sound/simple_card_utils.h>

int asoc_simple_card_parse_daifmt(struct device *dev,
@@ -165,6 +166,62 @@ int asoc_simple_card_parse_dai(struct device_node *node,
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);

+int asoc_simple_card_parse_graph_dai(struct device_node *ep,
+ struct device_node **dai_of_node,
+ const char **dai_name,
+ int *is_single_link)
+{
+ struct device_node *node, *port, *endpoint;
+ int i, id;
+
+ if (!ep)
+ return 0;
+
+ /*
+ * of_graph_get_port_parent() will call
+ * of_node_put(). So, call of_node_get() here
+ */
+ of_node_get(ep);
+ node = of_graph_get_port_parent(ep);
+
+ i = 0;
+ id = -1;
+ for_each_of_port(node, port) {
+ if (!of_graph_port_type_is_sound(port))
+ continue;
+
+ for_each_of_endpoint_in_port(port, endpoint) {
+ if (endpoint == ep)
+ id = i;
+ i++;
+ }
+ }
+ if (id < 0)
+ return -ENODEV;
+
+ /* Get dai->name */
+ if (dai_name) {
+ struct of_phandle_args args;
+ int ret;
+
+ args.np = node;
+ args.args[0] = id;
+ args.args_count = (i > 1);
+
+ ret = snd_soc_get_dai_name(&args, dai_name);
+ if (ret < 0)
+ return ret;
+ }
+
+ *dai_of_node = node;
+
+ if (is_single_link)
+ *is_single_link = (of_graph_get_sound_endpoint_count(node) == 1);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
+
int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
struct asoc_simple_dai *simple_dai)
{
--
1.9.1

2016-10-17 08:38:39

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 20/23] ASoC: add simple-graph-card document


From: Kuninori Morimoto <[email protected]>

Signed-off-by: Kuninori Morimoto <[email protected]>
---
.../bindings/sound/simple-graph-card.txt | 65 ++++++++++++++++++++++
1 file changed, 65 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/simple-graph-card.txt

diff --git a/Documentation/devicetree/bindings/sound/simple-graph-card.txt b/Documentation/devicetree/bindings/sound/simple-graph-card.txt
new file mode 100644
index 0000000..c191c0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/simple-graph-card.txt
@@ -0,0 +1,65 @@
+Simple-Graph-Card:
+
+Simple-Graph-Card specifies audio DAI connections of SoC <-> codec.
+It is based on common bindings for device graphs.
+see ${LINUX}/Documentation/devicetree/bindings/graph.txt
+
+Basically, Simple-Graph-Card is same as Simple-Card, but using graph style.
+see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
+
+Below are same as Simple-Card.
+
+- simple-audio-card,name
+- simple-audio-card,widgets
+- simple-audio-card,routing
+- simple-audio-card,mclk-fs
+- simple-audio-card,hp-det-gpio
+- simple-audio-card,mic-det-gpio
+- simple-audio-card,format
+- simple-audio-card,frame-master
+- simple-audio-card,bitclock-master
+- simple-audio-card,bitclock-inversion
+- simple-audio-card,frame-inversion
+- simple-audio-card,mclk-fs
+- simple-audio-card,dai-tdm-slot-num
+- simple-audio-card,dai-tdm-slot-width
+- clocks / system-clock-frequency
+
+This Simple-Graph-Card should be located as CPU driver's port[s].
+And then, CPU driver need to probe it by itself.
+
+Required properties:
+
+- compatible : "asoc-simple-graph-card";
+- type : "sound";
+
+Example
+
+ak4643: codec@12 {
+ compatible = "asahi-kasei,ak4643";
+ ...
+ port {
+ type = "sound";
+ ak4643_port: endpoint {
+ remote-endpoint = <&rcar_ak4643_port>;
+ clocks = <&audio_clock>;
+ };
+ };
+};
+
+rcar_sound {
+ ...
+ port {
+ compatible = "asoc-simple-graph-card";
+
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&ak4643_port>;
+ simple-audio-card,frame-master = <&ak4643_port>;
+ type = "sound";
+ rcar_ak4643_port: endpoint {
+ remote-endpoint = <&ak4643_port>;
+ playback = <&ssi0 &src2 &dvc0>;
+ capture = <&ssi1 &src3 &dvc1>;
+ };
+ };
+};
--
1.9.1

2016-10-17 08:38:20

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 17/23] of_graph: add of_graph_get_endpoint_count()


From: Kuninori Morimoto <[email protected]>

OF graph want to count its endpoint number, same as
of_get_child_count(). This patch adds of_graph_get_endpoint_count()
which can check specific type. It will count all endpoint if type
was NULL.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
drivers/of/base.c | 16 ++++++++++++++++
include/linux/of_graph.h | 8 ++++++++
2 files changed, 24 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 131f416..03a5bfc 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2529,3 +2529,19 @@ bool of_graph_port_type_is(struct device_node *port, char *type)
return false;
}
EXPORT_SYMBOL(of_graph_port_type_is);
+
+int of_graph_get_endpoint_count(const struct device_node *np, char *type)
+{
+ struct device_node *port, *endpoint;
+ int num = 0;
+
+ for_each_of_endpoint(np, port, endpoint) {
+ if (!type)
+ num++;
+ else
+ num += of_graph_port_type_is(port, type);
+ }
+
+ return num;
+}
+EXPORT_SYMBOL(of_graph_get_endpoint_count);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index eca1f3b..2d16be7 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -52,11 +52,13 @@ struct of_endpoint {
child = of_graph_get_next_endpoint(parent, child))

#define of_graph_port_type_is_sound(n) of_graph_port_type_is(n, "sound")
+#define of_graph_get_sound_endpoint_count(n) of_graph_get_endpoint_count(n, "sound")

#ifdef CONFIG_OF
int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
bool of_graph_port_type_is(struct device_node *port, char *type);
+int of_graph_get_endpoint_count(const struct device_node *np, char *type);
struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
struct device_node *of_graph_get_top_port(struct device *dev);
struct device_node *of_graph_get_next_port(const struct device_node *parent,
@@ -87,6 +89,12 @@ static bool of_graph_port_type_is(struct device_node *port, char *type)
return false;
}

+static inline int of_graph_get_endpoint_count(const struct device_node *np,
+ char *type)
+{
+ return 0;
+}
+
static inline struct device_node *of_graph_get_port_by_id(
struct device_node *node, u32 id)
{
--
1.9.1

2016-10-17 08:39:16

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 19/23] ASoC: simple-card-utils: add asoc_simple_card_try_to_probe_graph_card()

From: Kuninori Morimoto <[email protected]>

If CPU/Platform side driver probes successfully, and if it is supporting
both previous normal sound card style and graph style DT, it can call
asoc_simple_card_try_to_probe_graph_card().
It checks graph style DT, and do nothing if it was non graph style DT,
or register new simple-graph-card driver if graph style DT.

Signed-off-by: Kuninori Morimoto <[email protected]>
---
include/sound/simple_card_utils.h | 2 ++
sound/soc/generic/simple-card-utils.c | 42 +++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index c79263a..c8f090a 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -80,4 +80,6 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,

int asoc_simple_card_clean_reference(struct snd_soc_card *card);

+void asoc_simple_card_try_to_probe_graph_card(struct device *dev);
+
#endif /* __SIMPLE_CARD_CORE_H */
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 47a73ee..521257c 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
@@ -293,6 +294,47 @@ int asoc_simple_card_clean_reference(struct snd_soc_card *card)
}
EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);

+void asoc_simple_card_try_to_probe_graph_card(struct device *dev)
+{
+ struct platform_device_info pdevinfo;
+ struct device_node *node;
+ const char *compatible;
+ int ret;
+
+ node = of_graph_get_top_port(dev);
+ if (!node)
+ /*
+ * It doesn't have graph base sound DT.
+ * Do nothing here, It assumes that system has
+ * normal sound card.
+ */
+ return;
+
+ ret = of_property_read_string(node, "compatible", &compatible);
+ if (ret < 0)
+ goto probe_err;
+
+ /*
+ * FIXME
+ *
+ * It should use of_platform_xxx() instead of
+ * platform_device_register_full() ? but there is no solution.
+ * see also
+ * linux/sound/soc/generic/simple-graph-card.c :: asoc_simple_card_probe
+ */
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo.parent = dev;
+ pdevinfo.id = PLATFORM_DEVID_AUTO;
+ pdevinfo.name = compatible;
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+ platform_device_register_full(&pdevinfo);
+
+probe_err:
+ of_node_put(node);
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_try_to_probe_graph_card);
+
/* Module information */
MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
--
1.9.1

2016-10-17 08:39:30

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 21/23] ASoC: add simple-graph-card support


From: Kuninori Morimoto <[email protected]>

graph base DT binding are used on V4L2, and ALSA SoC is using different
style of DT. In case of simple case, ALSA SoC supports simple-card
driver.
In the future, V4L2 / ALSA will support HDMI, and then, DT bindings
between V4L2 / ALSA should be merged somehow.
This patch adds graph base DT binding with simple-card style

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/Kconfig | 7 +
sound/soc/generic/Makefile | 2 +
sound/soc/generic/simple-graph-card.c | 461 ++++++++++++++++++++++++++++++++++
3 files changed, 470 insertions(+)
create mode 100644 sound/soc/generic/simple-graph-card.c

diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
index b95ae49..764bc83 100644
--- a/sound/soc/generic/Kconfig
+++ b/sound/soc/generic/Kconfig
@@ -14,3 +14,10 @@ config SND_SIMPLE_SCU_CARD
help
This option enables generic simple SCU sound card support.
It supports DPCM of multi CPU single Codec ststem.
+
+config SND_SIMPLE_GRAPH_CARD
+ tristate "ASoC Simple Graph sound card support"
+ depends on OF
+ select SND_SIMPLE_CARD_UTILS
+ help
+ This option enables generic simple Graph sound card support
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
index ee750f3..94eb6f1 100644
--- a/sound/soc/generic/Makefile
+++ b/sound/soc/generic/Makefile
@@ -1,7 +1,9 @@
snd-soc-simple-card-utils-objs := simple-card-utils.o
snd-soc-simple-card-objs := simple-card.o
snd-soc-simple-scu-card-objs := simple-scu-card.o
+snd-soc-simple-graph-card-objs := simple-graph-card.o

obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o
obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o
+obj-$(CONFIG_SND_SIMPLE_GRAPH_CARD) += snd-soc-simple-graph-card.o
diff --git a/sound/soc/generic/simple-graph-card.c b/sound/soc/generic/simple-graph-card.c
new file mode 100644
index 0000000..3962b86
--- /dev/null
+++ b/sound/soc/generic/simple-graph-card.c
@@ -0,0 +1,461 @@
+/*
+ * ASoC simple graph sound card support
+ *
+ * Copyright (C) 2016 Renesas Solutions Corp.
+ * Kuninori Morimoto <[email protected]>
+ *
+ * based on ${LINUX}/sound/soc/generic/simple-card.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <sound/jack.h>
+#include <sound/simple_card_utils.h>
+
+struct asoc_simple_jack {
+ struct snd_soc_jack jack;
+ struct snd_soc_jack_pin pin;
+ struct snd_soc_jack_gpio gpio;
+};
+
+struct simple_card_data {
+ struct snd_soc_card snd_card;
+ struct simple_dai_props {
+ struct asoc_simple_dai cpu_dai;
+ struct asoc_simple_dai codec_dai;
+ unsigned int mclk_fs;
+ } *dai_props;
+ struct asoc_simple_jack hp_jack;
+ struct asoc_simple_jack mic_jack;
+ struct snd_soc_dai_link *dai_link;
+ unsigned int mclk_fs;
+};
+
+#define simple_priv_to_dev(priv) ((priv)->snd_card.dev)
+#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
+#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
+
+#define PREFIX "simple-audio-card,"
+
+#define asoc_simple_card_init_hp(card, node, sjack, prefix) \
+ asoc_simple_card_init_jack(card, node, sjack, 1, prefix)
+#define asoc_simple_card_init_mic(card, node, sjack, prefix) \
+ asoc_simple_card_init_jack(card, node, sjack, 0, prefix)
+static int asoc_simple_card_init_jack(struct snd_soc_card *card,
+ struct device_node *node,
+ struct asoc_simple_jack *sjack,
+ int is_hp, char *prefix)
+{
+ enum of_gpio_flags flags;
+ char prop[128];
+ char *pin_name;
+ char *gpio_name;
+ int mask;
+ int det;
+
+ sjack->gpio.gpio = -ENOENT;
+
+ if (is_hp) {
+ snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
+ pin_name = "Headphones";
+ gpio_name = "Headphone detection";
+ mask = SND_JACK_HEADPHONE;
+ } else {
+ snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
+ pin_name = "Mic Jack";
+ gpio_name = "Mic detection";
+ mask = SND_JACK_MICROPHONE;
+ }
+
+ det = of_get_named_gpio_flags(node, prop, 0, &flags);
+ if (det == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (gpio_is_valid(det)) {
+ sjack->pin.pin = pin_name;
+ sjack->pin.mask = mask;
+
+ sjack->gpio.name = gpio_name;
+ sjack->gpio.report = mask;
+ sjack->gpio.gpio = det;
+ sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
+ sjack->gpio.debounce_time = 150;
+
+ snd_soc_card_jack_new(card, pin_name, mask,
+ &sjack->jack,
+ &sjack->pin, 1);
+
+ snd_soc_jack_add_gpios(&sjack->jack, 1,
+ &sjack->gpio);
+ }
+
+ return 0;
+}
+
+static void asoc_simple_card_remove_jack(struct asoc_simple_jack *sjack)
+{
+ if (gpio_is_valid(sjack->gpio.gpio))
+ snd_soc_jack_free_gpios(&sjack->jack, 1, &sjack->gpio);
+}
+
+static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_dai_props *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+ int ret;
+
+ ret = clk_prepare_enable(dai_props->cpu_dai.clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(dai_props->codec_dai.clk);
+ if (ret)
+ clk_disable_unprepare(dai_props->cpu_dai.clk);
+
+ return ret;
+}
+
+static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_dai_props *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+
+ clk_disable_unprepare(dai_props->cpu_dai.clk);
+
+ clk_disable_unprepare(dai_props->codec_dai.clk);
+}
+
+static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_dai_props *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+ unsigned int mclk, mclk_fs = 0;
+ int ret = 0;
+
+ if (priv->mclk_fs)
+ mclk_fs = priv->mclk_fs;
+ else if (dai_props->mclk_fs)
+ mclk_fs = dai_props->mclk_fs;
+
+ if (mclk_fs) {
+ mclk = params_rate(params) * mclk_fs;
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+ SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP)
+ goto err;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+ SND_SOC_CLOCK_OUT);
+ if (ret && ret != -ENOTSUPP)
+ goto err;
+ }
+ return 0;
+err:
+ return ret;
+}
+
+static struct snd_soc_ops asoc_simple_card_ops = {
+ .startup = asoc_simple_card_startup,
+ .shutdown = asoc_simple_card_shutdown,
+ .hw_params = asoc_simple_card_hw_params,
+};
+
+static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct device *dev = simple_priv_to_dev(priv);
+ struct device *cpu_dev = dev->parent;
+ struct snd_soc_dai *codec = rtd->codec_dai;
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct simple_dai_props *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+ struct device_node *cpu_port = of_graph_get_top_port(cpu_dev);
+ int ret;
+
+ ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_init_hp(card, cpu_port, &priv->hp_jack, PREFIX);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_init_mic(card, cpu_port, &priv->hp_jack, PREFIX);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int asoc_simple_card_dai_link_of(struct device_node *cpu_ep,
+ struct simple_card_data *priv,
+ int idx)
+{
+ struct device *dev = simple_priv_to_dev(priv);
+ struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
+ struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
+ struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
+ struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
+ struct device_node *cpu_port;
+ struct device_node *cpu_remote_ep;
+ struct device_node *codec_ep;
+ int ret, single_cpu;
+
+ codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+ cpu_remote_ep = of_graph_get_remote_endpoint(codec_ep);
+
+ if (cpu_ep != cpu_remote_ep) {
+ dev_err(dev, "endpoint parse error\n");
+ ret = -EINVAL;
+ goto dai_link_of_err;
+ }
+
+ cpu_port = cpu_ep->parent;
+
+ ret = asoc_simple_card_parse_daifmt(dev, cpu_port, codec_ep,
+ PREFIX, &dai_link->dai_fmt);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ of_property_read_u32(cpu_port, "mclk-fs", &dai_props->mclk_fs);
+
+ ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link,
+ &single_cpu);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = asoc_simple_card_parse_graph_codec(codec_ep, dai_link);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = snd_soc_of_parse_tdm_slot(cpu_ep,
+ &cpu_dai->tx_slot_mask,
+ &cpu_dai->rx_slot_mask,
+ &cpu_dai->slots,
+ &cpu_dai->slot_width);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = snd_soc_of_parse_tdm_slot(codec_ep,
+ &codec_dai->tx_slot_mask,
+ &codec_dai->rx_slot_mask,
+ &codec_dai->slots,
+ &codec_dai->slot_width);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = asoc_simple_card_parse_clk_cpu(cpu_ep, dai_link, cpu_dai);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = asoc_simple_card_parse_clk_codec(codec_ep, dai_link, codec_dai);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = asoc_simple_card_canonicalize_dailink(dai_link);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
+ "%s-%s",
+ dai_link->cpu_dai_name,
+ dai_link->codec_dai_name);
+ if (ret < 0)
+ goto dai_link_of_err;
+
+ dai_link->ops = &asoc_simple_card_ops;
+ dai_link->init = asoc_simple_card_dai_init;
+
+ dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
+ dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
+ dev_dbg(dev, "\tcpu : %s / %d\n",
+ dai_link->cpu_dai_name,
+ dai_props->cpu_dai.sysclk);
+ dev_dbg(dev, "\tcodec : %s / %d\n",
+ dai_link->codec_dai_name,
+ dai_props->codec_dai.sysclk);
+
+ asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
+
+dai_link_of_err:
+ of_node_put(codec_ep);
+ of_node_put(cpu_remote_ep);
+
+ return ret;
+}
+
+static int asoc_simple_card_parse_of(struct device_node *node,
+ struct simple_card_data *priv)
+{
+ struct device *dev = simple_priv_to_dev(priv);
+ struct device *cpu_dev = dev->parent;
+ struct device_node *top_port = of_graph_get_top_port(cpu_dev);
+ struct snd_soc_card *card = &priv->snd_card;
+ struct device_node *port, *ep;
+ int i = 0, ret;
+
+ if (!node)
+ return -EINVAL;
+
+ for_each_of_port(node, port) {
+ if (!of_graph_port_type_is_sound(port))
+ continue;
+
+ /* The off-codec widgets */
+ if (of_property_read_bool(port, PREFIX "widgets")) {
+ ret = snd_soc_of_parse_audio_simple_widgets_from_node(
+ &priv->snd_card,
+ port, PREFIX "widgets");
+ if (ret)
+ return ret;
+ }
+
+ /* DAPM routes */
+ if (of_property_read_bool(port, PREFIX "routing")) {
+ ret = snd_soc_of_parse_audio_routing_from_node(
+ &priv->snd_card,
+ port, PREFIX "routing");
+ if (ret)
+ return ret;
+ }
+
+ /* Factor to mclk, used in hw_params() */
+ of_property_read_u32(port, PREFIX "mclk-fs", &priv->mclk_fs);
+
+ for_each_of_endpoint_in_port(port, ep) {
+ ret = asoc_simple_card_dai_link_of(ep, priv, i);
+ if (ret < 0) {
+ of_node_put(ep);
+ return ret;
+ }
+ i++;
+ }
+ }
+
+ ret = asoc_simple_card_parse_card_name(card, top_port, PREFIX);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int asoc_simple_card_probe(struct platform_device *pdev)
+{
+ struct simple_card_data *priv;
+ struct snd_soc_dai_link *dai_link;
+ struct simple_dai_props *dai_props;
+ struct device *dev = &pdev->dev;
+ struct device *cpu_dev = pdev->dev.parent;
+ struct device_node *cpu_node = cpu_dev->of_node;
+ int num, ret;
+
+ /* Allocate the private data and the DAI link array */
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ num = of_graph_get_sound_endpoint_count(cpu_node);
+
+ dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ if (!dai_props || !dai_link)
+ return -ENOMEM;
+
+ priv->dai_props = dai_props;
+ priv->dai_link = dai_link;
+
+ /* Init snd_soc_card */
+ priv->snd_card.owner = THIS_MODULE;
+ priv->snd_card.dev = dev;
+ priv->snd_card.dai_link = priv->dai_link;
+ priv->snd_card.num_links = num;
+
+ ret = asoc_simple_card_parse_of(cpu_node, priv);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "parse error %d\n", ret);
+ goto err;
+ }
+
+ /*
+ * FIXME
+ *
+ * This driver is assuming that it will be called from
+ * asoc_simple_card_try_to_probe_graph_card() which
+ * is using platform_device_register_full().
+ * This means it is not came from DT. But this driver itself
+ * will be used as part of ALSA SoC (= sound card).
+ * Because of these background, it might fail in
+ * snd_pcm_lib_malloc_pages() on .hw_params.
+ * Because, noone cares its dma_ops, and result of get_dma_ops()
+ * is based on its architecture.
+ * So, it should call arch_setup_dma_ops() from somewhere,
+ * otherwise, for example, ARM is no problem, but ARM64 will be fail.
+ * But, of_platform_device_xxx() are not good solution today.
+ * This driver calls it by itself here. Please fixme
+ * see also
+ * linux/sound/soc/generic/simple-card-utils.c ::
+ * asoc_simple_card_try_to_probe_graph_card()
+ */
+ of_dma_configure(dev, dev->of_node);
+
+ snd_soc_card_set_drvdata(&priv->snd_card, priv);
+
+ ret = devm_snd_soc_register_card(dev, &priv->snd_card);
+ if (ret >= 0)
+ return ret;
+err:
+ asoc_simple_card_clean_reference(&priv->snd_card);
+
+ return ret;
+}
+
+static int asoc_simple_card_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
+
+ asoc_simple_card_remove_jack(&priv->hp_jack);
+ asoc_simple_card_remove_jack(&priv->mic_jack);
+
+ return asoc_simple_card_clean_reference(&priv->snd_card);
+}
+
+static struct platform_driver asoc_simple_card = {
+ .driver = {
+ .name = "asoc-simple-graph-card",
+ },
+ .probe = asoc_simple_card_probe,
+ .remove = asoc_simple_card_remove,
+};
+module_platform_driver(asoc_simple_card);
+
+MODULE_ALIAS("platform:asoc-simple-graph-card");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Simple Graph Sound Card");
+MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
--
1.9.1

2016-10-17 08:39:40

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 22/23] ASoC: add simple-graph-scu-card document


From: Kuninori Morimoto <[email protected]>

Signed-off-by: Kuninori Morimoto <[email protected]>
---
.../bindings/sound/simple-graph-scu-card.txt | 66 ++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/simple-graph-scu-card.txt

diff --git a/Documentation/devicetree/bindings/sound/simple-graph-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-graph-scu-card.txt
new file mode 100644
index 0000000..81f64e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/simple-graph-scu-card.txt
@@ -0,0 +1,66 @@
+Simple-Graph-SCU-Card:
+
+Simple-Graph-SCU-Card specifies audio DAI connections of SoC <-> codec.
+It is based on common bindings for device graphs.
+see ${LINUX}/Documentation/devicetree/bindings/graph.txt
+
+Basically, Simple-Graph-SCU-Card is same as Simple-Card / Simple-Graph-Card.
+see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
+ ${LINUX}/Documentation/devicetree/bindings/sound/simple-graph-card.txt
+
+Main difference is that Simple-Graph-SCU-Card can use multi CPU.
+
+Required properties:
+
+- compatible : "asoc-simple-graph-scu-card";
+- type : "sound";
+- simple-audio-card,routing : see simple-card.txt
+
+Example
+
+ak4643: codec@12 {
+ compatible = "asahi-kasei,ak4643";
+ ...
+ port {
+ type = "sound";
+ ak4643_fe: endpoint@0 {
+ remote-endpoint = <&rsnd_fe>;
+ clocks = <&audio_clock>;
+ };
+ ak4643_be: endpoint@1 {
+ remote-endpoint = <&rsnd_be>;
+ };
+ };
+};
+
+rcar_sound {
+ ...
+ ports {
+ compatible = "asoc-simple-graph-scu-card";
+ simple-audio-card,name = "graph-sound";
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&rsnd_fe>;
+ simple-audio-card,frame-master = <&rsnd_fe>;
+ simple-audio-card,convert-rate = <48000>;
+ simple-audio-card,convert-channels = <2>;
+ simple-audio-card,prefix = "ak4642";
+ simple-audio-card,routing =
+ "ak4642 Playback", "DAI0 Playback",
+ "ak4642 Playback", "DAI1 Playback";
+
+ port@0 {
+ type = "sound";
+ rsnd_fe: endpoint@0 {
+ remote-endpoint = <&ak4643_fe>;
+ playback = <&src1 &ctu02 &mix0 &dvc0 &ssi0>;
+ };
+ };
+ port@1 {
+ type = "sound";
+ rsnd_be: endpoint@1 {
+ remote-endpoint = <&ak4643_be>;
+ playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
+ };
+ };
+ };
+};
--
1.9.1

2016-10-17 08:41:18

by Kuninori Morimoto

[permalink] [raw]
Subject: [PATCH 23/23] ASoC: add simple-graph-scu-card support


From: Kuninori Morimoto <[email protected]>

graph base DT binding are used on V4L2, and ALSA SoC is using different
style of DT. In case of simple case, ALSA SoC supports simple-card
driver.
In the future, V4L2 / ALSA will support HDMI, and then, DT bindings
between V4L2 / ALSA should be merged somehow.
Sometimes, we would like to use DPCM base simple-card on graph base DT.
This patch adds graph base DT binding of simple-scu-card

Signed-off-by: Kuninori Morimoto <[email protected]>
---
sound/soc/generic/Kconfig | 8 +
sound/soc/generic/Makefile | 2 +
sound/soc/generic/simple-graph-scu-card.c | 437 ++++++++++++++++++++++++++++++
3 files changed, 447 insertions(+)
create mode 100644 sound/soc/generic/simple-graph-scu-card.c

diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
index 764bc83..c2671c3 100644
--- a/sound/soc/generic/Kconfig
+++ b/sound/soc/generic/Kconfig
@@ -21,3 +21,11 @@ config SND_SIMPLE_GRAPH_CARD
select SND_SIMPLE_CARD_UTILS
help
This option enables generic simple Graph sound card support
+
+config SND_SIMPLE_GRAPH_SCU_CARD
+ tristate "ASoC Simple Graph SCU sound card support"
+ depends on OF
+ select SND_SIMPLE_CARD_UTILS
+ help
+ This option enables generic simple Graph SCU sound card support.
+ It supports DPCM of multi CPU single Codec ststem.
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
index 94eb6f1..fd75b55 100644
--- a/sound/soc/generic/Makefile
+++ b/sound/soc/generic/Makefile
@@ -2,8 +2,10 @@ snd-soc-simple-card-utils-objs := simple-card-utils.o
snd-soc-simple-card-objs := simple-card.o
snd-soc-simple-scu-card-objs := simple-scu-card.o
snd-soc-simple-graph-card-objs := simple-graph-card.o
+snd-soc-simple-graph-scu-card-objs := simple-graph-scu-card.o

obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o
obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o
obj-$(CONFIG_SND_SIMPLE_GRAPH_CARD) += snd-soc-simple-graph-card.o
+obj-$(CONFIG_SND_SIMPLE_GRAPH_SCU_CARD) += snd-soc-simple-graph-scu-card.o
diff --git a/sound/soc/generic/simple-graph-scu-card.c b/sound/soc/generic/simple-graph-scu-card.c
new file mode 100644
index 0000000..cb23b66
--- /dev/null
+++ b/sound/soc/generic/simple-graph-scu-card.c
@@ -0,0 +1,437 @@
+/*
+ * ASoC simple graph SCU sound card support
+ *
+ * Copyright (C) 2016 Renesas Solutions Corp.
+ * Kuninori Morimoto <[email protected]>
+ *
+ * based on
+ * ${LINUX}/sound/soc/generic/simple-graph-card.c
+ * ${LINUX}/sound/soc/generic/simple-scu-card.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <sound/jack.h>
+#include <sound/simple_card_utils.h>
+
+struct simple_card_data {
+ struct snd_soc_card snd_card;
+ struct snd_soc_codec_conf codec_conf;
+ struct asoc_simple_dai *dai_props;
+ struct snd_soc_dai_link *dai_link;
+ u32 convert_rate;
+ u32 convert_channels;
+};
+
+#define simple_priv_to_dev(priv) ((priv)->snd_card.dev)
+#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
+#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
+
+#define PREFIX "simple-audio-card,"
+
+static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct asoc_simple_dai *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+
+ return clk_prepare_enable(dai_props->clk);
+}
+
+static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct asoc_simple_dai *dai_props =
+ simple_priv_to_props(priv, rtd->num);
+
+ clk_disable_unprepare(dai_props->clk);
+}
+
+static struct snd_soc_ops asoc_simple_card_ops = {
+ .startup = asoc_simple_card_startup,
+ .shutdown = asoc_simple_card_shutdown,
+};
+
+static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_dai *dai;
+ struct snd_soc_dai_link *dai_link;
+ struct asoc_simple_dai *dai_props;
+ int num = rtd->num;
+
+ dai_link = simple_priv_to_link(priv, num);
+ dai_props = simple_priv_to_props(priv, num);
+ dai = dai_link->dynamic ?
+ rtd->cpu_dai :
+ rtd->codec_dai;
+
+ return asoc_simple_card_init_dai(dai, dai_props);
+}
+
+static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ if (priv->convert_rate)
+ rate->min =
+ rate->max = priv->convert_rate;
+
+ if (priv->convert_channels)
+ channels->min =
+ channels->max = priv->convert_channels;
+
+ return 0;
+}
+
+static int asoc_simple_card_dai_link_of(struct device_node *port,
+ struct device_node *ep,
+ struct simple_card_data *priv,
+ unsigned int daifmt,
+ int idx, int is_fe)
+{
+ struct device *dev = simple_priv_to_dev(priv);
+ struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
+ struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx);
+ int is_single_links = 0;
+ int ret;
+
+ if (is_fe) {
+ /* BE is dummy */
+ dai_link->codec_of_node = NULL;
+ dai_link->codec_dai_name = "snd-soc-dummy-dai";
+ dai_link->codec_name = "snd-soc-dummy";
+
+ /* FE settings */
+ dai_link->dynamic = 1;
+ dai_link->dpcm_merged_format = 1;
+
+ ret = asoc_simple_card_parse_graph_cpu(ep, dai_link,
+ &is_single_links);
+ if (ret)
+ return ret;
+
+ ret = asoc_simple_card_parse_clk_cpu(ep, dai_link, dai_props);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
+ "fe.%s",
+ dai_link->cpu_dai_name);
+ if (ret < 0)
+ return ret;
+
+ asoc_simple_card_canonicalize_cpu(dai_link, is_single_links);
+ } else {
+ /* FE is dummy */
+ dai_link->cpu_of_node = NULL;
+ dai_link->cpu_dai_name = "snd-soc-dummy-dai";
+ dai_link->cpu_name = "snd-soc-dummy";
+
+ /* BE settings */
+ dai_link->no_pcm = 1;
+ dai_link->be_hw_params_fixup = asoc_simple_card_be_hw_params_fixup;
+
+ ret = asoc_simple_card_parse_graph_codec(ep, dai_link);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_parse_clk_codec(ep, dai_link, dai_props);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
+ "be.%s",
+ dai_link->codec_dai_name);
+ if (ret < 0)
+ return ret;
+
+ snd_soc_of_parse_audio_prefix_from_node(&priv->snd_card,
+ port->parent,
+ &priv->codec_conf,
+ dai_link->codec_of_node,
+ PREFIX "prefix");
+ }
+
+ ret = snd_soc_of_parse_tdm_slot(ep,
+ &dai_props->tx_slot_mask,
+ &dai_props->rx_slot_mask,
+ &dai_props->slots,
+ &dai_props->slot_width);
+ if (ret)
+ return ret;
+
+ ret = asoc_simple_card_canonicalize_dailink(dai_link);
+ if (ret < 0)
+ return ret;
+
+ dai_link->dai_fmt = daifmt;
+ dai_link->dpcm_playback = 1;
+ dai_link->dpcm_capture = 1;
+ dai_link->ops = &asoc_simple_card_ops;
+ dai_link->init = asoc_simple_card_dai_init;
+
+ dev_dbg(dev, "\t%s / %04x / %d\n",
+ dai_link->name,
+ dai_link->dai_fmt,
+ dai_props->sysclk);
+
+ return 0;
+}
+
+static int asoc_simple_card_parse_of(struct device_node *node,
+ struct simple_card_data *priv)
+{
+ struct device *dev = simple_priv_to_dev(priv);
+ struct device *cpu_dev = dev->parent;
+ struct device_node *ports = of_graph_get_top_port(cpu_dev);
+ struct snd_soc_card *card = &priv->snd_card;
+ struct device_node *port, *cpu_ep, *r_cpu_ep, *codec_ep;
+ unsigned int daifmt = 0;
+ int i, ret, done;
+
+ if (!node)
+ return -EINVAL;
+
+ ret = snd_soc_of_parse_audio_routing_from_node(&priv->snd_card,
+ ports, PREFIX "routing");
+ if (ret)
+ return ret;
+
+ /* sampling rate convert */
+ of_property_read_u32(ports, PREFIX "convert-rate",
+ &priv->convert_rate);
+
+ /* channels transfer */
+ of_property_read_u32(ports, PREFIX "convert-channels",
+ &priv->convert_channels);
+
+ /*
+ * it supports multi CPU, single CODEC only here.
+ */
+
+ /* find 1st codec */
+ done = 0;
+ for_each_of_port(node, port) {
+ if (!of_graph_port_type_is_sound(port))
+ continue;
+
+ for_each_of_endpoint_in_port(port, cpu_ep) {
+ /* keep for_each for of_node_get/of_node_put */
+ if (done)
+ continue;
+
+ codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+ r_cpu_ep = of_graph_get_remote_endpoint(codec_ep);
+ of_node_put(codec_ep);
+ of_node_put(r_cpu_ep);
+ if (cpu_ep != r_cpu_ep) {
+ ret = -EINVAL;
+ goto parse_of_err;
+ }
+
+ ret = asoc_simple_card_parse_daifmt(dev,
+ ports, codec_ep,
+ PREFIX, &daifmt);
+ if (ret < 0)
+ goto parse_of_err;
+
+ done = 1;
+ }
+ }
+
+ /* Front-End (= CPU) */
+ i = 0;
+ for_each_of_port(node, port) {
+ if (!of_graph_port_type_is_sound(port))
+ continue;
+
+ for_each_of_endpoint_in_port(port, cpu_ep) {
+ ret = asoc_simple_card_dai_link_of(
+ port, cpu_ep, priv, daifmt, i, 1);
+ if (ret < 0)
+ goto parse_of_err;
+ i++;
+ }
+ }
+
+ /* Back-End (= Codec) */
+ done = 0;
+ for_each_of_port(node, port) {
+ if (!of_graph_port_type_is_sound(port))
+ continue;
+
+ /* keep for_each for of_node_get/of_node_put */
+ if (done)
+ continue;
+
+ for_each_of_endpoint_in_port(port, cpu_ep) {
+ /* keep for_each for of_node_get/of_node_put */
+ if (done)
+ continue;
+
+ codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+ r_cpu_ep = of_graph_get_remote_endpoint(codec_ep);
+ of_node_put(codec_ep);
+ of_node_put(r_cpu_ep);
+ if (cpu_ep != r_cpu_ep) {
+ ret = -EINVAL;
+ goto parse_of_err;
+ }
+
+ ret = asoc_simple_card_dai_link_of(
+ port, codec_ep, priv, daifmt, i, 0);
+ if (ret < 0)
+ goto parse_of_err;
+ i++;
+
+ done = 1;
+ }
+ }
+
+ ret = asoc_simple_card_parse_card_name(card, ports, PREFIX);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "New card: %s\n",
+ priv->snd_card.name ? priv->snd_card.name : "");
+ dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
+ dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
+
+ return 0;
+parse_of_err:
+ of_node_put(port);
+ of_node_put(cpu_ep);
+
+ return ret;
+}
+
+static int asoc_get_sound_port_count(struct device_node *cpu_node)
+{
+ int num;
+
+ /*
+ * it supports multi CPU, single CODEC only here.
+ */
+
+ /* CPU */
+ num = of_graph_get_sound_endpoint_count(cpu_node);
+
+ /* Codec */
+ num++;
+
+ return num;
+}
+
+static int asoc_simple_card_probe(struct platform_device *pdev)
+{
+ struct simple_card_data *priv;
+ struct snd_soc_dai_link *dai_link;
+ struct asoc_simple_dai *dai_props;
+ struct device *dev = &pdev->dev;
+ struct device *cpu_dev = pdev->dev.parent;
+ struct device_node *cpu_node = cpu_dev->of_node;
+ int num, ret;
+
+ /* Allocate the private data and the DAI link array */
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ num = asoc_get_sound_port_count(cpu_node);
+
+ dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ if (!dai_props || !dai_link)
+ return -ENOMEM;
+
+ priv->dai_props = dai_props;
+ priv->dai_link = dai_link;
+
+ /* Init snd_soc_card */
+ priv->snd_card.owner = THIS_MODULE;
+ priv->snd_card.dev = dev;
+ priv->snd_card.dai_link = priv->dai_link;
+ priv->snd_card.num_links = num;
+ priv->snd_card.codec_conf = &priv->codec_conf;
+ priv->snd_card.num_configs = 1;
+
+ ret = asoc_simple_card_parse_of(cpu_node, priv);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "parse error %d\n", ret);
+ goto err;
+ }
+
+ /*
+ * FIXME
+ *
+ * This driver is assuming that it will be called from
+ * asoc_simple_card_try_to_probe_graph_card() which
+ * is using platform_device_register_full().
+ * This means it is not came from DT. But this driver itself
+ * will be used as part of ALSA SoC (= sound card).
+ * Because of these background, it might fail in
+ * snd_pcm_lib_malloc_pages() on .hw_params.
+ * Because, noone cares its dma_ops, and result of get_dma_ops()
+ * is based on its architecture.
+ * So, it should call arch_setup_dma_ops() from somewhere,
+ * otherwise, for example, ARM is no problem, but ARM64 will be fail.
+ * But, of_platform_device_xxx() are not good solution today.
+ * This driver calls it by itself here. Please fixme
+ * see also
+ * linux/sound/soc/generic/simple-card-utils.c ::
+ * asoc_simple_card_try_to_probe_graph_card()
+ */
+ of_dma_configure(dev, dev->of_node);
+
+ snd_soc_card_set_drvdata(&priv->snd_card, priv);
+
+ ret = devm_snd_soc_register_card(dev, &priv->snd_card);
+ if (ret >= 0)
+ return ret;
+err:
+ asoc_simple_card_clean_reference(&priv->snd_card);
+
+ return ret;
+}
+
+static int asoc_simple_card_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
+
+ return asoc_simple_card_clean_reference(&priv->snd_card);
+}
+
+static struct platform_driver asoc_simple_card = {
+ .driver = {
+ .name = "asoc-simple-graph-scu-card",
+ },
+ .probe = asoc_simple_card_probe,
+ .remove = asoc_simple_card_remove,
+};
+module_platform_driver(asoc_simple_card);
+
+MODULE_ALIAS("platform:asoc-simple-graph-scu-card");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Simple Graph SCU Sound Card");
+MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
--
1.9.1

2016-10-18 07:10:41

by Jean-Francois Moine

[permalink] [raw]
Subject: Re: [alsa-devel] [PATCH 0/23] ASoC: add OF graph base simple-card

On Mon, 17 Oct 2016 08:30:49 +0000
Kuninori Morimoto <[email protected]> wrote:

> These are OF graph base simple-card patch-set.
> 1) - 3) : simple-scu-card cleanup
> 4) - 10) : soc-core prepare for OF graph card
> 11) - 17) : OF graph new feature
> 18) - 23) : OF graph base simple-card
>
> I posted 11) - 17) OF graph new feature patches before, and then Rob requested
> about usecase. 18) - 23) can be usecase for it.
> 1) - 10) are independent (= Mark)
> 11) - 17) are independent (= Rob)
> 18) - 23) are depends on 1) - 10) and 11) - 17) (= Mark)
>
> Kuninori Morimoto (23):
> 1) ASoC: simple-scu-card: code sync: follow to simple family style
> 2) ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv
> 3) ASoC: simple-scu-card: code sync: tidyup props/link naming
> 4) ASoC: soc-core: adjust for graph on snd_soc_of_parse_card_name
> 5) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_simple_widgets
> 6) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_routing
> 7) ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_prefix
> 8) ASoC: soc-core: snd_soc_get_dai_name() become non static
> 9) ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check
> 10) ASoC: simple-card-utils: adjust for graph on asoc_simple_card_parse_card_name
> 11) Documentation: of: add type property
> 12) of_graph: add of_graph_get_remote_endpoint()
> 13) of_graph: add of_graph_port_type_is()
> 14) of_graph: add of_graph_get_port_parent()
> 15) of_graph: add of_graph_get_top_port()
> 16) of_graph: add for_each_of_port() / for_each_of_endpoint_in_port()
> 17) of_graph: add of_graph_get_endpoint_count()
> 18) ASoC: simple-card-utils: add asoc_simple_card_parse_graph_dai()
> 19) ASoC: simple-card-utils: add asoc_simple_card_try_to_probe_graph_card()
> 20) ASoC: add simple-graph-card document
> 21) ASoC: add simple-graph-card support
> 22) ASoC: add simple-graph-scu-card document
> 23) ASoC: add simple-graph-scu-card support
[snip]

Hi Kuninori,

The patches 11..17 put trivial functions in the OF core. As they are
used by only a few systems, it would be better to define them as
macros, or in a module or in the simple-card-utils.

--
Ken ar c'henta? | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/

2016-10-18 07:27:25

by Jean-Francois Moine

[permalink] [raw]
Subject: Re: [alsa-devel] [PATCH 08/23] ASoC: soc-core: snd_soc_get_dai_name() become non static

On Mon, 17 Oct 2016 08:34:19 +0000
Kuninori Morimoto <[email protected]> wrote:

> From: Kuninori Morimoto <[email protected]>
>
> snd_soc_get_dai_name() is used from snd_soc_of_get_dai_name(),
> and it is assuming that DT is using "sound-dai" / "#sound-dai-cells".
> But graph base DT is using "remote-endpoint". This patch makes
> snd_soc_get_dai_name() non static for graph support.
>
> Signed-off-by: Kuninori Morimoto <[email protected]>
> ---
> include/sound/soc.h | 2 ++
> sound/soc/soc-core.c | 3 ++-
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index fd63d23..77b01c4 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -1677,6 +1677,8 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
> const char *prefix,
> struct device_node **bitclkmaster,
> struct device_node **framemaster);
> +int snd_soc_get_dai_name(struct of_phandle_args *args,
> + const char **dai_name);
> int snd_soc_of_get_dai_name(struct device_node *of_node,
> const char **dai_name);
> int snd_soc_of_get_dai_link_codecs(struct device *dev,
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index 8371488..6f911f4 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -3794,7 +3794,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
> }
> EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
>
> -static int snd_soc_get_dai_name(struct of_phandle_args *args,
> +int snd_soc_get_dai_name(struct of_phandle_args *args,
> const char **dai_name)
> {
> struct snd_soc_component *pos;
> @@ -3846,6 +3846,7 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args,
> mutex_unlock(&client_mutex);
> return ret;
> }
> +EXPORT_SYMBOL_GPL(snd_soc_get_dai_name);
>
> int snd_soc_of_get_dai_name(struct device_node *of_node,
> const char **dai_name)
> --
> 1.9.1

I already proposed this patch
http://mailman.alsa-project.org/pipermail/alsa-devel/2015-January/086870.html
but it seems people were not interested.
I hope now is the right time.

Acked-by: Jean-Francois Moine <[email protected]>

--
Ken ar c'henta? | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/

2016-10-18 08:44:53

by Kuninori Morimoto

[permalink] [raw]
Subject: Re: [alsa-devel] [PATCH 0/23] ASoC: add OF graph base simple-card


Hi Jean-Francois

> > These are OF graph base simple-card patch-set.
> > 1) - 3) : simple-scu-card cleanup
> > 4) - 10) : soc-core prepare for OF graph card
> > 11) - 17) : OF graph new feature
> > 18) - 23) : OF graph base simple-card
(snip)
> > 11) Documentation: of: add type property
> > 12) of_graph: add of_graph_get_remote_endpoint()
> > 13) of_graph: add of_graph_port_type_is()
> > 14) of_graph: add of_graph_get_port_parent()
> > 15) of_graph: add of_graph_get_top_port()
> > 16) of_graph: add for_each_of_port() / for_each_of_endpoint_in_port()
> > 17) of_graph: add of_graph_get_endpoint_count()
(snip)
> The patches 11..17 put trivial functions in the OF core. As they are
> used by only a few systems, it would be better to define them as
> macros, or in a module or in the simple-card-utils.

We can replace few drivers to use it. I will post it if these were accepted.
And let's follow Rob's opinion. Actually, these patches had posted
few month ago, and these already got OK from him.

Best regards
---
Kuninori Morimoto

2016-10-18 15:54:29

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH 20/23] ASoC: add simple-graph-card document

On Mon, Oct 17, 2016 at 3:38 AM, Kuninori Morimoto
<[email protected]> wrote:
>
> From: Kuninori Morimoto <[email protected]>
>
> Signed-off-by: Kuninori Morimoto <[email protected]>
> ---
> .../bindings/sound/simple-graph-card.txt | 65 ++++++++++++++++++++++
> 1 file changed, 65 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/sound/simple-graph-card.txt
>
> diff --git a/Documentation/devicetree/bindings/sound/simple-graph-card.txt b/Documentation/devicetree/bindings/sound/simple-graph-card.txt
> new file mode 100644
> index 0000000..c191c0d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/simple-graph-card.txt
> @@ -0,0 +1,65 @@
> +Simple-Graph-Card:
> +
> +Simple-Graph-Card specifies audio DAI connections of SoC <-> codec.
> +It is based on common bindings for device graphs.
> +see ${LINUX}/Documentation/devicetree/bindings/graph.txt
> +
> +Basically, Simple-Graph-Card is same as Simple-Card, but using graph style.
> +see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
> +
> +Below are same as Simple-Card.
> +
> +- simple-audio-card,name
> +- simple-audio-card,widgets
> +- simple-audio-card,routing
> +- simple-audio-card,mclk-fs
> +- simple-audio-card,hp-det-gpio
> +- simple-audio-card,mic-det-gpio
> +- simple-audio-card,format
> +- simple-audio-card,frame-master
> +- simple-audio-card,bitclock-master
> +- simple-audio-card,bitclock-inversion
> +- simple-audio-card,frame-inversion
> +- simple-audio-card,mclk-fs
> +- simple-audio-card,dai-tdm-slot-num
> +- simple-audio-card,dai-tdm-slot-width
> +- clocks / system-clock-frequency
> +
> +This Simple-Graph-Card should be located as CPU driver's port[s].
> +And then, CPU driver need to probe it by itself.
> +
> +Required properties:
> +
> +- compatible : "asoc-simple-graph-card";
> +- type : "sound";
> +
> +Example
> +
> +ak4643: codec@12 {
> + compatible = "asahi-kasei,ak4643";
> + ...
> + port {
> + type = "sound";
> + ak4643_port: endpoint {
> + remote-endpoint = <&rcar_ak4643_port>;
> + clocks = <&audio_clock>;

This belongs in the codec node.

> + };
> + };
> +};
> +
> +rcar_sound {
> + ...
> + port {
> + compatible = "asoc-simple-graph-card";
> +
> + simple-audio-card,format = "left_j";
> + simple-audio-card,bitclock-master = <&ak4643_port>;
> + simple-audio-card,frame-master = <&ak4643_port>;

Don't add a bunch of properties with in port and endpoint nodes. The
purpose is to describe the graph. Put these in the parent node or
perhaps the codec node.

> + type = "sound";

I'm still not convinced this is necessary. This is implied either by
the fact there is only one port or perhaps the compatible string.

> + rcar_ak4643_port: endpoint {
> + remote-endpoint = <&ak4643_port>;
> + playback = <&ssi0 &src2 &dvc0>;
> + capture = <&ssi1 &src3 &dvc1>;
> + };
> + };
> +};
> --
> 1.9.1
>

2016-10-19 01:36:52

by Kuninori Morimoto

[permalink] [raw]
Subject: Re: [PATCH 20/23] ASoC: add simple-graph-card document


Hi Rob

> > + type = "sound";
>
> I'm still not convinced this is necessary. This is implied either by
> the fact there is only one port or perhaps the compatible string.

Do you mean "on this sample" ? or in general ?
Indeed this sample is definitely for sound, so type is very clear
without property.
But in general, for example HDMI, it want to know port type.
Anyway, I can remove above "type" from this new sound driver.

> > +rcar_sound {
> > + ...
> > + port {
> > + compatible = "asoc-simple-graph-card";
> > +
> > + simple-audio-card,format = "left_j";
> > + simple-audio-card,bitclock-master = <&ak4643_port>;
> > + simple-audio-card,frame-master = <&ak4643_port>;
>
> Don't add a bunch of properties with in port and endpoint nodes. The
> purpose is to describe the graph. Put these in the parent node or
> perhaps the codec node.

These properties are needed on each ports/endpoints on sound at this point.
If ports/endpoints can't include these, I need to separate these,
is it correct approach ? ?? see below

-- current style --

ports {
compatible = "asoc-simple-graph-card";
simple-audio-card,name = "graph-sound";

port@0 {
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
simple-audio-card,frame-master = <&rcar_ak4613_port>;

type = "sound";
rcar_ak4613_port: endpoint {
remote-endpoint = <&ak4613_port>;
playback = <&ssi0 &src0 &dvc0>;
capture = <&ssi1 &src1 &dvc1>;
};
};
port@1 {
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
simple-audio-card,frame-master = <&rcar_hdmi0_port>;
type = "sound";
rcar_hdmi0_port: endpoint {
remote-endpoint = <&du_out_hdmi_snd0>;
playback = <&ssi2>;
};
};
port@2 {
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
simple-audio-card,frame-master = <&rcar_hdmi1_port>;
type = "sound";
rcar_hdmi1_port: endpoint {
remote-endpoint = <&du_out_hdmi_snd1>;
playback = <&ssi3>;
};
};
};

-- separate style --

ports {
port@0 {
rcar_ak4613_port: endpoint {
}
};
port@1 {
rcar_hdmi0_port: endpoint {
}
};
port@2 {
rcar_hdmi1_port: endpoint {
}
};
};

sound-xxx {
compatible = "asoc-simple-graph-card";

port@0 {
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
simple-audio-card,frame-master = <&rcar_ak4613_port>;
};
port@1 {
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
simple-audio-card,frame-master = <&rcar_hdmi0_port>;
};
port@2 {
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
simple-audio-card,frame-master = <&rcar_hdmi1_port>;
};
};

Best regards
---
Kuninori Morimoto

2016-10-19 02:40:31

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH 20/23] ASoC: add simple-graph-card document

On Tue, Oct 18, 2016 at 8:36 PM, Kuninori Morimoto
<[email protected]> wrote:
>
> Hi Rob
>
>> > + type = "sound";
>>
>> I'm still not convinced this is necessary. This is implied either by
>> the fact there is only one port or perhaps the compatible string.
>
> Do you mean "on this sample" ? or in general ?
> Indeed this sample is definitely for sound, so type is very clear
> without property.
> But in general, for example HDMI, it want to know port type.
> Anyway, I can remove above "type" from this new sound driver.

For HDMI, the port number should dictate which one is video and which is audio.

>> > +rcar_sound {
>> > + ...
>> > + port {
>> > + compatible = "asoc-simple-graph-card";
>> > +
>> > + simple-audio-card,format = "left_j";
>> > + simple-audio-card,bitclock-master = <&ak4643_port>;
>> > + simple-audio-card,frame-master = <&ak4643_port>;
>>
>> Don't add a bunch of properties with in port and endpoint nodes. The
>> purpose is to describe the graph. Put these in the parent node or
>> perhaps the codec node.
>
> These properties are needed on each ports/endpoints on sound at this point.
> If ports/endpoints can't include these, I need to separate these,
> is it correct approach ? ?? see below

Uhh, no. Not at all what I had in mind.

> -- current style --
>
> ports {
> compatible = "asoc-simple-graph-card";

I think your problems start with trying to extend simple-card. This
binding is anything but simple. I think using OF graph is a good idea,
but trying to make it completely generic is not.

> simple-audio-card,name = "graph-sound";
>
> port@0 {
> simple-audio-card,format = "left_j";
> simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
> simple-audio-card,frame-master = <&rcar_ak4613_port>;

These look like properties of the ak4613 to me, so put them in the
ak4613 node. If they are standard property names, then you just walk
the graph and get them.

>
> type = "sound";
> rcar_ak4613_port: endpoint {
> remote-endpoint = <&ak4613_port>;
> playback = <&ssi0 &src0 &dvc0>;
> capture = <&ssi1 &src1 &dvc1>;

Not really sure how you are using these to comment.

> };
> };
> port@1 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
> simple-audio-card,frame-master = <&rcar_hdmi0_port>;
> type = "sound";
> rcar_hdmi0_port: endpoint {
> remote-endpoint = <&du_out_hdmi_snd0>;
> playback = <&ssi2>;

If you are trying to describe a connection between hdmi_snd0 and ssi2,
then do just that. Add a port to ssi2 and connect it to hdmi_snd0.

> };
> };
> port@2 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
> simple-audio-card,frame-master = <&rcar_hdmi1_port>;
> type = "sound";
> rcar_hdmi1_port: endpoint {
> remote-endpoint = <&du_out_hdmi_snd1>;
> playback = <&ssi3>;
> };
> };
> };
>
> -- separate style --
>
> ports {
> port@0 {
> rcar_ak4613_port: endpoint {
> }
> };
> port@1 {
> rcar_hdmi0_port: endpoint {
> }
> };
> port@2 {
> rcar_hdmi1_port: endpoint {
> }
> };
> };
>
> sound-xxx {
> compatible = "asoc-simple-graph-card";
>
> port@0 {
> simple-audio-card,format = "left_j";
> simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
> simple-audio-card,frame-master = <&rcar_ak4613_port>;
> };
> port@1 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
> simple-audio-card,frame-master = <&rcar_hdmi0_port>;
> };
> port@2 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
> simple-audio-card,frame-master = <&rcar_hdmi1_port>;
> };
> };
>
> Best regards
> ---
> Kuninori Morimoto

2016-10-19 06:13:57

by Kuninori Morimoto

[permalink] [raw]
Subject: Re: [PATCH 20/23] ASoC: add simple-graph-card document


Hi Rob

Thank you for your feedback

> > Do you mean "on this sample" ? or in general ?
> > Indeed this sample is definitely for sound, so type is very clear
> > without property.
> > But in general, for example HDMI, it want to know port type.
> > Anyway, I can remove above "type" from this new sound driver.
>
> For HDMI, the port number should dictate which one is video and which is audio.

Hmm.. I will consider about that.

> > ports {
> > compatible = "asoc-simple-graph-card";
>
> I think your problems start with trying to extend simple-card. This
> binding is anything but simple. I think using OF graph is a good idea,
> but trying to make it completely generic is not.

Current ALSA SoC basically needs CPU/Codec/Card drivers.
If we use this new simple sound card, DT needs only CPU/Codec.
Card part will be created from CPU by using compatible = "xxx"
(= Card driver itself is needed, but no DT)

This "Card" part is related to its whole sound system.
If you want to use normal sound system, it will be "simple-card",
if you want to use feature sound system, it will be "xxxx-card".
This time, I'm focusing to simple one, someone will create xxxx-card,
but it is not me :)

> > port@0 {
> > simple-audio-card,format = "left_j";
> > simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
> > simple-audio-card,frame-master = <&rcar_ak4613_port>;
>
> These look like properties of the ak4613 to me, so put them in the
> ak4613 node. If they are standard property names, then you just walk
> the graph and get them.

These were "Card" part property, not ak4613 property.
It indicates which can be master (CPU or Codec) on sound system.

> > type = "sound";
> > rcar_ak4613_port: endpoint {
> > remote-endpoint = <&ak4613_port>;
> > playback = <&ssi0 &src0 &dvc0>;
> > capture = <&ssi1 &src1 &dvc1>;
>
> Not really sure how you are using these to comment.

I'm sorry, maybe your confusing is because this sample.
This playback/capture are Renesas CPU specific properties.
Renesas CPU port needs to know CPU-inside connection.

> > port@1 {
> > simple-audio-card,format = "i2s";
> > simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
> > simple-audio-card,frame-master = <&rcar_hdmi0_port>;
> > type = "sound";
> > rcar_hdmi0_port: endpoint {
> > remote-endpoint = <&du_out_hdmi_snd0>;
> > playback = <&ssi2>;
>
> If you are trying to describe a connection between hdmi_snd0 and ssi2,
> then do just that. Add a port to ssi2 and connect it to hdmi_snd0.

I'm sorry, same comment.
This "playback" is Renesas CPU specific property.
It indicating Renesas CPU inside connection

2016-10-21 05:45:50

by Kuninori Morimoto

[permalink] [raw]
Subject: Re: [PATCH 20/23] ASoC: add simple-graph-card document


Hi Rob

Can I continue this idea (= property on port/endpoint) ?
Of course I will remove "type" from OF graph.

> > > + type = "sound";
> >
> > I'm still not convinced this is necessary. This is implied either by
> > the fact there is only one port or perhaps the compatible string.
>
> Do you mean "on this sample" ? or in general ?
> Indeed this sample is definitely for sound, so type is very clear
> without property.
> But in general, for example HDMI, it want to know port type.
> Anyway, I can remove above "type" from this new sound driver.
>
> > > +rcar_sound {
> > > + ...
> > > + port {
> > > + compatible = "asoc-simple-graph-card";
> > > +
> > > + simple-audio-card,format = "left_j";
> > > + simple-audio-card,bitclock-master = <&ak4643_port>;
> > > + simple-audio-card,frame-master = <&ak4643_port>;
> >
> > Don't add a bunch of properties with in port and endpoint nodes. The
> > purpose is to describe the graph. Put these in the parent node or
> > perhaps the codec node.
>
> These properties are needed on each ports/endpoints on sound at this point.
> If ports/endpoints can't include these, I need to separate these,
> is it correct approach ? ?? see below
>
> -- current style --
>
> ports {
> compatible = "asoc-simple-graph-card";
> simple-audio-card,name = "graph-sound";
>
> port@0 {
> simple-audio-card,format = "left_j";
> simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
> simple-audio-card,frame-master = <&rcar_ak4613_port>;
>
> type = "sound";
> rcar_ak4613_port: endpoint {
> remote-endpoint = <&ak4613_port>;
> playback = <&ssi0 &src0 &dvc0>;
> capture = <&ssi1 &src1 &dvc1>;
> };
> };
> port@1 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
> simple-audio-card,frame-master = <&rcar_hdmi0_port>;
> type = "sound";
> rcar_hdmi0_port: endpoint {
> remote-endpoint = <&du_out_hdmi_snd0>;
> playback = <&ssi2>;
> };
> };
> port@2 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
> simple-audio-card,frame-master = <&rcar_hdmi1_port>;
> type = "sound";
> rcar_hdmi1_port: endpoint {
> remote-endpoint = <&du_out_hdmi_snd1>;
> playback = <&ssi3>;
> };
> };
> };
>
> -- separate style --
>
> ports {
> port@0 {
> rcar_ak4613_port: endpoint {
> }
> };
> port@1 {
> rcar_hdmi0_port: endpoint {
> }
> };
> port@2 {
> rcar_hdmi1_port: endpoint {
> }
> };
> };
>
> sound-xxx {
> compatible = "asoc-simple-graph-card";
>
> port@0 {
> simple-audio-card,format = "left_j";
> simple-audio-card,bitclock-master = <&rcar_ak4613_port>;
> simple-audio-card,frame-master = <&rcar_ak4613_port>;
> };
> port@1 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi0_port>;
> simple-audio-card,frame-master = <&rcar_hdmi0_port>;
> };
> port@2 {
> simple-audio-card,format = "i2s";
> simple-audio-card,bitclock-master = <&rcar_hdmi1_port>;
> simple-audio-card,frame-master = <&rcar_hdmi1_port>;
> };
> };
>
> Best regards
> ---
> Kuninori Morimoto

2016-10-28 18:48:45

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check" to the asoc tree

The patch

ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 6c1c06cb776cf9a34ceafc5be288aa3670aa3ef2 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 28 Oct 2016 03:38:28 +0000
Subject: [PATCH] ASoC: simple-card-utils: remove unnecessary cpu/codec pointer
check

Remove cpu/codec pointer check from asoc_simple_card_canonicalize_dailink()
This is verbose check, and will be issue if CPU name was created by
fmt_single_name() on simple-scu-card.c.
see also asoc_simple_card_canonicalize_cpu()

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/generic/simple-card-utils.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 1cb39309f5d5..e5b80f53093a 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -195,9 +195,6 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);

int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
{
- if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name)
- return -EINVAL;
-
/* Assumes platform == cpu */
if (!dai_link->platform_of_node)
dai_link->platform_of_node = dai_link->cpu_of_node;
--
2.10.1

2016-10-28 18:48:56

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: simple-scu-card: code sync: tidyup props/link naming" to the asoc tree

The patch

ASoC: simple-scu-card: code sync: tidyup props/link naming

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 193599264f3eb632f43f83f738b17241f91dbd5a Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 28 Oct 2016 03:38:00 +0000
Subject: [PATCH] ASoC: simple-scu-card: code sync: tidyup props/link naming

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronizes style to other simple card family so that be enable
to easy reviewing.

This patch uses dai_link/dai_props instead of links/props.

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index 1704b187f6ee..348e9a7c4d10 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -254,8 +254,8 @@ static int asoc_simple_card_parse_of(struct device_node *node,
static int asoc_simple_card_probe(struct platform_device *pdev)
{
struct simple_card_data *priv;
- struct snd_soc_dai_link *links;
- struct asoc_simple_dai *props;
+ struct snd_soc_dai_link *dai_link;
+ struct asoc_simple_dai *dai_props;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
int num, ret;
@@ -267,13 +267,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)

num = of_get_child_count(np);

- props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
- links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
- if (!props || !links)
+ dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ if (!dai_props || !dai_link)
return -ENOMEM;

- priv->dai_props = props;
- priv->dai_link = links;
+ priv->dai_props = dai_props;
+ priv->dai_link = dai_link;

/* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE;
--
2.10.1

2016-10-28 18:49:16

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv" to the asoc tree

The patch

ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 6910e8679ff4d256028003be2451deb31f13948e Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 28 Oct 2016 03:37:44 +0000
Subject: [PATCH] ASoC: simple-scu-card: code sync: rename
asoc_simple_card_priv

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronized simple card style to other simple card family

This patch renames asoc_simple_card_priv to simple_card_data,
same as other simple card family.

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index b8d8437ef3dd..1704b187f6ee 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -22,7 +22,7 @@
#include <sound/soc-dai.h>
#include <sound/simple_card_utils.h>

-struct asoc_simple_card_priv {
+struct simple_card_data {
struct snd_soc_card snd_card;
struct snd_soc_codec_conf codec_conf;
struct asoc_simple_dai *dai_props;
@@ -42,7 +42,7 @@ struct asoc_simple_card_priv {
static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct asoc_simple_dai *dai_props =
simple_priv_to_props(priv, rtd->num);

@@ -52,7 +52,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct asoc_simple_dai *dai_props =
simple_priv_to_props(priv, rtd->num);

@@ -66,7 +66,7 @@ static struct snd_soc_ops asoc_simple_card_ops = {

static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dai_props;
@@ -84,7 +84,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
- struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
@@ -102,7 +102,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
}

static int asoc_simple_card_dai_link_of(struct device_node *np,
- struct asoc_simple_card_priv *priv,
+ struct simple_card_data *priv,
unsigned int daifmt,
int idx, bool is_fe)
{
@@ -196,7 +196,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
}

static int asoc_simple_card_parse_of(struct device_node *node,
- struct asoc_simple_card_priv *priv)
+ struct simple_card_data *priv)

{
struct device *dev = simple_priv_to_dev(priv);
@@ -253,7 +253,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,

static int asoc_simple_card_probe(struct platform_device *pdev)
{
- struct asoc_simple_card_priv *priv;
+ struct simple_card_data *priv;
struct snd_soc_dai_link *links;
struct asoc_simple_dai *props;
struct device *dev = &pdev->dev;
--
2.10.1

2016-10-28 18:49:36

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: simple-scu-card: code sync: follow to simple family style" to the asoc tree

The patch

ASoC: simple-scu-card: code sync: follow to simple family style

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 15a190ffec3b3f5e632faaa01b92f4cef32d63a3 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 28 Oct 2016 03:37:26 +0000
Subject: [PATCH] ASoC: simple-scu-card: code sync: follow to simple family
style

simple sound card family are using very similar style, but because of its
historical reason, there are small differences. For example pointer style,
function name, caller postion etc...
This patch synchronized simple card style to other simple card family

Current simple-scu-card function naming is different from other simple card
family. And related to it, the necessary operation position is also
different. This patch synchronize these to other simple card family.

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
sound/soc/generic/simple-scu-card.c | 99 ++++++++++++++++---------------------
1 file changed, 43 insertions(+), 56 deletions(-)

diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index b9973a56bcb0..b8d8437ef3dd 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -101,7 +101,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}

-static int asoc_simple_card_parse_links(struct device_node *np,
+static int asoc_simple_card_dai_link_of(struct device_node *np,
struct asoc_simple_card_priv *priv,
unsigned int daifmt,
int idx, bool is_fe)
@@ -195,22 +195,35 @@ static int asoc_simple_card_parse_links(struct device_node *np,
return 0;
}

-static int asoc_simple_card_dai_link_of(struct device_node *node,
- struct asoc_simple_card_priv *priv)
+static int asoc_simple_card_parse_of(struct device_node *node,
+ struct asoc_simple_card_priv *priv)
+
{
struct device *dev = simple_priv_to_dev(priv);
struct device_node *np;
unsigned int daifmt = 0;
- int ret, i;
bool is_fe;
+ int ret, i;
+
+ if (!node)
+ return -EINVAL;
+
+ ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing");
+ if (ret < 0)
+ return ret;
+
+ /* sampling rate convert */
+ of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate);
+
+ /* channels transfer */
+ of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels);

/* find 1st codec */
np = of_get_child_by_name(node, PREFIX "codec");
if (!np)
return -ENODEV;

- ret = asoc_simple_card_parse_daifmt(dev, node, np,
- PREFIX, &daifmt);
+ ret = asoc_simple_card_parse_daifmt(dev, node, np, PREFIX, &daifmt);
if (ret < 0)
return ret;

@@ -220,58 +233,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
if (strcmp(np->name, PREFIX "cpu") == 0)
is_fe = true;

- ret = asoc_simple_card_parse_links(np, priv, daifmt, i, is_fe);
+ ret = asoc_simple_card_dai_link_of(np, priv, daifmt, i, is_fe);
if (ret < 0)
return ret;
i++;
}

- return 0;
-}
-
-static int asoc_simple_card_parse_of(struct device_node *node,
- struct asoc_simple_card_priv *priv,
- struct device *dev)
-{
- struct asoc_simple_dai *props;
- struct snd_soc_dai_link *links;
- int ret;
- int num;
-
- if (!node)
- return -EINVAL;
-
- num = of_get_child_count(node);
- props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
- links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
- if (!props || !links)
- return -ENOMEM;
-
- priv->dai_props = props;
- priv->dai_link = links;
-
- /* Init snd_soc_card */
- priv->snd_card.owner = THIS_MODULE;
- priv->snd_card.dev = dev;
- priv->snd_card.dai_link = priv->dai_link;
- priv->snd_card.num_links = num;
- priv->snd_card.codec_conf = &priv->codec_conf;
- priv->snd_card.num_configs = 1;
-
- ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing");
- if (ret < 0)
- return ret;
-
- /* sampling rate convert */
- of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate);
-
- /* channels transfer */
- of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels);
-
- ret = asoc_simple_card_dai_link_of(node, priv);
- if (ret < 0)
- return ret;
-
ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
if (ret < 0)
return ret;
@@ -287,16 +254,36 @@ static int asoc_simple_card_parse_of(struct device_node *node,
static int asoc_simple_card_probe(struct platform_device *pdev)
{
struct asoc_simple_card_priv *priv;
- struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_dai_link *links;
+ struct asoc_simple_dai *props;
struct device *dev = &pdev->dev;
- int ret;
+ struct device_node *np = pdev->dev.of_node;
+ int num, ret;

/* Allocate the private data */
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

- ret = asoc_simple_card_parse_of(np, priv, dev);
+ num = of_get_child_count(np);
+
+ props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
+ links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
+ if (!props || !links)
+ return -ENOMEM;
+
+ priv->dai_props = props;
+ priv->dai_link = links;
+
+ /* Init snd_soc_card */
+ priv->snd_card.owner = THIS_MODULE;
+ priv->snd_card.dev = dev;
+ priv->snd_card.dai_link = priv->dai_link;
+ priv->snd_card.num_links = num;
+ priv->snd_card.codec_conf = &priv->codec_conf;
+ priv->snd_card.num_configs = 1;
+
+ ret = asoc_simple_card_parse_of(np, priv);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret);
--
2.10.1

2016-11-11 15:29:07

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_simple_widgets" to the asoc tree

The patch

ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_simple_widgets

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 1ef5bcd57be5c8b31286b7b47828064be25f266b Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 11 Nov 2016 01:18:08 +0000
Subject: [PATCH] ASoC: soc-core: adjust for graph on
snd_soc_of_parse_audio_simple_widgets

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/sound/soc.h | 8 ++++++--
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8457aab9eab0..77b01c45ee8d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1647,8 +1647,12 @@ void snd_soc_util_exit(void);
int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
struct device_node *np,
const char *propname);
-int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
- const char *propname);
+#define snd_soc_of_parse_audio_simple_widgets(card, propname)\
+ snd_soc_of_parse_audio_simple_widgets_from_node(card, NULL, propname)
+int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
+
int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *tx_mask,
unsigned int *rx_mask,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 17132fb57930..6f911f4d413a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3462,14 +3462,17 @@ static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};

-int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
+int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
+ struct device_node *np,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
struct snd_soc_dapm_widget *widgets;
const char *template, *wname;
int i, j, num_widgets, ret;

+ if (!np)
+ np = card->dev->of_node;
+
num_widgets = of_property_count_strings(np, propname);
if (num_widgets < 0) {
dev_err(card->dev,
@@ -3540,7 +3543,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node);

static int snd_soc_of_get_slot_mask(struct device_node *np,
const char *prop_name,
--
2.10.2

2016-11-11 15:29:15

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: soc-core: snd_soc_get_dai_name() become non static" to the asoc tree

The patch

ASoC: soc-core: snd_soc_get_dai_name() become non static

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 1ad8ec535b997ed36c0f32c2616206725258dd30 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 11 Nov 2016 01:19:28 +0000
Subject: [PATCH] ASoC: soc-core: snd_soc_get_dai_name() become non static

snd_soc_get_dai_name() is used from snd_soc_of_get_dai_name(),
and it is assuming that DT is using "sound-dai" / "#sound-dai-cells".
But graph base DT is using "remote-endpoint". This patch makes
snd_soc_get_dai_name() non static for graph support.

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/sound/soc.h | 2 ++
sound/soc/soc-core.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 148bf553d598..6dffa9540a30 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1666,6 +1666,8 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
struct device_node **framemaster);
+int snd_soc_get_dai_name(struct of_phandle_args *args,
+ const char **dai_name);
int snd_soc_of_get_dai_name(struct device_node *of_node,
const char **dai_name);
int snd_soc_of_get_dai_link_codecs(struct device *dev,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ec881b8825b6..81b604151f26 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3787,7 +3787,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);

-static int snd_soc_get_dai_name(struct of_phandle_args *args,
+int snd_soc_get_dai_name(struct of_phandle_args *args,
const char **dai_name)
{
struct snd_soc_component *pos;
@@ -3839,6 +3839,7 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args,
mutex_unlock(&client_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(snd_soc_get_dai_name);

int snd_soc_of_get_dai_name(struct device_node *of_node,
const char **dai_name)
--
2.10.2

2016-11-11 15:29:28

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_routing" to the asoc tree

The patch

ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_routing

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 7364c8dc255232db33bcd1c5b19eb8f34cf6108a Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 11 Nov 2016 01:18:35 +0000
Subject: [PATCH] ASoC: soc-core: adjust for graph on
snd_soc_of_parse_audio_routing

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/sound/soc.h | 9 +++++++--
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 4f1c784e44f6..148bf553d598 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1655,8 +1655,13 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname);
-int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
- const char *propname);
+
+#define snd_soc_of_parse_audio_routing(card, propname) \
+ snd_soc_of_parse_audio_routing_from_node(card, NULL, propname)
+int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
+
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0bbcd903261..ec881b8825b6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3615,14 +3615,17 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);

-int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
+int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
+ struct device_node *np,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
int num_routes;
struct snd_soc_dapm_route *routes;
int i, ret;

+ if (!np)
+ np = card->dev->of_node;
+
num_routes = of_property_count_strings(np, propname);
if (num_routes < 0 || num_routes & 1) {
dev_err(card->dev,
@@ -3669,7 +3672,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node);

unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
--
2.10.2

2016-11-11 15:29:43

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_prefix" to the asoc tree

The patch

ASoC: soc-core: adjust for graph on snd_soc_of_parse_audio_prefix

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b6defcca0a604129155ae472b116a2e1688d8995 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 11 Nov 2016 01:19:03 +0000
Subject: [PATCH] ASoC: soc-core: adjust for graph on
snd_soc_of_parse_audio_prefix

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/sound/soc.h | 6 +++++-
sound/soc/soc-core.c | 9 ++++++---
2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6dffa9540a30..346223b38e0d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1651,7 +1651,11 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *rx_mask,
unsigned int *slots,
unsigned int *slot_width);
-void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
+#define snd_soc_of_parse_audio_prefix(card, codec_conf, of_node, propname) \
+ snd_soc_of_parse_audio_prefix_from_node(card, NULL, codec_conf, \
+ of_node, propname)
+void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
+ struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 81b604151f26..e4c90806fa10 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3595,15 +3595,18 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);

-void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
+void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
+ struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname)
{
- struct device_node *np = card->dev->of_node;
const char *str;
int ret;

+ if (!np)
+ np = card->dev->of_node;
+
ret = of_property_read_string(np, propname, &str);
if (ret < 0) {
/* no prefix is not error */
@@ -3613,7 +3616,7 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
codec_conf->of_node = of_node;
codec_conf->name_prefix = str;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node);

int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
struct device_node *np,
--
2.10.2

2016-11-11 15:29:05

by Mark Brown

[permalink] [raw]
Subject: Applied "ASoC: soc-core: adjust for graph on snd_soc_of_parse_card_name" to the asoc tree

The patch

ASoC: soc-core: adjust for graph on snd_soc_of_parse_card_name

has been applied to the asoc tree at

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 8f5ebb1bee15b5720741a98414767bb86f6c2b23 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <[email protected]>
Date: Fri, 11 Nov 2016 01:17:27 +0000
Subject: [PATCH] ASoC: soc-core: adjust for graph on
snd_soc_of_parse_card_name

It is assuming that the card related information is located on
"card" node, but graph case doesn't have it.
This patch adds node parameter to adjust for graph support

Signed-off-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
---
include/sound/soc.h | 7 +++++--
sound/soc/soc-core.c | 11 ++++++-----
2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 346223b38e0d..8457aab9eab0 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1642,8 +1642,11 @@ static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
int snd_soc_util_init(void);
void snd_soc_util_exit(void);

-int snd_soc_of_parse_card_name(struct snd_soc_card *card,
- const char *propname);
+#define snd_soc_of_parse_card_name(card, propname) \
+ snd_soc_of_parse_card_name_from_node(card, NULL, propname)
+int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname);
int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_parse_tdm_slot(struct device_node *np,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e4c90806fa10..17132fb57930 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3424,10 +3424,10 @@ void snd_soc_unregister_codec(struct device *dev)
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);

/* Retrieve a card's name from device tree */
-int snd_soc_of_parse_card_name(struct snd_soc_card *card,
- const char *propname)
+int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
+ struct device_node *np,
+ const char *propname)
{
- struct device_node *np;
int ret;

if (!card->dev) {
@@ -3435,7 +3435,8 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
return -EINVAL;
}

- np = card->dev->of_node;
+ if (!np)
+ np = card->dev->of_node;

ret = of_property_read_string_index(np, propname, 0, &card->name);
/*
@@ -3452,7 +3453,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,

return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node);

static const struct snd_soc_dapm_widget simple_widgets[] = {
SND_SOC_DAPM_MIC("Microphone", NULL),
--
2.10.2