Skip to content

Commit 767a1b5

Browse files
AaronDotbroonie
authored andcommitted
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>
1 parent 353530e commit 767a1b5

4 files changed

Lines changed: 65 additions & 59 deletions

File tree

sound/soc/loongson/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# SPDX-License-Identifier: GPL-2.0
22
#Platform Support
3-
snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_dma.o
3+
snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o
44
obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o snd-soc-loongson-i2s.o
55

66
snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o
77
obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o snd-soc-loongson-i2s.o
88

9-
snd-soc-loongson-i2s-y := loongson_i2s.o
9+
snd-soc-loongson-i2s-y := loongson_i2s.o loongson_dma.o
1010

1111
obj-$(CONFIG_SND_LOONGSON1_AC97) += loongson1_ac97.o
1212

sound/soc/loongson/loongson_dma.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,62 @@ const struct snd_soc_component_driver loongson_i2s_idma_component = {
344344
.mmap = loongson_idma_pcm_mmap,
345345
.pcm_new = loongson_idma_pcm_new,
346346
};
347+
EXPORT_SYMBOL_GPL(loongson_i2s_idma_component);
348+
349+
static const struct snd_pcm_hardware loongson_edma_hardware = {
350+
.info = SNDRV_PCM_INFO_MMAP |
351+
SNDRV_PCM_INFO_INTERLEAVED |
352+
SNDRV_PCM_INFO_MMAP_VALID |
353+
SNDRV_PCM_INFO_RESUME |
354+
SNDRV_PCM_INFO_PAUSE,
355+
.formats = SNDRV_PCM_FMTBIT_S16_LE |
356+
SNDRV_PCM_FMTBIT_S20_3LE |
357+
SNDRV_PCM_FMTBIT_S24_LE,
358+
.period_bytes_min = 128,
359+
.period_bytes_max = 128 * 1024,
360+
.periods_min = 1,
361+
.periods_max = 64,
362+
.buffer_bytes_max = 1024 * 1024,
363+
};
364+
365+
const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
366+
.pcm_hardware = &loongson_edma_hardware,
367+
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
368+
.prealloc_buffer_size = 128 * 1024,
369+
};
370+
EXPORT_SYMBOL_GPL(loongson_dmaengine_pcm_config);
371+
372+
/* External DMA component */
373+
static int loongson_edma_pcm_open(struct snd_soc_component *component,
374+
struct snd_pcm_substream *substream)
375+
{
376+
struct snd_pcm_runtime *runtime = substream->runtime;
377+
378+
if (substream->pcm->device & 1) {
379+
runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
380+
runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
381+
}
382+
383+
if (substream->pcm->device & 2)
384+
runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
385+
SNDRV_PCM_INFO_MMAP_VALID);
386+
/*
387+
* For mysterious reasons (and despite what the manual says)
388+
* playback samples are lost if the DMA count is not a multiple
389+
* of the DMA burst size. Let's add a rule to enforce that.
390+
*/
391+
snd_pcm_hw_constraint_step(runtime, 0,
392+
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
393+
snd_pcm_hw_constraint_step(runtime, 0,
394+
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
395+
snd_pcm_hw_constraint_integer(substream->runtime,
396+
SNDRV_PCM_HW_PARAM_PERIODS);
397+
398+
return 0;
399+
}
400+
401+
const struct snd_soc_component_driver loongson_i2s_edma_component = {
402+
.name = LS_I2S_DRVNAME,
403+
.open = loongson_edma_pcm_open,
404+
};
405+
EXPORT_SYMBOL_GPL(loongson_i2s_edma_component);

sound/soc/loongson/loongson_dma.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@
1010
#define _LOONGSON_DMA_H
1111

1212
extern const struct snd_soc_component_driver loongson_i2s_idma_component;
13+
extern const struct snd_soc_component_driver loongson_i2s_edma_component;
14+
extern const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config;
1315

1416
#endif

sound/soc/loongson/loongson_i2s_plat.c

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <sound/soc.h>
2020

2121
#include "loongson_i2s.h"
22+
#include "loongson_dma.h"
2223

2324
#define LOONGSON_I2S_RX_DMA_OFFSET 21
2425
#define LOONGSON_I2S_TX_DMA_OFFSET 18
@@ -29,62 +30,6 @@
2930
#define LOONGSON_DMA3_CONF 0x3
3031
#define LOONGSON_DMA4_CONF 0x4
3132

32-
/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */
33-
static const struct snd_pcm_hardware loongson_pcm_hardware = {
34-
.info = SNDRV_PCM_INFO_MMAP |
35-
SNDRV_PCM_INFO_INTERLEAVED |
36-
SNDRV_PCM_INFO_MMAP_VALID |
37-
SNDRV_PCM_INFO_RESUME |
38-
SNDRV_PCM_INFO_PAUSE,
39-
.formats = SNDRV_PCM_FMTBIT_S16_LE |
40-
SNDRV_PCM_FMTBIT_S20_3LE |
41-
SNDRV_PCM_FMTBIT_S24_LE,
42-
.period_bytes_min = 128,
43-
.period_bytes_max = 128 * 1024,
44-
.periods_min = 1,
45-
.periods_max = 64,
46-
.buffer_bytes_max = 1024 * 1024,
47-
};
48-
49-
static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
50-
.pcm_hardware = &loongson_pcm_hardware,
51-
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
52-
.prealloc_buffer_size = 128 * 1024,
53-
};
54-
55-
static int loongson_pcm_open(struct snd_soc_component *component,
56-
struct snd_pcm_substream *substream)
57-
{
58-
struct snd_pcm_runtime *runtime = substream->runtime;
59-
60-
if (substream->pcm->device & 1) {
61-
runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
62-
runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
63-
}
64-
65-
if (substream->pcm->device & 2)
66-
runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
67-
SNDRV_PCM_INFO_MMAP_VALID);
68-
/*
69-
* For mysterious reasons (and despite what the manual says)
70-
* playback samples are lost if the DMA count is not a multiple
71-
* of the DMA burst size. Let's add a rule to enforce that.
72-
*/
73-
snd_pcm_hw_constraint_step(runtime, 0,
74-
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
75-
snd_pcm_hw_constraint_step(runtime, 0,
76-
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
77-
snd_pcm_hw_constraint_integer(substream->runtime,
78-
SNDRV_PCM_HW_PARAM_PERIODS);
79-
80-
return 0;
81-
}
82-
83-
static const struct snd_soc_component_driver loongson_i2s_component_driver = {
84-
.name = LS_I2S_DRVNAME,
85-
.open = loongson_pcm_open,
86-
};
87-
8833
static int loongson_i2s_apbdma_config(struct platform_device *pdev)
8934
{
9035
int val;
@@ -147,7 +92,7 @@ static int loongson_i2s_plat_probe(struct platform_device *pdev)
14792
dev_set_name(dev, LS_I2S_DRVNAME);
14893
dev_set_drvdata(dev, i2s);
14994

150-
ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver,
95+
ret = devm_snd_soc_register_component(dev, &loongson_i2s_edma_component,
15196
&loongson_i2s_dai, 1);
15297
if (ret)
15398
return dev_err_probe(dev, ret, "failed to register DAI\n");

0 commit comments

Comments
 (0)