diff mbox

[18/23] ASoC: samsung: convert to dmaengine API

Message ID 1362505353-8873-19-git-send-email-arnd@arndb.de (mailing list archive)
State New, archived
Headers show

Commit Message

Arnd Bergmann March 5, 2013, 5:42 p.m. UTC
In order to build the exynos kernel with CONFIG_ARCH_MULTIPLATFORM,
we must convert all users of the Samsung private DMA interface to
the generic dmaengine API. This converts the sound/soc drivers,
breaking the older s3c platforms in the process, since they do not
support the dmaengine interface yet.

This patch must not get mainlined until mach-s3c* is also converted,
but can be used for testing in the meantime.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 sound/soc/samsung/ac97.c        |  15 ------
 sound/soc/samsung/dma.c         | 104 +++++++++++++++++++++-------------------
 sound/soc/samsung/dma.h         |   4 +-
 sound/soc/samsung/i2s.c         |   9 +---
 sound/soc/samsung/pcm.c         |  13 -----
 sound/soc/samsung/s3c2412-i2s.c |  10 ----
 sound/soc/samsung/s3c24xx-i2s.c |  10 ----
 sound/soc/samsung/spdif.c       |   6 ---
 8 files changed, 57 insertions(+), 114 deletions(-)

Comments

padma venkat March 6, 2013, 8:58 a.m. UTC | #1
Hi Arnd,

On Tue, Mar 5, 2013 at 11:12 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> In order to build the exynos kernel with CONFIG_ARCH_MULTIPLATFORM,
> we must convert all users of the Samsung private DMA interface to
> the generic dmaengine API. This converts the sound/soc drivers,
> breaking the older s3c platforms in the process, since they do not
> support the dmaengine interface yet.
>
> This patch must not get mainlined until mach-s3c* is also converted,
> but can be used for testing in the meantime.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  sound/soc/samsung/ac97.c        |  15 ------
>  sound/soc/samsung/dma.c         | 104 +++++++++++++++++++++-------------------
>  sound/soc/samsung/dma.h         |   4 +-
>  sound/soc/samsung/i2s.c         |   9 +---
>  sound/soc/samsung/pcm.c         |  13 -----
>  sound/soc/samsung/s3c2412-i2s.c |  10 ----
>  sound/soc/samsung/s3c24xx-i2s.c |  10 ----
>  sound/soc/samsung/spdif.c       |   6 ---
>  8 files changed, 57 insertions(+), 114 deletions(-)
>
> diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
> index c76abdf..214f454 100644
> --- a/sound/soc/samsung/ac97.c
> +++ b/sound/soc/samsung/ac97.c
> @@ -39,30 +39,15 @@ struct s3c_ac97_info {
>  };
>  static struct s3c_ac97_info s3c_ac97;
>
> -static struct s3c2410_dma_client s3c_dma_client_out = {
> -       .name = "AC97 PCMOut"
> -};
> -
> -static struct s3c2410_dma_client s3c_dma_client_in = {
> -       .name = "AC97 PCMIn"
> -};
> -
> -static struct s3c2410_dma_client s3c_dma_client_micin = {
> -       .name = "AC97 MicIn"
> -};
> -
>  static struct s3c_dma_params s3c_ac97_pcm_out = {
> -       .client         = &s3c_dma_client_out,
>         .dma_size       = 4,
>  };
>
>  static struct s3c_dma_params s3c_ac97_pcm_in = {
> -       .client         = &s3c_dma_client_in,
>         .dma_size       = 4,
>  };
>
>  static struct s3c_dma_params s3c_ac97_mic_in = {
> -       .client         = &s3c_dma_client_micin,
>         .dma_size       = 4,
>  };
>
> diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
> index 21b7926..67b8dcc 100644
> --- a/sound/soc/samsung/dma.c
> +++ b/sound/soc/samsung/dma.c
> @@ -16,14 +16,14 @@
>
>  #include <linux/slab.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/dmaengine.h>
>  #include <linux/module.h>
> +#include <linux/amba/pl330.h>
>
>  #include <sound/soc.h>
>  #include <sound/pcm_params.h>
>
>  #include <asm/dma.h>
> -#include <mach/hardware.h>
> -#include <mach/dma.h>
>
>  #include "dma.h"
>
> @@ -67,12 +67,16 @@ static void audio_buffdone(void *data);
>   * place a dma buffer onto the queue for the dma system
>   * to handle.
>   */
> +
>  static void dma_enqueue(struct snd_pcm_substream *substream)
>  {
>         struct runtime_data *prtd = substream->runtime->private_data;
>         dma_addr_t pos = prtd->dma_pos;
> +       unsigned long period = prtd->dma_period;
>         unsigned int limit;
> -       struct samsung_dma_prep dma_info;
> +       enum dma_transfer_direction direction;
> +       struct dma_chan *chan = prtd->params->ch;
> +       struct dma_async_tx_descriptor *desc;
>
>         pr_debug("Entered %s\n", __func__);
>
> @@ -81,29 +85,30 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
>         pr_debug("%s: loaded %d, limit %d\n",
>                                 __func__, prtd->dma_loaded, limit);
>
> -       dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
> -       dma_info.direction =
> -               (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
> -               ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
> -       dma_info.fp = audio_buffdone;
> -       dma_info.fp_param = substream;
> -       dma_info.period = prtd->dma_period;
> -       dma_info.len = prtd->dma_period*limit;
> +       direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
> +                    ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
>
>         while (prtd->dma_loaded < limit) {
>                 pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
>
> -               if ((pos + dma_info.period) > prtd->dma_end) {
> -                       dma_info.period  = prtd->dma_end - pos;
> +               if ((pos + period) > prtd->dma_end) {
> +                       period  = prtd->dma_end - pos;
>                         pr_debug("%s: corrected dma len %ld\n",
> -                                       __func__, dma_info.period);
> +                                       __func__, period);
>                 }
>
> -               dma_info.buf = pos;
> -               prtd->params->ops->prepare(prtd->params->ch, &dma_info);
> +               desc = dmaengine_prep_dma_cyclic(chan, pos,
> +                        prtd->dma_period*limit, period, direction,
> +                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> +
> +               if (desc) {
> +                       desc->callback = audio_buffdone;
> +                       desc->callback_param = substream;
> +                       dmaengine_submit(desc);
> +               }
>
>                 prtd->dma_loaded++;
> -               pos += prtd->dma_period;
> +               pos += period;
>                 if (pos >= prtd->dma_end)
>                         pos = prtd->dma_start;
>         }
> @@ -125,13 +130,6 @@ static void audio_buffdone(void *data)
>
>                 if (substream)
>                         snd_pcm_period_elapsed(substream);
> -
> -               spin_lock(&prtd->lock);
> -               if (!samsung_dma_has_circular()) {
> -                       prtd->dma_loaded--;
> -                       dma_enqueue(substream);
> -               }
> -               spin_unlock(&prtd->lock);
>         }
>  }
>
> @@ -144,8 +142,6 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
>         unsigned long totbytes = params_buffer_bytes(params);
>         struct s3c_dma_params *dma =
>                 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
> -       struct samsung_dma_req req;
> -       struct samsung_dma_config config;
>
>         pr_debug("Entered %s\n", __func__);
>
> @@ -157,26 +153,37 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
>         /* this may get called several times by oss emulation
>          * with different params -HW */
>         if (prtd->params == NULL) {
> +               struct dma_slave_config config;
> +               dma_cap_mask_t mask;
> +
>                 /* prepare DMA */
>                 prtd->params = dma;
>
> -               pr_debug("params %p, client %p, channel %d\n", prtd->params,
> -                       prtd->params->client, prtd->params->channel);
> -
> -               prtd->params->ops = samsung_dma_get_ops();
> -
> -               req.cap = (samsung_dma_has_circular() ?
> -                       DMA_CYCLIC : DMA_SLAVE);
> -               req.client = prtd->params->client;
> -               config.direction =
> -                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
> -                       ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
> -               config.width = prtd->params->dma_size;
> -               config.fifo = prtd->params->dma_addr;
> -               prtd->params->ch = prtd->params->ops->request(
> -                               prtd->params->channel, &req, rtd->cpu_dai->dev,
> -                               prtd->params->ch_name);
> -               prtd->params->ops->config(prtd->params->ch, &config);
> +               pr_debug("params %p, channel %d\n", prtd->params,
> +                        prtd->params->channel);
> +
> +               dma_cap_zero(mask);
> +               dma_cap_set(DMA_CYCLIC, mask);
> +
> +               prtd->params->ch = dma_request_slave_channel_compat(mask,
> +                       pl330_filter, (void *)prtd->params->channel,
> +                       rtd->cpu_dai->dev, prtd->params->ch_name);
> +
> +               memset(&config, 0, sizeof(struct dma_slave_config));
> +
> +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +                       config.direction = DMA_MEM_TO_DEV;
> +                       config.dst_addr = prtd->params->dma_size;
> +                       config.dst_addr_width = prtd->params->dma_addr;

dma_addr and dma_size got interchanged.

Except the above one I tested this patch on 5250. It's working fine.

> +                       config.dst_maxburst = 1;
> +                       dmaengine_slave_config(prtd->params->ch, &config);
> +               } else {
> +                       config.direction = DMA_DEV_TO_MEM;
> +                       config.src_addr = prtd->params->dma_addr;
> +                       config.src_addr_width = prtd->params->dma_size;
> +                       config.src_maxburst = 1;
> +                       dmaengine_slave_config(prtd->params->ch, &config);
> +               }
>         }
>
>         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> @@ -203,9 +210,8 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
>         snd_pcm_set_runtime_buffer(substream, NULL);
>
>         if (prtd->params) {
> -               prtd->params->ops->flush(prtd->params->ch);
> -               prtd->params->ops->release(prtd->params->ch,
> -                                       prtd->params->client);
> +               dmaengine_terminate_all(prtd->params->ch);
> +               dma_release_channel(prtd->params->ch);
>                 prtd->params = NULL;
>         }
>
> @@ -225,7 +231,7 @@ static int dma_prepare(struct snd_pcm_substream *substream)
>                 return 0;
>
>         /* flush the DMA channel */
> -       prtd->params->ops->flush(prtd->params->ch);
> +       dmaengine_terminate_all(prtd->params->ch);
>
>         prtd->dma_loaded = 0;
>         prtd->dma_pos = prtd->dma_start;
> @@ -248,12 +254,12 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 prtd->state |= ST_RUNNING;
> -               prtd->params->ops->trigger(prtd->params->ch);
> +               dma_async_issue_pending(prtd->params->ch);
>                 break;
>
>         case SNDRV_PCM_TRIGGER_STOP:
>                 prtd->state &= ~ST_RUNNING;
> -               prtd->params->ops->stop(prtd->params->ch);
> +               dmaengine_terminate_all(prtd->params->ch);
>                 break;
>
>         default:
> diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
> index 189a7a6..f7381be 100644
> --- a/sound/soc/samsung/dma.h
> +++ b/sound/soc/samsung/dma.h
> @@ -13,12 +13,10 @@
>  #define _S3C_AUDIO_H
>
>  struct s3c_dma_params {
> -       struct s3c2410_dma_client *client;      /* stream identifier */
>         int channel;                            /* Channel ID */
>         dma_addr_t dma_addr;
>         int dma_size;                   /* Size of the DMA transfer */
> -       unsigned ch;
> -       struct samsung_dma_ops *ops;
> +       struct dma_chan *ch;
>         char *ch_name;
>  };
>
> diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
> index d7231e3..2eed7a3 100644
> --- a/sound/soc/samsung/i2s.c
> +++ b/sound/soc/samsung/i2s.c
> @@ -18,12 +18,11 @@
>  #include <linux/of.h>
>  #include <linux/of_gpio.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/dmaengine.h>
>
>  #include <sound/soc.h>
>  #include <sound/pcm_params.h>
>
> -#include <mach/dma.h>
> -
>  #include <linux/platform_data/asoc-s3c.h>
>
>  #include "dma.h"
> @@ -1183,11 +1182,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
>
>         pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
>         pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
> -       pri_dai->dma_playback.client =
> -               (struct s3c2410_dma_client *)&pri_dai->dma_playback;
>         pri_dai->dma_playback.ch_name = "tx";
> -       pri_dai->dma_capture.client =
> -               (struct s3c2410_dma_client *)&pri_dai->dma_capture;
>         pri_dai->dma_capture.ch_name = "rx";
>         pri_dai->dma_playback.dma_size = 4;
>         pri_dai->dma_capture.dma_size = 4;
> @@ -1205,8 +1200,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
>                         goto err;
>                 }
>                 sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
> -               sec_dai->dma_playback.client =
> -                       (struct s3c2410_dma_client *)&sec_dai->dma_playback;
>                 sec_dai->dma_playback.ch_name = "tx-sec";
>
>                 if (!np) {
> diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
> index 13bab79..525b2d2 100644
> --- a/sound/soc/samsung/pcm.c
> +++ b/sound/soc/samsung/pcm.c
> @@ -20,7 +20,6 @@
>  #include <sound/pcm_params.h>
>
>  #include <linux/platform_data/asoc-s3c.h>
> -#include <mach/dma.h>
>
>  #include "dma.h"
>  #include "pcm.h"
> @@ -132,32 +131,20 @@ struct s3c_pcm_info {
>         struct s3c_dma_params   *dma_capture;
>  };
>
> -static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
> -       .name           = "PCM Stereo out"
> -};
> -
> -static struct s3c2410_dma_client s3c_pcm_dma_client_in = {
> -       .name           = "PCM Stereo in"
> -};
> -
>  static struct s3c_dma_params s3c_pcm_stereo_out[] = {
>         [0] = {
> -               .client         = &s3c_pcm_dma_client_out,
>                 .dma_size       = 4,
>         },
>         [1] = {
> -               .client         = &s3c_pcm_dma_client_out,
>                 .dma_size       = 4,
>         },
>  };
>
>  static struct s3c_dma_params s3c_pcm_stereo_in[] = {
>         [0] = {
> -               .client         = &s3c_pcm_dma_client_in,
>                 .dma_size       = 4,
>         },
>         [1] = {
> -               .client         = &s3c_pcm_dma_client_in,
>                 .dma_size       = 4,
>         },
>  };
> diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
> index 2213377..d43f00e 100644
> --- a/sound/soc/samsung/s3c2412-i2s.c
> +++ b/sound/soc/samsung/s3c2412-i2s.c
> @@ -31,23 +31,13 @@
>  #include "regs-i2s-v2.h"
>  #include "s3c2412-i2s.h"
>
> -static struct s3c2410_dma_client s3c2412_dma_client_out = {
> -       .name           = "I2S PCM Stereo out"
> -};
> -
> -static struct s3c2410_dma_client s3c2412_dma_client_in = {
> -       .name           = "I2S PCM Stereo in"
> -};
> -
>  static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
> -       .client         = &s3c2412_dma_client_out,
>         .channel        = DMACH_I2S_OUT,
>         .dma_addr       = S3C2410_PA_IIS + S3C2412_IISTXD,
>         .dma_size       = 4,
>  };
>
>  static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
> -       .client         = &s3c2412_dma_client_in,
>         .channel        = DMACH_I2S_IN,
>         .dma_addr       = S3C2410_PA_IIS + S3C2412_IISRXD,
>         .dma_size       = 4,
> diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
> index a7b17c1..d68c23d 100644
> --- a/sound/soc/samsung/s3c24xx-i2s.c
> +++ b/sound/soc/samsung/s3c24xx-i2s.c
> @@ -29,23 +29,13 @@
>  #include "dma.h"
>  #include "s3c24xx-i2s.h"
>
> -static struct s3c2410_dma_client s3c24xx_dma_client_out = {
> -       .name = "I2S PCM Stereo out"
> -};
> -
> -static struct s3c2410_dma_client s3c24xx_dma_client_in = {
> -       .name = "I2S PCM Stereo in"
> -};
> -
>  static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
> -       .client         = &s3c24xx_dma_client_out,
>         .channel        = DMACH_I2S_OUT,
>         .dma_addr       = S3C2410_PA_IIS + S3C2410_IISFIFO,
>         .dma_size       = 2,
>  };
>
>  static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
> -       .client         = &s3c24xx_dma_client_in,
>         .channel        = DMACH_I2S_IN,
>         .dma_addr       = S3C2410_PA_IIS + S3C2410_IISFIFO,
>         .dma_size       = 2,
> diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
> index 5008e5b..5c78c78 100644
> --- a/sound/soc/samsung/spdif.c
> +++ b/sound/soc/samsung/spdif.c
> @@ -18,7 +18,6 @@
>  #include <sound/pcm_params.h>
>
>  #include <linux/platform_data/asoc-s3c.h>
> -#include <mach/dma.h>
>
>  #include "dma.h"
>  #include "spdif.h"
> @@ -94,10 +93,6 @@ struct samsung_spdif_info {
>         struct s3c_dma_params   *dma_playback;
>  };
>
> -static struct s3c2410_dma_client spdif_dma_client_out = {
> -       .name           = "S/PDIF Stereo out",
> -};
> -
>  static struct s3c_dma_params spdif_stereo_out;
>  static struct samsung_spdif_info spdif_info;
>
> @@ -431,7 +426,6 @@ static int spdif_probe(struct platform_device *pdev)
>         }
>
>         spdif_stereo_out.dma_size = 2;
> -       spdif_stereo_out.client = &spdif_dma_client_out;
>         spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
>         spdif_stereo_out.channel = dma_res->start;
>
> --
> 1.8.1.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks
Padma
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann March 6, 2013, 12:01 p.m. UTC | #2
On Wednesday 06 March 2013, Padma Venkat wrote:

> > +               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> > +                       config.direction = DMA_MEM_TO_DEV;
> > +                       config.dst_addr = prtd->params->dma_size;
> > +                       config.dst_addr_width = prtd->params->dma_addr;
> 
> dma_addr and dma_size got interchanged.

Ok, fixed.

> Except the above one I tested this patch on 5250. It's working fine.

Thanks a lot for testing this!

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index c76abdf..214f454 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -39,30 +39,15 @@  struct s3c_ac97_info {
 };
 static struct s3c_ac97_info s3c_ac97;
 
-static struct s3c2410_dma_client s3c_dma_client_out = {
-	.name = "AC97 PCMOut"
-};
-
-static struct s3c2410_dma_client s3c_dma_client_in = {
-	.name = "AC97 PCMIn"
-};
-
-static struct s3c2410_dma_client s3c_dma_client_micin = {
-	.name = "AC97 MicIn"
-};
-
 static struct s3c_dma_params s3c_ac97_pcm_out = {
-	.client		= &s3c_dma_client_out,
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c_ac97_pcm_in = {
-	.client		= &s3c_dma_client_in,
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c_ac97_mic_in = {
-	.client		= &s3c_dma_client_micin,
 	.dma_size	= 4,
 };
 
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21b7926..67b8dcc 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -16,14 +16,14 @@ 
 
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/module.h>
+#include <linux/amba/pl330.h>
 
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
 #include <asm/dma.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
 
 #include "dma.h"
 
@@ -67,12 +67,16 @@  static void audio_buffdone(void *data);
  * place a dma buffer onto the queue for the dma system
  * to handle.
  */
+
 static void dma_enqueue(struct snd_pcm_substream *substream)
 {
 	struct runtime_data *prtd = substream->runtime->private_data;
 	dma_addr_t pos = prtd->dma_pos;
+	unsigned long period = prtd->dma_period;
 	unsigned int limit;
-	struct samsung_dma_prep dma_info;
+	enum dma_transfer_direction direction;
+	struct dma_chan *chan = prtd->params->ch;
+	struct dma_async_tx_descriptor *desc;
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -81,29 +85,30 @@  static void dma_enqueue(struct snd_pcm_substream *substream)
 	pr_debug("%s: loaded %d, limit %d\n",
 				__func__, prtd->dma_loaded, limit);
 
-	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
-	dma_info.direction =
-		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-		? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-	dma_info.fp = audio_buffdone;
-	dma_info.fp_param = substream;
-	dma_info.period = prtd->dma_period;
-	dma_info.len = prtd->dma_period*limit;
+	direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+		     ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
 
 	while (prtd->dma_loaded < limit) {
 		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-		if ((pos + dma_info.period) > prtd->dma_end) {
-			dma_info.period  = prtd->dma_end - pos;
+		if ((pos + period) > prtd->dma_end) {
+			period  = prtd->dma_end - pos;
 			pr_debug("%s: corrected dma len %ld\n",
-					__func__, dma_info.period);
+					__func__, period);
 		}
 
-		dma_info.buf = pos;
-		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
+		desc = dmaengine_prep_dma_cyclic(chan, pos,
+			 prtd->dma_period*limit, period, direction,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+		if (desc) {
+			desc->callback = audio_buffdone;
+			desc->callback_param = substream;
+			dmaengine_submit(desc);
+		}
 
 		prtd->dma_loaded++;
-		pos += prtd->dma_period;
+		pos += period;
 		if (pos >= prtd->dma_end)
 			pos = prtd->dma_start;
 	}
@@ -125,13 +130,6 @@  static void audio_buffdone(void *data)
 
 		if (substream)
 			snd_pcm_period_elapsed(substream);
-
-		spin_lock(&prtd->lock);
-		if (!samsung_dma_has_circular()) {
-			prtd->dma_loaded--;
-			dma_enqueue(substream);
-		}
-		spin_unlock(&prtd->lock);
 	}
 }
 
@@ -144,8 +142,6 @@  static int dma_hw_params(struct snd_pcm_substream *substream,
 	unsigned long totbytes = params_buffer_bytes(params);
 	struct s3c_dma_params *dma =
 		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	struct samsung_dma_req req;
-	struct samsung_dma_config config;
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -157,26 +153,37 @@  static int dma_hw_params(struct snd_pcm_substream *substream,
 	/* this may get called several times by oss emulation
 	 * with different params -HW */
 	if (prtd->params == NULL) {
+		struct dma_slave_config config;
+		dma_cap_mask_t mask;
+
 		/* prepare DMA */
 		prtd->params = dma;
 
-		pr_debug("params %p, client %p, channel %d\n", prtd->params,
-			prtd->params->client, prtd->params->channel);
-
-		prtd->params->ops = samsung_dma_get_ops();
-
-		req.cap = (samsung_dma_has_circular() ?
-			DMA_CYCLIC : DMA_SLAVE);
-		req.client = prtd->params->client;
-		config.direction =
-			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-			? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-		config.width = prtd->params->dma_size;
-		config.fifo = prtd->params->dma_addr;
-		prtd->params->ch = prtd->params->ops->request(
-				prtd->params->channel, &req, rtd->cpu_dai->dev,
-				prtd->params->ch_name);
-		prtd->params->ops->config(prtd->params->ch, &config);
+		pr_debug("params %p, channel %d\n", prtd->params,
+			 prtd->params->channel);
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_CYCLIC, mask);
+
+		prtd->params->ch = dma_request_slave_channel_compat(mask,
+			pl330_filter, (void *)prtd->params->channel,
+			rtd->cpu_dai->dev, prtd->params->ch_name);
+
+		memset(&config, 0, sizeof(struct dma_slave_config));
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			config.direction = DMA_MEM_TO_DEV;
+			config.dst_addr = prtd->params->dma_size;
+			config.dst_addr_width = prtd->params->dma_addr;
+			config.dst_maxburst = 1;
+			dmaengine_slave_config(prtd->params->ch, &config);
+		} else {
+			config.direction = DMA_DEV_TO_MEM;
+			config.src_addr = prtd->params->dma_addr;
+			config.src_addr_width = prtd->params->dma_size;
+			config.src_maxburst = 1;
+			dmaengine_slave_config(prtd->params->ch, &config);
+		}
 	}
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
@@ -203,9 +210,8 @@  static int dma_hw_free(struct snd_pcm_substream *substream)
 	snd_pcm_set_runtime_buffer(substream, NULL);
 
 	if (prtd->params) {
-		prtd->params->ops->flush(prtd->params->ch);
-		prtd->params->ops->release(prtd->params->ch,
-					prtd->params->client);
+		dmaengine_terminate_all(prtd->params->ch);
+		dma_release_channel(prtd->params->ch);
 		prtd->params = NULL;
 	}
 
@@ -225,7 +231,7 @@  static int dma_prepare(struct snd_pcm_substream *substream)
 		return 0;
 
 	/* flush the DMA channel */
-	prtd->params->ops->flush(prtd->params->ch);
+	dmaengine_terminate_all(prtd->params->ch);
 
 	prtd->dma_loaded = 0;
 	prtd->dma_pos = prtd->dma_start;
@@ -248,12 +254,12 @@  static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		prtd->state |= ST_RUNNING;
-		prtd->params->ops->trigger(prtd->params->ch);
+		dma_async_issue_pending(prtd->params->ch);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 		prtd->state &= ~ST_RUNNING;
-		prtd->params->ops->stop(prtd->params->ch);
+		dmaengine_terminate_all(prtd->params->ch);
 		break;
 
 	default:
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 189a7a6..f7381be 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -13,12 +13,10 @@ 
 #define _S3C_AUDIO_H
 
 struct s3c_dma_params {
-	struct s3c2410_dma_client *client;	/* stream identifier */
 	int channel;				/* Channel ID */
 	dma_addr_t dma_addr;
 	int dma_size;			/* Size of the DMA transfer */
-	unsigned ch;
-	struct samsung_dma_ops *ops;
+	struct dma_chan *ch;
 	char *ch_name;
 };
 
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d7231e3..2eed7a3 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -18,12 +18,11 @@ 
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
+#include <linux/dmaengine.h>
 
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
-#include <mach/dma.h>
-
 #include <linux/platform_data/asoc-s3c.h>
 
 #include "dma.h"
@@ -1183,11 +1182,7 @@  static int samsung_i2s_probe(struct platform_device *pdev)
 
 	pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
 	pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
-	pri_dai->dma_playback.client =
-		(struct s3c2410_dma_client *)&pri_dai->dma_playback;
 	pri_dai->dma_playback.ch_name = "tx";
-	pri_dai->dma_capture.client =
-		(struct s3c2410_dma_client *)&pri_dai->dma_capture;
 	pri_dai->dma_capture.ch_name = "rx";
 	pri_dai->dma_playback.dma_size = 4;
 	pri_dai->dma_capture.dma_size = 4;
@@ -1205,8 +1200,6 @@  static int samsung_i2s_probe(struct platform_device *pdev)
 			goto err;
 		}
 		sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
-		sec_dai->dma_playback.client =
-			(struct s3c2410_dma_client *)&sec_dai->dma_playback;
 		sec_dai->dma_playback.ch_name = "tx-sec";
 
 		if (!np) {
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 13bab79..525b2d2 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -20,7 +20,6 @@ 
 #include <sound/pcm_params.h>
 
 #include <linux/platform_data/asoc-s3c.h>
-#include <mach/dma.h>
 
 #include "dma.h"
 #include "pcm.h"
@@ -132,32 +131,20 @@  struct s3c_pcm_info {
 	struct s3c_dma_params	*dma_capture;
 };
 
-static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
-	.name		= "PCM Stereo out"
-};
-
-static struct s3c2410_dma_client s3c_pcm_dma_client_in = {
-	.name		= "PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c_pcm_stereo_out[] = {
 	[0] = {
-		.client		= &s3c_pcm_dma_client_out,
 		.dma_size	= 4,
 	},
 	[1] = {
-		.client		= &s3c_pcm_dma_client_out,
 		.dma_size	= 4,
 	},
 };
 
 static struct s3c_dma_params s3c_pcm_stereo_in[] = {
 	[0] = {
-		.client		= &s3c_pcm_dma_client_in,
 		.dma_size	= 4,
 	},
 	[1] = {
-		.client		= &s3c_pcm_dma_client_in,
 		.dma_size	= 4,
 	},
 };
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 2213377..d43f00e 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -31,23 +31,13 @@ 
 #include "regs-i2s-v2.h"
 #include "s3c2412-i2s.h"
 
-static struct s3c2410_dma_client s3c2412_dma_client_out = {
-	.name		= "I2S PCM Stereo out"
-};
-
-static struct s3c2410_dma_client s3c2412_dma_client_in = {
-	.name		= "I2S PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
-	.client		= &s3c2412_dma_client_out,
 	.channel	= DMACH_I2S_OUT,
 	.dma_addr	= S3C2410_PA_IIS + S3C2412_IISTXD,
 	.dma_size	= 4,
 };
 
 static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
-	.client		= &s3c2412_dma_client_in,
 	.channel	= DMACH_I2S_IN,
 	.dma_addr	= S3C2410_PA_IIS + S3C2412_IISRXD,
 	.dma_size	= 4,
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index a7b17c1..d68c23d 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -29,23 +29,13 @@ 
 #include "dma.h"
 #include "s3c24xx-i2s.h"
 
-static struct s3c2410_dma_client s3c24xx_dma_client_out = {
-	.name = "I2S PCM Stereo out"
-};
-
-static struct s3c2410_dma_client s3c24xx_dma_client_in = {
-	.name = "I2S PCM Stereo in"
-};
-
 static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
-	.client		= &s3c24xx_dma_client_out,
 	.channel	= DMACH_I2S_OUT,
 	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	.dma_size	= 2,
 };
 
 static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
-	.client		= &s3c24xx_dma_client_in,
 	.channel	= DMACH_I2S_IN,
 	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	.dma_size	= 2,
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 5008e5b..5c78c78 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -18,7 +18,6 @@ 
 #include <sound/pcm_params.h>
 
 #include <linux/platform_data/asoc-s3c.h>
-#include <mach/dma.h>
 
 #include "dma.h"
 #include "spdif.h"
@@ -94,10 +93,6 @@  struct samsung_spdif_info {
 	struct s3c_dma_params	*dma_playback;
 };
 
-static struct s3c2410_dma_client spdif_dma_client_out = {
-	.name		= "S/PDIF Stereo out",
-};
-
 static struct s3c_dma_params spdif_stereo_out;
 static struct samsung_spdif_info spdif_info;
 
@@ -431,7 +426,6 @@  static int spdif_probe(struct platform_device *pdev)
 	}
 
 	spdif_stereo_out.dma_size = 2;
-	spdif_stereo_out.client = &spdif_dma_client_out;
 	spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
 	spdif_stereo_out.channel = dma_res->start;