From patchwork Wed Dec 5 01:31:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 10712879 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B0A491057 for ; Wed, 5 Dec 2018 01:31:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C8862C4BC for ; Wed, 5 Dec 2018 01:31:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8FA472C4E5; Wed, 5 Dec 2018 01:31:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22A552C4BC for ; Wed, 5 Dec 2018 01:31:40 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id B6EFC267BCE; Wed, 5 Dec 2018 02:31:38 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id B9480267BCF; Wed, 5 Dec 2018 02:31:29 +0100 (CET) Received: from JPN01-TY1-obe.outbound.protection.outlook.com (mail-eopbgr1400133.outbound.protection.outlook.com [40.107.140.133]) by alsa0.perex.cz (Postfix) with ESMTP id 9169F267B88 for ; Wed, 5 Dec 2018 02:31:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=renesasgroup.onmicrosoft.com; s=selector1-renesas-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=YPOJKH6CQSYbub7UZnvR+CQpQ5bWVstpk2Ww9CLKADA=; b=QXCLlg20TiyLRbgr/9Qws8H1Fdn2Js38puT/5GarTKcJIgEyt9gYgFoxqLYWQal8sohkPU6rsNAV8u7WeFtNZCIy2w5KtKxb6nVrfhdDHK6s6eL3HzKIlhRFYXPmaT1++K1lZ7kyCFk2pCtO06GyQ/mxr/PJy3iZmv+0FgOACy8= Received: from TYAPR01MB3661.jpnprd01.prod.outlook.com (20.178.137.210) by TYAPR01MB1918.jpnprd01.prod.outlook.com (52.133.176.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1382.22; Wed, 5 Dec 2018 01:31:22 +0000 Received: from TYAPR01MB3661.jpnprd01.prod.outlook.com ([fe80::70b6:5ef2:3f71:77c7]) by TYAPR01MB3661.jpnprd01.prod.outlook.com ([fe80::70b6:5ef2:3f71:77c7%4]) with mapi id 15.20.1382.023; Wed, 5 Dec 2018 01:31:22 +0000 From: Kuninori Morimoto To: Mark Brown Thread-Topic: [PATCH 2/6] ASoC: audio-graph-card: merge audio-graph-scu-card Thread-Index: AQHUjDo6KJLNMUnpGUecMPAE8zTLEg== Date: Wed, 5 Dec 2018 01:31:22 +0000 Message-ID: <87y394dazc.wl-kuninori.morimoto.gx@renesas.com> References: <871s6wepmp.wl-kuninori.morimoto.gx@renesas.com> In-Reply-To: <871s6wepmp.wl-kuninori.morimoto.gx@renesas.com> Accept-Language: ja-JP, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: TYAPR01CA0155.jpnprd01.prod.outlook.com (2603:1096:404:7e::23) To TYAPR01MB3661.jpnprd01.prod.outlook.com (2603:1096:404:c1::18) authentication-results: spf=none (sender IP is ) smtp.mailfrom=kuninori.morimoto.gx@renesas.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [211.11.155.130] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; TYAPR01MB1918; 20:u7SAkaptyD1GgSwxLQJzg2bxAEvGqKYjoaGHVAO6NKllSlzLo7AGt3WngEB8XD2TMi4j9B2F14NA8wdPlMcmMwxfeRBQ/l0vik76tqnse7pqnJu3NaUGj3n40OXWZZOyS98kfrgKs2BxWp35gu5HciUufv6YLc71tHGVDuuaOeM= x-ms-office365-filtering-correlation-id: 135f5c14-4295-4935-4c66-08d65a515d0e x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390098)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:TYAPR01MB1918; x-ms-traffictypediagnostic: TYAPR01MB1918: x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(3002001)(3231455)(999002)(944501520)(52105112)(93006095)(93001095)(6055026)(148016)(149066)(150057)(6041310)(20161123558120)(20161123564045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(201708071742011)(7699051)(76991095); SRVR:TYAPR01MB1918; BCL:0; PCL:0; RULEID:; SRVR:TYAPR01MB1918; x-forefront-prvs: 08770259B4 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(39860400002)(346002)(136003)(376002)(366004)(396003)(199004)(189003)(97736004)(305945005)(6916009)(7736002)(53936002)(6116002)(3846002)(6436002)(26005)(8936002)(6486002)(316002)(76176011)(4744004)(6512007)(71190400001)(53946003)(71200400001)(476003)(68736007)(14454004)(446003)(2616005)(2906002)(25786009)(81166006)(5660300001)(105586002)(11346002)(478600001)(81156014)(66066001)(99286004)(8676002)(186003)(256004)(14444005)(386003)(52116002)(575784001)(86362001)(6506007)(106356001)(486006)(4326008)(36756003)(102836004); DIR:OUT; SFP:1102; SCL:1; SRVR:TYAPR01MB1918; H:TYAPR01MB3661.jpnprd01.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: renesas.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: BkaMt4w6KfU4GCDdIQ6+3C5wNXgREdGrDQPgD602E9a1VWhZn4bE1YwK3m8zoGLKymfkixWNhAGpnsbXv0qf36rr+vCURXXk7aipgvP2MespLV3Us3trK9ZshbSGlKkaD3fzwiA0brovDBCHw6nwWHlk2QapLvZNU6l3kCb4J+2wMTSJHXImn4mXRKeU8xQ5tDKVSGut56+W2MMkXHrhf5eapMeZX0t5yc8foTF3U7lNHjII2DiGCwrhgx/sKK+8occjXMIcpKHYYb3Suv8h5OlAjTx7iLguT/xaAgAVH/sig8by0KFgR6dRX5jLtPzLYlAnGRddEaE2B3XGVbrn2V08tboqA7lbrlVTOu//YhE= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <2707001E9D91714B8F4287BEBB0C5B80@jpnprd01.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-Network-Message-Id: 135f5c14-4295-4935-4c66-08d65a515d0e X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Dec 2018 01:31:22.2895 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 53d82571-da19-47e4-9cb4-625a166a4a2a X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYAPR01MB1918 Cc: Linux-ALSA Subject: [alsa-devel] [PATCH 2/6] ASoC: audio-graph-card: merge audio-graph-scu-card X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 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-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Kuninori Morimoto audio-graph-card and audio-graph-scu-card are very similar driver, but the former is supporting normal sound card, the latter is supporting DPCM sound card. We couldn't use normal sound and DPCM sound in same sound card by audio-graph-card. This patch merges both sound card into it. Now we can use both feature on same driver. audio-grap-card is now supporting .compatible = "audio-graph-scu-card". Signed-off-by: Kuninori Morimoto --- sound/soc/generic/Kconfig | 1 + sound/soc/generic/audio-graph-card.c | 358 ++++++++++++++++++++++++++++++----- 2 files changed, 313 insertions(+), 46 deletions(-) diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index fa5aff9..53957824 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -22,6 +22,7 @@ config SND_AUDIO_GRAPH_CARD help This option enables generic simple sound card support with OF-graph DT bindings. + It also support DPCM of multi CPU single Codec ststem. config SND_AUDIO_GRAPH_SCU_CARD tristate "ASoC Audio Graph SCU sound card support" diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 1da9532..5b8e7a1 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -27,6 +27,8 @@ struct graph_card_data { struct asoc_simple_dai *codec_dai; struct snd_soc_dai_link_component codecs; /* single codec */ struct snd_soc_dai_link_component platform; + struct asoc_simple_card_data adata; + struct snd_soc_codec_conf *codec_conf; unsigned int mclk_fs; } *dai_props; unsigned int mclk_fs; @@ -34,6 +36,8 @@ struct graph_card_data { struct asoc_simple_jack mic_jack; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; + struct asoc_simple_card_data adata; + struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; }; @@ -42,6 +46,8 @@ struct graph_card_data { #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)) +#define PREFIX "audio-graph-card," + static int asoc_graph_card_outdrv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -156,7 +162,140 @@ static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, +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 graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num); + + asoc_simple_card_convert_fixup(&dai_props->adata, params); + + /* overwrite by top level adata if exist */ + asoc_simple_card_convert_fixup(&priv->adata, params); + + return 0; +} + +static int asoc_graph_card_dai_link_of_dpcm(struct device_node *cpu_ep, + struct device_node *codec_ep, + struct graph_card_data *priv, + int *dai_idx, int link_idx, + int *conf_idx, int is_cpu) +{ + struct device *dev = graph_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, link_idx); + struct graph_dai_props *dai_props = graph_priv_to_props(priv, link_idx); + struct snd_soc_card *card = graph_priv_to_card(priv); + struct device_node *ep = is_cpu ? cpu_ep : codec_ep; + struct device_node *node = of_graph_get_port_parent(ep); + struct asoc_simple_dai *dai; + int ret; + + dev_dbg(dev, "link_of DPCM (for %s)\n", is_cpu ? "CPU" : "Codec"); + + if (is_cpu) { + struct snd_soc_dai_link_component *codecs; + + /* BE is dummy */ + codecs = dai_link->codecs; + codecs->of_node = NULL; + codecs->dai_name = "snd-soc-dummy-dai"; + codecs->name = "snd-soc-dummy"; + + /* FE settings */ + dai_link->dynamic = 1; + dai_link->dpcm_merged_format = 1; + + dai = + dai_props->cpu_dai = &priv->dais[(*dai_idx)++]; + + 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); + 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, + of_graph_get_endpoint_count(dai_link->cpu_of_node) == 1); + } else { + struct snd_soc_codec_conf *cconf; + + /* 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; + + dai = + dai_props->codec_dai = &priv->dais[(*dai_idx)++]; + + cconf = + dai_props->codec_conf = &priv->codec_conf[(*conf_idx)++]; + + 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); + if (ret < 0) + return ret; + + ret = asoc_simple_card_set_dailink_name(dev, dai_link, + "be.%s", + dai_link->codecs->dai_name); + if (ret < 0) + return ret; + + /* check "prefix" from top node */ + snd_soc_of_parse_audio_prefix(card, cconf, + dai_link->codecs->of_node, + "prefix"); + /* check "prefix" from each node if top doesn't have */ + if (!cconf->of_node) + snd_soc_of_parse_node_prefix(node, cconf, + dai_link->codecs->of_node, + PREFIX "prefix"); + } + + asoc_simple_card_parse_convert(dev, node, PREFIX, &dai_props->adata); + + ret = asoc_simple_card_of_parse_tdm(ep, dai); + if (ret) + return ret; + + ret = asoc_simple_card_canonicalize_dailink(dai_link); + if (ret < 0) + return ret; + + of_property_read_u32(ep, "mclk-fs", &dai_props->mclk_fs); + + ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep, + NULL, &dai_link->dai_fmt); + if (ret < 0) + return ret; + + 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; + + return 0; +} + +static int asoc_graph_card_dai_link_of(struct device_node *cpu_ep, + struct device_node *codec_ep, struct graph_card_data *priv, int *dai_idx, int link_idx) { @@ -165,10 +304,10 @@ static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, struct graph_dai_props *dai_props = graph_priv_to_props(priv, link_idx); struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; - struct device_node *cpu_ep = of_get_next_child(cpu_port, NULL); - struct device_node *codec_ep = of_graph_get_remote_endpoint(cpu_ep); int ret; + dev_dbg(dev, "link_of\n"); + cpu_dai = dai_props->cpu_dai = &priv->dais[(*dai_idx)++]; codec_dai = @@ -177,45 +316,45 @@ static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep, NULL, &dai_link->dai_fmt); if (ret < 0) - goto dai_link_of_err; + return ret; of_property_read_u32(cpu_ep, "mclk-fs", &dai_props->mclk_fs); of_property_read_u32(codec_ep, "mclk-fs", &dai_props->mclk_fs); ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_parse_graph_codec(codec_ep, dai_link); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_of_parse_tdm(cpu_ep, cpu_dai); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_of_parse_tdm(codec_ep, codec_dai); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_parse_clk_cpu(dev, cpu_ep, dai_link, cpu_dai); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_parse_clk_codec(dev, codec_ep, dai_link, codec_dai); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_canonicalize_dailink(dai_link); if (ret < 0) - goto dai_link_of_err; + return ret; ret = asoc_simple_card_set_dailink_name(dev, dai_link, "%s-%s", dai_link->cpu_dai_name, dai_link->codecs->dai_name); if (ret < 0) - goto dai_link_of_err; + return ret; dai_link->ops = &asoc_graph_card_ops; dai_link->init = asoc_graph_card_dai_init; @@ -223,11 +362,7 @@ static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, asoc_simple_card_canonicalize_cpu(dai_link, of_graph_get_endpoint_count(dai_link->cpu_of_node) == 1); -dai_link_of_err: - of_node_put(cpu_ep); - of_node_put(codec_ep); - - return ret; + return 0; } static int asoc_graph_card_parse_of(struct graph_card_data *priv) @@ -236,8 +371,14 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) 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 = NULL; + struct device_node *codec_ep = NULL; + struct device_node *codec_port = NULL; + struct device_node *codec_port_old = NULL; int rc, ret; - int link_idx, dai_idx; + int link_idx, dai_idx, conf_idx; + int cpu; ret = asoc_simple_card_of_parse_widgets(card, NULL); if (ret < 0) @@ -247,35 +388,153 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) if (ret < 0) return ret; + asoc_simple_card_parse_convert(dev, node, NULL, &priv->adata); + /* Factor to mclk, used in hw_params() */ of_property_read_u32(node, "mclk-fs", &priv->mclk_fs); - link_idx = 0; - dai_idx = 0; - of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { - ret = asoc_graph_card_dai_link_of(it.node, priv, - &dai_idx, link_idx++); - if (ret < 0) { - of_node_put(it.node); - - return ret; + link_idx = 0; + dai_idx = 0; + conf_idx = 0; + codec_port_old = NULL; + for (cpu = 1; cpu >= 0; cpu--) { + /* + * Detect all CPU first, and Detect all Codec 2nd. + * + * In Normal sound case, all DAIs are detected + * as "CPU-Codec". + * + * In DPCM sound case, + * all CPUs are detected as "CPU-dummy", and + * all Codecs are detected as "dummy-Codec". + * To avoid random sub-device numbering, + * detect "dummy-Codec" in last; + */ + 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); + codec_port = of_get_parent(codec_ep); + + of_node_put(cpu_ep); + of_node_put(cpu_port); + of_node_put(codec_ep); + of_node_put(codec_port); + it.node = NULL; + + dev_dbg(dev, "%pOFf <-> %pOFf\n", cpu_port, codec_port); + + if (of_get_child_count(codec_port) > 1) { + /* + * for DPCM sound + */ + if (!cpu) { + if (codec_port_old == codec_port) + continue; + codec_port_old = codec_port; + } + ret = asoc_graph_card_dai_link_of_dpcm( + cpu_ep, codec_ep, priv, + &dai_idx, link_idx++, + &conf_idx, cpu); + } else if (cpu) { + /* + * for Normal sound + */ + ret = asoc_graph_card_dai_link_of( + cpu_ep, codec_ep, priv, + &dai_idx, link_idx++); + } + if (ret < 0) + return ret; } } return asoc_simple_card_parse_card_name(card, NULL); } -static int asoc_graph_get_dais_count(struct device *dev) +static void asoc_graph_get_dais_count(struct device *dev, + int *link_num, + int *dais_num, + int *ccnf_num) { struct of_phandle_iterator it; struct device_node *node = dev->of_node; - int count = 0; + struct device_node *cpu_port; + struct device_node *cpu_ep; + struct device_node *codec_ep; + struct device_node *codec_port; + struct device_node *codec_port_old; + struct device_node *codec_port_old2; int rc; - of_for_each_phandle(&it, rc, node, "dais", NULL, 0) - count++; + /* + * link_num : number of links. + * CPU-Codec / CPU-dummy / dummy-Codec + * dais_num : number of DAIs + * ccnf_num : number of codec_conf + * same number for "dummy-Codec" + * + * ex1) + * CPU0 --- Codec0 link : 5 + * CPU1 --- Codec1 dais : 7 + * CPU2 -/ ccnf : 1 + * CPU3 --- Codec2 + * + * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec + * => 7 DAIs = 4xCPU + 3xCodec + * => 1 ccnf = 1xdummy-Codec + * + * ex2) + * CPU0 --- Codec0 link : 5 + * CPU1 --- Codec1 dais : 6 + * CPU2 -/ ccnf : 1 + * CPU3 -/ + * + * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec + * => 6 DAIs = 4xCPU + 2xCodec + * => 1 ccnf = 1xdummy-Codec + * + * ex3) + * CPU0 --- Codec0 link : 6 + * CPU1 -/ dais : 6 + * CPU2 --- Codec1 ccnf : 2 + * CPU3 -/ + * + * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec + * => 6 DAIs = 4xCPU + 2xCodec + * => 2 ccnf = 2xdummy-Codec + */ + codec_port_old = NULL; + codec_port_old2 = NULL; + 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); + codec_port = of_get_parent(codec_ep); + + of_node_put(cpu_ep); + of_node_put(cpu_port); + of_node_put(codec_ep); + of_node_put(codec_port); + it.node = NULL; + + (*link_num)++; + (*dais_num)++; + + if (codec_port_old == codec_port) { + if (codec_port_old2 != codec_port_old) { + (*link_num)++; + (*ccnf_num)++; + } + + codec_port_old2 = codec_port_old; + continue; + } - return count; + (*dais_num)++; + codec_port_old = codec_port; + } } static int asoc_graph_soc_card_probe(struct snd_soc_card *card) @@ -302,20 +561,23 @@ static int asoc_graph_card_probe(struct platform_device *pdev) struct asoc_simple_dai *dais; struct device *dev = &pdev->dev; struct snd_soc_card *card; - int num, ret, i; + struct snd_soc_codec_conf *cconf; + int lnum = 0, dnum = 0, cnum = 0; + int ret, i; /* 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) + asoc_graph_get_dais_count(dev, &lnum, &dnum, &cnum); + if (!lnum || !dnum) return -EINVAL; - dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL); - dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL); - dais = devm_kcalloc(dev, num * 2, sizeof(*dais), GFP_KERNEL); + dai_props = devm_kcalloc(dev, lnum, sizeof(*dai_props), GFP_KERNEL); + dai_link = devm_kcalloc(dev, lnum, sizeof(*dai_link), GFP_KERNEL); + dais = devm_kcalloc(dev, dnum, sizeof(*dais), GFP_KERNEL); + cconf = devm_kcalloc(dev, cnum, sizeof(*cconf), GFP_KERNEL); if (!dai_props || !dai_link || !dais) return -ENOMEM; @@ -325,7 +587,7 @@ static int asoc_graph_card_probe(struct platform_device *pdev) * see * soc-core.c :: snd_soc_init_multicodec() */ - for (i = 0; i < num; i++) { + for (i = 0; i < lnum; i++) { dai_link[i].codecs = &dai_props[i].codecs; dai_link[i].num_codecs = 1; dai_link[i].platform = &dai_props[i].platform; @@ -341,16 +603,19 @@ static int asoc_graph_card_probe(struct platform_device *pdev) priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; + priv->codec_conf = cconf; /* Init snd_soc_card */ card = graph_priv_to_card(priv); - card->owner = THIS_MODULE; - card->dev = dev; - card->dai_link = dai_link; - card->num_links = num; - card->dapm_widgets = asoc_graph_card_dapm_widgets; - card->num_dapm_widgets = ARRAY_SIZE(asoc_graph_card_dapm_widgets); - card->probe = asoc_graph_soc_card_probe; + card->owner = THIS_MODULE; + card->dev = dev; + card->dai_link = dai_link; + card->num_links = lnum; + card->dapm_widgets = asoc_graph_card_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(asoc_graph_card_dapm_widgets); + card->probe = asoc_graph_soc_card_probe; + card->codec_conf = cconf; + card->num_configs = cnum; ret = asoc_graph_card_parse_of(priv); if (ret < 0) { @@ -381,6 +646,7 @@ static int asoc_graph_card_remove(struct platform_device *pdev) static const struct of_device_id asoc_graph_of_match[] = { { .compatible = "audio-graph-card", }, + { .compatible = "audio-graph-scu-card", }, {}, }; MODULE_DEVICE_TABLE(of, asoc_graph_of_match);