[alsa-devel] [PATCH] ASoC: generic-dmaengine-pcm: Add an interface to override its functions
Nicolin Chen
b42378 at freescale.com
Tue Oct 15 09:49:20 CEST 2013
Each implementation of gerneric pcm dmaengine has been naturally
limited by the pre-defined gerneric functions. Thus add an extra
interface for user to create a backdoor so that they can override
those fixed functions for some uncommon requirements: using on-chip
memory for DMA buffers and accordingly different mmap function for
example, while at the meantime, they can continue to benifit from
the concise and wise generic pcm dmaengine.
Signed-off-by: Nicolin Chen <b42378 at freescale.com>
---
include/sound/dmaengine_pcm.h | 13 +++++++++++++
sound/core/pcm_dmaengine.c | 25 +++++++++++++++++++++++++
sound/soc/soc-generic-dmaengine-pcm.c | 30 ++++++++++++++++++------------
3 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index f11c35c..a6e9d04 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -33,6 +33,18 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
return DMA_DEV_TO_MEM;
}
+struct dmaengine_pcm {
+ struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1];
+ const struct snd_dmaengine_pcm_config *config;
+ struct snd_soc_platform platform;
+ unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
+{
+ return container_of(p, struct dmaengine_pcm, platform);
+}
+
int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
@@ -123,6 +135,7 @@ struct snd_dmaengine_pcm_config {
struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;
+ const struct snd_soc_platform_driver *driver;
const struct snd_pcm_hardware *pcm_hardware;
unsigned int prealloc_buffer_size;
};
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index aa924d9..d78a67e 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -186,8 +186,14 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
int ret;
+ if (config->driver->ops->trigger)
+ return config->driver->ops->trigger(substream, cmd);
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
ret = dmaengine_pcm_prepare_and_submit(substream);
@@ -224,6 +230,13 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
+
+ if (config->driver->ops->pointer)
+ return config->driver->ops->pointer(substream);
+
return bytes_to_frames(substream->runtime, prtd->pos);
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
@@ -238,11 +251,17 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
struct dma_tx_state state;
enum dma_status status;
unsigned int buf_size;
unsigned int pos = 0;
+ if (config->driver->ops->pointer)
+ return config->driver->ops->pointer(substream);
+
status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
buf_size = snd_pcm_lib_buffer_bytes(substream);
@@ -341,6 +360,12 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
+
+ if (config->driver->ops->close)
+ return config->driver->ops->close(substream);
kfree(prtd);
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index e29ec3c..6e66c53 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -24,18 +24,6 @@
#include <sound/dmaengine_pcm.h>
-struct dmaengine_pcm {
- struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1];
- const struct snd_dmaengine_pcm_config *config;
- struct snd_soc_platform platform;
- unsigned int flags;
-};
-
-static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
-{
- return container_of(p, struct dmaengine_pcm, platform);
-}
-
/**
* snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
* @substream: PCM substream
@@ -75,9 +63,13 @@ static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
struct dma_slave_config slave_config;
int ret;
+ if (config->driver->ops->hw_params)
+ return config->driver->ops->hw_params(substream, params);
+
if (pcm->config->prepare_slave_config) {
ret = pcm->config->prepare_slave_config(substream, params,
&slave_config);
@@ -96,9 +88,13 @@ static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = pcm->config;
struct dma_chan *chan = pcm->chan[substream->stream];
int ret;
+ if (config->driver->ops->open)
+ return config->driver->ops->open(substream);
+
ret = snd_soc_set_runtime_hwparams(substream,
pcm->config->pcm_hardware);
if (ret)
@@ -118,6 +114,13 @@ static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
static void dmaengine_pcm_free(struct snd_pcm *pcm)
{
+ struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+ struct dmaengine_pcm *dma_pcm = soc_platform_to_pcm(rtd->platform);
+ const struct snd_dmaengine_pcm_config *config = dma_pcm->config;
+
+ if (config->driver->pcm_free)
+ return config->driver->pcm_free(pcm);
+
snd_pcm_lib_preallocate_free_for_all(pcm);
}
@@ -145,6 +148,9 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
unsigned int i;
int ret;
+ if (config->driver->pcm_new)
+ return config->driver->pcm_new(rtd);
+
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
substream = rtd->pcm->streams[i].substream;
if (!substream)
--
1.8.4
More information about the Alsa-devel
mailing list