From patchwork Thu Jun 27 08:31:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elinor Montmasson X-Patchwork-Id: 13713967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4F21FC3064D for ; Thu, 27 Jun 2024 08:32:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=dhNRfzKELW27kNOTUmIVEYQ4XrB9IeZ7AciW7pULV5c=; b=DAH5LKd/iY4ANxJjy7BZH3qDFO 2wHUbabDjuzZffX+nBo3PVsspnd+nU0pzjFWwpfOyK38t2Z9CtslWGGiROuPSqj8dJMnpK1bcm3Px U2n4k3q10DAjKBPyAM8FfSBqOIfpZEh7GNVlsIQEDbGDRBUB+80nnqYtoSSEcdBIozLNDgFqHGSO9 taVIgn6et4SejMak+yYjCcbIxJGolSylH2dj2OVxh1iv1OObw5OMCc2Yo3p1I52WTt+Q4jZ62F07u f6uJ5PtonhJp0oJQtSz2cC9+kG201tdU5DjHs8qjGclLP8O94DEvonM3r3VZ7Zo43BwdhrtRFrQyK 23Sq0iQg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMkYG-00000009lS1-3cck; Thu, 27 Jun 2024 08:32:20 +0000 Received: from mail.savoirfairelinux.com ([208.88.110.44]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMkXu-00000009lGX-1Io4 for linux-arm-kernel@lists.infradead.org; Thu, 27 Jun 2024 08:32:00 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 96D289C595F; Thu, 27 Jun 2024 04:31:57 -0400 (EDT) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id pqa7RXwowKcA; Thu, 27 Jun 2024 04:31:54 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 0BCBA9C5A75; Thu, 27 Jun 2024 04:31:54 -0400 (EDT) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 0BCBA9C5A75 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1719477114; bh=dhNRfzKELW27kNOTUmIVEYQ4XrB9IeZ7AciW7pULV5c=; h=From:To:Date:Message-Id:MIME-Version; b=aTnKKtdgc6JnHgWB/cvCvmhpeVrGBrT3wjxpXcrjRx60SOva1Ubk2N55tBMC0cSjW LtAjRvmvCcmfVlUK4/lVNsrdRacGT7KITlRqQoyzd/583zQlt/ud/46kj4owL6lnP/ kRwoVwHjqGzfokSkDXAoHbZXUx+BJ1NoOse07YhPYKJJVDtTq40CKBjxkLqWg9EH+d yfSV7rXfQ0DaaxIaOWSWAHuHOS/GSX7BW2VbrnPT90tRYAu1E/pXn5RY+BMqDO3VdO 8Srx2KH0oCN6+3JN0PaXq/84Gq2k6U8SN1pYNg+R6lRK8+EpcIV+DWfWPj4muL8Vnx lygiRmPRCmTvA== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id YgG7cBm2VNzx; Thu, 27 Jun 2024 04:31:53 -0400 (EDT) Received: from gerard.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 0AE519C585F; Thu, 27 Jun 2024 04:31:50 -0400 (EDT) From: Elinor Montmasson To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Shawn Guo , Sascha Hauer , Fabio Estevam , Russell King , Catalin Marinas , Will Deacon , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Nicolin Chen Cc: Pengutronix Kernel Team , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, Elinor Montmasson , Philip-Dylan Subject: [PATCH v6 3/7] ASoC: fsl-asoc-card: add compatibility to use 2 codecs in dai-links Date: Thu, 27 Jun 2024 10:31:00 +0200 Message-Id: <20240627083104.123357-4-elinor.montmasson@savoirfairelinux.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240627083104.123357-1-elinor.montmasson@savoirfairelinux.com> References: <20240627083104.123357-1-elinor.montmasson@savoirfairelinux.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240627_013158_910230_B145CC77 X-CRM114-Status: GOOD ( 21.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Adapt the driver to work with configurations using two codecs or more. Modify fsl_asoc_card_probe() to handle use cases where 2 codecs are given in the device tree. This will be needed to add support for the SPDIF. Use cases using one codec will ignore any given codecs other than the first. Co-developed-by: Philip-Dylan Gleonec Signed-off-by: Philip-Dylan Gleonec Signed-off-by: Elinor Montmasson --- sound/soc/fsl/fsl-asoc-card.c | 279 ++++++++++++++++++++-------------- 1 file changed, 161 insertions(+), 118 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 805e2030bde4..87329731e02d 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -99,7 +99,7 @@ struct fsl_asoc_card_priv { struct simple_util_jack hp_jack; struct simple_util_jack mic_jack; struct platform_device *pdev; - struct codec_priv codec_priv; + struct codec_priv codec_priv[2]; struct cpu_priv cpu_priv; struct snd_soc_card card; u8 streams; @@ -172,10 +172,12 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct codec_priv *codec_priv = &priv->codec_priv; + struct codec_priv *codec_priv; + struct snd_soc_dai *codec_dai; struct cpu_priv *cpu_priv = &priv->cpu_priv; struct device *dev = rtd->card->dev; unsigned int pll_out; + int codec_idx; int ret; priv->sample_rate = params_rate(params); @@ -208,28 +210,32 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, } /* Specific configuration for PLL */ - if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { - if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) - pll_out = priv->sample_rate * 384; - else - pll_out = priv->sample_rate * 256; + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { + codec_priv = &priv->codec_priv[codec_idx]; - ret = snd_soc_dai_set_pll(snd_soc_rtd_to_codec(rtd, 0), - codec_priv->pll_id, - codec_priv->mclk_id, - codec_priv->mclk_freq, pll_out); - if (ret) { - dev_err(dev, "failed to start FLL: %d\n", ret); - goto fail; - } + if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { + if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) + pll_out = priv->sample_rate * 384; + else + pll_out = priv->sample_rate * 256; - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), - codec_priv->fll_id, - pll_out, SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_pll(codec_dai, + codec_priv->pll_id, + codec_priv->mclk_id, + codec_priv->mclk_freq, pll_out); + if (ret) { + dev_err(dev, "failed to start FLL: %d\n", ret); + goto fail; + } - if (ret && ret != -ENOTSUPP) { - dev_err(dev, "failed to set SYSCLK: %d\n", ret); - goto fail; + ret = snd_soc_dai_set_sysclk(codec_dai, + codec_priv->fll_id, + pll_out, SND_SOC_CLOCK_IN); + + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set SYSCLK: %d\n", ret); + goto fail; + } } } @@ -244,28 +250,34 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct codec_priv *codec_priv = &priv->codec_priv; + struct codec_priv *codec_priv; + struct snd_soc_dai *codec_dai; struct device *dev = rtd->card->dev; + int codec_idx; int ret; priv->streams &= ~BIT(substream->stream); - if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { - /* Force freq to be free_freq to avoid error message in codec */ - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), - codec_priv->mclk_id, - codec_priv->free_freq, - SND_SOC_CLOCK_IN); - if (ret) { - dev_err(dev, "failed to switch away from FLL: %d\n", ret); - return ret; - } + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { + codec_priv = &priv->codec_priv[codec_idx]; - ret = snd_soc_dai_set_pll(snd_soc_rtd_to_codec(rtd, 0), - codec_priv->pll_id, 0, 0, 0); - if (ret && ret != -ENOTSUPP) { - dev_err(dev, "failed to stop FLL: %d\n", ret); - return ret; + if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { + /* Force freq to be free_freq to avoid error message in codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, + codec_priv->mclk_id, + codec_priv->free_freq, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(dev, "failed to switch away from FLL: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, + codec_priv->pll_id, 0, 0, 0); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to stop FLL: %d\n", ret); + return ret; + } } } @@ -504,9 +516,10 @@ static int fsl_asoc_card_late_probe(struct snd_soc_card *card) struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); struct snd_soc_pcm_runtime *rtd = list_first_entry( &card->rtd_list, struct snd_soc_pcm_runtime, list); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct codec_priv *codec_priv = &priv->codec_priv; + struct snd_soc_dai *codec_dai; + struct codec_priv *codec_priv; struct device *dev = card->dev; + int codec_idx; int ret; if (fsl_asoc_card_is_ac97(priv)) { @@ -526,32 +539,37 @@ static int fsl_asoc_card_late_probe(struct snd_soc_card *card) return 0; } - ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, - codec_priv->mclk_freq, SND_SOC_CLOCK_IN); - if (ret && ret != -ENOTSUPP) { - dev_err(dev, "failed to set sysclk in %s\n", __func__); - return ret; - } + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { + codec_priv = &priv->codec_priv[codec_idx]; - if (!IS_ERR_OR_NULL(codec_priv->mclk)) - clk_prepare_enable(codec_priv->mclk); + ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, + codec_priv->mclk_freq, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set sysclk in %s\n", __func__); + return ret; + } + + if (!IS_ERR_OR_NULL(codec_priv->mclk)) + clk_prepare_enable(codec_priv->mclk); + } return 0; } static int fsl_asoc_card_probe(struct platform_device *pdev) { - struct device_node *cpu_np, *codec_np, *asrc_np; + struct device_node *cpu_np, *asrc_np; struct snd_soc_dai_link_component *codec_comp; + struct device_node *codec_np[2]; struct device_node *np = pdev->dev.of_node; struct platform_device *asrc_pdev = NULL; struct device_node *bitclkprovider = NULL; struct device_node *frameprovider = NULL; struct platform_device *cpu_pdev; struct fsl_asoc_card_priv *priv; - struct device *codec_dev = NULL; - const char *codec_dai_name; - const char *codec_dev_name; + struct device *codec_dev[2] = { NULL, NULL }; + const char *codec_dai_name[2]; + const char *codec_dev_name[2]; u32 asrc_fmt = 0; int codec_idx; u32 width; @@ -580,21 +598,25 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto fail; } - codec_np = of_parse_phandle(np, "audio-codec", 0); - if (codec_np) { - struct platform_device *codec_pdev; - struct i2c_client *codec_i2c; + codec_np[0] = of_parse_phandle(np, "audio-codec", 0); + codec_np[1] = of_parse_phandle(np, "audio-codec", 1); - codec_i2c = of_find_i2c_device_by_node(codec_np); - if (codec_i2c) { - codec_dev = &codec_i2c->dev; - codec_dev_name = codec_i2c->name; - } - if (!codec_dev) { - codec_pdev = of_find_device_by_node(codec_np); - if (codec_pdev) { - codec_dev = &codec_pdev->dev; - codec_dev_name = codec_pdev->name; + for (codec_idx = 0; codec_idx < 2; codec_idx++) { + if (codec_np[codec_idx]) { + struct platform_device *codec_pdev; + struct i2c_client *codec_i2c; + + codec_i2c = of_find_i2c_device_by_node(codec_np[codec_idx]); + if (codec_i2c) { + codec_dev[codec_idx] = &codec_i2c->dev; + codec_dev_name[codec_idx] = codec_i2c->name; + } + if (!codec_dev[codec_idx]) { + codec_pdev = of_find_device_by_node(codec_np[codec_idx]); + if (codec_pdev) { + codec_dev[codec_idx] = &codec_pdev->dev; + codec_dev_name[codec_idx] = codec_pdev->name; + } } } } @@ -604,12 +626,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) asrc_pdev = of_find_device_by_node(asrc_np); /* Get the MCLK rate only, and leave it controlled by CODEC drivers */ - if (codec_dev) { - struct clk *codec_clk = clk_get(codec_dev, NULL); + for (codec_idx = 0; codec_idx < 2; codec_idx++) { + if (codec_dev[codec_idx]) { + struct clk *codec_clk = clk_get(codec_dev[codec_idx], NULL); - if (!IS_ERR(codec_clk)) { - priv->codec_priv.mclk_freq = clk_get_rate(codec_clk); - clk_put(codec_clk); + if (!IS_ERR(codec_clk)) { + priv->codec_priv[codec_idx].mclk_freq = clk_get_rate(codec_clk); + clk_put(codec_clk); + } } } @@ -629,31 +653,33 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); priv->card.driver_name = DRIVER_NAME; - priv->codec_priv.fll_id = -1; - priv->codec_priv.pll_id = -1; + for (codec_idx = 0; codec_idx < 2; codec_idx++) { + priv->codec_priv[codec_idx].fll_id = -1; + priv->codec_priv[codec_idx].pll_id = -1; + } /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { - codec_dai_name = "cs42888"; - priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq; - priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq; + codec_dai_name[0] = "cs42888"; + priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv[0].mclk_freq; + priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv[0].mclk_freq; priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT; priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT; priv->cpu_priv.slot_width = 32; priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) { - codec_dai_name = "cs4271-hifi"; - priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK; + codec_dai_name[0] = "cs4271-hifi"; + priv->codec_priv[0].mclk_id = CS427x_SYSCLK_MCLK; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { - codec_dai_name = "sgtl5000"; - priv->codec_priv.mclk_id = SGTL5000_SYSCLK; + codec_dai_name[0] = "sgtl5000"; + priv->codec_priv[0].mclk_id = SGTL5000_SYSCLK; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) { - codec_dai_name = "tlv320aic32x4-hifi"; + codec_dai_name[0] = "tlv320aic32x4-hifi"; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) { - codec_dai_name = "tlv320dac31xx-hifi"; + codec_dai_name[0] = "tlv320dac31xx-hifi"; priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; priv->dai_link[1].dpcm_capture = 0; priv->dai_link[2].dpcm_capture = 0; @@ -662,23 +688,23 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map_tx; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { - codec_dai_name = "wm8962"; - priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; - priv->codec_priv.fll_id = WM8962_SYSCLK_FLL; - priv->codec_priv.pll_id = WM8962_FLL; + codec_dai_name[0] = "wm8962"; + priv->codec_priv[0].mclk_id = WM8962_SYSCLK_MCLK; + priv->codec_priv[0].fll_id = WM8962_SYSCLK_FLL; + priv->codec_priv[0].pll_id = WM8962_FLL; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) { - codec_dai_name = "wm8960-hifi"; - priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO; - priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO; + codec_dai_name[0] = "wm8960-hifi"; + priv->codec_priv[0].fll_id = WM8960_SYSCLK_AUTO; + priv->codec_priv[0].pll_id = WM8960_SYSCLK_AUTO; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) { - codec_dai_name = "ac97-hifi"; + codec_dai_name[0] = "ac97-hifi"; priv->dai_fmt = SND_SOC_DAIFMT_AC97; priv->card.dapm_routes = audio_map_ac97; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97); } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) { - codec_dai_name = "fsl-mqs-dai"; + codec_dai_name[0] = "fsl-mqs-dai"; priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_NB_NF; @@ -687,7 +713,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map_tx; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) { - codec_dai_name = "wm8524-hifi"; + codec_dai_name[0] = "wm8524-hifi"; priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; priv->dai_link[1].dpcm_capture = 0; priv->dai_link[2].dpcm_capture = 0; @@ -695,32 +721,32 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map_tx; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); } else if (of_device_is_compatible(np, "fsl,imx-audio-si476x")) { - codec_dai_name = "si476x-codec"; + codec_dai_name[0] = "si476x-codec"; priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; priv->card.dapm_routes = audio_map_rx; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx); } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) { - codec_dai_name = "wm8994-aif1"; + codec_dai_name[0] = "wm8994-aif1"; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; - priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1; - priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1; - priv->codec_priv.pll_id = WM8994_FLL1; - priv->codec_priv.free_freq = priv->codec_priv.mclk_freq; + priv->codec_priv[0].mclk_id = WM8994_FLL_SRC_MCLK1; + priv->codec_priv[0].fll_id = WM8994_SYSCLK_FLL1; + priv->codec_priv[0].pll_id = WM8994_FLL1; + priv->codec_priv[0].free_freq = priv->codec_priv[0].mclk_freq; priv->card.dapm_routes = NULL; priv->card.num_dapm_routes = 0; } else if (of_device_is_compatible(np, "fsl,imx-audio-nau8822")) { - codec_dai_name = "nau8822-hifi"; - priv->codec_priv.mclk_id = NAU8822_CLK_MCLK; - priv->codec_priv.fll_id = NAU8822_CLK_PLL; - priv->codec_priv.pll_id = NAU8822_CLK_PLL; + codec_dai_name[0] = "nau8822-hifi"; + priv->codec_priv[0].mclk_id = NAU8822_CLK_MCLK; + priv->codec_priv[0].fll_id = NAU8822_CLK_PLL; + priv->codec_priv[0].pll_id = NAU8822_CLK_PLL; priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; - if (codec_dev) - priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL); + if (codec_dev[0]) + priv->codec_priv[0].mclk = devm_clk_get(codec_dev[0], NULL); } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8904")) { - codec_dai_name = "wm8904-hifi"; - priv->codec_priv.mclk_id = WM8904_FLL_MCLK; - priv->codec_priv.fll_id = WM8904_CLK_FLL; - priv->codec_priv.pll_id = WM8904_FLL_MCLK; + codec_dai_name[0] = "wm8904-hifi"; + priv->codec_priv[0].mclk_id = WM8904_FLL_MCLK; + priv->codec_priv[0].fll_id = WM8904_CLK_FLL; + priv->codec_priv[0].pll_id = WM8904_FLL_MCLK; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); @@ -732,18 +758,30 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) * Allow setting mclk-id from the device-tree node. Otherwise, the * default value for each card configuration is used. */ - of_property_read_u32(np, "mclk-id", &priv->codec_priv.mclk_id); + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { + of_property_read_u32_index(np, "mclk-id", codec_idx, + &priv->codec_priv[codec_idx].mclk_id); + } /* Format info from DT is optional. */ snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL, &bitclkprovider, &frameprovider); if (bitclkprovider || frameprovider) { unsigned int daifmt = snd_soc_daifmt_parse_format(np, NULL); + bool codec_bitclkprovider = false; + bool codec_frameprovider = false; + + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { + if (bitclkprovider && codec_np[codec_idx] == bitclkprovider) + codec_bitclkprovider = true; + if (frameprovider && codec_np[codec_idx] == frameprovider) + codec_frameprovider = true; + } - if (codec_np == bitclkprovider) - daifmt |= (codec_np == frameprovider) ? + if (codec_bitclkprovider) + daifmt |= (codec_frameprovider) ? SND_SOC_DAIFMT_CBP_CFP : SND_SOC_DAIFMT_CBP_CFC; else - daifmt |= (codec_np == frameprovider) ? + daifmt |= (codec_frameprovider) ? SND_SOC_DAIFMT_CBC_CFP : SND_SOC_DAIFMT_CBC_CFC; /* Override dai_fmt with value from DT */ @@ -759,7 +797,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) of_node_put(bitclkprovider); of_node_put(frameprovider); - if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { + if (!fsl_asoc_card_is_ac97(priv) && !codec_dev[0]) { dev_dbg(&pdev->dev, "failed to find codec device\n"); ret = -EPROBE_DEFER; goto asrc_fail; @@ -798,7 +836,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(&priv->card, "model"); if (ret) { snprintf(priv->name, sizeof(priv->name), "%s-audio", - fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name); + fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name[0]); priv->card.name = priv->name; } priv->card.dai_link = priv->dai_link; @@ -820,11 +858,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Normal DAI Link */ priv->dai_link[0].cpus->of_node = cpu_np; - priv->dai_link[0].codecs[0].dai_name = codec_dai_name; + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { + codec_comp->dai_name = codec_dai_name[codec_idx]; + } - if (!fsl_asoc_card_is_ac97(priv)) - priv->dai_link[0].codecs[0].of_node = codec_np; - else { + if (!fsl_asoc_card_is_ac97(priv)) { + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { + codec_comp->of_node = codec_np[codec_idx]; + } + } else { u32 idx; ret = of_property_read_u32(cpu_np, "cell-index", &idx); @@ -926,7 +968,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) asrc_fail: of_node_put(asrc_np); - of_node_put(codec_np); + of_node_put(codec_np[0]); + of_node_put(codec_np[1]); put_device(&cpu_pdev->dev); fail: of_node_put(cpu_np);