Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] ASoC: add audio-graph-scu-card
@ 2017-05-18  1:43 Kuninori Morimoto
  2017-05-18  1:44 ` [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation Kuninori Morimoto
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Kuninori Morimoto @ 2017-05-18  1:43 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon, linux-renesas-soc


Hi Mark

These adds audio-graph-scu-card which is same as
simple-scu-card + OF-graph.

1) patch cleanups existing simple-scu-card document

Kuninori Morimoto (3):
  1) ASoC: simple-scu-card: cleanup documentation
  2) ASoC: add audio-graph-scu-card document
  3) ASoC: add audio-graph-scu-card support

 .../bindings/sound/audio-graph-scu-card.txt        |  72 ++++
 .../devicetree/bindings/sound/simple-scu-card.txt  |  65 ++--
 sound/soc/generic/Kconfig                          |   9 +
 sound/soc/generic/Makefile                         |   2 +
 sound/soc/generic/audio-graph-scu-card.c           | 416 +++++++++++++++++++++
 5 files changed, 523 insertions(+), 41 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
 create mode 100644 sound/soc/generic/audio-graph-scu-card.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation
  2017-05-18  1:43 [PATCH 0/3] ASoC: add audio-graph-scu-card Kuninori Morimoto
@ 2017-05-18  1:44 ` Kuninori Morimoto
  2017-05-19 17:04   ` Applied "ASoC: simple-scu-card: cleanup documentation" to the asoc tree Mark Brown
  2017-05-18  1:44 ` [PATCH 2/3] ASoC: add audio-graph-scu-card document Kuninori Morimoto
  2017-05-18  1:45 ` [PATCH 3/3] ASoC: add audio-graph-scu-card support Kuninori Morimoto
  2 siblings, 1 reply; 7+ messages in thread
From: Kuninori Morimoto @ 2017-05-18  1:44 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon, linux-renesas-soc


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

simple-scu-card is almost same as simple-card. This is already explained
in document. But simple-card and simple-scu-card both has same
explanation for same property. This patch forward explantion to
simple-card if possible to avoid duplication.

This patch also cleanup DT binding example which is not good matching
to simple-scu-card.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 .../devicetree/bindings/sound/simple-scu-card.txt  | 65 ++++++++--------------
 1 file changed, 24 insertions(+), 41 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt
index d6fe47e..e894cef 100644
--- a/Documentation/devicetree/bindings/sound/simple-scu-card.txt
+++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt
@@ -1,35 +1,29 @@
-ASoC simple SCU Sound Card
+ASoC Simple SCU Sound Card
 
-Simple-Card specifies audio DAI connections of SoC <-> codec.
+Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM".
+For example, you can use this driver if you want to exchange sampling rate convert,
+Mixing, etc...
 
 Required properties:
 
 - compatible				: "simple-scu-audio-card"
 					  "renesas,rsrc-card"
-
 Optional properties:
 
-- simple-audio-card,name		: User specified audio sound card name, one string
-					  property.
-- simple-audio-card,cpu			: CPU   sub-node
-- simple-audio-card,codec		: CODEC sub-node
+- simple-audio-card,name		: see simple-audio-card.txt
+- simple-audio-card,cpu			: see simple-audio-card.txt
+- simple-audio-card,codec		: see simple-audio-card.txt
 
 Optional subnode properties:
 
-- simple-audio-card,format		: CPU/CODEC common audio format.
-					  "i2s", "right_j", "left_j" , "dsp_a"
-					  "dsp_b", "ac97", "pdm", "msb", "lsb"
-- simple-audio-card,frame-master	: Indicates dai-link frame master.
-					  phandle to a cpu or codec subnode.
-- simple-audio-card,bitclock-master	: Indicates dai-link bit clock master.
-					  phandle to a cpu or codec subnode.
-- simple-audio-card,bitclock-inversion	: bool property. Add this if the
-					  dai-link uses bit clock inversion.
-- simple-audio-card,frame-inversion	: bool property. Add this if the
-					  dai-link uses frame clock inversion.
+- simple-audio-card,format		: see simple-audio-card.txt
+- simple-audio-card,frame-master	: see simple-audio-card.txt
+- simple-audio-card,bitclock-master	: see simple-audio-card.txt
+- simple-audio-card,bitclock-inversion	: see simple-audio-card.txt
+- simple-audio-card,frame-inversion	: see simple-audio-card.txt
 - simple-audio-card,convert-rate	: platform specified sampling rate convert
 - simple-audio-card,convert-channels	: platform specified converted channel size (2 - 8 ch)
-- simple-audio-card,prefix		: see audio-routing
+- simple-audio-card,prefix		: see routing
 - simple-audio-card,routing		: A list of the connections between audio components.
 					  Each entry is a pair of strings, the first being the connection's sink,
 					  the second being the connection's source. Valid names for sources.
@@ -38,19 +32,11 @@ Optional subnode properties:
 
 Required CPU/CODEC subnodes properties:
 
-- sound-dai				: phandle and port of CPU/CODEC
+- sound-dai				: see simple-audio-card.txt
 
 Optional CPU/CODEC subnodes properties:
 
-- clocks / system-clock-frequency	: specify subnode's clock if needed.
-					  it can be specified via "clocks" if system has
-					  clock node (= common clock), or "system-clock-frequency"
-					  (if system doens't support common clock)
-					  If a clock is specified, it is
-					  enabled with clk_prepare_enable()
-					  in dai startup() and disabled with
-					  clk_disable_unprepare() in dai
-					  shutdown().
+- clocks / system-clock-frequency	: see simple-audio-card.txt
 
 Example 1. Sampling Rate Covert
 
@@ -59,11 +45,10 @@ sound {
 
 	simple-audio-card,name = "rsnd-ak4643";
 	simple-audio-card,format = "left_j";
-	simple-audio-card,format = "left_j";
 	simple-audio-card,bitclock-master = <&sndcodec>;
 	simple-audio-card,frame-master = <&sndcodec>;
 
-	simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */
+	simple-audio-card,convert-rate = <48000>;
 
 	simple-audio-card,prefix = "ak4642";
 	simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
@@ -79,20 +64,18 @@ sound {
 	};
 };
 
-Example 2. 2 CPU 1 Codec
+Example 2. 2 CPU 1 Codec (Mixing)
 
 sound {
-	compatible = "renesas,rsrc-card";
-
-	card-name = "rsnd-ak4643";
-	format = "left_j";
-	bitclock-master = <&dpcmcpu>;
-	frame-master = <&dpcmcpu>;
+	compatible = "simple-scu-audio-card";
 
-	convert-rate = <48000>;  /* see audio_clk_a */
+	simple-audio-card,name = "rsnd-ak4643";
+	simple-audio-card,format = "left_j";
+	simple-audio-card,bitclock-master = <&dpcmcpu>;
+	simple-audio-card,frame-master = <&dpcmcpu>;
 
-	audio-prefix = "ak4642";
-	audio-routing = "ak4642 Playback", "DAI0 Playback",
+	simple-audio-card,prefix = "ak4642";
+	simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
 			"ak4642 Playback", "DAI1 Playback";
 
 	dpcmcpu: cpu@0 {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] ASoC: add audio-graph-scu-card document
  2017-05-18  1:43 [PATCH 0/3] ASoC: add audio-graph-scu-card Kuninori Morimoto
  2017-05-18  1:44 ` [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation Kuninori Morimoto
@ 2017-05-18  1:44 ` Kuninori Morimoto
  2017-05-29 14:02   ` Applied "ASoC: add audio-graph-scu-card document" to the asoc tree Mark Brown
  2017-05-18  1:45 ` [PATCH 3/3] ASoC: add audio-graph-scu-card support Kuninori Morimoto
  2 siblings, 1 reply; 7+ messages in thread
From: Kuninori Morimoto @ 2017-05-18  1:44 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon, linux-renesas-soc


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 .../bindings/sound/audio-graph-scu-card.txt        | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt

diff --git a/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
new file mode 100644
index 0000000..b2dd23f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
@@ -0,0 +1,72 @@
+Audio-Graph-SCU-Card:
+
+Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM".
+
+It is based on common bindings for device graphs.
+see ${LINUX}/Documentation/devicetree/bindings/graph.txt
+
+Basically, Audio-Graph-SCU-Card property is same as
+Simple-Card / Simple-SCU-Card / Audio-Graph-Card.
+see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
+    ${LINUX}/Documentation/devicetree/bindings/sound/simple-scu-card.txt
+    ${LINUX}/Documentation/devicetree/bindings/sound/audio-graph-card.txt
+
+Below are same as Simple-Card / Audio-Graph-Card.
+
+- label
+- dai-format
+- frame-master
+- bitclock-master
+- bitclock-inversion
+- frame-inversion
+- dai-tdm-slot-num
+- dai-tdm-slot-width
+- clocks / system-clock-frequency
+
+Below are same as Simple-SCU-Card.
+
+- convert-rate
+- convert-channels
+- prefix
+- routing
+
+Required properties:
+
+- compatible				: "audio-graph-scu-card";
+- dais					: list of CPU DAI port{s}
+
+Example
+
+	sound_card {
+		compatible = "audio-graph-scu-card";
+
+		label = "sound-card";
+		prefix = "codec";
+		routing = "codec Playback", "DAI0 Playback",
+			"codec Playback", "DAI1 Playback";
+		convert-rate = <48000>;
+
+		dais = <&cpu_port>;
+	};
+
+	audio-codec {
+		...
+
+		port {
+			codec_endpoint: endpoint {
+				remote-endpoint = <&cpu_endpoint>;
+			};
+		};
+	};
+
+	dai-controller {
+		...
+		cpu_port: port {
+			cpu_endpoint: endpoint {
+				remote-endpoint = <&codec_endpoint>;
+
+				dai-format = "left_j";
+				...
+			};
+		};
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] ASoC: add audio-graph-scu-card support
  2017-05-18  1:43 [PATCH 0/3] ASoC: add audio-graph-scu-card Kuninori Morimoto
  2017-05-18  1:44 ` [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation Kuninori Morimoto
  2017-05-18  1:44 ` [PATCH 2/3] ASoC: add audio-graph-scu-card document Kuninori Morimoto
@ 2017-05-18  1:45 ` Kuninori Morimoto
  2017-05-29 14:02   ` Applied "ASoC: add audio-graph-scu-card support" to the asoc tree Mark Brown
  2 siblings, 1 reply; 7+ messages in thread
From: Kuninori Morimoto @ 2017-05-18  1:45 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon, linux-renesas-soc


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

OF-graph base DT binding is used on V4L2, and ALSA SoC is using
different style of DT today. Now ALSA SoC supports simple-card driver
for generic/simple sound card, and we have simple-scu-card driver
for simple-card + ALSA DPCM case.
In the future, V4L2 / ALSA will support HDMI, and then, DT bindings
between V4L2 / ALSA should be merged.
This patch adds new Audio Graph SCU Card which is OF-graph base of
simple-scu-card

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/generic/Kconfig                |   9 +
 sound/soc/generic/Makefile               |   2 +
 sound/soc/generic/audio-graph-scu-card.c | 416 +++++++++++++++++++++++++++++++
 3 files changed, 427 insertions(+)
 create mode 100644 sound/soc/generic/audio-graph-scu-card.c

diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
index 121a48e..c954be0 100644
--- a/sound/soc/generic/Kconfig
+++ b/sound/soc/generic/Kconfig
@@ -22,3 +22,12 @@ config SND_AUDIO_GRAPH_CARD
 	help
 	  This option enables generic simple simple sound card support
 	  with OF-graph DT bindings.
+
+config SND_AUDIO_GRAPH_SCU_CARD
+	tristate "ASoC Audio Graph SCU sound card support"
+	depends on OF
+	select SND_SIMPLE_CARD_UTILS
+	help
+	  This option enables generic simple SCU sound card support
+	  with OF-graph DT bindings.
+	  It supports DPCM of multi CPU single Codec ststem.
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
index 670068f..9e00052 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-audio-graph-card-objs	:= audio-graph-card.o
+snd-soc-audio-graph-scu-card-objs	:= audio-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_AUDIO_GRAPH_CARD)	+= snd-soc-audio-graph-card.o
+obj-$(CONFIG_SND_AUDIO_GRAPH_SCU_CARD)	+= snd-soc-audio-graph-scu-card.o
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c
new file mode 100644
index 0000000..64e8b97
--- /dev/null
+++ b/sound/soc/generic/audio-graph-scu-card.c
@@ -0,0 +1,416 @@
+/*
+ * ASoC audio graph SCU sound card support
+ *
+ * Copyright (C) 2017 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on
+ *	${LINUX}/sound/soc/generic/simple-scu-card.c
+ *	${LINUX}/sound/soc/generic/audio-graph-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 graph_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 graph_priv_to_card(priv) (&(priv)->snd_card)
+#define graph_priv_to_props(priv, i) ((priv)->dai_props + (i))
+#define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev)
+#define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i))
+
+static int asoc_graph_card_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
+
+	return clk_prepare_enable(dai_props->clk);
+}
+
+static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
+
+	clk_disable_unprepare(dai_props->clk);
+}
+
+static struct snd_soc_ops asoc_graph_card_ops = {
+	.startup = asoc_graph_card_startup,
+	.shutdown = asoc_graph_card_shutdown,
+};
+
+static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct graph_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	= graph_priv_to_link(priv, num);
+	dai_props	= graph_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_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					       struct snd_pcm_hw_params *params)
+{
+	struct graph_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_graph_card_dai_link_of(struct device_node *ep,
+				       struct graph_card_data *priv,
+				       unsigned int daifmt,
+				       int idx, int is_fe)
+{
+	struct device *dev = graph_priv_to_dev(priv);
+	struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, idx);
+	struct snd_soc_card *card = graph_priv_to_card(priv);
+	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);
+		if (ret)
+			return ret;
+
+		ret = asoc_simple_card_parse_clk_cpu(dev, 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;
+
+		/* card->num_links includes Codec */
+		asoc_simple_card_canonicalize_cpu(dai_link,
+					(card->num_links - 1) == 1);
+	} 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_graph_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(dev, 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(card,
+					      &priv->codec_conf,
+					      dai_link->codec_of_node,
+					      "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_graph_card_ops;
+	dai_link->init			= asoc_graph_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_graph_card_parse_of(struct graph_card_data *priv)
+{
+	struct of_phandle_iterator it;
+	struct device *dev = graph_priv_to_dev(priv);
+	struct snd_soc_card *card = graph_priv_to_card(priv);
+	struct device_node *node = dev->of_node;
+	struct device_node *cpu_port;
+	struct device_node *cpu_ep;
+	struct device_node *codec_ep;
+	struct device_node *rcpu_ep;
+	unsigned int daifmt = 0;
+	int dai_idx, ret;
+	int rc, codec;
+
+	if (!node)
+		return -EINVAL;
+
+	/*
+	 * we need to consider "widgets", "mclk-fs" around here
+	 * see simple-card
+	 */
+
+	ret = snd_soc_of_parse_audio_routing(card, "routing");
+	if (ret)
+		return ret;
+
+	/* sampling rate convert */
+	of_property_read_u32(node, "convert-rate", &priv->convert_rate);
+
+	/* channels transfer */
+	of_property_read_u32(node, "convert-channels", &priv->convert_channels);
+
+	/*
+	 * it supports multi CPU, single CODEC only here
+	 * see asoc_graph_get_dais_count
+	 */
+
+	/* find 1st codec */
+	of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+		cpu_port = it.node;
+		cpu_ep   = of_get_next_child(cpu_port, NULL);
+		codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+		rcpu_ep  = of_graph_get_remote_endpoint(codec_ep);
+
+		of_node_put(cpu_port);
+		of_node_put(cpu_ep);
+		of_node_put(codec_ep);
+		of_node_put(rcpu_ep);
+
+		if (!codec_ep)
+			continue;
+
+		if (rcpu_ep != cpu_ep) {
+			dev_err(dev, "remote-endpoint missmatch (%s/%s/%s)\n",
+				cpu_ep->name, codec_ep->name, rcpu_ep->name);
+			ret = -EINVAL;
+			goto parse_of_err;
+		}
+
+		ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
+							    NULL, &daifmt);
+		if (ret < 0)
+			goto parse_of_err;
+	}
+
+	dai_idx = 0;
+	for (codec = 0; codec < 2; codec++) {
+		/*
+		 * To listup valid sounds continuously,
+		 * detect all CPU-dummy first, and
+		 * detect all dummy-Codec second
+		 */
+		of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+			cpu_port = it.node;
+			cpu_ep   = of_get_next_child(cpu_port, NULL);
+			codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+
+			of_node_put(cpu_port);
+			of_node_put(cpu_ep);
+			of_node_put(codec_ep);
+
+			if (codec) {
+				if (!codec_ep)
+					continue;
+
+				/* Back-End (= Codec) */
+				ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0);
+				if (ret < 0)
+					goto parse_of_err;
+			} else {
+				/* Front-End (= CPU) */
+				ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1);
+				if (ret < 0)
+					goto parse_of_err;
+			}
+		}
+	}
+
+	ret = asoc_simple_card_parse_card_name(card, NULL);
+	if (ret)
+		goto parse_of_err;
+
+	dev_dbg(dev, "New card: %s\n",
+		card->name ? card->name : "");
+	dev_dbg(dev, "convert_rate     %d\n", priv->convert_rate);
+	dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
+
+	ret = 0;
+
+parse_of_err:
+	return ret;
+}
+
+static int asoc_graph_get_dais_count(struct device *dev)
+{
+	struct of_phandle_iterator it;
+	struct device_node *node = dev->of_node;
+	struct device_node *cpu_port;
+	struct device_node *cpu_ep;
+	struct device_node *codec_ep;
+	int count = 0;
+	int rc;
+
+	of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+		cpu_port = it.node;
+		cpu_ep   = of_get_next_child(cpu_port, NULL);
+		codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+
+		of_node_put(cpu_port);
+		of_node_put(cpu_ep);
+		of_node_put(codec_ep);
+
+		if (cpu_ep)
+			count++;
+		if (codec_ep)
+			count++;
+	}
+
+	return count;
+}
+
+static int asoc_graph_card_probe(struct platform_device *pdev)
+{
+	struct graph_card_data *priv;
+	struct snd_soc_dai_link *dai_link;
+	struct asoc_simple_dai *dai_props;
+	struct device *dev = &pdev->dev;
+	struct snd_soc_card *card;
+	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_graph_get_dais_count(dev);
+	if (num == 0)
+		return -EINVAL;
+
+	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 */
+	card = graph_priv_to_card(priv);
+	card->owner		= THIS_MODULE;
+	card->dev		= dev;
+	card->dai_link		= priv->dai_link;
+	card->num_links		= num;
+	card->codec_conf	= &priv->codec_conf;
+	card->num_configs	= 1;
+
+	ret = asoc_graph_card_parse_of(priv);
+	if (ret < 0) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "parse error %d\n", ret);
+		goto err;
+	}
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	ret = devm_snd_soc_register_card(dev, card);
+	if (ret >= 0)
+		return ret;
+err:
+	asoc_simple_card_clean_reference(card);
+
+	return ret;
+}
+
+static int asoc_graph_card_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	return asoc_simple_card_clean_reference(card);
+}
+
+static const struct of_device_id asoc_graph_of_match[] = {
+	{ .compatible = "audio-graph-scu-card", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, asoc_graph_of_match);
+
+static struct platform_driver asoc_graph_card = {
+	.driver = {
+		.name = "asoc-audio-graph-scu-card",
+		.of_match_table = asoc_graph_of_match,
+	},
+	.probe = asoc_graph_card_probe,
+	.remove = asoc_graph_card_remove,
+};
+module_platform_driver(asoc_graph_card);
+
+MODULE_ALIAS("platform:asoc-audio-graph-scu-card");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Audio Graph SCU Sound Card");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Applied "ASoC: simple-scu-card: cleanup documentation" to the asoc tree
  2017-05-18  1:44 ` [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation Kuninori Morimoto
@ 2017-05-19 17:04   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2017-05-19 17:04 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Mark Brown

The patch

   ASoC: simple-scu-card: cleanup documentation

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 55cfebfede61cedf60289a7bd20e93a1c83a39a9 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 18 May 2017 01:44:27 +0000
Subject: [PATCH] ASoC: simple-scu-card: cleanup documentation

simple-scu-card is almost same as simple-card. This is already explained
in document. But simple-card and simple-scu-card both has same
explanation for same property. This patch forward explantion to
simple-card if possible to avoid duplication.

This patch also cleanup DT binding example which is not good matching
to simple-scu-card.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 .../devicetree/bindings/sound/simple-scu-card.txt  | 65 ++++++++--------------
 1 file changed, 24 insertions(+), 41 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt
index d6fe47ed09af..e894cef1d314 100644
--- a/Documentation/devicetree/bindings/sound/simple-scu-card.txt
+++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt
@@ -1,35 +1,29 @@
-ASoC simple SCU Sound Card
+ASoC Simple SCU Sound Card
 
-Simple-Card specifies audio DAI connections of SoC <-> codec.
+Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM".
+For example, you can use this driver if you want to exchange sampling rate convert,
+Mixing, etc...
 
 Required properties:
 
 - compatible				: "simple-scu-audio-card"
 					  "renesas,rsrc-card"
-
 Optional properties:
 
-- simple-audio-card,name		: User specified audio sound card name, one string
-					  property.
-- simple-audio-card,cpu			: CPU   sub-node
-- simple-audio-card,codec		: CODEC sub-node
+- simple-audio-card,name		: see simple-audio-card.txt
+- simple-audio-card,cpu			: see simple-audio-card.txt
+- simple-audio-card,codec		: see simple-audio-card.txt
 
 Optional subnode properties:
 
-- simple-audio-card,format		: CPU/CODEC common audio format.
-					  "i2s", "right_j", "left_j" , "dsp_a"
-					  "dsp_b", "ac97", "pdm", "msb", "lsb"
-- simple-audio-card,frame-master	: Indicates dai-link frame master.
-					  phandle to a cpu or codec subnode.
-- simple-audio-card,bitclock-master	: Indicates dai-link bit clock master.
-					  phandle to a cpu or codec subnode.
-- simple-audio-card,bitclock-inversion	: bool property. Add this if the
-					  dai-link uses bit clock inversion.
-- simple-audio-card,frame-inversion	: bool property. Add this if the
-					  dai-link uses frame clock inversion.
+- simple-audio-card,format		: see simple-audio-card.txt
+- simple-audio-card,frame-master	: see simple-audio-card.txt
+- simple-audio-card,bitclock-master	: see simple-audio-card.txt
+- simple-audio-card,bitclock-inversion	: see simple-audio-card.txt
+- simple-audio-card,frame-inversion	: see simple-audio-card.txt
 - simple-audio-card,convert-rate	: platform specified sampling rate convert
 - simple-audio-card,convert-channels	: platform specified converted channel size (2 - 8 ch)
-- simple-audio-card,prefix		: see audio-routing
+- simple-audio-card,prefix		: see routing
 - simple-audio-card,routing		: A list of the connections between audio components.
 					  Each entry is a pair of strings, the first being the connection's sink,
 					  the second being the connection's source. Valid names for sources.
@@ -38,19 +32,11 @@ Optional subnode properties:
 
 Required CPU/CODEC subnodes properties:
 
-- sound-dai				: phandle and port of CPU/CODEC
+- sound-dai				: see simple-audio-card.txt
 
 Optional CPU/CODEC subnodes properties:
 
-- clocks / system-clock-frequency	: specify subnode's clock if needed.
-					  it can be specified via "clocks" if system has
-					  clock node (= common clock), or "system-clock-frequency"
-					  (if system doens't support common clock)
-					  If a clock is specified, it is
-					  enabled with clk_prepare_enable()
-					  in dai startup() and disabled with
-					  clk_disable_unprepare() in dai
-					  shutdown().
+- clocks / system-clock-frequency	: see simple-audio-card.txt
 
 Example 1. Sampling Rate Covert
 
@@ -59,11 +45,10 @@ sound {
 
 	simple-audio-card,name = "rsnd-ak4643";
 	simple-audio-card,format = "left_j";
-	simple-audio-card,format = "left_j";
 	simple-audio-card,bitclock-master = <&sndcodec>;
 	simple-audio-card,frame-master = <&sndcodec>;
 
-	simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */
+	simple-audio-card,convert-rate = <48000>;
 
 	simple-audio-card,prefix = "ak4642";
 	simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
@@ -79,20 +64,18 @@ sound {
 	};
 };
 
-Example 2. 2 CPU 1 Codec
+Example 2. 2 CPU 1 Codec (Mixing)
 
 sound {
-	compatible = "renesas,rsrc-card";
-
-	card-name = "rsnd-ak4643";
-	format = "left_j";
-	bitclock-master = <&dpcmcpu>;
-	frame-master = <&dpcmcpu>;
+	compatible = "simple-scu-audio-card";
 
-	convert-rate = <48000>;  /* see audio_clk_a */
+	simple-audio-card,name = "rsnd-ak4643";
+	simple-audio-card,format = "left_j";
+	simple-audio-card,bitclock-master = <&dpcmcpu>;
+	simple-audio-card,frame-master = <&dpcmcpu>;
 
-	audio-prefix = "ak4642";
-	audio-routing = "ak4642 Playback", "DAI0 Playback",
+	simple-audio-card,prefix = "ak4642";
+	simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
 			"ak4642 Playback", "DAI1 Playback";
 
 	dpcmcpu: cpu@0 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Applied "ASoC: add audio-graph-scu-card support" to the asoc tree
  2017-05-18  1:45 ` [PATCH 3/3] ASoC: add audio-graph-scu-card support Kuninori Morimoto
@ 2017-05-29 14:02   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2017-05-29 14:02 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Mark Brown

The patch

   ASoC: add audio-graph-scu-card support

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 87f937b45f7dacfb09e6f7dddb2db8484dc0e8e3 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 18 May 2017 01:45:37 +0000
Subject: [PATCH] ASoC: add audio-graph-scu-card support

OF-graph base DT binding is used on V4L2, and ALSA SoC is using
different style of DT today. Now ALSA SoC supports simple-card driver
for generic/simple sound card, and we have simple-scu-card driver
for simple-card + ALSA DPCM case.
In the future, V4L2 / ALSA will support HDMI, and then, DT bindings
between V4L2 / ALSA should be merged.
This patch adds new Audio Graph SCU Card which is OF-graph base of
simple-scu-card

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/generic/Kconfig                |   9 +
 sound/soc/generic/Makefile               |   2 +
 sound/soc/generic/audio-graph-scu-card.c | 416 +++++++++++++++++++++++++++++++
 3 files changed, 427 insertions(+)
 create mode 100644 sound/soc/generic/audio-graph-scu-card.c

diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
index 121a48e8bb7d..c954be0a0f96 100644
--- a/sound/soc/generic/Kconfig
+++ b/sound/soc/generic/Kconfig
@@ -22,3 +22,12 @@ config SND_AUDIO_GRAPH_CARD
 	help
 	  This option enables generic simple simple sound card support
 	  with OF-graph DT bindings.
+
+config SND_AUDIO_GRAPH_SCU_CARD
+	tristate "ASoC Audio Graph SCU sound card support"
+	depends on OF
+	select SND_SIMPLE_CARD_UTILS
+	help
+	  This option enables generic simple SCU sound card support
+	  with OF-graph DT bindings.
+	  It supports DPCM of multi CPU single Codec ststem.
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
index 670068f257b9..9e000523a3b4 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-audio-graph-card-objs	:= audio-graph-card.o
+snd-soc-audio-graph-scu-card-objs	:= audio-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_AUDIO_GRAPH_CARD)	+= snd-soc-audio-graph-card.o
+obj-$(CONFIG_SND_AUDIO_GRAPH_SCU_CARD)	+= snd-soc-audio-graph-scu-card.o
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c
new file mode 100644
index 000000000000..64e8b9728580
--- /dev/null
+++ b/sound/soc/generic/audio-graph-scu-card.c
@@ -0,0 +1,416 @@
+/*
+ * ASoC audio graph SCU sound card support
+ *
+ * Copyright (C) 2017 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on
+ *	${LINUX}/sound/soc/generic/simple-scu-card.c
+ *	${LINUX}/sound/soc/generic/audio-graph-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 graph_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 graph_priv_to_card(priv) (&(priv)->snd_card)
+#define graph_priv_to_props(priv, i) ((priv)->dai_props + (i))
+#define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev)
+#define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i))
+
+static int asoc_graph_card_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
+
+	return clk_prepare_enable(dai_props->clk);
+}
+
+static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
+
+	clk_disable_unprepare(dai_props->clk);
+}
+
+static struct snd_soc_ops asoc_graph_card_ops = {
+	.startup = asoc_graph_card_startup,
+	.shutdown = asoc_graph_card_shutdown,
+};
+
+static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct graph_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	= graph_priv_to_link(priv, num);
+	dai_props	= graph_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_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					       struct snd_pcm_hw_params *params)
+{
+	struct graph_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_graph_card_dai_link_of(struct device_node *ep,
+				       struct graph_card_data *priv,
+				       unsigned int daifmt,
+				       int idx, int is_fe)
+{
+	struct device *dev = graph_priv_to_dev(priv);
+	struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx);
+	struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, idx);
+	struct snd_soc_card *card = graph_priv_to_card(priv);
+	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);
+		if (ret)
+			return ret;
+
+		ret = asoc_simple_card_parse_clk_cpu(dev, 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;
+
+		/* card->num_links includes Codec */
+		asoc_simple_card_canonicalize_cpu(dai_link,
+					(card->num_links - 1) == 1);
+	} 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_graph_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(dev, 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(card,
+					      &priv->codec_conf,
+					      dai_link->codec_of_node,
+					      "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_graph_card_ops;
+	dai_link->init			= asoc_graph_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_graph_card_parse_of(struct graph_card_data *priv)
+{
+	struct of_phandle_iterator it;
+	struct device *dev = graph_priv_to_dev(priv);
+	struct snd_soc_card *card = graph_priv_to_card(priv);
+	struct device_node *node = dev->of_node;
+	struct device_node *cpu_port;
+	struct device_node *cpu_ep;
+	struct device_node *codec_ep;
+	struct device_node *rcpu_ep;
+	unsigned int daifmt = 0;
+	int dai_idx, ret;
+	int rc, codec;
+
+	if (!node)
+		return -EINVAL;
+
+	/*
+	 * we need to consider "widgets", "mclk-fs" around here
+	 * see simple-card
+	 */
+
+	ret = snd_soc_of_parse_audio_routing(card, "routing");
+	if (ret)
+		return ret;
+
+	/* sampling rate convert */
+	of_property_read_u32(node, "convert-rate", &priv->convert_rate);
+
+	/* channels transfer */
+	of_property_read_u32(node, "convert-channels", &priv->convert_channels);
+
+	/*
+	 * it supports multi CPU, single CODEC only here
+	 * see asoc_graph_get_dais_count
+	 */
+
+	/* find 1st codec */
+	of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+		cpu_port = it.node;
+		cpu_ep   = of_get_next_child(cpu_port, NULL);
+		codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+		rcpu_ep  = of_graph_get_remote_endpoint(codec_ep);
+
+		of_node_put(cpu_port);
+		of_node_put(cpu_ep);
+		of_node_put(codec_ep);
+		of_node_put(rcpu_ep);
+
+		if (!codec_ep)
+			continue;
+
+		if (rcpu_ep != cpu_ep) {
+			dev_err(dev, "remote-endpoint missmatch (%s/%s/%s)\n",
+				cpu_ep->name, codec_ep->name, rcpu_ep->name);
+			ret = -EINVAL;
+			goto parse_of_err;
+		}
+
+		ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
+							    NULL, &daifmt);
+		if (ret < 0)
+			goto parse_of_err;
+	}
+
+	dai_idx = 0;
+	for (codec = 0; codec < 2; codec++) {
+		/*
+		 * To listup valid sounds continuously,
+		 * detect all CPU-dummy first, and
+		 * detect all dummy-Codec second
+		 */
+		of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+			cpu_port = it.node;
+			cpu_ep   = of_get_next_child(cpu_port, NULL);
+			codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+
+			of_node_put(cpu_port);
+			of_node_put(cpu_ep);
+			of_node_put(codec_ep);
+
+			if (codec) {
+				if (!codec_ep)
+					continue;
+
+				/* Back-End (= Codec) */
+				ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0);
+				if (ret < 0)
+					goto parse_of_err;
+			} else {
+				/* Front-End (= CPU) */
+				ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1);
+				if (ret < 0)
+					goto parse_of_err;
+			}
+		}
+	}
+
+	ret = asoc_simple_card_parse_card_name(card, NULL);
+	if (ret)
+		goto parse_of_err;
+
+	dev_dbg(dev, "New card: %s\n",
+		card->name ? card->name : "");
+	dev_dbg(dev, "convert_rate     %d\n", priv->convert_rate);
+	dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
+
+	ret = 0;
+
+parse_of_err:
+	return ret;
+}
+
+static int asoc_graph_get_dais_count(struct device *dev)
+{
+	struct of_phandle_iterator it;
+	struct device_node *node = dev->of_node;
+	struct device_node *cpu_port;
+	struct device_node *cpu_ep;
+	struct device_node *codec_ep;
+	int count = 0;
+	int rc;
+
+	of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
+		cpu_port = it.node;
+		cpu_ep   = of_get_next_child(cpu_port, NULL);
+		codec_ep = of_graph_get_remote_endpoint(cpu_ep);
+
+		of_node_put(cpu_port);
+		of_node_put(cpu_ep);
+		of_node_put(codec_ep);
+
+		if (cpu_ep)
+			count++;
+		if (codec_ep)
+			count++;
+	}
+
+	return count;
+}
+
+static int asoc_graph_card_probe(struct platform_device *pdev)
+{
+	struct graph_card_data *priv;
+	struct snd_soc_dai_link *dai_link;
+	struct asoc_simple_dai *dai_props;
+	struct device *dev = &pdev->dev;
+	struct snd_soc_card *card;
+	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_graph_get_dais_count(dev);
+	if (num == 0)
+		return -EINVAL;
+
+	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 */
+	card = graph_priv_to_card(priv);
+	card->owner		= THIS_MODULE;
+	card->dev		= dev;
+	card->dai_link		= priv->dai_link;
+	card->num_links		= num;
+	card->codec_conf	= &priv->codec_conf;
+	card->num_configs	= 1;
+
+	ret = asoc_graph_card_parse_of(priv);
+	if (ret < 0) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "parse error %d\n", ret);
+		goto err;
+	}
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	ret = devm_snd_soc_register_card(dev, card);
+	if (ret >= 0)
+		return ret;
+err:
+	asoc_simple_card_clean_reference(card);
+
+	return ret;
+}
+
+static int asoc_graph_card_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	return asoc_simple_card_clean_reference(card);
+}
+
+static const struct of_device_id asoc_graph_of_match[] = {
+	{ .compatible = "audio-graph-scu-card", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, asoc_graph_of_match);
+
+static struct platform_driver asoc_graph_card = {
+	.driver = {
+		.name = "asoc-audio-graph-scu-card",
+		.of_match_table = asoc_graph_of_match,
+	},
+	.probe = asoc_graph_card_probe,
+	.remove = asoc_graph_card_remove,
+};
+module_platform_driver(asoc_graph_card);
+
+MODULE_ALIAS("platform:asoc-audio-graph-scu-card");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Audio Graph SCU Sound Card");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Applied "ASoC: add audio-graph-scu-card document" to the asoc tree
  2017-05-18  1:44 ` [PATCH 2/3] ASoC: add audio-graph-scu-card document Kuninori Morimoto
@ 2017-05-29 14:02   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2017-05-29 14:02 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Mark Brown

The patch

   ASoC: add audio-graph-scu-card document

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 be10ee2cd351818738097c782b4493e09c6d14f6 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 18 May 2017 01:44:46 +0000
Subject: [PATCH] ASoC: add audio-graph-scu-card document

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 .../bindings/sound/audio-graph-scu-card.txt        | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt

diff --git a/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
new file mode 100644
index 000000000000..b2dd23fd2135
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
@@ -0,0 +1,72 @@
+Audio-Graph-SCU-Card:
+
+Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM".
+
+It is based on common bindings for device graphs.
+see ${LINUX}/Documentation/devicetree/bindings/graph.txt
+
+Basically, Audio-Graph-SCU-Card property is same as
+Simple-Card / Simple-SCU-Card / Audio-Graph-Card.
+see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
+    ${LINUX}/Documentation/devicetree/bindings/sound/simple-scu-card.txt
+    ${LINUX}/Documentation/devicetree/bindings/sound/audio-graph-card.txt
+
+Below are same as Simple-Card / Audio-Graph-Card.
+
+- label
+- dai-format
+- frame-master
+- bitclock-master
+- bitclock-inversion
+- frame-inversion
+- dai-tdm-slot-num
+- dai-tdm-slot-width
+- clocks / system-clock-frequency
+
+Below are same as Simple-SCU-Card.
+
+- convert-rate
+- convert-channels
+- prefix
+- routing
+
+Required properties:
+
+- compatible				: "audio-graph-scu-card";
+- dais					: list of CPU DAI port{s}
+
+Example
+
+	sound_card {
+		compatible = "audio-graph-scu-card";
+
+		label = "sound-card";
+		prefix = "codec";
+		routing = "codec Playback", "DAI0 Playback",
+			"codec Playback", "DAI1 Playback";
+		convert-rate = <48000>;
+
+		dais = <&cpu_port>;
+	};
+
+	audio-codec {
+		...
+
+		port {
+			codec_endpoint: endpoint {
+				remote-endpoint = <&cpu_endpoint>;
+			};
+		};
+	};
+
+	dai-controller {
+		...
+		cpu_port: port {
+			cpu_endpoint: endpoint {
+				remote-endpoint = <&codec_endpoint>;
+
+				dai-format = "left_j";
+				...
+			};
+		};
+	};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-05-29 14:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-18  1:43 [PATCH 0/3] ASoC: add audio-graph-scu-card Kuninori Morimoto
2017-05-18  1:44 ` [PATCH 1/3] ASoC: simple-scu-card: cleanup documentation Kuninori Morimoto
2017-05-19 17:04   ` Applied "ASoC: simple-scu-card: cleanup documentation" to the asoc tree Mark Brown
2017-05-18  1:44 ` [PATCH 2/3] ASoC: add audio-graph-scu-card document Kuninori Morimoto
2017-05-29 14:02   ` Applied "ASoC: add audio-graph-scu-card document" to the asoc tree Mark Brown
2017-05-18  1:45 ` [PATCH 3/3] ASoC: add audio-graph-scu-card support Kuninori Morimoto
2017-05-29 14:02   ` Applied "ASoC: add audio-graph-scu-card support" to the asoc tree Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox