From: Binbin Zhou Date: Mon, 1 Jun 2026 09:29:39 +0000 (+0800) Subject: ASoC: loongson: Separate external shared DMA from the platform interface X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=767a1b50c1f0d5d2090cab52a08dc794b9830938;p=thirdparty%2Flinux.git ASoC: loongson: Separate external shared DMA from the platform interface 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 Link: https://patch.msgid.link/979368ad269f192703ed24e9a19eebce32316745.1780304703.git.zhoubinbin@loongson.cn Signed-off-by: Mark Brown --- diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile index 4c6d3130bcee..6e43672071fc 100644 --- a/sound/soc/loongson/Makefile +++ b/sound/soc/loongson/Makefile @@ -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 diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c index f51b5b94e3ab..ed970343d283 100644 --- a/sound/soc/loongson/loongson_dma.c +++ b/sound/soc/loongson/loongson_dma.c @@ -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); diff --git a/sound/soc/loongson/loongson_dma.h b/sound/soc/loongson/loongson_dma.h index 8a8fa8abd85a..a040681d2693 100644 --- a/sound/soc/loongson/loongson_dma.h +++ b/sound/soc/loongson/loongson_dma.h @@ -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 diff --git a/sound/soc/loongson/loongson_i2s_plat.c b/sound/soc/loongson/loongson_i2s_plat.c index f8d7aca8b903..ac054b6ce632 100644 --- a/sound/soc/loongson/loongson_i2s_plat.c +++ b/sound/soc/loongson/loongson_i2s_plat.c @@ -19,6 +19,7 @@ #include #include "loongson_i2s.h" +#include "loongson_dma.h" #define LOONGSON_I2S_RX_DMA_OFFSET 21 #define LOONGSON_I2S_TX_DMA_OFFSET 18 @@ -29,62 +30,6 @@ #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");