diff mbox series

ASoC: fsl_micfil: Add decimation filter bypass mode support

Message ID 20250206030306.2618620-1-shengjiu.wang@nxp.com (mailing list archive)
State Accepted
Commit 21aa330fec31bb530a4ef6c9555fb157d0711112
Headers show
Series ASoC: fsl_micfil: Add decimation filter bypass mode support | expand

Commit Message

Shengjiu Wang Feb. 6, 2025, 3:03 a.m. UTC
When decimation filter bypass mode is enabled, PDM data can be
written into FIFO directly without any processing.

The interface of this mode is DSD big endian format, when
user needs this format, then this mode is enabled.

This mode is only for the i.MX943 platform currently.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 sound/soc/fsl/fsl_micfil.c | 49 ++++++++++++++++++++++++++++++++++----
 sound/soc/fsl/fsl_micfil.h |  1 +
 2 files changed, 45 insertions(+), 5 deletions(-)

Comments

Mark Brown Feb. 11, 2025, 7:13 p.m. UTC | #1
On Thu, 06 Feb 2025 11:03:06 +0800, Shengjiu Wang wrote:
> When decimation filter bypass mode is enabled, PDM data can be
> written into FIFO directly without any processing.
> 
> The interface of this mode is DSD big endian format, when
> user needs this format, then this mode is enabled.
> 
> This mode is only for the i.MX943 platform currently.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: fsl_micfil: Add decimation filter bypass mode support
      commit: 21aa330fec31bb530a4ef6c9555fb157d0711112

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
diff mbox series

Patch

diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index fa4136683392..73d8910a6188 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -19,6 +19,7 @@ 
 #include <linux/dma/imx-dma.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
 #include <sound/core.h>
@@ -78,6 +79,7 @@  struct fsl_micfil {
 	struct fsl_micfil_verid verid;
 	struct fsl_micfil_param param;
 	bool mclk_flag;  /* mclk enable flag */
+	bool dec_bypass;
 };
 
 struct fsl_micfil_soc_data {
@@ -129,7 +131,7 @@  static struct fsl_micfil_soc_data fsl_micfil_imx943 = {
 	.fifos = 8,
 	.fifo_depth = 32,
 	.dataline =  0xf,
-	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_BE,
 	.use_edma = true,
 	.use_verid = true,
 	.volume_sx = false,
@@ -724,14 +726,14 @@  static int fsl_micfil_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (ret)
 			return ret;
 
-		if (micfil->vad_enabled)
+		if (micfil->vad_enabled && !micfil->dec_bypass)
 			fsl_micfil_hwvad_enable(micfil);
 
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (micfil->vad_enabled)
+		if (micfil->vad_enabled && !micfil->dec_bypass)
 			fsl_micfil_hwvad_disable(micfil);
 
 		/* Disable the module */
@@ -778,8 +780,9 @@  static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
 {
 	struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
 	unsigned int channels = params_channels(params);
+	snd_pcm_format_t format = params_format(params);
 	unsigned int rate = params_rate(params);
-	int clk_div = 8;
+	int clk_div = 8, mclk_rate, div_multiply_k;
 	int osr = MICFIL_OSR_DEFAULT;
 	int ret;
 
@@ -801,7 +804,39 @@  static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
 
 	micfil->mclk_flag = true;
 
-	ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8);
+	/* floor(K * CLKDIV) */
+	switch (micfil->quality) {
+	case QUALITY_HIGH:
+		div_multiply_k = clk_div >> 1;
+		break;
+	case QUALITY_LOW:
+	case QUALITY_VLOW1:
+		div_multiply_k = clk_div << 1;
+		break;
+	case QUALITY_VLOW2:
+		div_multiply_k = clk_div << 2;
+		break;
+	case QUALITY_MEDIUM:
+	case QUALITY_VLOW0:
+	default:
+		div_multiply_k = clk_div;
+		break;
+	}
+
+	if (format == SNDRV_PCM_FORMAT_DSD_U32_BE) {
+		micfil->dec_bypass = true;
+		/*
+		 * According to equation 29 in RM:
+		 * MCLK_CLK_ROOT = PDM CLK rate * 2 * floor(K * CLKDIV)
+		 * PDM CLK rate = rate * physical bit width (32)
+		 */
+		mclk_rate = rate * div_multiply_k * 32 * 2;
+	} else {
+		micfil->dec_bypass = false;
+		mclk_rate = rate * clk_div * osr * 8;
+	}
+
+	ret = clk_set_rate(micfil->mclk, mclk_rate);
 	if (ret)
 		return ret;
 
@@ -809,6 +844,10 @@  static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
 	if (ret)
 		return ret;
 
+	regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
+			   MICFIL_CTRL2_DEC_BYPASS,
+			   micfil->dec_bypass ? MICFIL_CTRL2_DEC_BYPASS : 0);
+
 	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
 				 MICFIL_CTRL2_CLKDIV | MICFIL_CTRL2_CICOSR,
 				 FIELD_PREP(MICFIL_CTRL2_CLKDIV, clk_div) |
diff --git a/sound/soc/fsl/fsl_micfil.h b/sound/soc/fsl/fsl_micfil.h
index aa3661ea4ffc..fdfe4e7125bc 100644
--- a/sound/soc/fsl/fsl_micfil.h
+++ b/sound/soc/fsl/fsl_micfil.h
@@ -53,6 +53,7 @@ 
 #define MICFIL_CTRL1_CHEN(ch)		BIT(ch)
 
 /* MICFIL Control Register 2 -- REG_MICFILL_CTRL2 0x04 */
+#define MICFIL_CTRL2_DEC_BYPASS		BIT(31)
 #define MICFIL_CTRL2_QSEL_SHIFT		25
 #define MICFIL_CTRL2_QSEL		GENMASK(27, 25)
 #define MICFIL_QSEL_MEDIUM_QUALITY	0