mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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 <zhoubinbin@loongson.cn> Link: https://patch.msgid.link/979368ad269f192703ed24e9a19eebce32316745.1780304703.git.zhoubinbin@loongson.cn Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
353530ece8
commit
767a1b50c1
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user