From patchwork Thu Jun 20 08:42:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704979 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 639BA3A1AC; Thu, 20 Jun 2024 08:43:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; cv=none; b=jb9I+wFUlhNbImVhWMCEuVNESTPcOMILaRVNu8ef3zTM77ZVSozH+PLLm5vC4QuneaymIb3PTptwQc2ScXEtGnPxv/ozmF5oNAoo/11jbQhZyJJFx+5W14zuSWDb8sQtRSOXKMi0pTjHDpUzLY6Vwy2toP83kKYEgofTXaxn5sE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; c=relaxed/simple; bh=JyxXab3gh+wCGMjIW6vDCbjLfD//HftTPx3aJXGP3m8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XDdmlY2bNqncXVhZaNHAalBtx9LKikJNo06YaIGjqur0EX8kViZHABNK7r1591wjoBJ3hV+dTZfm2nqyMTLrEZdIcBlEQEHTHQJeEp1Xz+fcF+ItYE1Jl0/Qa86/ay1xb5F0IM14au6afl7usTL2KS8Qh8WevOGTaYboCiBajag= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Y7/+Kz/c; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Y7/+Kz/c" Received: by mail.gandi.net (Postfix) with ESMTPA id 808192000D; Thu, 20 Jun 2024 08:43:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872991; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=O2OniZ6NTuy93VyAe8/Sk6MsW0dFYWJCYUEKa4O7/i0=; b=Y7/+Kz/c2jd/6tPcvE4E6ugSwG+0jYbXBS0aNFaULtDeHyZliwze4pTKKBYpKGOFnk4PGV V+eXJJgSOFwRhBinungwT/q9hAcrnHhSX3Wd3XjRnb/lEJX0MkYC2BeyAMahoDqNzoK4ZF /GjZ74Lw/mJ0XF5OrPMkaaort1alUt01luU3ORpix/o6+6fwJ1UEw8AtFm7KHawEhQUoBY 9z2gXIW11ZJIRDy+aWdga+Jazrjwm+9BFM1/CTKr8U+OQkIP/1+63VOZQ/F2VlkQ17wfog CyeVK92Ty+SSqwldY65xQ0qcGjYBHYWT+II2yqH7dmbT7iIIW3zKknFlcGMf3w== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni , stable@vger.kernel.org Subject: [PATCH 01/10] ASoC: fsl: fsl_qmc_audio: Check devm_kasprintf() returned value Date: Thu, 20 Jun 2024 10:42:48 +0200 Message-ID: <20240620084300.397853-2-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com devm_kasprintf() can return a NULL pointer on failure but this returned value is not checked. Fix this lack and check the returned value. Fixes: 075c7125b11c ("ASoC: fsl: Add support for QMC audio") Cc: stable@vger.kernel.org Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index bfaaa451735b..dd90ef16fa97 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -604,6 +604,8 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", np->parent->name, qmc_dai->id); + if (!qmc_dai->name) + return -ENOMEM; qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, "fsl,qmc-chan"); From patchwork Thu Jun 20 08:42:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704981 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B4E219DF6D; Thu, 20 Jun 2024 08:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873001; cv=none; b=rc1AhYl8I+3EY9GG54B8guV8Cc/ntzyZM1ntKyCiX+rJ+JJRqePeQBXrxh2U/C61M8C8wKOzZNRN1L26+BmXYURqiF5uyIWNnssaxYAt/ZJnSHJe1/IsGR3nbSMik7S034cbuFq+MyAKgVNcEFQbXR7j830DyDPZ7GBiwuy7ltE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873001; c=relaxed/simple; bh=GaT+5Okx/oGaUT+xmbDP0mhLQm3Dnt3jOzk1ZVn025o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o5RCIK433FFKLCi68RrfWjgUKj1dZ+WT0TWQodxuXIueG945OVvKVE2Hsa60El+vZ126hB8d71D+0T00qRel/IOOq3UGM4RsusX8NSu9EfYEjVtjHD6wvRCrkzhJUk+4A0crfo2Y6d2CP1exS8o/QNtWmYLy8MJgFZ8hcZ7EYcI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=mN7634T+; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="mN7634T+" Received: by mail.gandi.net (Postfix) with ESMTPA id 9EEC120004; Thu, 20 Jun 2024 08:43:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872992; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DgnTidH1/Oa8bludXLWM/W7+X2Tacy46pQTzIGVhdS4=; b=mN7634T+gH4+tgRV5Uc5ilL3nwvnWdrM5D0uzsx/tt4Pstm7kDUnFUSodjD1zQAAn+KbPW HeMgv5y8lUz1nMF8/8XLu0J/yEz8dh7vW3ZzPQi/49LtjZSOSkvbgeVK/5g9wdG3BymVNO BCm/tib4OmuqXAJJSiyvVkG7SYShR9N/XgLekhfYFWzTPHXR1tmMNS+pvttxWaRe8JpD6A 0vR7C/BIdeyJmlzH0KTj1blP1MpOQsGtRU2V76DCazH637i0KWSkXDNWlXzrAA3Xbm4IiG un7Ks6Md1VCa6ZqFg5lwwl3mlwIw5Rn0wXZ4JCDWYoFxwb0QwZPhEul3fEVnOg== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 02/10] ASoC: fsl: fsl_qmc_audio: Fix issues detected by checkpatch Date: Thu, 20 Jun 2024 10:42:49 +0200 Message-ID: <20240620084300.397853-3-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com ./scripts/checkpatch.pl --strict --codespell detected several issues when running on the fsl_qmc_audio.c file: - CHECK: spaces preferred around that '*' (ctx:VxV) - CHECK: Alignment should match open parenthesis - CHECK: Comparison to NULL could be written "!prtd" - CHECK: spaces preferred around that '/' (ctx:VxV) - CHECK: Lines should not end with a '(' - CHECK: Please don't use multiple blank lines Some of them are present several times. Fix all of these issues without any functional changes. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 65 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index dd90ef16fa97..917a32389f3d 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -54,7 +54,7 @@ static int qmc_audio_pcm_construct(struct snd_soc_component *component, return ret; snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, - 64*1024, 64*1024); + 64 * 1024, 64 * 1024); return 0; } @@ -89,8 +89,8 @@ static void qmc_audio_pcm_write_complete(void *context) prtd->period_ptr_submitted = prtd->dma_buffer_start; ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", ret); @@ -118,8 +118,8 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i prtd->period_ptr_submitted = prtd->dma_buffer_start; ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_read_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); @@ -144,8 +144,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Submit first chunk ... */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -159,8 +159,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, /* ... and send it */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -169,8 +169,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, } else { /* Submit first chunk ... */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_read_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(component->dev, "read_submit failed %d\n", ret); @@ -184,8 +184,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, /* ... and send it */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_read_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -220,8 +220,8 @@ static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *compone } static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, - const struct of_phandle_args *args, - const char **dai_name) + const struct of_phandle_args *args, + const char **dai_name) { struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); struct snd_soc_dai_driver *dai_driver; @@ -245,10 +245,10 @@ static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE, .period_bytes_min = 32, - .period_bytes_max = 64*1024, + .period_bytes_max = 64 * 1024, .periods_min = 2, - .periods_max = 2*1024, - .buffer_bytes_max = 64*1024, + .periods_max = 2 * 1024, + .buffer_bytes_max = 64 * 1024, }; static int qmc_audio_pcm_open(struct snd_soc_component *component, @@ -266,7 +266,7 @@ static int qmc_audio_pcm_open(struct snd_soc_component *component, return ret; prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); - if (prtd == NULL) + if (!prtd) return -ENOMEM; runtime->private_data = prtd; @@ -329,13 +329,13 @@ static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai, ch.max = nb_ts; break; case 16: - ch.max = nb_ts/2; + ch.max = nb_ts / 2; break; case 32: - ch.max = nb_ts/4; + ch.max = nb_ts / 4; break; case 64: - ch.max = nb_ts/8; + ch.max = nb_ts / 8; break; default: dev_err(qmc_dai->dev, "format physical width %u not supported\n", @@ -356,9 +356,8 @@ static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); } -static int qmc_dai_hw_rule_capture_channels_by_format( - struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +static int qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct qmc_dai *qmc_dai = rule->private; @@ -394,18 +393,16 @@ static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai, return snd_mask_refine(f_old, &f_new); } -static int qmc_dai_hw_rule_playback_format_by_channels( - struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +static int qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct qmc_dai *qmc_dai = rule->private; return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); } -static int qmc_dai_hw_rule_capture_format_by_channels( - struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct qmc_dai *qmc_dai = rule->private; @@ -413,7 +410,7 @@ static int qmc_dai_hw_rule_capture_format_by_channels( } static int qmc_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + struct snd_soc_dai *dai) { struct qmc_dai_prtd *prtd = substream->runtime->private_data; snd_pcm_hw_rule_func_t hw_rule_channels_by_format; @@ -587,7 +584,8 @@ static u64 qmc_audio_formats(u8 nb_ts) } static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, - struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) + struct qmc_dai *qmc_dai, + struct snd_soc_dai_driver *qmc_soc_dai_driver) { struct qmc_chan_info info; u32 val; @@ -704,7 +702,6 @@ static int qmc_audio_probe(struct platform_device *pdev) i++; } - platform_set_drvdata(pdev, qmc_audio); ret = devm_snd_soc_register_component(qmc_audio->dev, From patchwork Thu Jun 20 08:42:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704984 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CD3E19FA67; Thu, 20 Jun 2024 08:43:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873003; cv=none; b=ibovFJthnkZdXUgIoRNhSGZ5J/FdLI1PwC4qvUUfjo+qSab8txntrTgg1YME2jDopQdY5jX9L+KpPCde52BCCeVwuYRrE8nv7VEsXpj+cM6HDTQtabXo7VYO8HBc3PebznK/CkL6cb2VQ59yFE/JuOOiXrB12pfUU2Er3gk2IIs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873003; c=relaxed/simple; bh=qIFtrk4+jNTGagJEvJP5YHoAWF+6D2TUEBk4+yKW9OU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i32SMbwK6PbExyJtA44RicNu5YBoZk2ccxYXDaDLUau+FNEL1eqgyHnFa6110wINEiFpIjnC+LngtR6RpSeHQhbj3dFQIeQjGQirPj64Q1wKpqBNaQG+wXGI+l9tf0Lef7C5ZT5W0OCqNG16sOUqVIrjs16Gz27L8hHwxOqY5Gg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=AWbHokCp; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="AWbHokCp" Received: by mail.gandi.net (Postfix) with ESMTPA id B86202000E; Thu, 20 Jun 2024 08:43:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872993; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Qz56XJSUWFIXioYtOWzibVEtfgyCjJ8wlnP/M2Ai9vM=; b=AWbHokCpxotyrZuw1NlkQ2ZXO2viJ65ahJRtBSnWBWLVA0yV09QVhY4z1epYHtYnt+NMMK vcc9NB9k6m9ZXdTniL8PM42Klu3XTbN5b7nKj8uCG1c0phhmvoDKsLql4RwftbhAK9zBey SugYVBLETSYrliS9FpbxOkplqU4Rjxy94IYiQgYeTk0c6AL9zIkGWuK6+pTh9ALYTeqv+9 X1q/R0ydUxz6VkGtTx0erij7w1jgFtXLXvIaS/8DczmSEHQPVrX2lA05jkRaXaOcS3g/tm DoiQFKfku+oAuzBglYeE/Y7x9BfLNjO/WpnIq6eq2Cz5etK8YiyV7zJI/dDzfA== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 03/10] ASoC: fsl: fsl_qmc_audio: Split channel buffer and PCM pointer handling Date: Thu, 20 Jun 2024 10:42:50 +0200 Message-ID: <20240620084300.397853-4-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com The driver mixes some internal values for channel DMA buffer handling and PCM pointer handling. In the currently supported interleaved mode, this mix does not lead to any issues but in order to prepare the support for the non-interleaved mode, having them clearly separated will ease the support and avoid additional computation to convert values used in channel DMA buffer management in values usable for PCM pointer. Use a specific set of variable for PCM pointer handling and an other set for channel DMA buffer. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 84 +++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 917a32389f3d..e8281e548746 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -35,11 +35,16 @@ struct qmc_audio { struct qmc_dai_prtd { struct qmc_dai *qmc_dai; - dma_addr_t dma_buffer_start; - dma_addr_t period_ptr_submitted; - dma_addr_t period_ptr_ended; - dma_addr_t dma_buffer_end; - size_t period_size; + + snd_pcm_uframes_t buffer_ended; + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + + dma_addr_t ch_dma_addr_start; + dma_addr_t ch_dma_addr_current; + dma_addr_t ch_dma_addr_end; + size_t ch_dma_size; + struct snd_pcm_substream *substream; }; @@ -65,13 +70,17 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct qmc_dai_prtd *prtd = substream->runtime->private_data; - prtd->dma_buffer_start = runtime->dma_addr; - prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); - prtd->period_size = params_period_bytes(params); - prtd->period_ptr_submitted = prtd->dma_buffer_start; - prtd->period_ptr_ended = prtd->dma_buffer_start; prtd->substream = substream; + prtd->buffer_ended = 0; + prtd->buffer_size = params_buffer_size(params); + prtd->period_size = params_period_size(params); + + prtd->ch_dma_addr_start = runtime->dma_addr; + prtd->ch_dma_addr_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; + prtd->ch_dma_size = params_period_bytes(params); + return 0; } @@ -80,16 +89,16 @@ static void qmc_audio_pcm_write_complete(void *context) struct qmc_dai_prtd *prtd = context; int ret; - prtd->period_ptr_ended += prtd->period_size; - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) - prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->buffer_ended += prtd->period_size; + if (prtd->buffer_ended >= prtd->buffer_size) + prtd->buffer_ended = 0; - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", @@ -104,21 +113,21 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i struct qmc_dai_prtd *prtd = context; int ret; - if (length != prtd->period_size) { + if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", - length, prtd->period_size); + length, prtd->ch_dma_size); } - prtd->period_ptr_ended += prtd->period_size; - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) - prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->buffer_ended += prtd->period_size; + if (prtd->buffer_ended >= prtd->buffer_size) + prtd->buffer_ended = 0; - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", @@ -144,7 +153,7 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Submit first chunk ... */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", @@ -153,13 +162,13 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, } /* ... prepare next one ... */ - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", @@ -169,7 +178,7 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, } else { /* Submit first chunk ... */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(component->dev, "read_submit failed %d\n", @@ -178,13 +187,13 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, } /* ... prepare next one ... */ - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", @@ -215,8 +224,7 @@ static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *compone { struct qmc_dai_prtd *prtd = substream->runtime->private_data; - return bytes_to_frames(substream->runtime, - prtd->period_ptr_ended - prtd->dma_buffer_start); + return prtd->buffer_ended; } static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, From patchwork Thu Jun 20 08:42:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704986 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3784B1A4F1F; Thu, 20 Jun 2024 08:43:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873004; cv=none; b=ZsNfPh24BN1WBTJvunStkBx+cSVNR7bEELo2uSLfLe8Q9z9rXl+KHLBNDFP8eAQ5xrpEx0IKlXTp4ECerZoUvW4aZIMLluu1pf8Z7BNuSpaLawZvASiUJV00/WWOmYZOlCkzakyXDkCPSagsiMhkMSg93lL01+TKoW1FM+7p+Qk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873004; c=relaxed/simple; bh=AxIKPqTO+wF+1yoEnfWDUj8D8R3BzcUWs0scf2kg4mU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jBCTDLRERmkGhspzvdkSbQxcJ4zvfbYbU8smpMJBpp6b9K/RE8DrlMoopTs0brUcJ65Wn/V/gV5+lQstfcCm4wvVW/8FQ0lUCPCsg40bxeWVZ3coe3eWn4RfWr/xgiaZo+Bk0h2xSGP3jPFa05pZw5jLiHn2q4rQIi6p8DJBt18= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=e9ggyz3+; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="e9ggyz3+" Received: by mail.gandi.net (Postfix) with ESMTPA id D358620011; Thu, 20 Jun 2024 08:43:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872994; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EFI+0E0euoS+1MCJ9IhOD3qEiKcvASTCp8dMcDFqcOg=; b=e9ggyz3+6HHiSIpE/iQE79+VB+G+1HKI0ClqW79MRrOOy8T7fXlAMKw4WIXXKungvubb4f U4bQHzxdmr2RKQEFz7Ov7VRzFfEwisFMTpCTGNProk/T0XFUTxjNZCdMxvPAziN9d1nIrx AQ8LWvEtHlG6sX5m0Lgl5XAdkY1B75R3ePcdks7wQWyGgQvV61TcANwNfHhFLkHaGPWYD3 VvUVP6D/eMJ0FUCS9UTI5fhfUrlJLSCsiLsMRVeRGnrqcgk70lTKCqjEey9n1RNyJcrTji PGroAx7J9W8cJSGP+WiJ7byUQ3mgfEY8T3KT/M01rmvh9DatmlZG4FDwFnkV6w== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 04/10] ASoC: fsl: fsl_qmc_audio: Identify the QMC channel involved in completion routines Date: Thu, 20 Jun 2024 10:42:51 +0200 Message-ID: <20240620084300.397853-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com The current QMC audio driver uses only one QMC channel per DAI. The context used by QMC channel transfer (read and write) completion routines does not contains any QMC channel and the only one available per DAI is used to schedule the next transfer. This works pretty well with only one QMC channel per DAI. The future support for non-inlerleave mode will use several QMC channel per DAI. In that case, QMC channel transfer completion routines need to identify the QMC channel related to the completion. In order to fill this lack, even if identifying the current QMC channel among several QMC channels is not needed for the current code, add one indirection level and introduce the qmc_dai_chan data structrure. This structure contains the QMC channel involved in the completion and refererences to the runtime context (capture and playback) used by the DAI. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 72 +++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index e8281e548746..b07770257bad 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -17,13 +17,19 @@ #include #include +struct qmc_dai_chan { + struct qmc_dai_prtd *prtd_tx; + struct qmc_dai_prtd *prtd_rx; + struct qmc_chan *qmc_chan; +}; + struct qmc_dai { char *name; int id; struct device *dev; - struct qmc_chan *qmc_chan; unsigned int nb_tx_ts; unsigned int nb_rx_ts; + struct qmc_dai_chan chan; }; struct qmc_audio { @@ -86,9 +92,12 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, static void qmc_audio_pcm_write_complete(void *context) { - struct qmc_dai_prtd *prtd = context; + struct qmc_dai_chan *chan = context; + struct qmc_dai_prtd *prtd; int ret; + prtd = chan->prtd_tx; + prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) prtd->buffer_ended = 0; @@ -97,9 +106,10 @@ static void qmc_audio_pcm_write_complete(void *context) if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, prtd); + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", ret); @@ -110,9 +120,12 @@ static void qmc_audio_pcm_write_complete(void *context) static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { - struct qmc_dai_prtd *prtd = context; + struct qmc_dai_chan *chan = context; + struct qmc_dai_prtd *prtd; int ret; + prtd = chan->prtd_rx; + if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", length, prtd->ch_dma_size); @@ -126,9 +139,10 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, prtd); + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); @@ -151,10 +165,13 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + prtd->qmc_dai->chan.prtd_tx = prtd; + /* Submit first chunk ... */ - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, prtd); + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -167,19 +184,23 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, prtd); + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); return ret; } } else { + prtd->qmc_dai->chan.prtd_rx = prtd; + /* Submit first chunk ... */ - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, prtd); + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(component->dev, "read_submit failed %d\n", ret); @@ -192,9 +213,10 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, prtd); + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -489,7 +511,7 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { chan_param.mode = QMC_TRANSPARENT; chan_param.transp.max_rx_buf_size = params_period_bytes(params); - ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); + ret = qmc_chan_set_param(qmc_dai->chan.qmc_chan, &chan_param); if (ret) { dev_err(dai->dev, "set param failed %d\n", ret); @@ -520,23 +542,23 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = qmc_chan_start(qmc_dai->qmc_chan, direction); + ret = qmc_chan_start(qmc_dai->chan.qmc_chan, direction); if (ret) return ret; break; case SNDRV_PCM_TRIGGER_STOP: - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); if (ret) return ret; - ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); + ret = qmc_chan_reset(qmc_dai->chan.qmc_chan, direction); if (ret) return ret; break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); if (ret) return ret; break; @@ -613,10 +635,10 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * if (!qmc_dai->name) return -ENOMEM; - qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, - "fsl,qmc-chan"); - if (IS_ERR(qmc_dai->qmc_chan)) { - ret = PTR_ERR(qmc_dai->qmc_chan); + qmc_dai->chan.qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, + "fsl,qmc-chan"); + if (IS_ERR(qmc_dai->chan.qmc_chan)) { + ret = PTR_ERR(qmc_dai->chan.qmc_chan); return dev_err_probe(qmc_audio->dev, ret, "dai %d get QMC channel failed\n", qmc_dai->id); } @@ -624,7 +646,7 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_soc_dai_driver->id = qmc_dai->id; qmc_soc_dai_driver->name = qmc_dai->name; - ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); + ret = qmc_chan_get_info(qmc_dai->chan.qmc_chan, &info); if (ret) { dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", qmc_dai->id, ret); From patchwork Thu Jun 20 08:42:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704978 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CEB0719D094; Thu, 20 Jun 2024 08:43:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; cv=none; b=OZjv6S9kHqJovAxVO1WhJ72UmcUIfDwiYeoQ2vA5kkfKcpGfTj58uVd4IN1Mo3c+4VKeMJAP/3LhmL32aiJC5HBxsUzLPFeOXWT8N4tkC3/fhleXJ6V1ylNUM1FqXeSBe3X4E2V6fCqBRuXzgjPPtfi6WjIRKq/Iz+80P1AUtdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; c=relaxed/simple; bh=g06udzdr3FQ3GGjFDr6DB3X29brZkwlgc30sknmNjdM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TjxllRPr/oHxOnzCKonWwsbzs+ecJJ4YuZGen8v0l1wgEBHLTC/K1GdVjOuJoyx9y/MRpTdTOjf57t+N2umWNq6fIAYQAU+Edfb3B0xZVhhayNam/6ZJQjHGB8T+BPRoi+Peu5/8e23qaJbjX72XN3tjwkvKKRXgjg2HnglfKCo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=a97esiVn; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="a97esiVn" Received: by mail.gandi.net (Postfix) with ESMTPA id E8D0920005; Thu, 20 Jun 2024 08:43:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872996; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/jcw3B7br9mMf7ih+RGvbztJQGfoFsNFtd4Dmae4m5o=; b=a97esiVnJn41eMUraY8MB3Zy2tdFjuOc1bB72Im5wsV7wGp00opmdS75RCaZBrcqwnIYBo CbExXz+Zmlrrhg8vhuMJGJYFSIAMM4jOP7IJc9opSTfpOo3ouxRuigsFbZICp/rV/iTbc7 XDLhPEN9H05uYDZD+5fR1JYISMPCUHD7PBTGx3ATXXuQ7q5rWkdA4jDUMaEswD+IdlEXXN IYPMadbr9RX4TDh3vxDWzpAQ1WAPAJMycwZMrIXr/DP5WlYDVVKduYe9asrAadK3KzJMX3 7RIwBS3G86/V3qG1f0VDh4g1lwgkkZ3Yk9vsbgzuFpaO9Vb8e9wjeVvG+Sc00w== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 05/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_audio_pcm_{read,write}_submit() Date: Thu, 20 Jun 2024 10:42:52 +0200 Message-ID: <20240620084300.397853-6-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com Submitting data to QMC channels is done in several places: transfer completions and DAI start. The operation done is simple and consist in one function call. With the future introduction of support for non-interleaved mode, submitting data will be more complex. To avoid copy/paste of code in several places, introduce qmc_audio_pcm_{read,write}_submit() whose goal is to handle this data submission. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 93 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index b07770257bad..36145f1ddbf1 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -90,11 +90,29 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, return 0; } +static void qmc_audio_pcm_write_complete(void *context); + +static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) +{ + int ret; + + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, + prtd->ch_dma_addr_current, prtd->ch_dma_size, + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + ret); + return ret; + } + + return 0; +} + static void qmc_audio_pcm_write_complete(void *context) { struct qmc_dai_chan *chan = context; struct qmc_dai_prtd *prtd; - int ret; prtd = chan->prtd_tx; @@ -106,23 +124,33 @@ static void qmc_audio_pcm_write_complete(void *context) if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); + qmc_audio_pcm_write_submit(prtd); + + snd_pcm_period_elapsed(prtd->substream); +} + +static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags); + +static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) +{ + int ret; + + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, + prtd->ch_dma_addr_current, prtd->ch_dma_size, + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { - dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); } - snd_pcm_period_elapsed(prtd->substream); + return 0; } static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { struct qmc_dai_chan *chan = context; struct qmc_dai_prtd *prtd; - int ret; prtd = chan->prtd_rx; @@ -139,14 +167,7 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", - ret); - } + qmc_audio_pcm_read_submit(prtd); snd_pcm_period_elapsed(prtd->substream); } @@ -168,15 +189,9 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->qmc_dai->chan.prtd_tx = prtd; /* Submit first chunk ... */ - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(component->dev, "write_submit failed %d\n", - ret); + ret = qmc_audio_pcm_write_submit(prtd); + if (ret) return ret; - } /* ... prepare next one ... */ prtd->ch_dma_addr_current += prtd->ch_dma_size; @@ -184,28 +199,16 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(component->dev, "write_submit failed %d\n", - ret); + ret = qmc_audio_pcm_write_submit(prtd); + if (ret) return ret; - } } else { prtd->qmc_dai->chan.prtd_rx = prtd; /* Submit first chunk ... */ - ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(component->dev, "read_submit failed %d\n", - ret); + ret = qmc_audio_pcm_read_submit(prtd); + if (ret) return ret; - } /* ... prepare next one ... */ prtd->ch_dma_addr_current += prtd->ch_dma_size; @@ -213,15 +216,9 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; /* ... and send it */ - ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(component->dev, "write_submit failed %d\n", - ret); + ret = qmc_audio_pcm_read_submit(prtd); + if (ret) return ret; - } } break; From patchwork Thu Jun 20 08:42:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704980 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8E3E19DF6C; Thu, 20 Jun 2024 08:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; cv=none; b=YOtqQA4rITQGnjfnBQSTwFF4h/DUn6sFehSINF9Y9A2r9gZDd4lDGW4k2DVslbE2gNeKtwo9cQIST8ggQd/QKcu9QH8tuW3YbUMUUydrQxoWUQEgG3ow4sSm65wtkEehB41EPa9k6YNVG95M4GN0JXq7ywd6vN73cYFueIvypEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873000; c=relaxed/simple; bh=nVi64ptT3yeC9c3LdQUftdhINtCOQi2phyoQtm7QQOw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hGzLsliYF11gLUDOaOMad6cJiVmnbTNDUhlMEHyEqHYJLbIeysC+ecC0MUT8aKUFEqN2AXf3Zv8mFIZV3jcZrevqTca4HlrXIlbqxcZmHpKeE9wTHtqLAsmRz7qEwoGYUvLeW36TjwNb24OSCbarGUAFqp92x0e7zl9nzb+60X8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=JMOTMWHl; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="JMOTMWHl" Received: by mail.gandi.net (Postfix) with ESMTPA id 240FB2000A; Thu, 20 Jun 2024 08:43:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872997; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XcZoHw1OxV6TsmAdg+08k1YhnLc5NmNZMePFnQJFI74=; b=JMOTMWHljpjCiEnj20gVflZbP5I0/oA0m5LI7Peo2g6KnbKgJM+tpDzkfM60wiK006X4rD fdJ+B7kHZfNdZ1wTM9N+lqNE0kDbAjNf7LysqWif9DsZBNhinrBuS5CUowXI5Dcg/pRLAs reYJFaKbfMDOSThnKTcGOB0PageUCGNZZXa2g9rAmdAt9+N5wIRGOYOkZJ1PETHJz3OJ2x qvVBt66rDKhQwnn0/bwwJ4qtm02pn5w51tXQQ9gyujkTyHeeWJ0BEqHIZi2CYAaPTwFMEQ zBMSXhdRBYeowrpIqM4FpapoCbb++LQHx6r8bgAie559o0HfGxskJl3NQnzICQ== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 06/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_dai_constraints_interleaved() Date: Thu, 20 Jun 2024 10:42:53 +0200 Message-ID: <20240620084300.397853-7-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com Constraints are set by qmc_dai_startup(). These constraints are specific to the interleaved mode. With the future introduction of support for non-interleaved mode, a new set of constraints will be set. To make the code clear and keep qmc_dai_startup() simple, extract the current interleaved mode constraints settings to a specific function. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 37 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 36145f1ddbf1..f70c6c8eec4a 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -436,24 +436,14 @@ static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params * return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); } -static int qmc_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream, + struct qmc_dai *qmc_dai) { - struct qmc_dai_prtd *prtd = substream->runtime->private_data; snd_pcm_hw_rule_func_t hw_rule_channels_by_format; snd_pcm_hw_rule_func_t hw_rule_format_by_channels; - struct qmc_dai *qmc_dai; unsigned int frame_bits; int ret; - qmc_dai = qmc_dai_get_data(dai); - if (!qmc_dai) { - dev_err(dai->dev, "Invalid dai\n"); - return -EINVAL; - } - - prtd->qmc_dai = qmc_dai; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; @@ -468,7 +458,7 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, hw_rule_channels_by_format, qmc_dai, SNDRV_PCM_HW_PARAM_FORMAT, -1); if (ret) { - dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret); return ret; } @@ -476,7 +466,7 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, hw_rule_format_by_channels, qmc_dai, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (ret) { - dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret); return ret; } @@ -484,13 +474,30 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_FRAME_BITS, frame_bits); if (ret < 0) { - dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); return ret; } return 0; } +static int qmc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + struct qmc_dai *qmc_dai; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + prtd->qmc_dai = qmc_dai; + + return qmc_dai_constraints_interleaved(substream, qmc_dai); +} + static int qmc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) From patchwork Thu Jun 20 08:42:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704982 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D009D19DF71; Thu, 20 Jun 2024 08:43:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873002; cv=none; b=U/nbb3SgRYbgOrQmCca87VBYBjd+YmlUIic/dszaeOps4OYlYirU4y6ifPEODS73jqr0QwOW0/WhxdrX8VzIK4MF4seIbVQUws2p/SZOYYoqg3HpD7TO8RxkqiVbt/0ja0BHVE+yv9QPkBNb5FklD4VLTugpSCfo6gLr+e71p1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873002; c=relaxed/simple; bh=D7OEHiuwtCmqscXQl50KmY2kl3bSEyKNKVR8ivbxxAI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p0l+uG5a6jskrzm/Ngh94B/60bcnbOvugDYALVfQh7ACZhQpfCOrpH0XALkHAmTcDJyjzRe6JB+Gwo/2hWOlFH3fdQwwzo7rNcjXeAkYlycHooLbUhtqAiCXKqFhlPraLnokRoekuTWYLyyRwGkfayLjVIO3diCijHptF2HmvVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=jGNmymnm; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="jGNmymnm" Received: by mail.gandi.net (Postfix) with ESMTPA id 3FE7820013; Thu, 20 Jun 2024 08:43:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872998; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=whVnLEA8ZlMjzaDgw2XCJrm9u7TT3FhF+CXLz0Vls7M=; b=jGNmymnmfvAR6A9q/BlIf7N42FT7M+vILYHL1nny2UG+6idM7bZWmfTdX0lHc3JWpACMxI /mdk64X8GVSIgLjV3LZVF+cgYYl0+WqPlujHKbZCV+bp/rKuFM7R21vJqkh841XhCDdFvK 7bn28mjEptskNmS+oFjKyw0JHrXkzzvHS6AKmGzjESGZbrJEccVCmnPk3ZdXH5Fk6PiziB SHTv+aBeFgQFgl/khW1AH9M/UG/DStZqz2SzolNy9bNImKcmlAdJ3TvmHgTZ0MFnFPaNzD x7GVpoCOYOs0PpvFKOTK8gizo2QRP1qg9oBGFD56fZRkAfOADZMeoCqb+p6fkg== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 07/10] soc: fsl: cpm1: qmc: Introduce functions to get a channel from a phandle list Date: Thu, 20 Jun 2024 10:42:54 +0200 Message-ID: <20240620084300.397853-8-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com qmc_chan_get_byphandle() and the resource managed version retrieve a channel from a simple phandle. Extend the API and introduce qmc_chan_get_byphandles_index() and the resource managed version in order to retrieve a channel from a phandle list using the provided index to identify the phandle in the list. Also update qmc_chan_get_byphandle() and the resource managed version to use qmc_chan_get_byphandles_index() and so avoid code duplication. Signed-off-by: Herve Codina --- drivers/soc/fsl/qe/qmc.c | 19 +++++++++++-------- include/soc/fsl/qe/qmc.h | 25 ++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index f498db9abe35..e23d60018400 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -1777,13 +1777,15 @@ static struct qmc_chan *qmc_chan_get_from_qmc(struct device_node *qmc_np, unsign return qmc_chan; } -struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name) +struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, + const char *phandles_name, + int index) { struct of_phandle_args out_args; struct qmc_chan *qmc_chan; int ret; - ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, + ret = of_parse_phandle_with_fixed_args(np, phandles_name, 1, index, &out_args); if (ret < 0) return ERR_PTR(ret); @@ -1797,7 +1799,7 @@ struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phan of_node_put(out_args.np); return qmc_chan; } -EXPORT_SYMBOL(qmc_chan_get_byphandle); +EXPORT_SYMBOL(qmc_chan_get_byphandles_index); struct qmc_chan *qmc_chan_get_bychild(struct device_node *np) { @@ -1827,9 +1829,10 @@ static void devm_qmc_chan_release(struct device *dev, void *res) qmc_chan_put(*qmc_chan); } -struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, - struct device_node *np, - const char *phandle_name) +struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, + struct device_node *np, + const char *phandles_name, + int index) { struct qmc_chan *qmc_chan; struct qmc_chan **dr; @@ -1838,7 +1841,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, if (!dr) return ERR_PTR(-ENOMEM); - qmc_chan = qmc_chan_get_byphandle(np, phandle_name); + qmc_chan = qmc_chan_get_byphandles_index(np, phandles_name, index); if (!IS_ERR(qmc_chan)) { *dr = qmc_chan; devres_add(dev, dr); @@ -1848,7 +1851,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, return qmc_chan; } -EXPORT_SYMBOL(devm_qmc_chan_get_byphandle); +EXPORT_SYMBOL(devm_qmc_chan_get_byphandles_index); struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev, struct device_node *np) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 2a333fc1ea81..0fa7205145ce 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -16,11 +16,30 @@ struct device_node; struct device; struct qmc_chan; -struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name); +struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, + const char *phandles_name, + int index); +struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, + struct device_node *np, + const char *phandles_name, + int index); + +static inline struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, + const char *phandle_name) +{ + return qmc_chan_get_byphandles_index(np, phandle_name, 0); +} + +static inline struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, + struct device_node *np, + const char *phandle_name) +{ + return devm_qmc_chan_get_byphandles_index(dev, np, phandle_name, 0); +} + struct qmc_chan *qmc_chan_get_bychild(struct device_node *np); void qmc_chan_put(struct qmc_chan *chan); -struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, struct device_node *np, - const char *phandle_name); + struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev, struct device_node *np); enum qmc_mode { From patchwork Thu Jun 20 08:42:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704983 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E52019FA6B; Thu, 20 Jun 2024 08:43:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873003; cv=none; b=iqkVTaGmmPF0PXnLhz66uQxgezpeOVJXXMQhnZc/XIyAA921HjyvtAJE2QRO68z//selrkE1XsNvT9LXSL+oUcJZCkMb7XXEsCq/UTjHsxwDxPXjtiedmrInFGy9IxHJxdmZzkYAx1yzvTllhtmr39nI2w9dGRtRHQE2JcRCqgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873003; c=relaxed/simple; bh=/gkMygh09ZpiD7BTBSHMvPXyxlus217LmQzwwIIdnOk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S8CoR246Wt7boWwvPwg7uTnRX1s/2rpxc+CWttzl4kne5+WRwaB0G714rfDJsElLX9K1RZvcQvy34eeGl0qRWSEoauAbf8vvj1Du3WKwSMPd9nAsY2/SESSPeocP4ki+aEsFNrX9ameVp5oADhUeuZC/b/57yQWRzwtnP32mcjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=BYraRfk7; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="BYraRfk7" Received: by mail.gandi.net (Postfix) with ESMTPA id 5E33D20012; Thu, 20 Jun 2024 08:43:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718872999; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YDLRcTY0BkTaFAdlLFjztJqIMTmDai9TLYinXM16row=; b=BYraRfk7fEz5L1838NbMQUtgasaGC3yafWba1AA59mzifxKYEytwkNwf8SyIWpTY3kgf6B XVylMtJ5iP8zPd51l9KZueVKs9oinG3sl6rbBmqPv7N/6EmTdGrluo/VNLTg6qjw1NVJ5K FxI9ONYG7CI54wUSXtP8pOp/P6Q7OuDTS/4XCYA8fJ3iZ5xX/HN37b9QFIO0OqRZskePlB L91Bt6v+i5rN5HUE8T5+kkQFZ0M0AKz8O/Spdg6uN9XAhBPsCZbP6cwciBfrvrhyDFvpEf ggReD1B+0vtfuCPOfKDWeEOU4Tr4aTq27ArjK8IYP4XQs5WublUbr+biTu74ig== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 08/10] soc: fsl: cpm1: qmc: Introduce qmc_chan_count_phandles() Date: Thu, 20 Jun 2024 10:42:55 +0200 Message-ID: <20240620084300.397853-9-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com No function in the QMC API is available to get the number of phandles present in a phandle list. Fill this lack introducing qmc_chan_count_phandles(). Signed-off-by: Herve Codina --- drivers/soc/fsl/qe/qmc.c | 13 +++++++++++++ include/soc/fsl/qe/qmc.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index e23d60018400..76bb496305a0 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -1777,6 +1777,19 @@ static struct qmc_chan *qmc_chan_get_from_qmc(struct device_node *qmc_np, unsign return qmc_chan; } +int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name) +{ + int count; + + /* phandles are fixed args phandles with one arg */ + count = of_count_phandle_with_args(np, phandles_name, NULL); + if (count < 0) + return count; + + return count / 2; +} +EXPORT_SYMBOL(qmc_chan_count_phandles); + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, const char *phandles_name, int index) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 0fa7205145ce..294e42ea8d4c 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -16,6 +16,8 @@ struct device_node; struct device; struct qmc_chan; +int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name); + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, const char *phandles_name, int index); From patchwork Thu Jun 20 08:42:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704985 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 276DD1A4F17; Thu, 20 Jun 2024 08:43:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873004; cv=none; b=bjPRrkyLf/NHfQgSXOVvqP6LSwm9alJc6jVS3PUVm9fAzfbheZ0nkjLO6qirPAo+xVbv6xfAO8gFfNkbqOMeVIQA2c4fdKpLV5ytGAKW4iDGuc+hOJa+UXYy5Sa8g3bKm6BFdGYGcuVd09HwRmPlt4wPbxlKfdcEog0rgVUozCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873004; c=relaxed/simple; bh=rBkSeB69MknRRW1vvLLHZBCUsHjl3fAMU+GE38ZYnJk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PNLiBiRctHcyuLzKqoR3yDZRV99zXJ+ihPnIjLgwlkLBfgZYZOJk9MH2EQgihoqlI6onu8SD4F1CVSdgCGDshWqiX7vHIuwy4IF9Xy3UUV4/dF4LkfFAK8w9SNKLjT17VIPpfLRZoXdxq57JEXZe8BwUYvLfGz6C4ejKT80FwOE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=ew1lZeu1; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ew1lZeu1" Received: by mail.gandi.net (Postfix) with ESMTPA id 806CD20016; Thu, 20 Jun 2024 08:43:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718873000; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LQir0ryB/8aPBX/LEL6U1QothG+zRSSIaipi9sCzLmY=; b=ew1lZeu1oYh7noJ/c69BVNsPhRCTgkWHP3qwLlXxKKhYbGmkbHKPiXHyqURBfmqSYorKIm ScesK+S0610KGyeAzFMxdNifl136+7dKBnmCpdCAx8UtdDbqgk4Q+K/Fu8MmcJRUnXyEco aI8lxmr++LgOF8ZbFK5gZ80NcQ9Srn7oGRytUndRQtMbXrE1E9D2/NzYn3JAciPjbe/nV0 fbWdYz4bqFuodE7bo8he2o4vth9amo92zSTDN+52ISW+898gFDU65YN4FIhuQ+i1cfnnOz LNJdsvWx4mTDJytFSARmGafznmz15swgkXh4wv7MOz2vBe4XOfKuwD+RIbgu2w== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 09/10] dt-bindings: sound: fsl,qmc-audio: Add support for multiple QMC channels per DAI Date: Thu, 20 Jun 2024 10:42:56 +0200 Message-ID: <20240620084300.397853-10-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com The QMC audio uses one QMC channel per DAI and uses this QMC channel to transmit interleaved audio channel samples. In order to work in non-interleave mode, a QMC audio DAI needs to use multiple QMC channels. In that case, the DAI maps each QMC channel to exactly one audio channel. Allow QMC audio DAIs with multiple QMC channels attached. Signed-off-by: Herve Codina Reviewed-by: Rob Herring (Arm) --- .../bindings/sound/fsl,qmc-audio.yaml | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml index b522ed7dcc51..a23e49198c37 100644 --- a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml @@ -12,7 +12,9 @@ maintainers: description: | The QMC audio is an ASoC component which uses QMC (QUICC Multichannel Controller) channels to transfer the audio data. - It provides as many DAI as the number of QMC channel used. + It provides several DAIs. For each DAI, the DAI is working in interleaved mode + if only one QMC channel is used by the DAI or it is working in non-interleaved + mode if several QMC channels are used by the DAI. allOf: - $ref: dai-common.yaml# @@ -45,12 +47,19 @@ patternProperties: fsl,qmc-chan: $ref: /schemas/types.yaml#/definitions/phandle-array items: - - items: - - description: phandle to QMC node - - description: Channel number + items: + - description: phandle to QMC node + - description: Channel number + minItems: 1 description: - Should be a phandle/number pair. The phandle to QMC node and the QMC - channel to use for this DAI. + Should be a phandle/number pair list. The list of phandle to QMC node + and the QMC channel pair to use for this DAI. + If only one phandle/number pair is provided, this DAI works in + interleaved mode, i.e. audio channels for this DAI are interleaved in + the QMC channel. If more than one pair is provided, this DAI works + in non-interleave mode. In that case the first audio channel uses the + the first QMC channel, the second audio channel uses the second QMC + channel, etc... required: - reg @@ -79,6 +88,11 @@ examples: reg = <17>; fsl,qmc-chan = <&qmc 17>; }; + dai@18 { + reg = <18>; + /* Non-interleaved mode */ + fsl,qmc-chan = <&qmc 18>, <&qmc 19>; + }; }; sound { @@ -115,4 +129,19 @@ examples: dai-tdm-slot-rx-mask = <0 0 1 0 1 0 1 0 1>; }; }; + simple-audio-card,dai-link@2 { + reg = <2>; + format = "dsp_b"; + cpu { + sound-dai = <&audio_controller 18>; + }; + codec { + sound-dai = <&codec3>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + /* TS 9, 10 */ + dai-tdm-slot-tx-mask = <0 0 0 0 0 0 0 0 0 1 1>; + dai-tdm-slot-rx-mask = <0 0 0 0 0 0 0 0 0 1 1>; + }; + }; }; From patchwork Thu Jun 20 08:42:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13704987 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 677321A8C1B; Thu, 20 Jun 2024 08:43:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873006; cv=none; b=F4rG+K38zXtw0FLB4GWDofeigsQ9NTEF46S8EstTUH8DwwLjY88Lh/b7NGwQlq5jbXs56d39CZc1FZGyOGrx+Dy3+OZNFSGSYur0KMdZbSeGp042a1RffsTFwH5iCNldHx78RxpVdyiW3oTk/HYMbHf50QNa4kW9aqzS3+mPH8U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718873006; c=relaxed/simple; bh=E7QteoRl9C/26FVsU8W19YlEcEq7QMmxRnUbBiatoxI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JAUmK1a+1MKew9iEFY3kb5K91q9rt7iGxqBrReEumcREYmXs6RxzbU9loC2biVyfTtroffmztdwPD7w+0XVhJD3P2RH/bgIB44OjPLHdxayDaNrOeYtxmZD7fJQtiFj2WzVWAdlwKouMktNKosVPZZ37hrTDT5gG47zMROV3dm0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=GoTeOBpg; arc=none smtp.client-ip=217.70.183.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="GoTeOBpg" Received: by mail.gandi.net (Postfix) with ESMTPA id ACCF32000F; Thu, 20 Jun 2024 08:43:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1718873001; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H5chFE+ZESv7+kYmcebDJI0Kxhrb7TL7gOP4tBovzzY=; b=GoTeOBpgOWdzE8ehiTQQMWnYvQzQXKyzDeITHpAikjQlsxU+BUr+FLX0CwYnt+T4ilBKeH JVH6pGmT15C6VFklk0uXaPY8Xk8uyArpzG5eoS8y5u/ebF7H1I3DatiPiq1kvomxGO6j2X 3wFE+/P3nNDcqBQd0ZfeaAHxV4m+IgQFPz1ST9A/wquKqWdlDiH52etaSQCJyus8rpn+xM 7HrquhIJ5R9FMKm5mrbXQaTmWBpj8LRr5bn8XBX7S/iqD96o1lQc5NAmwww/y2AXsvfNqJ emAHCYA3MOfhhV/v03yUpYm5B2J5h2FLfGZQ9whIH87k29RYq3QWKWSOHn+14w== From: Herve Codina To: Herve Codina , Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Qiang Zhao , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Jaroslav Kysela , Takashi Iwai , Christophe Leroy Cc: alsa-devel@alsa-project.org, linuxppc-dev@lists.ozlabs.org, linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Petazzoni Subject: [PATCH 10/10] ASoC: fsl: fsl_qmc_audio: Add support for non-interleaved mode. Date: Thu, 20 Jun 2024 10:42:57 +0200 Message-ID: <20240620084300.397853-11-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240620084300.397853-1-herve.codina@bootlin.com> References: <20240620084300.397853-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com The current fsl_qmc_audio works in interleaved mode. The audio samples are interleaved and all data are sent to (received from) one QMC channel. Using several QMC channels, non interleaved mode can be easily supported. In that case, data related to ch0 are sent to (received from) the first QMC channel, data related to ch1 use the next QMC channel and so on up to the last channel. In terms of constraints and settings, the two modes are slightly different: - Interleaved mode: - The sample size should fit in the number of time-slots available for the QMC channel. - The number of audio channels should fit in the number of time-slots (taking into account the sample size) available for the QMC channel. - Non-interleaved mode: - The number of audio channels is the number of available QMC channels. - Each QMC channel should have the same number of time-slots. - The sample size equals the number of time-slots of one QMC channel. Add support for the non-interleaved mode allowing multiple QMC channel per DAI. The DAI switches in non-interleaved mode when more that one QMC channel is available. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 371 +++++++++++++++++++++++++++------- 1 file changed, 296 insertions(+), 75 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index f70c6c8eec4a..1560731c8372 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -29,7 +29,11 @@ struct qmc_dai { struct device *dev; unsigned int nb_tx_ts; unsigned int nb_rx_ts; - struct qmc_dai_chan chan; + + unsigned int nb_chans_avail; + unsigned int nb_chans_used_tx; + unsigned int nb_chans_used_rx; + struct qmc_dai_chan *chans; }; struct qmc_audio { @@ -50,7 +54,10 @@ struct qmc_dai_prtd { dma_addr_t ch_dma_addr_current; dma_addr_t ch_dma_addr_end; size_t ch_dma_size; + size_t ch_dma_offset; + unsigned int channels; + DECLARE_BITMAP(chans_pending, 64); struct snd_pcm_substream *substream; }; @@ -69,6 +76,17 @@ static int qmc_audio_pcm_construct(struct snd_soc_component *component, return 0; } +static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access) +{ + switch (access) { + case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED: + case SNDRV_PCM_ACCESS_RW_INTERLEAVED: + return true; + default: + return false; + } +}; + static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -76,6 +94,14 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct qmc_dai_prtd *prtd = substream->runtime->private_data; + /* + * In interleaved mode, the driver uses one QMC channel for all audio + * channels whereas in non-interleaved mode, it uses one QMC channel per + * audio channel. + */ + prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ? + 1 : params_channels(params); + prtd->substream = substream; prtd->buffer_ended = 0; @@ -83,9 +109,10 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, prtd->period_size = params_period_size(params); prtd->ch_dma_addr_start = runtime->dma_addr; - prtd->ch_dma_addr_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels; + prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset; prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - prtd->ch_dma_size = params_period_bytes(params); + prtd->ch_dma_size = params_period_bytes(params) / prtd->channels; return 0; } @@ -94,16 +121,23 @@ static void qmc_audio_pcm_write_complete(void *context); static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) { + unsigned int i; int ret; - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", - ret); - return ret; + for (i = 0; i < prtd->channels; i++) { + bitmap_set(prtd->chans_pending, i, 1); + + ret = qmc_chan_write_submit(prtd->qmc_dai->chans[i].qmc_chan, + prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, + prtd->ch_dma_size, + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chans[i]); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n", + i, ret); + bitmap_clear(prtd->chans_pending, i, 1); + return ret; + } } return 0; @@ -116,6 +150,16 @@ static void qmc_audio_pcm_write_complete(void *context) prtd = chan->prtd_tx; + /* Mark the current channel as completed */ + bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); + + /* + * All QMC channels involved must have completed their transfer before + * submitting a new one. + */ + if (!bitmap_empty(prtd->chans_pending, 64)) + return; + prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) prtd->buffer_ended = 0; @@ -133,15 +177,23 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) { + unsigned int i; int ret; - ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", - ret); + for (i = 0; i < prtd->channels; i++) { + bitmap_set(prtd->chans_pending, i, 1); + + ret = qmc_chan_read_submit(prtd->qmc_dai->chans[i].qmc_chan, + prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, + prtd->ch_dma_size, + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chans[i]); + if (ret) { + dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n", + i, ret); + bitmap_clear(prtd->chans_pending, i, 1); + return ret; + } } return 0; @@ -154,11 +206,21 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i prtd = chan->prtd_rx; + /* Mark the current channel as completed */ + bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); + if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", length, prtd->ch_dma_size); } + /* + * All QMC channels involved must have completed their transfer before + * submitting a new one. + */ + if (!bitmap_empty(prtd->chans_pending, 64)) + return; + prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) prtd->buffer_ended = 0; @@ -176,6 +238,7 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { struct qmc_dai_prtd *prtd = substream->runtime->private_data; + unsigned int i; int ret; if (!prtd->qmc_dai) { @@ -185,8 +248,10 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, switch (cmd) { case SNDRV_PCM_TRIGGER_START: + bitmap_zero(prtd->chans_pending, 64); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - prtd->qmc_dai->chan.prtd_tx = prtd; + for (i = 0; i < prtd->channels; i++) + prtd->qmc_dai->chans[i].prtd_tx = prtd; /* Submit first chunk ... */ ret = qmc_audio_pcm_write_submit(prtd); @@ -203,7 +268,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, if (ret) return ret; } else { - prtd->qmc_dai->chan.prtd_rx = prtd; + for (i = 0; i < prtd->channels; i++) + prtd->qmc_dai->chans[i].prtd_rx = prtd; /* Submit first chunk ... */ ret = qmc_audio_pcm_read_submit(prtd); @@ -270,6 +336,7 @@ static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_NONINTERLEAVED | SNDRV_PCM_INFO_PAUSE, .period_bytes_min = 32, .period_bytes_max = 64 * 1024, @@ -442,6 +509,7 @@ static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream, snd_pcm_hw_rule_func_t hw_rule_channels_by_format; snd_pcm_hw_rule_func_t hw_rule_format_by_channels; unsigned int frame_bits; + u64 access; int ret; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -478,6 +546,44 @@ static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream, return ret; } + access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED | + 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED; + ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS, + access); + if (ret) { + dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret); + return ret; + } + + return 0; +} + +static int qmc_dai_constraints_noninterleaved(struct snd_pcm_substream *substream, + struct qmc_dai *qmc_dai) +{ + unsigned int frame_bits; + u64 access; + int ret; + + frame_bits = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ? + qmc_dai->nb_rx_ts * 8 : qmc_dai->nb_tx_ts * 8; + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + frame_bits); + if (ret < 0) { + dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + return ret; + } + + access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED | + 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; + ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS, + access); + if (ret) { + dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret); + return ret; + } + return 0; } @@ -495,7 +601,9 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, prtd->qmc_dai = qmc_dai; - return qmc_dai_constraints_interleaved(substream, qmc_dai); + return qmc_dai->nb_chans_avail > 1 ? + qmc_dai_constraints_noninterleaved(substream, qmc_dai) : + qmc_dai_constraints_interleaved(substream, qmc_dai); } static int qmc_dai_hw_params(struct snd_pcm_substream *substream, @@ -503,7 +611,9 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct qmc_chan_param chan_param = {0}; + unsigned int nb_chans_used; struct qmc_dai *qmc_dai; + unsigned int i; int ret; qmc_dai = qmc_dai_get_data(dai); @@ -512,15 +622,34 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* + * In interleaved mode, the driver uses one QMC channel for all audio + * channels whereas in non-interleaved mode, it uses one QMC channel per + * audio channel. + */ + nb_chans_used = qmc_audio_access_is_interleaved(params_access(params)) ? + 1 : params_channels(params); + + if (nb_chans_used > qmc_dai->nb_chans_avail) { + dev_err(dai->dev, "Not enough qmc_chans. Need %u, avail %u\n", + nb_chans_used, qmc_dai->nb_chans_avail); + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { chan_param.mode = QMC_TRANSPARENT; - chan_param.transp.max_rx_buf_size = params_period_bytes(params); - ret = qmc_chan_set_param(qmc_dai->chan.qmc_chan, &chan_param); - if (ret) { - dev_err(dai->dev, "set param failed %d\n", - ret); - return ret; + chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used; + for (i = 0; i < nb_chans_used; i++) { + ret = qmc_chan_set_param(qmc_dai->chans[i].qmc_chan, &chan_param); + if (ret) { + dev_err(dai->dev, "chans[%u], set param failed %d\n", + i, ret); + return ret; + } } + qmc_dai->nb_chans_used_rx = nb_chans_used; + } else { + qmc_dai->nb_chans_used_tx = nb_chans_used; } return 0; @@ -529,9 +658,12 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream, static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { + unsigned int nb_chans_used; struct qmc_dai *qmc_dai; + unsigned int i; int direction; - int ret; + int ret = 0; + int ret_tmp; qmc_dai = qmc_dai_get_data(dai); if (!qmc_dai) { @@ -539,30 +671,50 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, return -EINVAL; } - direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - QMC_CHAN_WRITE : QMC_CHAN_READ; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = QMC_CHAN_WRITE; + nb_chans_used = qmc_dai->nb_chans_used_tx; + } else { + direction = QMC_CHAN_READ; + nb_chans_used = qmc_dai->nb_chans_used_rx; + } switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = qmc_chan_start(qmc_dai->chan.qmc_chan, direction); - if (ret) - return ret; + for (i = 0; i < nb_chans_used; i++) { + ret = qmc_chan_start(qmc_dai->chans[i].qmc_chan, direction); + if (ret) + goto err_stop; + } break; case SNDRV_PCM_TRIGGER_STOP: - ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); - if (ret) - return ret; - ret = qmc_chan_reset(qmc_dai->chan.qmc_chan, direction); + /* Stop and reset all QMC channels and return the first error encountered */ + for (i = 0; i < nb_chans_used; i++) { + ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); + if (!ret) + ret = ret_tmp; + if (ret_tmp) + continue; + + ret_tmp = qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); + if (!ret) + ret = ret_tmp; + } if (ret) return ret; break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); + /* Stop all QMC channels and return the first error encountered */ + for (i = 0; i < nb_chans_used; i++) { + ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); + if (!ret) + ret = ret_tmp; + } if (ret) return ret; break; @@ -572,6 +724,13 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, } return 0; + +err_stop: + while (i--) { + qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); + qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); + } + return ret; } static const struct snd_soc_dai_ops qmc_dai_ops = { @@ -580,7 +739,7 @@ static const struct snd_soc_dai_ops qmc_dai_ops = { .hw_params = qmc_dai_hw_params, }; -static u64 qmc_audio_formats(u8 nb_ts) +static u64 qmc_audio_formats(u8 nb_ts, bool is_noninterleaved) { unsigned int format_width; unsigned int chan_width; @@ -612,6 +771,13 @@ static u64 qmc_audio_formats(u8 nb_ts) if (format_width > chan_width || chan_width % format_width) continue; + /* + * In non interleaved mode, we can only support formats that + * can fit only 1 time in the channel + */ + if (is_noninterleaved && format_width != chan_width) + continue; + formats_mask |= pcm_format_to_bits(format); } return formats_mask; @@ -622,6 +788,12 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * struct snd_soc_dai_driver *qmc_soc_dai_driver) { struct qmc_chan_info info; + unsigned long rx_fs_rate; + unsigned long tx_fs_rate; + unsigned int nb_tx_ts; + unsigned int nb_rx_ts; + unsigned int i; + int count; u32 val; int ret; @@ -639,56 +811,105 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * if (!qmc_dai->name) return -ENOMEM; - qmc_dai->chan.qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, - "fsl,qmc-chan"); - if (IS_ERR(qmc_dai->chan.qmc_chan)) { - ret = PTR_ERR(qmc_dai->chan.qmc_chan); - return dev_err_probe(qmc_audio->dev, ret, - "dai %d get QMC channel failed\n", qmc_dai->id); - } + count = qmc_chan_count_phandles(np, "fsl,qmc-chan"); + if (count < 0) + return dev_err_probe(qmc_audio->dev, count, + "dai %d get number of QMC channel failed\n", qmc_dai->id); + if (!count) + return dev_err_probe(qmc_audio->dev, -EINVAL, + "dai %d no QMC channel defined\n", qmc_dai->id); - qmc_soc_dai_driver->id = qmc_dai->id; - qmc_soc_dai_driver->name = qmc_dai->name; + qmc_dai->chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->chans), GFP_KERNEL); + if (!qmc_dai->chans) + return -ENOMEM; - ret = qmc_chan_get_info(qmc_dai->chan.qmc_chan, &info); - if (ret) { - dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", - qmc_dai->id, ret); - return ret; - } - dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", - qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); + for (i = 0; i < count; i++) { + qmc_dai->chans[i].qmc_chan = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np, + "fsl,qmc-chan", i); + if (IS_ERR(qmc_dai->chans[i].qmc_chan)) { + return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->chans[i].qmc_chan), + "dai %d get QMC channel %d failed\n", qmc_dai->id, i); + } - if (info.mode != QMC_TRANSPARENT) { - dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", - qmc_dai->id, info.mode); - return -EINVAL; + ret = qmc_chan_get_info(qmc_dai->chans[i].qmc_chan, &info); + if (ret) { + dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n", + qmc_dai->id, i, ret); + return ret; + } + dev_info(qmc_audio->dev, "dai %d QMC channel %d mode %d, nb_tx_ts %u, nb_rx_ts %u\n", + qmc_dai->id, i, info.mode, info.nb_tx_ts, info.nb_rx_ts); + + if (info.mode != QMC_TRANSPARENT) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n", + qmc_dai->id, i, info.mode); + return -EINVAL; + } + + /* + * All channels must have the same number of Tx slots and the + * same numbers of Rx slots. + */ + if (i == 0) { + nb_tx_ts = info.nb_tx_ts; + nb_rx_ts = info.nb_rx_ts; + tx_fs_rate = info.tx_fs_rate; + rx_fs_rate = info.rx_fs_rate; + } else { + if (nb_tx_ts != info.nb_tx_ts) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n", + qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts); + return -EINVAL; + } + if (nb_rx_ts != info.nb_rx_ts) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n", + qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts); + return -EINVAL; + } + if (tx_fs_rate != info.tx_fs_rate) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n", + qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate); + return -EINVAL; + } + if (rx_fs_rate != info.rx_fs_rate) { + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n", + qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate); + return -EINVAL; + } + } } - qmc_dai->nb_tx_ts = info.nb_tx_ts; - qmc_dai->nb_rx_ts = info.nb_rx_ts; + + qmc_dai->nb_chans_avail = count; + qmc_dai->nb_tx_ts = nb_tx_ts * count; + qmc_dai->nb_rx_ts = nb_rx_ts * count; + + qmc_soc_dai_driver->id = qmc_dai->id; + qmc_soc_dai_driver->name = qmc_dai->name; qmc_soc_dai_driver->playback.channels_min = 0; qmc_soc_dai_driver->playback.channels_max = 0; - if (qmc_dai->nb_tx_ts) { + if (nb_tx_ts) { qmc_soc_dai_driver->playback.channels_min = 1; - qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; + qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts; } - qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); + qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts, + count > 1 ? true : false); qmc_soc_dai_driver->capture.channels_min = 0; qmc_soc_dai_driver->capture.channels_max = 0; - if (qmc_dai->nb_rx_ts) { + if (nb_rx_ts) { qmc_soc_dai_driver->capture.channels_min = 1; - qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; + qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts; } - qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); - - qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); - qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; - qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; - qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); - qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; - qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; + qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts, + count > 1 ? true : false); + + qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate); + qmc_soc_dai_driver->playback.rate_min = tx_fs_rate; + qmc_soc_dai_driver->playback.rate_max = tx_fs_rate; + qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate); + qmc_soc_dai_driver->capture.rate_min = rx_fs_rate; + qmc_soc_dai_driver->capture.rate_max = rx_fs_rate; qmc_soc_dai_driver->ops = &qmc_dai_ops;