From patchwork Tue Jun 22 01:15:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 465936 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6DF4EC4743C for ; Tue, 22 Jun 2021 01:18:21 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E881C610C7 for ; Tue, 22 Jun 2021 01:18:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E881C610C7 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 87EBB168C; Tue, 22 Jun 2021 03:17:29 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 87EBB168C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624324699; bh=T7p8KbodmMDouUik5+F8S3uG3i6ELViK+YzUm7BGMdQ=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=L7ZjV3JMe0cn2GmafyaSwyFs2fdVxmCJ5MjjzBs6QufBiuSEI1i5p6qTJQ8rm9AQg TJixMv4B540TJVt0rtdqG7UXPzCHM4y9GHvEbAhAaqAfDe6JzwSqae6gc7krzEQEdf XDfAvPw4jsPBU0MNjOPPtu1/I8Urs8rpCb0rUyXc= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id C2B3EF804D9; Tue, 22 Jun 2021 03:15:20 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7DAD8F80517; Tue, 22 Jun 2021 03:15:19 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 52FB7F804D9 for ; Tue, 22 Jun 2021 03:15:12 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 52FB7F804D9 Date: 22 Jun 2021 10:15:11 +0900 X-IronPort-AV: E=Sophos;i="5.83,290,1616425200"; d="scan'208";a="85109292" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 22 Jun 2021 10:15:11 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id E60B6400D0C5; Tue, 22 Jun 2021 10:15:11 +0900 (JST) Message-ID: <87pmwe3dk0.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH RFC 08/15] ASoC: audio-graph-card2: add Multi CPU/Codec support User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown , Rob Herring In-Reply-To: <871r8u4s6q.wl-kuninori.morimoto.gx@renesas.com> References: <871r8u4s6q.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto This patch adds Multi CPU/Codec support to audio-graph-card2. One note today is that ASoC doesn't support N CPUs to M CODECs (It supports "1 CPU to N Codecs" or "N CPUs to N Codecs"). Multi CPU/Codec support needs to have extra node (X) to indicate it. <- multi_CPU -> <-- multi_Codec --> ****** CPU1 <--> * * <--> Codec1 CPU2 <--> * * <--> Codec2 ****** sound { compatible = "audio-graph-card2"; (A) links = <&multi>; }; (X) multi_CPU_CODEC { compatible = "audio-graph-card2-multi"; /* for CPU */ (B) multi: ports@0 { port@0 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; }; port@1 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; }; /* for Codec */ ports@1 { port@0 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; port@1 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; }; }; }; CPU { ports { bitclock-master; frame-master; port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; }; port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; }; }; }; Codec { ports { port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; }; port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; }; }; }; "links" need to indicate Multi connection's CPU node (A)(B). Signed-off-by: Kuninori Morimoto --- include/sound/graph_card.h | 3 + sound/soc/generic/audio-graph-card2.c | 173 ++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index 03df4c5a7151..d0ccb7afda78 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -18,6 +18,7 @@ struct graph_custom_hooks { int (*hook_post)(struct asoc_simple_priv *priv); GRAPH_CUSTOM custom_normal; GRAPH_CUSTOM custom_dpcm; + GRAPH_CUSTOM custom_multi; }; int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); @@ -28,5 +29,7 @@ int audio_graph2_link_normal(struct asoc_simple_priv *priv, struct device_node *lnk, struct link_info *li); int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, struct device_node *lnk, struct link_info *li); +int audio_graph2_link_multi(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); #endif /* __GRAPH_CARD_H */ diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index b288975ffde2..ece0f7d28437 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -134,14 +134,66 @@ ... }; }; + + + ************************************ + Multi-CPU/Codec + ************************************ + +<- multi_CPU -> + <-- multi_Codec --> + ****** +CPU1 <--> * * <--> Codec1 +CPU2 <--> * * <--> Codec2 + ****** + *NOTE* + N cpus to M codecs is not yet supported + at ASoC framework for now. + + sound { + compatible = "audio-graph-card2"; + + links = <&multi>; + }; + + multi_CPU_CODEC { + compatible = "audio-graph-card2-multi"; + + multi: ports@0 { + port@0 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; }; + port@1 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; }; + }; + ports@1 { + port@0 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; + port@1 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; }; + }; +}; + + CPU { + ports { + bitclock-master; + frame-master; + port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; }; + port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; }; + }; + }; + + Codec { + ports { + port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; }; + port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; }; + }; + }; */ enum graph_type { GRAPH_NORMAL, GRAPH_DPCM, + GRAPH_MULTI, }; #define GRAPH_COMPATIBLE_DPCM "audio-graph-card2-dsp" +#define GRAPH_COMPATIBLE_MULTI "audio-graph-card2-multi" #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") @@ -166,6 +218,8 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv, if (strcmp(string, GRAPH_COMPATIBLE_DPCM) == 0) type = GRAPH_DPCM; + else if (strcmp(string, GRAPH_COMPATIBLE_MULTI) == 0) + type = GRAPH_MULTI; end: #ifdef DEBUG { @@ -179,6 +233,9 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv, else str = "DPCM Back-End"; break; + case GRAPH_MULTI: + str = "MULTI"; + break; default: break; } @@ -649,6 +706,78 @@ int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, } EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); +int audio_graph2_link_multi(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct device_node *top = of_get_parent(lnk); + struct device_node *first_rep = NULL; + struct device_node *ports = lnk; + struct device_node *port; + char dai_name[64]; + int is_cpu = 1; + int i; + + /* + * top: MULTI { + * compatible = "audio-graph-card2-multi"; + * + * // CPU + * loop-0 ports@0 { + * port@0 { ep: endpoint { remote-endpoint = <&r_ep>; }; }; + * ... + * }; + * // Codec + * loop-1 ports@1 { + * ... + * }; + * }; + */ +ports_loop: + i = 0; + for_each_port_of_node(ports, port) { + struct device_node *ep = port_to_endpoint(port); + struct device_node *rep = of_graph_get_remote_endpoint(ep); + int ret, is_single_links = 0; + + if (!first_rep) + first_rep = rep; + + ret = graph_parse_node(priv, rep, li, i, + is_cpu ? &is_single_links : NULL); + + of_node_put(ep); + of_node_put(rep); + + if (ret < 0) + return ret; + + if (is_cpu) { + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, i); + + asoc_simple_canonicalize_cpu(cpus, is_single_links); + } + + i++; + } + + /* + * 1st turn was for CPU ports (is_cpu = 1) + * 2nd turn is for Codec ports (is_cpu = 0) + */ + is_cpu--; + if (is_cpu == 0) { + ports = of_get_next_child(top, ports); + goto ports_loop; + } + + snprintf(dai_name, sizeof(dai_name), "multi-%pOFP", top); + + return graph_link_init(priv, first_rep, li, 1, dai_name); +} +EXPORT_SYMBOL_GPL(audio_graph2_link_multi); + static int graph_link(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -672,6 +801,12 @@ static int graph_link(struct asoc_simple_priv *priv, else func = audio_graph2_link_dpcm; break; + case GRAPH_MULTI: + if (hooks && hooks->custom_multi) + func = hooks->custom_multi; + else + func = audio_graph2_link_multi; + break; } if (!func) { @@ -734,6 +869,41 @@ static int graph_count_dsp(struct asoc_simple_priv *priv, return 0; } +static int graph_count_multi(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct device_node *top = of_get_parent(lnk); + struct device_node *cpu_ports = lnk; + struct device_node *codec_ports = of_get_next_child(top, cpu_ports); + + of_node_get(cpu_ports); /* for vs of_get_next_child() */ + + /* + * MULTI { + * compatible = "audio-graph-card2-multi"; + * + * // CPU + * => lnk: ports@0 { + * port@0 { endpoint { ... }; }; + * ... + * }; + * // Codec + * ports@1 { + * port@0 { endpoint { ... }; }; + * ... + * }; + * }; + */ + li->num[li->link].cpus = of_graph_get_port_count(cpu_ports); + li->num[li->link].codecs = of_graph_get_port_count(codec_ports); + + of_node_put(top); + of_node_put(codec_ports); + + return 0; +} + static int graph_count(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -756,6 +926,9 @@ static int graph_count(struct asoc_simple_priv *priv, case GRAPH_DPCM: func = graph_count_dsp; break; + case GRAPH_MULTI: + func = graph_count_multi; + break; } if (!func) {