[alsa-devel] [PATCH v3 0/4] ASoc: samsung: update s3c24xx to dmaengine and common clk framework
This series updates s3c24{xx,12}-i2s driver to use newer DMA and CLK APIs.
v2: use hardcoded dma channel number v3: rebase onto v3.16-rc1, add common clk framework-related changes
Vasily Khoruzhick (4): ASoC: samsung: s3c24{xx,12}-i2s: port to use generic dmaengine API ASoC: samsung: drop support for legacy S3C24XX DMA API ASoC: samsung: s3c2412-i2s: Move to clk_prepare_enable/clk_disable_unprepare ASoC: samsung: s3c24xx-i2s: Move to clk_prepare_enable/clk_disable_unprepare
sound/soc/samsung/Kconfig | 12 +- sound/soc/samsung/Makefile | 2 - sound/soc/samsung/dma.c | 454 ---------------------------------------- sound/soc/samsung/dmaengine.c | 3 + sound/soc/samsung/s3c-i2s-v2.c | 17 +- sound/soc/samsung/s3c2412-i2s.c | 51 +++-- sound/soc/samsung/s3c24xx-i2s.c | 62 +++--- 7 files changed, 61 insertions(+), 540 deletions(-) delete mode 100644 sound/soc/samsung/dma.c
Use dmaengine instead of legacy s3c24xx DMA API for s3c24xx and s3c2412
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com --- sound/soc/samsung/Kconfig | 9 +++---- sound/soc/samsung/dmaengine.c | 3 +++ sound/soc/samsung/s3c-i2s-v2.c | 17 +------------ sound/soc/samsung/s3c2412-i2s.c | 47 +++++++++++++++++----------------- sound/soc/samsung/s3c24xx-i2s.c | 56 +++++++++++++++++++---------------------- 5 files changed, 56 insertions(+), 76 deletions(-)
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 753b8c9..98767d3 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,11 +1,10 @@ config SND_SOC_SAMSUNG tristate "ASoC support for Samsung" depends on PLAT_SAMSUNG - select S3C2410_DMA if ARCH_S3C24XX + select S3C24XX_DMAC if ARCH_S3C24XX select S3C64XX_PL080 if ARCH_S3C64XX - select SND_S3C_DMA if !ARCH_S3C24XX - select SND_S3C_DMA_LEGACY if ARCH_S3C24XX - select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX + select SND_S3C_DMA + select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for codecs attached to the Samsung SoCs' Audio interfaces. You will also need to @@ -19,7 +18,6 @@ config SND_S3C_DMA_LEGACY
config SND_S3C24XX_I2S tristate - select S3C24XX_DMA
config SND_S3C_I2SV2_SOC tristate @@ -27,7 +25,6 @@ config SND_S3C_I2SV2_SOC config SND_S3C2412_SOC_I2S tristate select SND_S3C_I2SV2_SOC - select S3C2410_DMA
config SND_SAMSUNG_PCM tristate diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index a0e4e79..506f5bf 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c @@ -17,6 +17,7 @@
#include <linux/module.h> #include <linux/amba/pl08x.h> +#include <linux/platform_data/dma-s3c24xx.h>
#include <sound/core.h> #include <sound/pcm.h> @@ -29,6 +30,8 @@
#ifdef CONFIG_ARCH_S3C64XX #define filter_fn pl08x_filter_id +#elif defined(CONFIG_ARCH_S3C24XX) +#define filter_fn s3c24xx_dma_filter #else #define filter_fn NULL #endif diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 0ff4bbe..de6c321 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -392,8 +392,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; int ret = 0; - struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
pr_debug("Entered %s\n", __func__);
@@ -424,13 +422,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
local_irq_restore(irqs);
- /* - * Load the next buffer to DMA to meet the reqirement - * of the auto reload mechanism of S3C24XX. - * This call won't bother S3C64XX. - */ - s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); - break;
case SNDRV_PCM_TRIGGER_STOP: @@ -644,12 +635,6 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, /* record our i2s structure for later use in the callbacks */ snd_soc_dai_set_drvdata(dai, i2s);
- i2s->regs = ioremap(base, 0x100); - if (i2s->regs == NULL) { - dev_err(dev, "cannot ioremap registers\n"); - return -ENXIO; - } - i2s->iis_pclk = clk_get(dev, "iis"); if (IS_ERR(i2s->iis_pclk)) { dev_err(dev, "failed to get iis_clock\n"); @@ -729,7 +714,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, struct snd_soc_component_driver *cmp_drv, struct snd_soc_dai_driver *dai_drv) { - struct snd_soc_dai_ops *ops = dai_drv->ops; + struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops;
ops->trigger = s3c2412_i2s_trigger; if (!ops->hw_params) diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 08c059b..d9d27cc 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -33,25 +33,19 @@ #include "regs-i2s-v2.h" #include "s3c2412-i2s.h"
-static struct s3c_dma_client s3c2412_dma_client_out = { - .name = "I2S PCM Stereo out" -}; - -static struct s3c_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, + .client = + (struct s3c_dma_client *)&s3c2412_i2s_pcm_stereo_out, .channel = DMACH_I2S_OUT, - .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, + .ch_name = "tx", .dma_size = 4, };
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { - .client = &s3c2412_dma_client_in, + .client = + (struct s3c_dma_client *)&s3c2412_i2s_pcm_stereo_in, .channel = DMACH_I2S_IN, - .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, + .ch_name = "rx", .dma_size = 4, };
@@ -63,6 +57,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
pr_debug("Entered %s\n", __func__);
+ samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, + &s3c2412_i2s_pcm_stereo_in); + ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); if (ret) return ret; @@ -70,10 +67,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
- s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); + s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk"); if (IS_ERR(s3c2412_i2s.iis_cclk)) { pr_err("failed to get i2sclk clock\n"); - iounmap(s3c2412_i2s.regs); return PTR_ERR(s3c2412_i2s.iis_cclk); }
@@ -94,8 +90,6 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) static int s3c2412_i2s_remove(struct snd_soc_dai *dai) { clk_disable(s3c2412_i2s.iis_cclk); - clk_put(s3c2412_i2s.iis_cclk); - iounmap(s3c2412_i2s.regs);
return 0; } @@ -105,18 +99,10 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); - struct s3c_dma_params *dma_data; u32 iismod;
pr_debug("Entered %s\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_data = i2s->dma_playback; - else - dma_data = i2s->dma_capture; - - snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); - iismod = readl(i2s->regs + S3C2412_IISMOD); pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
@@ -169,6 +155,19 @@ static const struct snd_soc_component_driver s3c2412_i2s_component = { static int s3c2412_iis_dev_probe(struct platform_device *pdev) { int ret = 0; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Can't get IO resource.\n"); + return -ENOENT; + } + s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res); + if (s3c2412_i2s.regs == NULL) + return -ENXIO; + + s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD; + s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD;
ret = s3c_i2sv2_register_component(&pdev->dev, -1, &s3c2412_i2s_component, diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 9aba9fb..6f3ee87 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -31,25 +31,19 @@ #include "dma.h" #include "s3c24xx-i2s.h"
-static struct s3c_dma_client s3c24xx_dma_client_out = { - .name = "I2S PCM Stereo out" -}; - -static struct s3c_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, + .client = + (struct s3c_dma_client *)&s3c24xx_i2s_pcm_stereo_out, .channel = DMACH_I2S_OUT, - .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, + .ch_name = "tx", .dma_size = 2, };
static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { - .client = &s3c24xx_dma_client_in, + .client = + (struct s3c_dma_client *)&s3c24xx_i2s_pcm_stereo_in, .channel = DMACH_I2S_IN, - .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, + .ch_name = "rx", .dma_size = 2, };
@@ -231,18 +225,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s3c_dma_params *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; u32 iismod;
pr_debug("Entered %s\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_data = &s3c24xx_i2s_pcm_stereo_out; - else - dma_data = &s3c24xx_i2s_pcm_stereo_in; - - snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); + dma_data = snd_soc_dai_get_dma_data(dai, substream);
/* Working copies of register */ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -251,11 +239,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, switch (params_width(params)) { case 8: iismod &= ~S3C2410_IISMOD_16BIT; - dma_data->dma_size = 1; + dma_data->addr_width = 1; break; case 16: iismod |= S3C2410_IISMOD_16BIT; - dma_data->dma_size = 2; + dma_data->addr_width = 2; break; default: return -EINVAL; @@ -270,8 +258,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { int ret = 0; - struct s3c_dma_params *dma_data = - snd_soc_dai_get_dma_data(dai, substream);
pr_debug("Entered %s\n", __func__);
@@ -290,7 +276,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, else s3c24xx_snd_txctrl(1);
- s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -380,14 +365,12 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) { pr_debug("Entered %s\n", __func__);
- s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); - if (s3c24xx_i2s.regs == NULL) - return -ENXIO; + samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, + &s3c24xx_i2s_pcm_stereo_in);
- s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); + s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis"); if (IS_ERR(s3c24xx_i2s.iis_clk)) { pr_err("failed to get iis_clock\n"); - iounmap(s3c24xx_i2s.regs); return PTR_ERR(s3c24xx_i2s.iis_clk); } clk_enable(s3c24xx_i2s.iis_clk); @@ -474,6 +457,19 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { int ret = 0; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Can't get IO resource.\n"); + return -ENOENT; + } + s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); + if (s3c24xx_i2s.regs == NULL) + return -ENXIO; + + s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; + s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO;
ret = devm_snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com --- sound/soc/samsung/Kconfig | 3 - sound/soc/samsung/Makefile | 2 - sound/soc/samsung/dma.c | 454 --------------------------------------------- 3 files changed, 459 deletions(-)
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 98767d3..17547a4 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -13,9 +13,6 @@ config SND_SOC_SAMSUNG config SND_S3C_DMA tristate
-config SND_S3C_DMA_LEGACY - tristate - config SND_S3C24XX_I2S tristate
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 6d0212b..6469199 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -1,6 +1,5 @@ # S3c24XX Platform Support snd-soc-s3c-dma-objs := dmaengine.o -snd-soc-s3c-dma-legacy-objs := dma.o snd-soc-idma-objs := idma.o snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o @@ -11,7 +10,6 @@ snd-soc-pcm-objs := pcm.o snd-soc-i2s-objs := i2s.o
obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o -obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c deleted file mode 100644 index d9dc7bc..0000000 --- a/sound/soc/samsung/dma.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * dma.c -- ALSA Soc Audio Layer - * - * (c) 2006 Wolfson Microelectronics PLC. - * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com - * - * Copyright 2004-2005 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks ben@simtec.co.uk - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include <linux/slab.h> -#include <linux/dma-mapping.h> -#include <linux/module.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" - -#define ST_RUNNING (1<<0) -#define ST_OPENED (1<<1) - -static const struct snd_pcm_hardware dma_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, - .buffer_bytes_max = 128*1024, - .period_bytes_min = PAGE_SIZE, - .period_bytes_max = PAGE_SIZE*2, - .periods_min = 2, - .periods_max = 128, - .fifo_size = 32, -}; - -struct runtime_data { - spinlock_t lock; - int state; - unsigned int dma_loaded; - unsigned int dma_period; - dma_addr_t dma_start; - dma_addr_t dma_pos; - dma_addr_t dma_end; - struct s3c_dma_params *params; -}; - -static void audio_buffdone(void *data); - -/* dma_enqueue - * - * 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 int limit; - struct samsung_dma_prep dma_info; - - pr_debug("Entered %s\n", __func__); - - limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; - - 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; - - if (dma_info.cap == DMA_CYCLIC) { - dma_info.buf = pos; - prtd->params->ops->prepare(prtd->params->ch, &dma_info); - prtd->dma_loaded += limit; - return; - } - - 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; - pr_debug("%s: corrected dma len %ld\n", - __func__, dma_info.period); - } - - dma_info.buf = pos; - prtd->params->ops->prepare(prtd->params->ch, &dma_info); - - prtd->dma_loaded++; - pos += prtd->dma_period; - if (pos >= prtd->dma_end) - pos = prtd->dma_start; - } - - prtd->dma_pos = pos; -} - -static void audio_buffdone(void *data) -{ - struct snd_pcm_substream *substream = data; - struct runtime_data *prtd = substream->runtime->private_data; - - pr_debug("Entered %s\n", __func__); - - if (prtd->state & ST_RUNNING) { - prtd->dma_pos += prtd->dma_period; - if (prtd->dma_pos >= prtd->dma_end) - prtd->dma_pos = prtd->dma_start; - - 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); - } -} - -static int dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - 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__); - - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!dma) - return 0; - - /* this may get called several times by oss emulation - * with different params -HW */ - if (prtd->params == NULL) { - /* 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); - if (!prtd->params->ch) { - pr_err("Failed to allocate DMA channel\n"); - return -ENXIO; - } - prtd->params->ops->config(prtd->params->ch, &config); - } - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - runtime->dma_bytes = totbytes; - - spin_lock_irq(&prtd->lock); - prtd->dma_loaded = 0; - prtd->dma_period = params_period_bytes(params); - prtd->dma_start = runtime->dma_addr; - prtd->dma_pos = prtd->dma_start; - prtd->dma_end = prtd->dma_start + totbytes; - spin_unlock_irq(&prtd->lock); - - return 0; -} - -static int dma_hw_free(struct snd_pcm_substream *substream) -{ - struct runtime_data *prtd = substream->runtime->private_data; - - pr_debug("Entered %s\n", __func__); - - 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); - prtd->params = NULL; - } - - return 0; -} - -static int dma_prepare(struct snd_pcm_substream *substream) -{ - struct runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - pr_debug("Entered %s\n", __func__); - - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!prtd->params) - return 0; - - /* flush the DMA channel */ - prtd->params->ops->flush(prtd->params->ch); - - prtd->dma_loaded = 0; - prtd->dma_pos = prtd->dma_start; - - /* enqueue dma buffers */ - dma_enqueue(substream); - - return ret; -} - -static int dma_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - pr_debug("Entered %s\n", __func__); - - spin_lock(&prtd->lock); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - prtd->state |= ST_RUNNING; - prtd->params->ops->trigger(prtd->params->ch); - break; - - case SNDRV_PCM_TRIGGER_STOP: - prtd->state &= ~ST_RUNNING; - prtd->params->ops->stop(prtd->params->ch); - break; - - default: - ret = -EINVAL; - break; - } - - spin_unlock(&prtd->lock); - - return ret; -} - -static snd_pcm_uframes_t -dma_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct runtime_data *prtd = runtime->private_data; - unsigned long res; - - pr_debug("Entered %s\n", __func__); - - res = prtd->dma_pos - prtd->dma_start; - - pr_debug("Pointer offset: %lu\n", res); - - /* we seem to be getting the odd error from the pcm library due - * to out-of-bounds pointers. this is maybe due to the dma engine - * not having loaded the new values for the channel before being - * called... (todo - fix ) - */ - - if (res >= snd_pcm_lib_buffer_bytes(substream)) { - if (res == snd_pcm_lib_buffer_bytes(substream)) - res = 0; - } - - return bytes_to_frames(substream->runtime, res); -} - -static int dma_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct runtime_data *prtd; - - pr_debug("Entered %s\n", __func__); - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - snd_soc_set_runtime_hwparams(substream, &dma_hardware); - - prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); - if (prtd == NULL) - return -ENOMEM; - - spin_lock_init(&prtd->lock); - - runtime->private_data = prtd; - return 0; -} - -static int dma_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct runtime_data *prtd = runtime->private_data; - - pr_debug("Entered %s\n", __func__); - - if (!prtd) - pr_debug("dma_close called with prtd == NULL\n"); - - kfree(prtd); - - return 0; -} - -static int dma_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - pr_debug("Entered %s\n", __func__); - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops dma_ops = { - .open = dma_open, - .close = dma_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = dma_hw_params, - .hw_free = dma_hw_free, - .prepare = dma_prepare, - .trigger = dma_trigger, - .pointer = dma_pointer, - .mmap = dma_mmap, -}; - -static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = dma_hardware.buffer_bytes_max; - - pr_debug("Entered %s\n", __func__); - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - return 0; -} - -static void dma_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - pr_debug("Entered %s\n", __func__); - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static int dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; - - pr_debug("Entered %s\n", __func__); - - ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } -out: - return ret; -} - -static struct snd_soc_platform_driver samsung_asoc_platform = { - .ops = &dma_ops, - .pcm_new = dma_new, - .pcm_free = dma_free_dma_buffers, -}; - -void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, - struct s3c_dma_params *playback, - struct s3c_dma_params *capture) -{ - snd_soc_dai_init_dma_data(dai, playback, capture); -} -EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); - -int samsung_asoc_dma_platform_register(struct device *dev) -{ - return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); -} -EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); - -MODULE_AUTHOR("Ben Dooks, ben@simtec.co.uk"); -MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); -MODULE_LICENSE("GPL");
Use clk_prepare_enable/clk_disable_unprepare to make the driver work properly with common clock framework.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com --- sound/soc/samsung/s3c2412-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index d9d27cc..d6bc6dc 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -76,7 +76,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) /* Set MPLL as the source for IIS CLK */
clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); - clk_enable(s3c2412_i2s.iis_cclk); + clk_prepare_enable(s3c2412_i2s.iis_cclk);
s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
@@ -89,7 +89,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
static int s3c2412_i2s_remove(struct snd_soc_dai *dai) { - clk_disable(s3c2412_i2s.iis_cclk); + clk_disable_unprepare(s3c2412_i2s.iis_cclk);
return 0; }
Use clk_prepare_enable/clk_disable_unprepare to make the driver work properly with common clock framework.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com --- sound/soc/samsung/s3c24xx-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 6f3ee87..e8b9852 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -373,7 +373,7 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) pr_err("failed to get iis_clock\n"); return PTR_ERR(s3c24xx_i2s.iis_clk); } - clk_enable(s3c24xx_i2s.iis_clk); + clk_prepare_enable(s3c24xx_i2s.iis_clk);
/* Configure the I2S pins (GPE0...GPE4) in correct mode */ s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), @@ -397,7 +397,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR);
- clk_disable(s3c24xx_i2s.iis_clk); + clk_disable_unprepare(s3c24xx_i2s.iis_clk);
return 0; } @@ -405,7 +405,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) { pr_debug("Entered %s\n", __func__); - clk_enable(s3c24xx_i2s.iis_clk); + clk_prepare_enable(s3c24xx_i2s.iis_clk);
writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
On Mon, Jun 23, 2014 at 11:24:03PM +0300, Vasily Khoruzhick wrote:
This series updates s3c24{xx,12}-i2s driver to use newer DMA and CLK APIs.
Applied all, thanks.
participants (2)
-
Mark Brown
-
Vasily Khoruzhick