aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/spear
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/spear')
-rw-r--r--sound/soc/spear/Kconfig9
-rw-r--r--sound/soc/spear/Makefile8
-rw-r--r--sound/soc/spear/spdif_in.c51
-rw-r--r--sound/soc/spear/spdif_out.c74
-rw-r--r--sound/soc/spear/spear_pcm.c187
-rw-r--r--sound/soc/spear/spear_pcm.h24
6 files changed, 101 insertions, 252 deletions
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig
new file mode 100644
index 00000000000..0a53053495f
--- /dev/null
+++ b/sound/soc/spear/Kconfig
@@ -0,0 +1,9 @@
+config SND_SPEAR_SOC
+ tristate
+ select SND_DMAENGINE_PCM
+
+config SND_SPEAR_SPDIF_OUT
+ tristate
+
+config SND_SPEAR_SPDIF_IN
+ tristate
diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile
new file mode 100644
index 00000000000..c4ea7161056
--- /dev/null
+++ b/sound/soc/spear/Makefile
@@ -0,0 +1,8 @@
+# SPEAR Platform Support
+snd-soc-spear-pcm-objs := spear_pcm.o
+snd-soc-spear-spdif-in-objs := spdif_in.o
+snd-soc-spear-spdif-out-objs := spdif_out.o
+
+obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o
+obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o
+obj-$(CONFIG_SND_SPEAR_SPDIF_OUT) += snd-soc-spear-spdif-out.o
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index c7c4b20395b..4ab442a63d7 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -18,12 +18,14 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <sound/dmaengine_pcm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/spear_dma.h>
#include <sound/spear_spdif.h>
#include "spdif_in_regs.h"
+#include "spear_pcm.h"
struct spdif_in_params {
u32 format;
@@ -37,6 +39,8 @@ struct spdif_in_dev {
struct device *dev;
void (*reset_perip)(void);
int irq;
+ struct snd_dmaengine_dai_dma_data dma_params_rx;
+ struct snd_dmaengine_pcm_config config;
};
static void spdif_in_configure(struct spdif_in_dev *host)
@@ -49,15 +53,13 @@ static void spdif_in_configure(struct spdif_in_dev *host)
writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK);
}
-static int spdif_in_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *cpu_dai)
+static int spdif_in_dai_probe(struct snd_soc_dai *dai)
{
- struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
+ struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
- if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
- return -EINVAL;
+ host->dma_params_rx.filter_data = &host->dma_params;
+ dai->capture_dma_data = &host->dma_params_rx;
- snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
return 0;
}
@@ -70,7 +72,6 @@ static void spdif_in_shutdown(struct snd_pcm_substream *substream,
return;
writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK);
- snd_soc_dai_set_dma_data(dai, substream, NULL);
}
static void spdif_in_format(struct spdif_in_dev *host, u32 format)
@@ -151,13 +152,13 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
}
static struct snd_soc_dai_ops spdif_in_dai_ops = {
- .startup = spdif_in_startup,
.shutdown = spdif_in_shutdown,
.trigger = spdif_in_trigger,
.hw_params = spdif_in_hw_params,
};
-struct snd_soc_dai_driver spdif_in_dai = {
+static struct snd_soc_dai_driver spdif_in_dai = {
+ .probe = spdif_in_dai_probe,
.capture = {
.channels_min = 2,
.channels_max = 2,
@@ -170,6 +171,10 @@ struct snd_soc_dai_driver spdif_in_dai = {
.ops = &spdif_in_dai_ops,
};
+static const struct snd_soc_component_driver spdif_in_component = {
+ .name = "spdif-in",
+};
+
static irqreturn_t spdif_in_irq(int irq, void *arg)
{
struct spdif_in_dev *host = (struct spdif_in_dev *)arg;
@@ -231,7 +236,7 @@ static int spdif_in_probe(struct platform_device *pdev)
if (host->irq < 0)
return -EINVAL;
- host->clk = clk_get(&pdev->dev, NULL);
+ host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk))
return PTR_ERR(host->clk);
@@ -244,7 +249,6 @@ static int spdif_in_probe(struct platform_device *pdev)
host->dma_params.addr = res_fifo->start;
host->dma_params.max_burst = 16;
host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- host->dma_params.filter = pdata->filter;
host->reset_perip = pdata->reset_perip;
host->dev = &pdev->dev;
@@ -253,36 +257,21 @@ static int spdif_in_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0,
"spdif-in", host);
if (ret) {
- clk_put(host->clk);
dev_warn(&pdev->dev, "request_irq failed\n");
return ret;
}
- ret = snd_soc_register_dai(&pdev->dev, &spdif_in_dai);
- if (ret != 0) {
- clk_put(host->clk);
+ ret = devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
+ &spdif_in_dai, 1);
+ if (ret)
return ret;
- }
- return 0;
+ return devm_spear_pcm_platform_register(&pdev->dev, &host->config,
+ pdata->filter);
}
-static int spdif_in_remove(struct platform_device *pdev)
-{
- struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
-
- snd_soc_unregister_dai(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
-
- clk_put(host->clk);
-
- return 0;
-}
-
-
static struct platform_driver spdif_in_driver = {
.probe = spdif_in_probe,
- .remove = spdif_in_remove,
.driver = {
.name = "spdif-in",
.owner = THIS_MODULE,
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 5eac4cda2fd..19cca043e6e 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -18,10 +18,12 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <sound/dmaengine_pcm.h>
#include <sound/soc.h>
#include <sound/spear_dma.h>
#include <sound/spear_spdif.h>
#include "spdif_out_regs.h"
+#include "spear_pcm.h"
struct spdif_out_params {
u32 rate;
@@ -35,6 +37,8 @@ struct spdif_out_dev {
struct spdif_out_params saved_params;
u32 running;
void __iomem *io_base;
+ struct snd_dmaengine_dai_dma_data dma_params_tx;
+ struct snd_dmaengine_pcm_config config;
};
static void spdif_out_configure(struct spdif_out_dev *host)
@@ -62,8 +66,6 @@ static int spdif_out_startup(struct snd_pcm_substream *substream,
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return -EINVAL;
- snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
-
ret = clk_enable(host->clk);
if (ret)
return ret;
@@ -84,7 +86,6 @@ static void spdif_out_shutdown(struct snd_pcm_substream *substream,
clk_disable(host->clk);
host->running = false;
- snd_soc_dai_set_dma_data(dai, substream, NULL);
}
static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq,
@@ -212,10 +213,7 @@ static int spdif_digital_mute(struct snd_soc_dai *dai, int mute)
static int spdif_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct snd_soc_card *card = codec->card;
- struct snd_soc_pcm_runtime *rtd = card->rtd;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
ucontrol->value.integer.value[0] = host->saved_params.mute;
@@ -225,10 +223,7 @@ static int spdif_mute_get(struct snd_kcontrol *kcontrol,
static int spdif_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct snd_soc_card *card = codec->card;
- struct snd_soc_pcm_runtime *rtd = card->rtd;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
if (host->saved_params.mute == ucontrol->value.integer.value[0])
@@ -243,8 +238,13 @@ static const struct snd_kcontrol_new spdif_out_controls[] = {
spdif_mute_get, spdif_mute_put),
};
-int spdif_soc_dai_probe(struct snd_soc_dai *dai)
+static int spdif_soc_dai_probe(struct snd_soc_dai *dai)
{
+ struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
+
+ host->dma_params_tx.filter_data = &host->dma_params;
+ dai->playback_dma_data = &host->dma_params_tx;
+
return snd_soc_add_dai_controls(dai, spdif_out_controls,
ARRAY_SIZE(spdif_out_controls));
}
@@ -270,6 +270,10 @@ static struct snd_soc_dai_driver spdif_out_dai = {
.ops = &spdif_out_dai_ops,
};
+static const struct snd_soc_component_driver spdif_out_component = {
+ .name = "spdif-out",
+};
+
static int spdif_out_probe(struct platform_device *pdev)
{
struct spdif_out_dev *host;
@@ -277,30 +281,18 @@ static int spdif_out_probe(struct platform_device *pdev)
struct resource *res;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name)) {
- dev_warn(&pdev->dev, "Failed to get memory resourse\n");
- return -ENOENT;
- }
-
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
if (!host) {
dev_warn(&pdev->dev, "kzalloc fail\n");
return -ENOMEM;
}
- host->io_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!host->io_base) {
- dev_warn(&pdev->dev, "ioremap failed\n");
- return -ENOMEM;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ host->io_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(host->io_base))
+ return PTR_ERR(host->io_base);
- host->clk = clk_get(&pdev->dev, NULL);
+ host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk))
return PTR_ERR(host->clk);
@@ -310,29 +302,16 @@ static int spdif_out_probe(struct platform_device *pdev)
host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA;
host->dma_params.max_burst = 16;
host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- host->dma_params.filter = pdata->filter;
dev_set_drvdata(&pdev->dev, host);
- ret = snd_soc_register_dai(&pdev->dev, &spdif_out_dai);
- if (ret != 0) {
- clk_put(host->clk);
+ ret = devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
+ &spdif_out_dai, 1);
+ if (ret)
return ret;
- }
-
- return 0;
-}
-static int spdif_out_remove(struct platform_device *pdev)
-{
- struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
-
- snd_soc_unregister_dai(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
-
- clk_put(host->clk);
-
- return 0;
+ return devm_spear_pcm_platform_register(&pdev->dev, &host->config,
+ pdata->filter);
}
#ifdef CONFIG_PM
@@ -373,7 +352,6 @@ static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \
static struct platform_driver spdif_out_driver = {
.probe = spdif_out_probe,
- .remove = spdif_out_remove,
.driver = {
.name = "spdif-out",
.owner = THIS_MODULE,
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 9b76cc5a114..0e5a8f35d0a 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -13,19 +13,14 @@
#include <linux/module.h>
#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm.h>
-#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/spear_dma.h>
+#include "spear_pcm.h"
-struct snd_pcm_hardware spear_pcm_hardware = {
+static const struct snd_pcm_hardware spear_pcm_hardware = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
@@ -37,178 +32,24 @@ struct snd_pcm_hardware spear_pcm_hardware = {
.fifo_size = 0, /* fifo size in bytes */
};
-static int spear_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
- return 0;
-}
-
-static int spear_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- snd_pcm_set_runtime_buffer(substream, NULL);
-
- return 0;
-}
-
-static int spear_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- struct spear_dma_data *dma_data = (struct spear_dma_data *)
- snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- int ret;
-
- ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware);
- if (ret)
- return ret;
-
- ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data);
- if (ret)
- return ret;
-
- snd_dmaengine_pcm_set_data(substream, dma_data);
-
- return 0;
-}
-
-static int spear_pcm_close(struct snd_pcm_substream *substream)
-{
-
- snd_dmaengine_pcm_close(substream);
-
- return 0;
-}
-
-static int spear_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area, runtime->dma_addr,
- runtime->dma_bytes);
-}
-
-static struct snd_pcm_ops spear_pcm_ops = {
- .open = spear_pcm_open,
- .close = spear_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = spear_pcm_hw_params,
- .hw_free = spear_pcm_hw_free,
- .trigger = snd_dmaengine_pcm_trigger,
- .pointer = snd_dmaengine_pcm_pointer,
- .mmap = spear_pcm_mmap,
+static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
+ .pcm_hardware = &spear_pcm_hardware,
+ .prealloc_buffer_size = 16 * 1024,
};
-static int
-spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
- size_t size)
+int devm_spear_pcm_platform_register(struct device *dev,
+ struct snd_dmaengine_pcm_config *config,
+ bool (*filter)(struct dma_chan *chan, void *slave))
{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
-
- 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;
-
- dev_info(buf->dev.dev,
- " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *)buf->area, (void *)buf->addr, size);
+ *config = spear_dmaengine_pcm_config;
+ config->compat_filter_fn = filter;
- buf->bytes = size;
- return 0;
+ return snd_dmaengine_pcm_register(dev, config,
+ SND_DMAENGINE_PCM_FLAG_NO_DT |
+ SND_DMAENGINE_PCM_FLAG_COMPAT);
}
-
-static void spear_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf || !buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
-
-static int spear_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
-{
- int ret;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &spear_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
- if (dai->driver->playback.channels_min) {
- ret = spear_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK,
- spear_pcm_hardware.buffer_bytes_max);
- if (ret)
- return ret;
- }
-
- if (dai->driver->capture.channels_min) {
- ret = spear_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE,
- spear_pcm_hardware.buffer_bytes_max);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-struct snd_soc_platform_driver spear_soc_platform = {
- .ops = &spear_pcm_ops,
- .pcm_new = spear_pcm_new,
- .pcm_free = spear_pcm_free,
-};
-
-static int spear_soc_platform_probe(struct platform_device *pdev)
-{
- return snd_soc_register_platform(&pdev->dev, &spear_soc_platform);
-}
-
-static int spear_soc_platform_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_platform(&pdev->dev);
-
- return 0;
-}
-
-static struct platform_driver spear_pcm_driver = {
- .driver = {
- .name = "spear-pcm-audio",
- .owner = THIS_MODULE,
- },
-
- .probe = spear_soc_platform_probe,
- .remove = spear_soc_platform_remove,
-};
-
-module_platform_driver(spear_pcm_driver);
+EXPORT_SYMBOL_GPL(devm_spear_pcm_platform_register);
MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
MODULE_DESCRIPTION("SPEAr PCM DMA module");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:spear-pcm-audio");
diff --git a/sound/soc/spear/spear_pcm.h b/sound/soc/spear/spear_pcm.h
new file mode 100644
index 00000000000..9b0ca62d6f0
--- /dev/null
+++ b/sound/soc/spear/spear_pcm.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SPEAR_PCM_H__
+#define __SPEAR_PCM_H__
+
+int devm_spear_pcm_platform_register(struct device *dev,
+ struct snd_dmaengine_pcm_config *config,
+ bool (*filter)(struct dma_chan *chan, void *slave));
+
+#endif