From patchwork Tue Jul 20 01:40:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 12387255 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 1F376C07E95 for ; Tue, 20 Jul 2021 01:42:57 +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 3EFDA610CC for ; Tue, 20 Jul 2021 01:42:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3EFDA610CC 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 C51DB165D; Tue, 20 Jul 2021 03:42:04 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C51DB165D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745374; bh=zZnfRykQpfe5V2DMH5YZv2qPXZlQW+pNf7qMy4h6Y1Q=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=JpqFAqf22UdVKh5NFSGbYE5pLwbxsOJ1yhcnfTfPzJxyZXM5zlBQ995FQK0vTVojo cciV/XjK540S1gUEjHNw/BfkAiV2j9mdLxd7HZgrRwPlwk7XxNl1arkVnUExFoW3pA AnKHfMBiIdKSwARej5Stk3rqbAIwUxh1B14A+iJs= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6A673F804FC; Tue, 20 Jul 2021 03:40:28 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 02E12F80516; Tue, 20 Jul 2021 03:40:26 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 9507DF804FD for ; Tue, 20 Jul 2021 03:40:19 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9507DF804FD Date: 20 Jul 2021 10:40:19 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88181512" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 20 Jul 2021 10:40:19 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 2B91F41532D4; Tue, 20 Jul 2021 10:40:19 +0900 (JST) Message-ID: <87zguhvk3g.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 07/14] ASoC: audio-graph-card2: add Multi CPU/Codec support User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.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). Link: https://lore.kernel.org/r/87k0xszlep.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto --- include/sound/graph_card.h | 3 + sound/soc/generic/audio-graph-card2.c | 172 ++++++++++++++++++++++++++ 2 files changed, 175 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..f77cf02c0eef 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,77 @@ 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 *ep; + 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_endpoint_of_node(ports, ep) { + 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 +800,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 +868,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_endpoint_count(cpu_ports); + li->num[li->link].codecs = of_graph_get_endpoint_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 +925,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) {