]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: loongson: Separate external shared DMA from the platform interface
authorBinbin Zhou <zhoubinbin@loongson.cn>
Mon, 1 Jun 2026 09:29:39 +0000 (17:29 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 2 Jun 2026 15:21:46 +0000 (16:21 +0100)
The Loongson I2S platform driver (used on LS2K1000, LS7A etc.) relies on
an external DMA engine (e.g., dw_dmac) rather than the internal DMA.
However, its DMA-related code was originally embedded in
loongson_i2s_plat.c, duplicating logic that should be shared.

Extract the external DMA (eDMA) support from the platform driver and move
it into loongson_dma.c alongside the existing internal DMA (iDMA) code.

This change eliminates code duplication and prepares for future
consolidation of DMA selection logic.

Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Link: https://patch.msgid.link/979368ad269f192703ed24e9a19eebce32316745.1780304703.git.zhoubinbin@loongson.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/loongson/Makefile
sound/soc/loongson/loongson_dma.c
sound/soc/loongson/loongson_dma.h
sound/soc/loongson/loongson_i2s_plat.c

index 4c6d3130bcee673390537df99bb4968a7961ea72..6e43672071fc7424e0806d5db6efacd21460c428 100644 (file)
@@ -1,12 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
 #Platform Support
-snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_dma.o
+snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o
 obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o snd-soc-loongson-i2s.o
 
 snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o
 obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o snd-soc-loongson-i2s.o
 
-snd-soc-loongson-i2s-y := loongson_i2s.o
+snd-soc-loongson-i2s-y := loongson_i2s.o loongson_dma.o
 
 obj-$(CONFIG_SND_LOONGSON1_AC97) += loongson1_ac97.o
 
index f51b5b94e3ab018edb6fcbbce78dfb60a0b792d9..ed970343d283f3f825be65c5268e3f310c344567 100644 (file)
@@ -344,3 +344,62 @@ const struct snd_soc_component_driver loongson_i2s_idma_component = {
        .mmap           = loongson_idma_pcm_mmap,
        .pcm_new        = loongson_idma_pcm_new,
 };
+EXPORT_SYMBOL_GPL(loongson_i2s_idma_component);
+
+static const struct snd_pcm_hardware loongson_edma_hardware = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_RESUME |
+               SNDRV_PCM_INFO_PAUSE,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE |
+                  SNDRV_PCM_FMTBIT_S20_3LE |
+                  SNDRV_PCM_FMTBIT_S24_LE,
+       .period_bytes_min = 128,
+       .period_bytes_max = 128 * 1024,
+       .periods_min = 1,
+       .periods_max = 64,
+       .buffer_bytes_max = 1024 * 1024,
+};
+
+const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
+       .pcm_hardware = &loongson_edma_hardware,
+       .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+       .prealloc_buffer_size = 128 * 1024,
+};
+EXPORT_SYMBOL_GPL(loongson_dmaengine_pcm_config);
+
+/* External DMA component */
+static int loongson_edma_pcm_open(struct snd_soc_component *component,
+                                 struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       if (substream->pcm->device & 1) {
+               runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
+               runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+       }
+
+       if (substream->pcm->device & 2)
+               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
+                                     SNDRV_PCM_INFO_MMAP_VALID);
+       /*
+        * For mysterious reasons (and despite what the manual says)
+        * playback samples are lost if the DMA count is not a multiple
+        * of the DMA burst size.  Let's add a rule to enforce that.
+        */
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
+       snd_pcm_hw_constraint_integer(substream->runtime,
+                                     SNDRV_PCM_HW_PARAM_PERIODS);
+
+       return 0;
+}
+
+const struct snd_soc_component_driver loongson_i2s_edma_component = {
+       .name   = LS_I2S_DRVNAME,
+       .open   = loongson_edma_pcm_open,
+};
+EXPORT_SYMBOL_GPL(loongson_i2s_edma_component);
index 8a8fa8abd85a554093cf041c60ca2e6d45487ef4..a040681d269359c4474a16f4213cbef25bae8ddb 100644 (file)
@@ -10,5 +10,7 @@
 #define _LOONGSON_DMA_H
 
 extern const struct snd_soc_component_driver loongson_i2s_idma_component;
+extern const struct snd_soc_component_driver loongson_i2s_edma_component;
+extern const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config;
 
 #endif
index f8d7aca8b9033059ab312ce99658108962c5c74e..ac054b6ce6322f98c0254bb118f946175deb6f73 100644 (file)
@@ -19,6 +19,7 @@
 #include <sound/soc.h>
 
 #include "loongson_i2s.h"
+#include "loongson_dma.h"
 
 #define LOONGSON_I2S_RX_DMA_OFFSET     21
 #define LOONGSON_I2S_TX_DMA_OFFSET     18
 #define LOONGSON_DMA3_CONF     0x3
 #define LOONGSON_DMA4_CONF     0x4
 
-/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */
-static const struct snd_pcm_hardware loongson_pcm_hardware = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_MMAP_VALID |
-               SNDRV_PCM_INFO_RESUME |
-               SNDRV_PCM_INFO_PAUSE,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE |
-                  SNDRV_PCM_FMTBIT_S20_3LE |
-                  SNDRV_PCM_FMTBIT_S24_LE,
-       .period_bytes_min = 128,
-       .period_bytes_max = 128 * 1024,
-       .periods_min = 1,
-       .periods_max = 64,
-       .buffer_bytes_max = 1024 * 1024,
-};
-
-static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
-       .pcm_hardware = &loongson_pcm_hardware,
-       .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
-       .prealloc_buffer_size = 128 * 1024,
-};
-
-static int loongson_pcm_open(struct snd_soc_component *component,
-                            struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       if (substream->pcm->device & 1) {
-               runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
-               runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
-       }
-
-       if (substream->pcm->device & 2)
-               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
-                                     SNDRV_PCM_INFO_MMAP_VALID);
-       /*
-        * For mysterious reasons (and despite what the manual says)
-        * playback samples are lost if the DMA count is not a multiple
-        * of the DMA burst size.  Let's add a rule to enforce that.
-        */
-       snd_pcm_hw_constraint_step(runtime, 0,
-                                  SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
-       snd_pcm_hw_constraint_step(runtime, 0,
-                                  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
-       snd_pcm_hw_constraint_integer(substream->runtime,
-                                     SNDRV_PCM_HW_PARAM_PERIODS);
-
-       return 0;
-}
-
-static const struct snd_soc_component_driver loongson_i2s_component_driver = {
-       .name   = LS_I2S_DRVNAME,
-       .open   = loongson_pcm_open,
-};
-
 static int loongson_i2s_apbdma_config(struct platform_device *pdev)
 {
        int val;
@@ -147,7 +92,7 @@ static int loongson_i2s_plat_probe(struct platform_device *pdev)
        dev_set_name(dev, LS_I2S_DRVNAME);
        dev_set_drvdata(dev, i2s);
 
-       ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver,
+       ret = devm_snd_soc_register_component(dev, &loongson_i2s_edma_component,
                                              &loongson_i2s_dai, 1);
        if (ret)
                return dev_err_probe(dev, ret, "failed to register DAI\n");