diff options
author | Mark Brown <broonie@linaro.org> | 2013-08-15 11:37:38 +0100 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-15 11:37:38 +0100 |
commit | 743c5bb898be45009770c144e5e14e4f448e56b9 (patch) | |
tree | 40fff57c975f89da4a90922c165595840e99093a /sound/soc | |
parent | 8fe120b5a665fc869c23f86e4964b801f6e53486 (diff) | |
parent | b7ae6f31d8243ec684af16bc5c763eccdfabaec0 (diff) | |
download | op-kernel-dev-743c5bb898be45009770c144e5e14e4f448e56b9.zip op-kernel-dev-743c5bb898be45009770c144e5e14e4f448e56b9.tar.gz |
Merge branch 'topic/dma' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-omap
Conflicts:
sound/soc/omap/Kconfig
Diffstat (limited to 'sound/soc')
27 files changed, 84 insertions, 462 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 45eeaa9..5138b84 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -26,12 +26,9 @@ if SND_SOC config SND_SOC_AC97_BUS bool -config SND_SOC_DMAENGINE_PCM - bool - config SND_SOC_GENERIC_DMAENGINE_PCM bool - select SND_SOC_DMAENGINE_PCM + select SND_DMAENGINE_PCM # All the supported SoCs source "sound/soc/atmel/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index bc02614..61a64d2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,10 +1,6 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o -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 diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 1d38fd0..d128265 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c @@ -81,7 +81,9 @@ static void atmel_pcm_dma_irq(u32 ssc_sr, /* stop RX and capture: will be enabled again at restart */ ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable); + snd_pcm_stream_lock(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(substream); /* now drain RHR and read status to remove xrun condition */ ssc_readx(prtd->ssc->regs, SSC_RHR); diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index d6f7694..c8a2de1 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c @@ -341,7 +341,7 @@ static struct platform_driver au1xac97c_driver = { .remove = au1xac97c_drvremove, }; -module_platform_driver(&au1xac97c_driver); +module_platform_driver(au1xac97c_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index efb1dae..e82eb37 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -294,11 +294,12 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) /* Request PB3 as reset pin */ ret = devm_gpio_request_one(&pdev->dev, CONFIG_SND_BF5XX_RESET_GPIO_NUM, - GPIOF_OUT_INIT_HIGH, "SND_AD198x RESET") { + GPIOF_OUT_INIT_HIGH, "SND_AD198x RESET"); + if (ret) { dev_err(&pdev->dev, "Failed to request GPIO_%d for reset: %d\n", CONFIG_SND_BF5XX_RESET_GPIO_NUM, ret); - goto gpio_err; + return ret; } #endif diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index 15c635e..0c3e22d 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h @@ -9,7 +9,6 @@ #ifndef _BF5XX_AC97_H #define _BF5XX_AC97_H -extern struct snd_ac97_bus_ops bf5xx_ac97_ops; extern struct snd_ac97 *ac97; /* Frame format in memory, only support stereo currently */ struct ac97_frame { diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index ac73c60..04491f0 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -102,13 +102,13 @@ static struct ep93xx_ac97_info *ep93xx_ac97_info; static struct ep93xx_dma_data ep93xx_ac97_pcm_out = { .name = "ac97-pcm-out", - .dma_port = EP93XX_DMA_AAC1, + .port = EP93XX_DMA_AAC1, .direction = DMA_MEM_TO_DEV, }; static struct ep93xx_dma_data ep93xx_ac97_pcm_in = { .name = "ac97-pcm-in", - .dma_port = EP93XX_DMA_AAC1, + .port = EP93XX_DMA_AAC1, .direction = DMA_DEV_TO_MEM, }; diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 3eeada5..566a367 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1612,7 +1612,7 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) static void max98088_sync_cache(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; + u8 *reg_cache = codec->reg_cache; int i; if (!codec->cache_sync) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d441559..6c8a9e7 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -38,7 +38,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_CHIP_CLK_CTRL, 0x0008 }, { SGTL5000_CHIP_I2S_CTRL, 0x0010 }, - { SGTL5000_CHIP_SSS_CTRL, 0x0008 }, + { SGTL5000_CHIP_SSS_CTRL, 0x0010 }, { SGTL5000_CHIP_DAC_VOL, 0x3c3c }, { SGTL5000_CHIP_PAD_STRENGTH, 0x015f }, { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 }, @@ -1527,6 +1527,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, if (IS_ERR(sgtl5000->mclk)) { ret = PTR_ERR(sgtl5000->mclk); dev_err(&client->dev, "Failed to get mclock: %d\n", ret); + /* Defer the probe to see if the clk will be provided later */ + if (ret == -ENOENT) + return -EPROBE_DEFER; return ret; } diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 4b69229..2f8c889 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -347,7 +347,7 @@ #define SGTL5000_PLL_INT_DIV_MASK 0xf800 #define SGTL5000_PLL_INT_DIV_SHIFT 11 #define SGTL5000_PLL_INT_DIV_WIDTH 5 -#define SGTL5000_PLL_FRAC_DIV_MASK 0x0700 +#define SGTL5000_PLL_FRAC_DIV_MASK 0x07ff #define SGTL5000_PLL_FRAC_DIV_SHIFT 0 #define SGTL5000_PLL_FRAC_DIV_WIDTH 11 diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index f5e8356..10adc41 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -410,6 +410,16 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) rec->command, rec->length); len = rec->length + 8; + xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); + if (!xfer) { + dev_err(codec->dev, "Failed to allocate xfer\n"); + ret = -ENOMEM; + goto abort; + } + + xfer->codec = codec; + list_add_tail(&xfer->list, &xfer_list); + out = kzalloc(len, GFP_KERNEL); if (!out) { dev_err(codec->dev, @@ -417,6 +427,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) ret = -ENOMEM; goto abort1; } + xfer->t.rx_buf = out; img = kzalloc(len, GFP_KERNEL); if (!img) { @@ -425,24 +436,13 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) ret = -ENOMEM; goto abort1; } + xfer->t.tx_buf = img; byte_swap_64((u64 *)&rec->command, img, len); - xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); - if (!xfer) { - dev_err(codec->dev, "Failed to allocate xfer\n"); - ret = -ENOMEM; - goto abort1; - } - - xfer->codec = codec; - list_add_tail(&xfer->list, &xfer_list); - spi_message_init(&xfer->m); xfer->m.complete = wm0010_boot_xfer_complete; xfer->m.context = xfer; - xfer->t.tx_buf = img; - xfer->t.rx_buf = out; xfer->t.len = len; xfer->t.bits_per_word = 8; diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 029f31c..d8fc531 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -921,6 +921,7 @@ static struct snd_soc_dai_driver wm8978_dai = { .formats = WM8978_FORMATS, }, .ops = &wm8978_dai_ops, + .symmetric_rates = 1, }; static int wm8978_suspend(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1d4b1ec..ba832b7 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3852,8 +3852,6 @@ static void wm8958_mic_work(struct work_struct *work) mic_complete_work.work); struct snd_soc_codec *codec = wm8994->hubs.codec; - dev_crit(codec->dev, "MIC WORK %x\n", wm8994->mic_status); - pm_runtime_get_sync(codec->dev); mutex_lock(&wm8994->accdet_lock); @@ -3863,8 +3861,6 @@ static void wm8958_mic_work(struct work_struct *work) mutex_unlock(&wm8994->accdet_lock); pm_runtime_put(codec->dev); - - dev_crit(codec->dev, "MIC WORK %x DONE\n", wm8994->mic_status); } static irqreturn_t wm8958_mic_irq(int irq, void *data) diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 44b5acf..daa78a0 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -1,7 +1,7 @@ config SND_OMAP_SOC tristate "SoC Audio for the Texas Instruments OMAP chips" depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST) - select SND_SOC_DMAENGINE_PCM + select SND_DMAENGINE_PCM config SND_OMAP_SOC_DMIC tristate diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index eb68c7d..361e4c0 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -1012,28 +1012,33 @@ int omap_mcbsp_init(struct platform_device *pdev) } } - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!res) { - dev_err(&pdev->dev, "invalid rx DMA channel\n"); - return -ENODEV; - } - /* RX DMA request number, and port address configuration */ - mcbsp->dma_req[1] = res->start; - mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; - mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); - mcbsp->dma_data[1].maxburst = 4; + if (!pdev->dev.of_node) { + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (!res) { + dev_err(&pdev->dev, "invalid tx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[0] = res->start; + mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!res) { - dev_err(&pdev->dev, "invalid tx DMA channel\n"); - return -ENODEV; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (!res) { + dev_err(&pdev->dev, "invalid rx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[1] = res->start; + mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; + } else { + mcbsp->dma_data[0].filter_data = "tx"; + mcbsp->dma_data[1].filter_data = "rx"; } - /* TX DMA request number, and port address configuration */ - mcbsp->dma_req[0] = res->start; - mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; + mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0); mcbsp->dma_data[0].maxburst = 4; + mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); + mcbsp->dma_data[1].maxburst = 4; + mcbsp->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(mcbsp->fclk)) { ret = PTR_ERR(mcbsp->fclk); diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 2ad0370..4db1f8e 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -57,7 +57,6 @@ struct omap_dmic { struct mutex mutex; struct snd_dmaengine_dai_dma_data dma_data; - unsigned int dma_req; }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) @@ -478,15 +477,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) } dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dmic->dev, "invalid dma resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - - dmic->dma_req = res->start; - dmic->dma_data.filter_data = &dmic->dma_req; + dmic->dma_data.filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (!res) { diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index eb05c7e..a49dc52 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -66,7 +66,6 @@ struct omap_mcpdm { bool restart; struct snd_dmaengine_dai_dma_data dma_data[2]; - unsigned int dma_req[2]; }; /* @@ -477,19 +476,8 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); - if (!res) - return -ENODEV; - - mcpdm->dma_req[0] = res->start; - mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0]; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); - if (!res) - return -ENODEV; - - mcpdm->dma_req[1] = res->start; - mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1]; + mcpdm->dma_data[0].filter_data = "dn_link"; + mcpdm->dma_data[1].filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (res == NULL) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index c28e042..a11405d 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -113,14 +113,25 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_dmaengine_dai_dma_data *dma_data; + int ret; snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - return snd_dmaengine_pcm_open_request_chan(substream, - omap_dma_filter_fn, - dma_data->filter_data); + /* DT boot: filter_data is the DMA name */ + if (rtd->cpu_dai->dev->of_node) { + struct dma_chan *chan; + + chan = dma_request_slave_channel(rtd->cpu_dai->dev, + dma_data->filter_data); + ret = snd_dmaengine_pcm_open(substream, chan); + } else { + ret = snd_dmaengine_pcm_open_request_chan(substream, + omap_dma_filter_fn, + dma_data->filter_data); + } + return ret; } static int omap_pcm_mmap(struct snd_pcm_substream *substream, diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b358094..4db74a0 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -11,7 +11,7 @@ config SND_PXA2XX_SOC config SND_MMP_SOC bool "Soc Audio for Marvell MMP chips" depends on ARCH_MMP - select SND_SOC_DMAENGINE_PCM + select SND_DMAENGINE_PCM select SND_ARM help Say Y if you want to add support for codecs attached to diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 1358c7d..d0740a7 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -128,7 +128,9 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) substream->runtime && snd_pcm_running(substream)) { dev_dbg(pcm->dev, "xrun\n"); + snd_pcm_stream_lock(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(substream); ret = IRQ_HANDLED; } diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 7a17346..959c702 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -742,13 +742,13 @@ static int config_setup(struct i2s_dai *i2s) return -EAGAIN; } - /* Don't bother RFS, BFS & PSR in Slave mode */ - if (is_slave(i2s)) - return 0; - set_bfs(i2s, bfs); set_rfs(i2s, rfs); + /* Don't bother with PSR in Slave mode */ + if (is_slave(i2s)) + return 0; + if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { psr = i2s->rclk_srcrate / i2s->frmclk / rfs; writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0ec070c..d82ee38 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3908,10 +3908,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, { /* create platform component name */ platform->name = fmt_single_name(dev, &platform->id); - if (platform->name == NULL) { - kfree(platform); + if (platform->name == NULL) return -ENOMEM; - } platform->dev = dev; platform->driver = platform_drv; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b941908..bd16010 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2733,7 +2733,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, } mutex_unlock(&card->dapm_mutex); - return 0; + return change; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); @@ -2861,7 +2861,6 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int change; - int ret = 0; int wi; if (ucontrol->value.enumerated.item[0] >= e->max) @@ -2881,7 +2880,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, } mutex_unlock(&card->dapm_mutex); - return ret; + return change; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c deleted file mode 100644 index aa924d9..0000000 --- a/sound/soc/soc-dmaengine-pcm.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (C) 2012, Analog Devices Inc. - * Author: Lars-Peter Clausen <lars@metafoo.de> - * - * Based on: - * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> - * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. - * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - * Copyright (C) 2006 Applied Data Systems - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/dmaengine.h> -#include <linux/slab.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> - -#include <sound/dmaengine_pcm.h> - -struct dmaengine_pcm_runtime_data { - struct dma_chan *dma_chan; - dma_cookie_t cookie; - - unsigned int pos; -}; - -static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( - const struct snd_pcm_substream *substream) -{ - return substream->runtime->private_data; -} - -struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - - return prtd->dma_chan; -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); - -/** - * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config - * @substream: PCM substream - * @params: hw_params - * @slave_config: DMA slave config - * - * This function can be used to initialize a dma_slave_config from a substream - * and hw_params in a dmaengine based PCM driver implementation. - */ -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) -{ - enum dma_slave_buswidth buswidth; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; - break; - case SNDRV_PCM_FORMAT_S16_LE: - buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S20_3LE: - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; - break; - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - slave_config->direction = DMA_MEM_TO_DEV; - slave_config->dst_addr_width = buswidth; - } else { - slave_config->direction = DMA_DEV_TO_MEM; - slave_config->src_addr_width = buswidth; - } - - slave_config->device_fc = false; - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); - -/** - * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config - * using DAI DMA data. - * @substream: PCM substream - * @dma_data: DAI DMA data - * @slave_config: DMA slave configuration - * - * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and - * slave_id fields of the DMA slave config from the same fields of the DAI DMA - * data struct. The src and dst fields will be initialized depending on the - * direction of the substream. If the substream is a playback stream the dst - * fields will be initialized, if it is a capture stream the src fields will be - * initialized. The {dst,src}_addr_width field will only be initialized if the - * addr_width field of the DAI DMA data struct is not equal to - * DMA_SLAVE_BUSWIDTH_UNDEFINED. - */ -void snd_dmaengine_pcm_set_config_from_dai_data( - const struct snd_pcm_substream *substream, - const struct snd_dmaengine_dai_dma_data *dma_data, - struct dma_slave_config *slave_config) -{ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - slave_config->dst_addr = dma_data->addr; - slave_config->dst_maxburst = dma_data->maxburst; - if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) - slave_config->dst_addr_width = dma_data->addr_width; - } else { - slave_config->src_addr = dma_data->addr; - slave_config->src_maxburst = dma_data->maxburst; - if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) - slave_config->src_addr_width = dma_data->addr_width; - } - - slave_config->slave_id = dma_data->slave_id; -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); - -static void dmaengine_pcm_dma_complete(void *arg) -{ - struct snd_pcm_substream *substream = arg; - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - - prtd->pos += snd_pcm_lib_period_bytes(substream); - if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) - prtd->pos = 0; - - snd_pcm_period_elapsed(substream); -} - -static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - struct dma_chan *chan = prtd->dma_chan; - struct dma_async_tx_descriptor *desc; - enum dma_transfer_direction direction; - unsigned long flags = DMA_CTRL_ACK; - - direction = snd_pcm_substream_to_dma_direction(substream); - - if (!substream->runtime->no_period_wakeup) - flags |= DMA_PREP_INTERRUPT; - - prtd->pos = 0; - desc = dmaengine_prep_dma_cyclic(chan, - substream->runtime->dma_addr, - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), direction, flags); - - if (!desc) - return -ENOMEM; - - desc->callback = dmaengine_pcm_dma_complete; - desc->callback_param = substream; - prtd->cookie = dmaengine_submit(desc); - - return 0; -} - -/** - * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation - * @substream: PCM substream - * @cmd: Trigger command - * - * Returns 0 on success, a negative error code otherwise. - * - * This function can be used as the PCM trigger callback for dmaengine based PCM - * driver implementations. - */ -int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - int ret; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - ret = dmaengine_pcm_prepare_and_submit(substream); - if (ret) - return ret; - dma_async_issue_pending(prtd->dma_chan); - break; - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dmaengine_resume(prtd->dma_chan); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dmaengine_pause(prtd->dma_chan); - break; - case SNDRV_PCM_TRIGGER_STOP: - dmaengine_terminate_all(prtd->dma_chan); - break; - default: - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); - -/** - * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation - * @substream: PCM substream - * - * This function is deprecated and should not be used by new drivers, as its - * results may be unreliable. - */ -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); - return bytes_to_frames(substream->runtime, prtd->pos); -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); - -/** - * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation - * @substream: PCM substream - * - * This function can be used as the PCM pointer callback for dmaengine based PCM - * driver implementations. - */ -snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - struct dma_tx_state state; - enum dma_status status; - unsigned int buf_size; - unsigned int pos = 0; - - 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); - if (state.residue > 0 && state.residue <= buf_size) - pos = buf_size - state.residue; - } - - return bytes_to_frames(substream->runtime, pos); -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); - -/** - * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM - * @filter_fn: Filter function used to request the DMA channel - * @filter_data: Data passed to the DMA filter function - * - * Returns NULL or the requested DMA channel. - * - * This function request a DMA channel for usage with dmaengine PCM. - */ -struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, - void *filter_data) -{ - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_CYCLIC, mask); - - return dma_request_channel(mask, filter_fn, filter_data); -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); - -/** - * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream - * @substream: PCM substream - * @chan: DMA channel to use for data transfers - * - * Returns 0 on success, a negative error code otherwise. - * - * The function should usually be called from the pcm open callback. Note that - * this function will use private_data field of the substream's runtime. So it - * is not availabe to your pcm driver implementation. - */ -int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, - struct dma_chan *chan) -{ - struct dmaengine_pcm_runtime_data *prtd; - int ret; - - if (!chan) - return -ENXIO; - - ret = snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - - prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); - if (!prtd) - return -ENOMEM; - - prtd->dma_chan = chan; - - substream->runtime->private_data = prtd; - - return 0; -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); - -/** - * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel - * @substream: PCM substream - * @filter_fn: Filter function used to request the DMA channel - * @filter_data: Data passed to the DMA filter function - * - * Returns 0 on success, a negative error code otherwise. - * - * This function will request a DMA channel using the passed filter function and - * data. The function should usually be called from the pcm open callback. Note - * that this function will use private_data field of the substream's runtime. So - * it is not availabe to your pcm driver implementation. - */ -int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, - dma_filter_fn filter_fn, void *filter_data) -{ - return snd_dmaengine_pcm_open(substream, - snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); - -/** - * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream - * @substream: PCM substream - */ -int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - - kfree(prtd); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); - -/** - * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel - * @substream: PCM substream - * - * Releases the DMA channel associated with the PCM substream. - */ -int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) -{ - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - - dma_release_channel(prtd->dma_chan); - - return snd_dmaengine_pcm_close(substream); -} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); - -MODULE_LICENSE("GPL"); diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig index 3567d73..0a53053 100644 --- a/sound/soc/spear/Kconfig +++ b/sound/soc/spear/Kconfig @@ -1,6 +1,6 @@ config SND_SPEAR_SOC tristate - select SND_SOC_DMAENGINE_PCM + select SND_DMAENGINE_PCM config SND_SPEAR_SPDIF_OUT tristate diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index e58233f..6c48662 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -389,9 +389,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->capture_dma_data.slave_id = of_dma[1]; ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; - ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - ac97->capture_dma_data.maxburst = 4; - ac97->capture_dma_data.slave_id = of_dma[0]; + ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + ac97->playback_dma_data.maxburst = 4; + ac97->playback_dma_data.slave_id = of_dma[1]; ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); if (ret) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 5eaa12c..551b3c9 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -323,8 +323,8 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) } spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; - spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - spdif->capture_dma_data.maxburst = 4; + spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + spdif->playback_dma_data.maxburst = 4; spdif->playback_dma_data.slave_id = dmareq->start; pm_runtime_enable(&pdev->dev); |