diff mbox series

ASoC: atmel: mchp-i2s-mcc: Improve maxburst calculation for better performance

Message ID 20240905095633.113784-1-andrei.simion@microchip.com (mailing list archive)
State Accepted
Commit 03667e3d4fbcaf6228fd642464467366f0b693de
Headers show
Series ASoC: atmel: mchp-i2s-mcc: Improve maxburst calculation for better performance | expand

Commit Message

Andrei Simion Sept. 5, 2024, 9:56 a.m. UTC
From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>

The period size represents the size of the DMA descriptor. To ensure all
DMA descriptors start from a well-aligned address, the period size must
be divided by (sample size * maxburst), not just by maxburst.
This adjustment allows for computing a higher maxburst value, thereby
increasing the performance of the DMA transfer.
Previously, snd_pcm_lib_period_bytes() returned 0 because the runtime HW
parameters are computed after the hw_params() callbacks are used.
To address this, we now use params_*() functions to compute the period
size accurately. This change optimizes the DMA transfer performance by
ensuring proper alignment and efficient use of maxburst values.

Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
[andrei.simion@microchip.com: Reword commit message and commit title.
Add macros with values for maximum DMA chunk size allowed.
Add DMA_BURST_ALIGNED preprocessor function to check the alignment of the
DMA burst]
Signed-off-by: Andrei Simion <andrei.simion@microchip.com>
---
 sound/soc/atmel/mchp-i2s-mcc.c | 38 +++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)


base-commit: fdadd93817f124fd0ea6ef251d4a1068b7feceba

Comments

Mark Brown Sept. 5, 2024, 2:43 p.m. UTC | #1
On Thu, 05 Sep 2024 12:56:33 +0300, Andrei Simion wrote:
> The period size represents the size of the DMA descriptor. To ensure all
> DMA descriptors start from a well-aligned address, the period size must
> be divided by (sample size * maxburst), not just by maxburst.
> This adjustment allows for computing a higher maxburst value, thereby
> increasing the performance of the DMA transfer.
> Previously, snd_pcm_lib_period_bytes() returned 0 because the runtime HW
> parameters are computed after the hw_params() callbacks are used.
> To address this, we now use params_*() functions to compute the period
> size accurately. This change optimizes the DMA transfer performance by
> ensuring proper alignment and efficient use of maxburst values.
> 
> [...]

Applied to

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

Thanks!

[1/1] ASoC: atmel: mchp-i2s-mcc: Improve maxburst calculation for better performance
      commit: 03667e3d4fbcaf6228fd642464467366f0b693de

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/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 193dd7acceb0..35a56b266b8d 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -221,6 +221,15 @@ 
 #define MCHP_I2SMCC_MAX_CHANNELS		8
 #define MCHP_I2MCC_TDM_SLOT_WIDTH		32
 
+/*
+ * ---- DMA chunk size allowed ----
+ */
+#define MCHP_I2SMCC_DMA_8_WORD_CHUNK			8
+#define MCHP_I2SMCC_DMA_4_WORD_CHUNK			4
+#define MCHP_I2SMCC_DMA_2_WORD_CHUNK			2
+#define MCHP_I2SMCC_DMA_1_WORD_CHUNK			1
+#define DMA_BURST_ALIGNED(_p, _s, _w)		!(_p % (_s * _w))
+
 static const struct regmap_config mchp_i2s_mcc_regmap_config = {
 	.reg_bits = 32,
 	.reg_stride = 4,
@@ -504,12 +513,30 @@  static int mchp_i2s_mcc_is_running(struct mchp_i2s_mcc_dev *dev)
 	return !!(sr & (MCHP_I2SMCC_SR_TXEN | MCHP_I2SMCC_SR_RXEN));
 }
 
+static inline int mchp_i2s_mcc_period_to_maxburst(int period_size, int sample_size)
+{
+	int p_size = period_size;
+	int s_size = sample_size;
+
+	if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_8_WORD_CHUNK))
+		return MCHP_I2SMCC_DMA_8_WORD_CHUNK;
+	if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_4_WORD_CHUNK))
+		return MCHP_I2SMCC_DMA_4_WORD_CHUNK;
+	if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_2_WORD_CHUNK))
+		return MCHP_I2SMCC_DMA_2_WORD_CHUNK;
+	return MCHP_I2SMCC_DMA_1_WORD_CHUNK;
+}
+
 static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params *params,
 				  struct snd_soc_dai *dai)
 {
 	unsigned long rate = 0;
 	struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai);
+	int sample_bytes = params_physical_width(params) / 8;
+	int period_bytes = params_period_size(params) *
+		params_channels(params) * sample_bytes;
+	int maxburst;
 	u32 mra = 0;
 	u32 mrb = 0;
 	unsigned int channels = params_channels(params);
@@ -519,9 +546,9 @@  static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
 	int ret;
 	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
-	dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
+	dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u period_bytes=%d\n",
 		__func__, params_rate(params), params_format(params),
-		params_width(params), params_channels(params));
+		params_width(params), params_channels(params), period_bytes);
 
 	switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
@@ -630,11 +657,12 @@  static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
 	 * We must have the same burst size configured
 	 * in the DMA transfer and in out IP
 	 */
-	mrb |= MCHP_I2SMCC_MRB_DMACHUNK(channels);
+	maxburst = mchp_i2s_mcc_period_to_maxburst(period_bytes, sample_bytes);
+	mrb |= MCHP_I2SMCC_MRB_DMACHUNK(maxburst);
 	if (is_playback)
-		dev->playback.maxburst = 1 << (fls(channels) - 1);
+		dev->playback.maxburst = maxburst;
 	else
-		dev->capture.maxburst = 1 << (fls(channels) - 1);
+		dev->capture.maxburst = maxburst;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S8: