All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
To: Mark Brown <broonie@kernel.org>
Cc: Linux-ALSA <alsa-devel@alsa-project.org>
Subject: [PATCH v3 07/16] ASoC: rich-graph-card: add DPCM support
Date: 10 Sep 2021 10:22:27 +0900	[thread overview]
Message-ID: <87k0jpusvi.wl-kuninori.morimoto.gx@renesas.com> (raw)
In-Reply-To: <87tuitusy4.wl-kuninori.morimoto.gx@renesas.com>


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

This patch adds DPCM support to rich-graph-card.
It uses "dpcm" node (= C), needs to have routing (= A),
need to indicate both FE/BE at links (= B).
dpcm ports@0 is for FE (= D), port@1 is for BE (= D).
remote-endpoint can use both Single/Multi connection.

			DSP
		  ************
	PCM0 <--> * fe0  be0 * <--> DAI0: Codec Headset
	PCM1 <--> * fe1  be1 * <--> DAI1: Codec Speakers
	PCM2 <--> * fe2  be2 * <--> DAI2: MODEM
	PCM3 <--> * fe3  be3 * <--> DAI3: BT
		  *	 be4 * <--> DAI4: DMIC
		  *	 be5 * <--> DAI5: FM
		  ************

	sound {
		compatible = "rich-graph-card";

		// indicate routing
(A)		routing = "xxx Playback", "xxx Playback",
			  "xxx Playback", "xxx Playback",
			  "xxx Playback", "xxx Playback";

		// indicate all Front-End, Back-End in DPCM case
(B)		links = <&fe0, &fe1, ...
			 &be0, &be1, ...

(C)		dpcm {
			// Front-End
(D)			ports@0 {
				fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
				fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
				...
			};
			// Back-End
(E)			ports@1 {
				be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
				be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
				...
			};
		};
	};

	CPU {
		ports {
			bitclock-master;
			frame-master;
			port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
			port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
			...
		};
	};

	Codec {
		ports {
			port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
			port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
			...
		};
	};

Link: https://lore.kernel.org/r/87k0xszlep.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 include/sound/graph_card.h          |   3 +
 sound/soc/generic/rich-graph-card.c | 254 ++++++++++++++++++++++++++++
 2 files changed, 257 insertions(+)

diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h
index 7a22513146c0..c7b632d3e5ff 100644
--- a/include/sound/graph_card.h
+++ b/include/sound/graph_card.h
@@ -17,6 +17,7 @@ struct graph_custom_hooks {
 	int (*hook_pre)(struct asoc_simple_priv *priv);
 	int (*hook_post)(struct asoc_simple_priv *priv);
 	GRAPH_CUSTOM custom_normal;
+	GRAPH_CUSTOM custom_dpcm;
 };
 
 int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
@@ -25,5 +26,7 @@ int rich_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev,
 
 int rich_graph_link_normal(struct asoc_simple_priv *priv,
 			   struct device_node *lnk, struct link_info *li);
+int rich_graph_link_dpcm(struct asoc_simple_priv *priv,
+			 struct device_node *lnk, struct link_info *li);
 
 #endif /* __GRAPH_CARD_H */
diff --git a/sound/soc/generic/rich-graph-card.c b/sound/soc/generic/rich-graph-card.c
index 6ce7001fab2e..e69fb5e73d62 100644
--- a/sound/soc/generic/rich-graph-card.c
+++ b/sound/soc/generic/rich-graph-card.c
@@ -116,15 +116,77 @@ links indicates connection part of CPU side (= A).
 	};
  };
 
+ ************************************
+	DPCM
+ ************************************
+
+		DSP
+	   ************
+ PCM0 <--> * fe0  be0 * <--> DAI0: Codec Headset
+ PCM1 <--> * fe1  be1 * <--> DAI1: Codec Speakers
+ PCM2 <--> * fe2  be2 * <--> DAI2: MODEM
+ PCM3 <--> * fe3  be3 * <--> DAI3: BT
+	   *	  be4 * <--> DAI4: DMIC
+	   *	  be5 * <--> DAI5: FM
+	   ************
+
+ sound {
+	compatible = "rich-graph-card";
+
+	// indicate routing
+	routing = "xxx Playback", "xxx Playback",
+		  "xxx Playback", "xxx Playback",
+		  "xxx Playback", "xxx Playback";
+
+	// indicate all Front-End, Back-End
+	links = <&fe0, &fe1, ...,
+		 &be0, &be1, ...>;
+
+	dpcm {
+		// Front-End
+		ports@0 {
+			fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
+			fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
+			...
+		};
+		// Back-End
+		ports@1 {
+			be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
+			be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
+			...
+		};
+	};
+ };
+
+ CPU {
+	ports {
+		bitclock-master;
+		frame-master;
+		port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
+		port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
+		...
+	};
+ };
+
+ Codec {
+	ports {
+		port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
+		port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
+		...
+	};
+ };
+
 */
 
 enum graph_type {
 	GRAPH_NORMAL,
+	GRAPH_DPCM,
 
 	GRAPH_MULTI,	/* don't use ! Use this only in __graph_get_type() */
 };
 
 #define GRAPH_NODENAME_MULTI	"multi"
+#define GRAPH_NODENAME_DPCM	"dpcm"
 
 #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
 
@@ -147,6 +209,9 @@ static enum graph_type __graph_get_type(struct device_node *lnk)
 	if (of_node_name_eq(np, GRAPH_NODENAME_MULTI))
 		return GRAPH_MULTI;
 
+	if (of_node_name_eq(np, GRAPH_NODENAME_DPCM))
+		return GRAPH_DPCM;
+
 	return GRAPH_NORMAL;
 }
 
@@ -164,6 +229,17 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv,
 		struct device *dev = simple_priv_to_dev(priv);
 		const char *str = "Normal";
 
+		switch (type) {
+		case GRAPH_DPCM:
+			if (asoc_graph_is_ports0(lnk))
+				str = "DPCM Front-End";
+			else
+				str = "DPCM Back-End";
+			break;
+		default:
+			break;
+		}
+
 		dev_dbg(dev, "%pOF (%s)", lnk, str);
 	}
 #endif
@@ -322,6 +398,22 @@ static int asoc_simple_parse_dai(struct device_node *ep,
 	return 0;
 }
 
+static void graph_parse_convert(struct device_node *ep,
+				struct simple_dai_props *props)
+{
+	struct device_node *port = of_get_parent(ep);
+	struct device_node *ports = of_get_parent(port);
+	struct asoc_simple_data *adata = &props->adata;
+
+	if (of_node_name_eq(ports, "ports"))
+		asoc_simple_parse_convert(ports, NULL, adata);
+	asoc_simple_parse_convert(port, NULL, adata);
+	asoc_simple_parse_convert(ep,   NULL, adata);
+
+	of_node_put(port);
+	of_node_put(ports);
+}
+
 static void graph_parse_mclk_fs(struct device_node *ep,
 				struct simple_dai_props *props)
 {
@@ -394,11 +486,37 @@ static int __graph_parse_node(struct asoc_simple_priv *priv,
 							       cpus->dai_name,   cpu_multi,
 							     codecs->dai_name, codec_multi);
 			break;
+		case GRAPH_DPCM:
+			if (is_cpu)
+				asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
+						cpus->of_node, cpus->dai_name, cpu_multi);
+			else
+				asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
+						codecs->of_node, codecs->dai_name, codec_multi);
+			break;
 		default:
 			break;
 		}
 	}
 
+	/*
+	 * Check "prefix" from top node
+	 * if DPCM-BE case
+	 */
+	if (!is_cpu && gtype == GRAPH_DPCM) {
+		struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
+		struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
+		struct device_node *rport  = of_get_parent(ep);
+		struct device_node *rports = of_get_parent(rport);
+
+		if (of_node_name_eq(rports, "ports"))
+			snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
+		snd_soc_of_parse_node_prefix(rport,  cconf, codecs->of_node, "prefix");
+
+		of_node_put(rport);
+		of_node_put(rports);
+	}
+
 	if (is_cpu) {
 		struct snd_soc_dai_link_component *cpus = dlc;
 		struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx);
@@ -582,6 +700,98 @@ int rich_graph_link_normal(struct asoc_simple_priv *priv,
 }
 EXPORT_SYMBOL_GPL(rich_graph_link_normal);
 
+int rich_graph_link_dpcm(struct asoc_simple_priv *priv,
+			 struct device_node *lnk,
+			 struct link_info *li)
+{
+	struct device_node *ep = port_to_endpoint(lnk);
+	struct device_node *rep = of_graph_get_remote_endpoint(ep);
+	struct device_node *rport = of_graph_get_remote_port(ep);
+	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
+	struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
+	int is_cpu = asoc_graph_is_ports0(lnk);
+	int ret;
+
+	if (is_cpu) {
+		/*
+		 * dpcm {
+		 *	// Front-End
+		 *	ports@0 {
+		 * =>		lnk: port@0 { ep: { ... = rep }; };
+		 *		 ...
+		 *	};
+		 *	// Back-End
+		 *	ports@0 {
+		 *		 ...
+		 *	};
+		 * };
+		 *
+		 * CPU {
+		 *	rports: ports {
+		 *		rport: port@0 { rep: { ... = ep } };
+		 *	}
+		 * }
+		 */
+		/*
+		 * setup CPU here, Codec is already set as dummy.
+		 * see
+		 *	asoc_simple_init_priv()
+		 */
+		dai_link->dynamic		= 1;
+		dai_link->dpcm_merged_format	= 1;
+
+		ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
+		if (ret)
+			goto err;
+	} else {
+		/*
+		 * dpcm {
+		 *	// Front-End
+		 *	ports@0 {
+		 *		 ...
+		 *	};
+		 *	// Back-End
+		 *	ports@0 {
+		 * =>		lnk: port@0 { ep: { ... = rep; }; };
+		 *		 ...
+		 *	};
+		 * };
+		 *
+		 * Codec {
+		 *	rports: ports {
+		 *		rport: port@0 { rep: { ... = ep; }; };
+		 *	}
+		 * }
+		 */
+		/*
+		 * setup Codec here, CPU is already set as dummy.
+		 * see
+		 *	asoc_simple_init_priv()
+		 */
+
+		/* BE settings */
+		dai_link->no_pcm		= 1;
+		dai_link->be_hw_params_fixup	= asoc_simple_be_hw_params_fixup;
+
+		ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
+		if (ret < 0)
+			goto err;
+	}
+
+	graph_parse_convert(rep, dai_props);
+
+	snd_soc_dai_link_set_capabilities(dai_link);
+
+	graph_link_init(priv, rport, li, is_cpu);
+err:
+	of_node_put(ep);
+	of_node_put(rep);
+	of_node_put(rport);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rich_graph_link_dpcm);
+
 static int graph_link(struct asoc_simple_priv *priv,
 		      struct graph_custom_hooks *hooks,
 		      enum graph_type gtype,
@@ -599,6 +809,12 @@ static int graph_link(struct asoc_simple_priv *priv,
 		else
 			func = rich_graph_link_normal;
 		break;
+	case GRAPH_DPCM:
+		if (hooks && hooks->custom_dpcm)
+			func = hooks->custom_dpcm;
+		else
+			func = rich_graph_link_dpcm;
+		break;
 	default:
 		break;
 	}
@@ -665,6 +881,41 @@ static int graph_count_normal(struct asoc_simple_priv *priv,
 	return 0;
 }
 
+static int graph_count_dpcm(struct asoc_simple_priv *priv,
+			    struct device_node *lnk,
+			    struct link_info *li)
+{
+	struct device_node *ep = port_to_endpoint(lnk);
+	struct device_node *rport = of_graph_get_remote_port(ep);
+
+	/*
+	 * dpcm {
+	 *	// Front-End
+	 *	ports@0 {
+	 * =>		lnk: port@0 { endpoint { ... }; };
+	 *		 ...
+	 *	};
+	 *	// Back-End
+	 *	ports@1 {
+	 * =>		lnk: port@0 { endpoint { ... }; };
+	 *		 ...
+	 *	};
+	 * };
+	 */
+
+	if (asoc_graph_is_ports0(lnk)) {
+		li->num[li->link].cpus		= graph_counter(rport); /* FE */
+		li->num[li->link].platforms	= graph_counter(rport);
+	} else {
+		li->num[li->link].codecs	= graph_counter(rport); /* BE */
+	}
+
+	of_node_put(ep);
+	of_node_put(rport);
+
+	return 0;
+}
+
 static int graph_count(struct asoc_simple_priv *priv,
 		       struct graph_custom_hooks *hooks,
 		       enum graph_type gtype,
@@ -684,6 +935,9 @@ static int graph_count(struct asoc_simple_priv *priv,
 	case GRAPH_NORMAL:
 		func = graph_count_normal;
 		break;
+	case GRAPH_DPCM:
+		func = graph_count_dpcm;
+		break;
 	default:
 	}
 
-- 
2.25.1


  parent reply	other threads:[~2021-09-10  1:24 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-10  1:20 [PATCH v3 00/16] ASoC: Add Rich Graph Card support Kuninori Morimoto
2021-09-10  1:21 ` [PATCH v3 01/16] ASoC: test-component: add Test Component YAML bindings Kuninori Morimoto
2021-10-01 20:11   ` Mark Brown
2021-09-10  1:21 ` [PATCH v3 02/16] ASoC: test-component: add Test Component for Sound debug/test Kuninori Morimoto
2021-09-10  1:21 ` [PATCH v3 03/16] ASoC: simple-card-utils: add asoc_graph_is_ports0() Kuninori Morimoto
2021-09-10  1:22 ` [PATCH v3 04/16] ASoC: simple-card-utils: add codec2codec support Kuninori Morimoto
2021-09-10  1:22 ` [PATCH v3 05/16] ASoC: add Rich Graph Card driver Kuninori Morimoto
2021-09-12 10:24   ` kernel test robot
2021-09-12 10:24     ` kernel test robot
2021-09-10  1:22 ` [PATCH v3 06/16] ASoC: rich-graph-card: add Multi CPU/Codec support Kuninori Morimoto
2021-09-10  1:22 ` Kuninori Morimoto [this message]
2021-09-10  1:22 ` [PATCH v3 08/16] ASoC: rich-graph-card: add Codec2Codec support Kuninori Morimoto
2021-09-12  6:43   ` kernel test robot
2021-09-12  6:43     ` kernel test robot
2021-09-10  1:22 ` [PATCH v3 09/16] ASoC: add Rich Graph Card Yaml Document Kuninori Morimoto
2021-10-01 21:06   ` Mark Brown
2021-10-04  1:50     ` Kuninori Morimoto
2021-10-05 17:26       ` Mark Brown
2021-09-10  1:22 ` [PATCH v3 10/16] ASoC: add Rich Graph Card Custom Sample Kuninori Morimoto
2021-09-10  1:22 ` [PATCH v3 11/16] ASoC: rich-graph-card-sample.dtsi: add Sample DT for Normal (Single) Kuninori Morimoto
2021-09-10  1:22 ` [PATCH v3 12/16] ASoC: rich-graph-card-sample.dtsi: add Sample DT for Normal (Nulti) Kuninori Morimoto
2021-09-10  1:22 ` [PATCH v3 13/16] ASoC: rich-graph-card-sample.dtsi: add DPCM sample (Single) Kuninori Morimoto
2021-09-10  1:23 ` [PATCH v3 14/16] ASoC: rich-graph-card-sample.dtsi: add DPCM sample (Multi) Kuninori Morimoto
2021-09-10  1:23 ` [PATCH v3 15/16] ASoC: rich-graph-card-sample.dtsi: add Codec2Codec sample (Single) Kuninori Morimoto
2021-09-10  1:23 ` [PATCH v3 16/16] ASoC: rich-graph-card-sample.dtsi: add Codec2Codec sample (Multi) Kuninori Morimoto
2021-09-29 22:23 ` [PATCH v3 00/16] ASoC: Add Rich Graph Card support Kuninori Morimoto
2021-09-30 12:15   ` Mark Brown
2021-09-30 22:38     ` Kuninori Morimoto
2021-10-01  5:43 ` Péter Ujfalusi
2021-10-01  6:48   ` Kuninori Morimoto
2021-10-01 20:01     ` Mark Brown
2021-10-03 23:52       ` Kuninori Morimoto
2021-10-04 16:54         ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k0jpusvi.wl-kuninori.morimoto.gx@renesas.com \
    --to=kuninori.morimoto.gx@renesas.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.