From patchwork Mon Jul 1 11:30:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717942 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 3B84C14A086; Mon, 1 Jul 2024 11:31:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833521; cv=none; b=jzS3isBIy34WH3UY0xOixyrJweu5YdF0WK6K98u2QfcE0i37V4XpM2oQdHW9HBJ/UxKPbfgLPZTQtD/rHIXAcHd/tVuDa4LmXcR9K70Ab50FhemIcL8fpi61sp660Bed9N8sPKyOS2Or611EwwiaVaSp6nVIlOXkhEnv1Wlqr9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833521; c=relaxed/simple; bh=JyxXab3gh+wCGMjIW6vDCbjLfD//HftTPx3aJXGP3m8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FkyVSaMxwF6Yed7oBasfRElin+FhEiDzH0qB4fRZFRnvnccxbBzqBkVvNKRCHWxKFPzX1NjKyjo3Djk3/YiqvkhouKlPR2S9G7WeRgV4ZX0le7VCW3FS4fXhN2wDu203y6nPWK68jN5McGUBx9aFYegs1GhV7X8xanm335379pU= 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=fY5JNPPN; arc=none smtp.client-ip=217.70.183.193 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="fY5JNPPN" Received: by mail.gandi.net (Postfix) with ESMTPA id 5EB47240002; Mon, 1 Jul 2024 11:31:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833511; 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=fY5JNPPNTUPd+3WwdpltqYwI63mL9XXxlIkXhbS6hKe5rdPZ4lvBOQfo5N0juytrcdShcz MmlHt9VD3Xu6TUoWvSWvKIMPGLqmySiXL6B/mRONseF5N76usRmMgMq8+2+PrH1sU2w3S8 0gh+G3GYDDEnDNJ6AZ+3xsfj5zl5VEIhgmsX2ykfDBZTLsfkVq8fqSWHvbYaguK1hhfpGl 1BaL2FMf4IVKA9yB+WQGAGqUR64suAfhLN2M3peUznZjgN6NtROnfFLuFEPF61HfZ28Uj4 xj40osEIqZmE25n5f5YKzg9JLX9Io/Myd1eOjD1HLLLvMdWMvDZhSoqNN4mmDQ== 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 v2 01/10] ASoC: fsl: fsl_qmc_audio: Check devm_kasprintf() returned value Date: Mon, 1 Jul 2024 13:30:28 +0200 Message-ID: <20240701113038.55144-2-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717944 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 5634A14A0B2; Mon, 1 Jul 2024 11:32:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833522; cv=none; b=HDqP3hazKUGRC+5Ym9UIRxkg7HbUGunSf0Jr0QG7HNbUvQ2209ywT9009JJfdbbup2PAaDA8tkn565gmlwMbzljJlhNV7ZlH8+OuPAqDSXLL7mGJjtFSZy+mw39lqOVbPD6syYGLAgLFbekOn4QBt5jCbTuxSW4qOaSc1F+lpDs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833522; c=relaxed/simple; bh=GaT+5Okx/oGaUT+xmbDP0mhLQm3Dnt3jOzk1ZVn025o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AaiVN9kXS5l4RGSnBrPRK69WOOjy+qv0y2z5HYCVTSQJeJyGcBr0i9nVg054SHGa2lv00b9xSP/h9O/DDJhPGRU0lOzbvYrV4QamErOEE9PaFxGrl3Kl9DsqzhDAdVh805+8uvFsmPO3NnWGsfAn4quur3gn1ERmJ1jMNGa7KO0= 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=ZnoUMiVn; arc=none smtp.client-ip=217.70.183.193 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="ZnoUMiVn" Received: by mail.gandi.net (Postfix) with ESMTPA id 107CC24000B; Mon, 1 Jul 2024 11:31:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833513; 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=ZnoUMiVnb11UJdZZbvnee3w//260YfU36UdASsrxZKtnLT0RSKHw60Gza9IE+R0YneEvYO tGWwWBBjeDjc6MpybIvG2HH1uC++vXDFQpA1OYb4LxIOAPth4DVobC5KlVAi0UJGEHRYjV yuo1iIyZbcWezpzaje5Kh9wauaRxPh+pzTFwa/w/eb7ly3tsq0zx8t64ONw/NAs2WbM+Wm lWcqMP4Cw+klG8jOSHpxUWyAgAD9pD/Zl4f3SyYXTwXcqMUvNYKfYlJF8o2GfWy+L38E/S niiucXksWmGXv+kb/b2Kuu8Pu7ybwCHfqeOurvgvtYv5fVg9IavdiSh1R1WX6A== 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 v2 02/10] ASoC: fsl: fsl_qmc_audio: Fix issues detected by checkpatch Date: Mon, 1 Jul 2024 13:30:29 +0200 Message-ID: <20240701113038.55144-3-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717946 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 4349614B970; Mon, 1 Jul 2024 11:32:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833524; cv=none; b=AS6R5JmVsusGbaFRfM6THY+kq+oI9BG9iFvfIAvZbK7paXXjeiLOIub2RoZheZFE6TjA/mcI62JF9BzMC9duKeYwJuhfeHGILhuye5alwlo/JYTkcIBvl99tNWdDGPaQM4jHloKLejJMADNIYFURmOS6AZmwKcTrrugwF7EDXSM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833524; c=relaxed/simple; bh=qIFtrk4+jNTGagJEvJP5YHoAWF+6D2TUEBk4+yKW9OU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KIkF8hFRg38pQZ9d0ZTa4eADgWuEe7tFxV+aryik2c3ucNsFo4ww6qgtwZALD15D0jMT8EgVUjHp1zt7AA+Z0C/tYhTJicgiszIfjI5fgb71D1Ql5nApAPqu1atDEHuhrBM4mIKiYNIqoWt7uOAfqESXfuH58pfqkKrWUNsMP/w= 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=Qn7BuU8l; arc=none smtp.client-ip=217.70.183.193 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="Qn7BuU8l" Received: by mail.gandi.net (Postfix) with ESMTPA id D103624000C; Mon, 1 Jul 2024 11:31:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833515; 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=Qn7BuU8l4SABc26cXeY5fXzvX2JTxMN+hjuYbmlIbf/hJmf8HHCixsYahNv4qs8XCW/pS3 53S40kUKmjlqpFimDWiAoLHlL+agIhJwTb4t1K95F4fBk3psHH/NlmPC+NR2MPWDm3j+ss njv/7N3MJNClabHkBe1NuYnKMix8hkCaAgZL1jfMkAw8g8Jnu+E0SnpatGeW3Fc53YPHZK +83BSiZJxLC5oTwoKxkcpeAiW41vz34NJ3QpsjQyicnyUah1B7ELrLunAkOgbq40BNAELQ QmGlmFYhHckomdhk/A9nUwU6w5Sk8mbTyPUJ2Yn5N8vebjN+k/BF9JWP6aV50g== 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 v2 03/10] ASoC: fsl: fsl_qmc_audio: Split channel buffer and PCM pointer handling Date: Mon, 1 Jul 2024 13:30:30 +0200 Message-ID: <20240701113038.55144-4-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717941 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 A86EB145B09; Mon, 1 Jul 2024 11:31:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833521; cv=none; b=a528jvwPhfIjALPUxWLkg6/PLO6fUJYzf/yQ4d+DY9yt1VgkxsdZkL8REoCOKe0K5542CKLTWIR1Na2llcnm/pZV2hH3Gy6UQ373FWVSWFs8YV/b7CNfwxzcZ65UL2HrWtR/XtnN8PASKFaF+RUogBYGvmUPbg/V63odEmgjg0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833521; c=relaxed/simple; bh=AxIKPqTO+wF+1yoEnfWDUj8D8R3BzcUWs0scf2kg4mU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b8BeykjTywKA9/Z9t/DX7MNcapF+z6JGeNJ+zXr1Zxay27soSm6A+rWlUjJNv1t+/WEZhqCfnUMpi5R34gTQuBuh4+zjEzif7xGx+jOeNIH+ysVg+uD/0ufQaLo7Qhj4e5PHjfmcUUN8goeF55O1ekPedY+xDlzftzv6jrxX5y8= 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=eu/vYyAI; arc=none smtp.client-ip=217.70.183.193 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="eu/vYyAI" Received: by mail.gandi.net (Postfix) with ESMTPA id 7D21124000E; Mon, 1 Jul 2024 11:31:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833517; 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=eu/vYyAIhSyp0MjAJ9CkOyycqPE4aKe+kZlJsGs/gJ8AikcYDe5G+tBh3h3T2c6jtrj5B4 /podCnym9i5XJF8szSMFTlXRdXc12SrJzaZ2wBh8ZEnKh3DfrLCbxXl1wOq/dYzRVufR4Y zR+xYcvz0NbmXb+EiPeL0ztJo/UpRPzMtJy7V5LRTfxy2avf8XHtMYW2xcE/7008XPQQDb LYlgqfNhEyjxBf70HDlgNA9fKCY8GynEokn6gKEWGdOBBEWWteYdApxITW7XO85RKnLkiz VAb+Aahu9A2eXtQPrVnaKu4SdgydbVgDP8rs9FWPUfjL8uGlbX0hikmWeW2lsA== 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 v2 04/10] ASoC: fsl: fsl_qmc_audio: Identify the QMC channel involved in completion routines Date: Mon, 1 Jul 2024 13:30:31 +0200 Message-ID: <20240701113038.55144-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717943 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 53C7A14A0AD; Mon, 1 Jul 2024 11:32:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833522; cv=none; b=brFhcf1jvD/NVFZF0b2dR6sid/gevUQnyxpgLDM8ypCMvsXM7YB7MmPkYEUYIkkvhN0uPUlpvhd2qSXRNCLIZttEgHqomtooZXofO5aQxSqho3+GbtVfrfaK7GjiAnfRrNrG/kOTKtKTxDLBXrQb+fiq/8l/aUYVdiDNKbR3dHw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833522; c=relaxed/simple; bh=g06udzdr3FQ3GGjFDr6DB3X29brZkwlgc30sknmNjdM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oGAExKrVTpU6AGU/i3Cy4X1bfJ+YXsxoTuQtI2NZ5vrYipMho/bkuD4493Zk61NR0CtULq2cADesJi54RGTHPdhku05mwSNWP100yQ7QWZnT3BBvPIAU95hLCeQi3+5lDfAMBytzQaPCO4rFLJpPR/Azo0yd4ZbBUqZrGLu3c7c= 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=IC5jzmz3; arc=none smtp.client-ip=217.70.183.193 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="IC5jzmz3" Received: by mail.gandi.net (Postfix) with ESMTPA id 205FF24000A; Mon, 1 Jul 2024 11:31:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833518; 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=IC5jzmz3RVMVKUDvfu2V+XY4gJ+VHN6WFRD8L1onHskN2e69nRp7IeJEgXosa6zV1QNFxs zV59lemE1n19UnDiU/okAXlc69cTrM8bVVX50Rsjk+xsNww3u8LFC1Lkt/cgHjKddn3Ypw fX5OXOELddg8RQOVke87B1O+lFsWJMt6YI5DsztR3UBqXpEuwwcce/eKLkDFYkRfhCucys niF7SwR7wVERwg7MQ/5erLs6/tRk+tgG2cwqMmyjXZ0Ntu88AuvL3vTeNH1Itfpjhbzct/ c6eF2AcA3bZT9tnwAdbnYgL5+kQllm3lqYy81VtTzTYd85qFkUajhWjEmC9/6w== 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 v2 05/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_audio_pcm_{read,write}_submit() Date: Mon, 1 Jul 2024 13:30:32 +0200 Message-ID: <20240701113038.55144-6-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717945 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 CA82414B077; Mon, 1 Jul 2024 11:32:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833524; cv=none; b=j2Wnii4UQJ1pmiUO09NLK0e8F6jU1M1/suJ2kkjXlr5IO6gt2CkT7rRhJnw077+DOvjuga37XJB4GQM/CH+28oxI8ADcAijKf9L3fKRWeylLsg3S0NtwT44qRVNiHMMmBLjTl6mGeMhLAnfBV61zRtra4NVZafSZumqRVX+R3uI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833524; c=relaxed/simple; bh=nVi64ptT3yeC9c3LdQUftdhINtCOQi2phyoQtm7QQOw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FBXu+ZquCZ5C9CBT0jwyzDW5O+T3oraJse6gLNowJVVJFgoRHxSMkzj2d4uKsMzLcTGOOA0itWih1NqU0WAsDCSpRv80CSiI5lAwnQrTPLVBrpYafIUO/N64o/cajRNxihTH0yHpdMH+AoIW3oSCZTXIOC/okC1M3wb9R3cTKxM= 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=M/BsLWhQ; arc=none smtp.client-ip=217.70.183.193 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="M/BsLWhQ" Received: by mail.gandi.net (Postfix) with ESMTPA id CD8B624000D; Mon, 1 Jul 2024 11:31:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833520; 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=M/BsLWhQlhBXtz7jXLYBkW328atssS5Oa1BgPQh367OA0eJfDC1DPdTxY1nVe/S8uzbizj F5Eb586GxIKNTMEJygbBtWYVusUY31BevPhabLHPYdD8Mjxf0fYzdiakKRwIZsmWFF6aYP KlSL7hNso/mgc0iyJiCSZAkV6Ac/NYcos2eyHxHDk3GsHca/RGj9MwGLPkkGzIjrvCCVEi t1iNScaRt7SbiJiQjMQfcnuU5mBSwODUaLkGRjyVbKotKQ/TYFq71Lumb9TQLKiib/EAcB ROm5vUAoNGG9Oxql1dx+33gEEYsc1PfIkF2ff/kT+JNMc+h5fsW+Ob2ox3aZYw== 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 v2 06/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_dai_constraints_interleaved() Date: Mon, 1 Jul 2024 13:30:33 +0200 Message-ID: <20240701113038.55144-7-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717947 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 CA31D14C585; Mon, 1 Jul 2024 11:32:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833525; cv=none; b=C6Vis0r41ZOr4h1bPoZGjQQ4VWcwpp+7xgnEeMK8CNmzU/fs7srJKE9NiAJ8sZSB5mevgOx2jCVUdhe/02po4xlZC4l6LHEyCzKWaX9uMLEb193i0gi16yS9L3yQkwq85dM8+xRAdE0hlqBalhjhKwEZS7f2EO1cCFz2KlNwYzs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833525; c=relaxed/simple; bh=D7OEHiuwtCmqscXQl50KmY2kl3bSEyKNKVR8ivbxxAI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QkGULIlYWHmMw6ojZHhe4rsqdQygeRUakfhLL9+/ZU6bu+eHsePwwqPIkIgbjdp0qA93d6V4xLVPuvG1mMUr/CtAv5FwIMd50WOV1yhT9WMb7gXXNoRjw60DtXJ8S1LaS3S/jNpLIbv7+5FMZh2NiQfwVo9PDPEtaN1qChIBgz8= 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=NhLEq7Ck; arc=none smtp.client-ip=217.70.183.193 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="NhLEq7Ck" Received: by mail.gandi.net (Postfix) with ESMTPA id 52553240013; Mon, 1 Jul 2024 11:32:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833521; 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=NhLEq7CkU8wxtHpprCD50uFD85Wl6dF6F+fncT71vMCc7u9QHMXp8q8QuyJlxCu/b4dAkD BU8F/aGL2Drp8gFthnSuqt+Efo8otL4s/fYM2fmc4KuCwmdu+mtEL678tjvvrogpYp/QRz nAUqYQTDT7a06Df/GVQe1438nC9H3K8RiEDvATwunATYSV6nCx6G2CMMR9j4j9im6ZTbCp qlHqwn0Qi6FMlIzdNLvK+ZaTAkaPYl6uVNwk+lKlhZ8YC2bD8deg5O4ae7hVIzRpOAoaQI ANujLhl7u7nt5c8Bs0kief2IElhSRPVNLdH+6sw9c99MCFGQk5yepN3jXyHDJA== 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 v2 07/10] soc: fsl: cpm1: qmc: Introduce functions to get a channel from a phandle list Date: Mon, 1 Jul 2024 13:30:34 +0200 Message-ID: <20240701113038.55144-8-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717948 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 C384D14E2CC; Mon, 1 Jul 2024 11:32:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833525; cv=none; b=Gp9IJpypdn7iaNI2h2sW2ZjhhdBSkyB8EmGVqVM+Tr8s2M9lelrZ8OIGHK6SOpTMqjuePCPv9AW0k2H9o2S3aBtrSSKcidZWyZ1KvXrAI0a3g74ddrSt2bn4TkDoO/3Y2J0sAMxaPt0XgAKXltqF5URu7EhWXyf4G6H2tik1gE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833525; c=relaxed/simple; bh=/gkMygh09ZpiD7BTBSHMvPXyxlus217LmQzwwIIdnOk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hZVhYYxkx7jfaljBS75UMgErEN+Gzi0Z0//8VTCozeHaJBK1hYEfTnIfOLcnsEtVvP/CgOrgGiGW+qkvBWj7IYBfgtifNZhW6MLyWPuNar4aft2qz6JTMDrS5YnD6KMA4xGcbeSo895JlvzWuDL7FnGIZPtXnAz7fg6RPtxujQI= 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=QT8erB9g; arc=none smtp.client-ip=217.70.183.193 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="QT8erB9g" Received: by mail.gandi.net (Postfix) with ESMTPA id 65EA0240004; Mon, 1 Jul 2024 11:32:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833522; 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=QT8erB9gCf6OWkg7I6bDNvSwNHrlZgWewAb/9E6bxyHgTRCqj2DNQZFNSOaK+ddE7EkNU5 jxbm2hC72zLFhJ3/KQF480Glzu92tNXYsL9yyhfIXf2cQ/oWJG1G1jLWjhBNgQD3Yznk/5 tseXa4zkp148CetvvWDLVuqw3Gvwgh3otEYTaDYPHfjxJ6gkOLYkdcONzryFfWuYO909oT 7WybA9ia1UvUI1jQECS5En7l0ppFDRxfQmkGLcnHJrc/s7w+RZTKvukKsg7WA8A67bj5Q2 t5ImicTFkaiRPQBVPJDCKPqDh+LPY1cP/XWhxPE4VAohS5ZM9RXw5M4CfTW4Pg== 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 v2 08/10] soc: fsl: cpm1: qmc: Introduce qmc_chan_count_phandles() Date: Mon, 1 Jul 2024 13:30:35 +0200 Message-ID: <20240701113038.55144-9-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717949 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 CEBB514F9FA; Mon, 1 Jul 2024 11:32:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833527; cv=none; b=hNvosdhZ3qbvL2Fv/D834TQC4StHSDk5u1LvEzNZyj5o09/scM20OPyLVB5VGgGmfPcKL75DbA+PP33ze14rlJFHDTfrj1hryISWgUctADs25yYmbCNPframgc88vBbNrKpA9oTdBjHtYKBEQATjoDM12WTNCc6nfSvZE2wX9Nc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833527; c=relaxed/simple; bh=IWqKgpcTwbg0LZqPsWGdtlP3A/WVEiC2gYH8LGWVs7A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PoR3sDTn4RQ+A7F1yg9Xdivixo0ZvF6TTLrK4XkvBDObpTF3AUczYX2V6OVh+tDeVnjaH+gU6QbC3DvFUTriifKkZTYITCYCm/6zxo1gl/tzaR+hrTEC1DsosoYN3AKnjUDVSalHUfoL8vk3OMTa61GyHCUjuqvvoLHL1VVv1Ho= 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=EgTc1gzy; arc=none smtp.client-ip=217.70.183.193 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="EgTc1gzy" Received: by mail.gandi.net (Postfix) with ESMTPA id 61907240002; Mon, 1 Jul 2024 11:32:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833523; 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=sfZG8ibbCskYBjaUkA70z76iMY7bqlElSDzCQwYJd/Q=; b=EgTc1gzyL3pfQ/KiFB1+225D05a2zp0EmLxLD6bIkUkfH3Wuh89+7jJMk5AQIPp/HLbD6t yA4E5HXwpI8PwPNBcBIjahlOB4VSB3dk2ICdAYPWgTQYbJsTuR8WzLwTevV/fxpqkyq36d pAI/Fz9TzxqWDGjwXHX1+64JzI9hLIb/1cQacvmIG/shvLmQXfVBH0ezFegtgf47x/5Ze6 c/2xhoAs1Y2OnFaCi4j9lRtdaplZnBE1mJFy7j636J31Wzvpke7r8dkPPxNPURjIFEpkuL n13DR2gHrMhPuykXfOxu/TnsCr/b5yU1gvXhMu8dSodSiauju9bdJAwbt1VKlQ== 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 v2 09/10] dt-bindings: sound: fsl,qmc-audio: Add support for multiple QMC channels per DAI Date: Mon, 1 Jul 2024 13:30:36 +0200 Message-ID: <20240701113038.55144-10-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 Mon Jul 1 11:30:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 13717950 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) (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 05FDB1534EC; Mon, 1 Jul 2024 11:32:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833528; cv=none; b=tRnUZZA0sqjGY2VHAOdNatE5slY+1MZTeUdMgCkMgiUT3054n9N7bZoIvcVr8dJFxYrWzwgupP2vZLQbhDli4ICQJsqk282qm4w/wBN/0PTYTUnXF0PTGBKf0ZYatreCSYQbBxvrBM+JB+jYRBHd1WrmKhyNHUoRldXeFO5Z5zI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719833528; c=relaxed/simple; bh=UEB2pUzUcoOt0r1h8EKSYRRzfI8FEyPBiM/jSqQN/Wg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jIiSUnQhtswB1qkc2aqtmAAgq6HonORvM9cHLe/BlnMcOn1VbBLDny3SNGdBNnUOZhJXg+R2k6Ke/fVR/dHGf7Ov51WLngLRPWxpoywSH7mVw/j6iMWADPNMEoEIs7IHS4us0blhUTQh6eTyccPOvRvaLzkpNODLGRTDy4jrJ0g= 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=hIqvZEVT; arc=none smtp.client-ip=217.70.183.193 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="hIqvZEVT" Received: by mail.gandi.net (Postfix) with ESMTPA id 6A39624000A; Mon, 1 Jul 2024 11:32:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1719833524; 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=eHG8lPGlQk6+IXxucX4unaLMS1tOpOoqGN2wBV2+b+Q=; b=hIqvZEVTTPI12BajyP21kj3t7NtwnC954hShbuFKmK5JJeq6vp54mDZjTm23yj/6j7ZtFH t2ap7DyW39eljVQG7nzdhf7/1XLJSpSL+JCp/p9VORtV8arvgj6Xlci4F/ujchA68jeY8S l9qO9XA4aZduY7lXPxC7Y+E9OLQhlbh7kIpTq4SZf3SQNNeYFQ2XwRe5Y91bf5k94aVWcg QJskuGVUbqu1DS7I5tlAxqdqmCXo/Qvprlez7yTMXVoDlmPtMwW7Cq2immyfT3Kabbjv9f Yd9mYpv9kXB+ofkaBrxlZxYSskntHgswokugaE5SY16dYK+95MtGdyk10ZtaAA== 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 v2 10/10] ASoC: fsl: fsl_qmc_audio: Add support for non-interleaved mode. Date: Mon, 1 Jul 2024 13:30:37 +0200 Message-ID: <20240701113038.55144-11-herve.codina@bootlin.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240701113038.55144-1-herve.codina@bootlin.com> References: <20240701113038.55144-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 | 372 +++++++++++++++++++++++++++------- 1 file changed, 297 insertions(+), 75 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index f70c6c8eec4a..8668abd35208 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,18 @@ 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: + break; + } + 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 +95,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 +110,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 +122,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 +151,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 +178,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 +207,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 +239,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 +249,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 +269,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 +337,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 +510,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 +547,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 +602,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 +612,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 +623,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 +659,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 +672,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 +725,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 +740,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 +772,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 +789,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 +812,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;