Skip to content

Commit

Permalink
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Brown committed Apr 23, 2013
2 parents 5561f17 + 6f1fd93 commit 9eb8ae7
Show file tree
Hide file tree
Showing 25 changed files with 605 additions and 580 deletions.
70 changes: 69 additions & 1 deletion include/sound/dmaengine_pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define __SOUND_DMAENGINE_PCM_H__

#include <sound/pcm.h>
#include <sound/soc.h>
#include <linux/dmaengine.h>

/**
Expand All @@ -39,9 +40,15 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);

int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data);
struct dma_chan *chan);
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);

int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data);
int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);

struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
void *filter_data);
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);

/**
Expand All @@ -68,4 +75,65 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
const struct snd_dmaengine_dai_dma_data *dma_data,
struct dma_slave_config *config);


/*
* Try to request the DMA channel using compat_request_channel or
* compat_filter_fn if it couldn't be requested through devicetree.
*/
#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0)
/*
* Don't try to request the DMA channels through devicetree. This flag only
* makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well.
*/
#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1)
/*
* The platforms dmaengine driver does not support reporting the amount of
* bytes that are still left to transfer.
*/
#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2)
/*
* The PCM is half duplex and the DMA channel is shared between capture and
* playback.
*/
#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)

/**
* struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM
* @prepare_slave_config: Callback used to fill in the DMA slave_config for a
* PCM substream. Will be called from the PCM drivers hwparams callback.
* @compat_request_channel: Callback to request a DMA channel for platforms
* which do not use devicetree.
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
* Note: If both compat_request_channel and compat_filter_fn are set
* compat_request_channel will be used to request the channel and
* compat_filter_fn will be ignored. Otherwise the channel will be requested
* using dma_request_channel with compat_filter_fn as the filter function.
*/
struct snd_dmaengine_pcm_config {
int (*prepare_slave_config)(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);
struct dma_chan *(*compat_request_channel)(
struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;

const struct snd_pcm_hardware *pcm_hardware;
unsigned int prealloc_buffer_size;
};

int snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config,
unsigned int flags);
void snd_dmaengine_pcm_unregister(struct device *dev);

int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);

#endif
4 changes: 4 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ int snd_soc_poweroff(struct device *dev);
int snd_soc_register_platform(struct device *dev,
const struct snd_soc_platform_driver *platform_drv);
void snd_soc_unregister_platform(struct device *dev);
int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
const struct snd_soc_platform_driver *platform_drv);
void snd_soc_remove_platform(struct snd_soc_platform *platform);
struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev);
int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai);
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ config SND_SOC_AC97_BUS
config SND_SOC_DMAENGINE_PCM
bool

config SND_SOC_GENERIC_DMAENGINE_PCM
bool
select SND_SOC_DMAENGINE_PCM

# All the supported SoCs
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-dmaengine-pcm.o
endif

ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
endif

obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += generic/
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/atmel/atmel-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
if (ssc->pdev)
sdata = ssc->pdev->dev.platform_data;

ret = snd_dmaengine_pcm_open(substream, filter, sdata);
ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
if (ret) {
pr_err("atmel-pcm: dmaengine pcm open failed\n");
return -EINVAL;
Expand All @@ -171,7 +171,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,

return 0;
err:
snd_dmaengine_pcm_close(substream);
snd_dmaengine_pcm_close_release_chan(substream);
return ret;
}

Expand All @@ -197,7 +197,7 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)

static struct snd_pcm_ops atmel_pcm_ops = {
.open = atmel_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = atmel_pcm_hw_params,
.prepare = atmel_pcm_dma_prepare,
Expand Down
5 changes: 3 additions & 2 deletions sound/soc/cirrus/ep93xx-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)

snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);

return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
return snd_dmaengine_pcm_open_request_chan(substream,
ep93xx_pcm_dma_filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
}

Expand Down Expand Up @@ -100,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops ep93xx_pcm_ops = {
.open = ep93xx_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free,
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/fsl/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ config SND_SOC_IMX_PCM_FIQ

config SND_SOC_IMX_PCM_DMA
bool
select SND_SOC_DMAENGINE_PCM
select SND_SOC_GENERIC_DMAENGINE_PCM
select SND_SOC_IMX_PCM

config SND_SOC_IMX_AUDMUX
Expand Down
19 changes: 13 additions & 6 deletions sound/soc/fsl/fsl_ssi.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,12 +425,6 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
ssi_private->second_stream = substream;
}

if (ssi_private->ssi_on_imx)
snd_soc_dai_set_dma_data(dai, substream,
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
&ssi_private->dma_params_tx :
&ssi_private->dma_params_rx);

return 0;
}

Expand Down Expand Up @@ -552,6 +546,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
}
}

static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
{
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);

if (ssi_private->ssi_on_imx) {
dai->playback_dma_data = &ssi_private->dma_params_tx;
dai->capture_dma_data = &ssi_private->dma_params_rx;
}

return 0;
}

static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
.startup = fsl_ssi_startup,
.hw_params = fsl_ssi_hw_params,
Expand All @@ -561,6 +567,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {

/* Template for the CPU dai driver structure */
static struct snd_soc_dai_driver fsl_ssi_dai_template = {
.probe = fsl_ssi_dai_probe,
.playback = {
/* The SSI does not support monaural audio. */
.channels_min = 2,
Expand Down
76 changes: 15 additions & 61 deletions sound/soc/fsl/imx-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,12 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/types.h>

#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>

Expand All @@ -44,32 +34,7 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
}

static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct dma_slave_config slave_config;
int ret;

ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
if (ret)
return ret;

snd_dmaengine_pcm_set_config_from_dai_data(substream,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
&slave_config);

ret = dmaengine_slave_config(chan, &slave_config);
if (ret)
return ret;

snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

return 0;
}

static struct snd_pcm_hardware snd_imx_hardware = {
static const struct snd_pcm_hardware imx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
Expand All @@ -88,33 +53,22 @@ static struct snd_pcm_hardware snd_imx_hardware = {
.fifo_size = 0,
};

static int snd_imx_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;

snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);

return snd_dmaengine_pcm_open(substream, filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
}

static struct snd_pcm_ops imx_pcm_ops = {
.open = snd_imx_open,
.close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger,
.pointer = snd_dmaengine_pcm_pointer_no_residue,
.mmap = snd_imx_pcm_mmap,
};

static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
.ops = &imx_pcm_ops,
.pcm_new = imx_pcm_new,
.pcm_free = imx_pcm_free,
static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
.pcm_hardware = &imx_pcm_hardware,
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
.compat_filter_fn = filter,
.prealloc_buffer_size = IMX_SSI_DMABUF_SIZE,
};

int imx_pcm_dma_init(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
SND_DMAENGINE_PCM_FLAG_NO_DT |
SND_DMAENGINE_PCM_FLAG_COMPAT);
}

void imx_pcm_dma_exit(struct platform_device *pdev)
{
snd_dmaengine_pcm_unregister(&pdev->dev);
}
6 changes: 5 additions & 1 deletion sound/soc/fsl/imx-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ static int imx_pcm_probe(struct platform_device *pdev)

static int imx_pcm_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
snd_soc_unregister_platform(&pdev->dev);
else
imx_pcm_dma_exit(pdev);

return 0;
}

Expand Down
5 changes: 5 additions & 0 deletions sound/soc/fsl/imx-pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ void imx_pcm_free(struct snd_pcm *pcm);

#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
int imx_pcm_dma_init(struct platform_device *pdev);
void imx_pcm_dma_exit(struct platform_device *pdev);
#else
static inline int imx_pcm_dma_init(struct platform_device *pdev)
{
return -ENODEV;
}

static inline void imx_pcm_dma_exit(struct platform_device *pdev)
{
}
#endif

#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
Expand Down
22 changes: 4 additions & 18 deletions sound/soc/fsl/imx-ssi.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,23 +232,6 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}

static int imx_ssi_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_dmaengine_dai_dma_data *dma_data;

/* Tx/Rx config */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_data = &ssi->dma_params_tx;
else
dma_data = &ssi->dma_params_rx;

snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);

return 0;
}

/*
* Should only be called when port is inactive (i.e. SSIEN = 0),
* although can be called multiple times by upper layers.
Expand Down Expand Up @@ -353,7 +336,6 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}

static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
.startup = imx_ssi_startup,
.hw_params = imx_ssi_hw_params,
.set_fmt = imx_ssi_set_dai_fmt,
.set_clkdiv = imx_ssi_set_dai_clkdiv,
Expand All @@ -373,6 +355,10 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst);
writel(val, ssi->base + SSI_SFCSR);

/* Tx/Rx config */
dai->playback_dma_data = &ssi->dma_params_tx;
dai->capture_dma_data = &ssi->dma_params_rx;

return 0;
}

Expand Down
Loading

0 comments on commit 9eb8ae7

Please sign in to comment.