Commit 38e8c895 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/dma' into asoc-next

parents d66e065c 69b6f196
...@@ -32,9 +32,6 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) ...@@ -32,9 +32,6 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
return DMA_DEV_TO_MEM; return DMA_DEV_TO_MEM;
} }
void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data);
void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream);
int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, 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); const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
...@@ -47,4 +44,28 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); ...@@ -47,4 +44,28 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
/**
* struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
* @addr: Address of the DAI data source or destination register.
* @addr_width: Width of the DAI data source or destination register.
* @maxburst: Maximum number of words(note: words, as in units of the
* src_addr_width member, not bytes) that can be send to or received from the
* DAI in one burst.
* @slave_id: Slave requester id for the DMA channel.
* @filter_data: Custom DMA channel filter data, this will usually be used when
* requesting the DMA channel.
*/
struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
enum dma_slave_buswidth addr_width;
u32 maxburst;
unsigned int slave_id;
void *filter_data;
};
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 *config);
#endif #endif
...@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { ...@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
static void atmel_pcm_dma_irq(u32 ssc_sr, static void atmel_pcm_dma_irq(u32 ssc_sr,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_pcm_dma_params *prtd; struct atmel_pcm_dma_params *prtd;
prtd = snd_dmaengine_pcm_get_data(substream); prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (ssc_sr & prtd->mask->ssc_error) { if (ssc_sr & prtd->mask->ssc_error) {
if (snd_pcm_running(substream)) if (snd_pcm_running(substream))
...@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave) ...@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave)
} }
static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
{ {
struct atmel_pcm_dma_params *prtd;
struct ssc_device *ssc; struct ssc_device *ssc;
struct dma_chan *dma_chan; struct dma_chan *dma_chan;
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
int ret; int ret;
prtd = snd_dmaengine_pcm_get_data(substream);
ssc = prtd->ssc; ssc = prtd->ssc;
ret = snd_hwparams_to_dma_slave_config(substream, params, ret = snd_hwparams_to_dma_slave_config(substream, params,
...@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, ...@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
slave_config.src_maxburst = 1; slave_config.src_maxburst = 1;
} }
slave_config.device_fc = false;
dma_chan = snd_dmaengine_pcm_get_chan(substream); dma_chan = snd_dmaengine_pcm_get_chan(substream);
if (dmaengine_slave_config(dma_chan, &slave_config)) { if (dmaengine_slave_config(dma_chan, &slave_config)) {
pr_err("atmel-pcm: failed to configure dma channel\n"); pr_err("atmel-pcm: failed to configure dma channel\n");
...@@ -164,9 +161,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -164,9 +161,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
snd_dmaengine_pcm_set_data(substream, prtd); ret = atmel_pcm_configure_dma(substream, params, prtd);
ret = atmel_pcm_configure_dma(substream, params);
if (ret) { if (ret) {
pr_err("atmel-pcm: failed to configure dmai\n"); pr_err("atmel-pcm: failed to configure dmai\n");
goto err; goto err;
...@@ -182,9 +177,10 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -182,9 +177,10 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_pcm_dma_params *prtd; struct atmel_pcm_dma_params *prtd;
prtd = snd_dmaengine_pcm_get_data(substream); prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error); ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable); ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
...@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream) ...@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int atmel_pcm_close(struct snd_pcm_substream *substream)
{
snd_dmaengine_pcm_close(substream);
return 0;
}
static struct snd_pcm_ops atmel_pcm_ops = { static struct snd_pcm_ops atmel_pcm_ops = {
.open = atmel_pcm_open, .open = atmel_pcm_open,
.close = atmel_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = atmel_pcm_hw_params, .hw_params = atmel_pcm_hw_params,
.prepare = atmel_pcm_dma_prepare, .prepare = atmel_pcm_dma_prepare,
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include "ep93xx-pcm.h"
static int edb93xx_hw_params(struct snd_pcm_substream *substream, static int edb93xx_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <linux/platform_data/dma-ep93xx.h> #include <linux/platform_data/dma-ep93xx.h>
#include "ep93xx-pcm.h"
/* /*
* Per channel (1-4) registers. * Per channel (1-4) registers.
...@@ -101,14 +100,16 @@ struct ep93xx_ac97_info { ...@@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
/* currently ALSA only supports a single AC97 device */ /* currently ALSA only supports a single AC97 device */
static struct ep93xx_ac97_info *ep93xx_ac97_info; static struct ep93xx_ac97_info *ep93xx_ac97_info;
static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { static struct ep93xx_dma_data ep93xx_ac97_pcm_out = {
.name = "ac97-pcm-out", .name = "ac97-pcm-out",
.dma_port = EP93XX_DMA_AAC1, .dma_port = EP93XX_DMA_AAC1,
.direction = DMA_MEM_TO_DEV,
}; };
static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { static struct ep93xx_dma_data ep93xx_ac97_pcm_in = {
.name = "ac97-pcm-in", .name = "ac97-pcm-in",
.dma_port = EP93XX_DMA_AAC1, .dma_port = EP93XX_DMA_AAC1,
.direction = DMA_DEV_TO_MEM,
}; };
static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
...@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, ...@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct ep93xx_pcm_dma_params *dma_data; struct ep93xx_dma_data *dma_data;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_data = &ep93xx_ac97_pcm_out; dma_data = &ep93xx_ac97_pcm_out;
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include <mach/ep93xx-regs.h> #include <mach/ep93xx-regs.h>
#include <linux/platform_data/dma-ep93xx.h> #include <linux/platform_data/dma-ep93xx.h>
#include "ep93xx-pcm.h"
#define EP93XX_I2S_TXCLKCFG 0x00 #define EP93XX_I2S_TXCLKCFG 0x00
#define EP93XX_I2S_RXCLKCFG 0x04 #define EP93XX_I2S_RXCLKCFG 0x04
#define EP93XX_I2S_GLCTRL 0x0C #define EP93XX_I2S_GLCTRL 0x0C
...@@ -62,18 +60,20 @@ struct ep93xx_i2s_info { ...@@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
struct clk *mclk; struct clk *mclk;
struct clk *sclk; struct clk *sclk;
struct clk *lrclk; struct clk *lrclk;
struct ep93xx_pcm_dma_params *dma_params; struct ep93xx_dma_data *dma_data;
void __iomem *regs; void __iomem *regs;
}; };
struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
[SNDRV_PCM_STREAM_PLAYBACK] = { [SNDRV_PCM_STREAM_PLAYBACK] = {
.name = "i2s-pcm-out", .name = "i2s-pcm-out",
.dma_port = EP93XX_DMA_I2S1, .port = EP93XX_DMA_I2S1,
.direction = DMA_MEM_TO_DEV,
}, },
[SNDRV_PCM_STREAM_CAPTURE] = { [SNDRV_PCM_STREAM_CAPTURE] = {
.name = "i2s-pcm-in", .name = "i2s-pcm-in",
.dma_port = EP93XX_DMA_I2S1, .port = EP93XX_DMA_I2S1,
.direction = DMA_DEV_TO_MEM,
}, },
}; };
...@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, ...@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
snd_soc_dai_set_dma_data(cpu_dai, substream, snd_soc_dai_set_dma_data(cpu_dai, substream,
&info->dma_params[substream->stream]); &info->dma_data[substream->stream]);
return 0; return 0;
} }
...@@ -407,7 +407,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) ...@@ -407,7 +407,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
} }
dev_set_drvdata(&pdev->dev, info); dev_set_drvdata(&pdev->dev, info);
info->dma_params = ep93xx_i2s_dma_params; info->dma_data = ep93xx_i2s_dma_data;
err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
&ep93xx_i2s_dai, 1); &ep93xx_i2s_dai, 1);
......
...@@ -29,8 +29,6 @@ ...@@ -29,8 +29,6 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/ep93xx-regs.h> #include <mach/ep93xx-regs.h>
#include "ep93xx-pcm.h"
static const struct snd_pcm_hardware ep93xx_pcm_hardware = { static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
.info = (SNDRV_PCM_INFO_MMAP | .info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
...@@ -68,40 +66,11 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) ...@@ -68,40 +66,11 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
static int ep93xx_pcm_open(struct snd_pcm_substream *substream) static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct ep93xx_pcm_dma_params *dma_params;
struct ep93xx_dma_data *dma_data;
int ret;
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
if (!dma_data) snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
return -ENOMEM;
dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
dma_data->port = dma_params->dma_port;
dma_data->name = dma_params->name;
dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
if (ret) {
kfree(dma_data);
return ret;
}
snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
{
struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
snd_dmaengine_pcm_close(substream);
kfree(dma_data);
return 0;
} }
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
...@@ -131,7 +100,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -131,7 +100,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops ep93xx_pcm_ops = { static struct snd_pcm_ops ep93xx_pcm_ops = {
.open = ep93xx_pcm_open, .open = ep93xx_pcm_open,
.close = ep93xx_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params, .hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free, .hw_free = ep93xx_pcm_hw_free,
......
/*
* sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
*
* 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 version 2 as
* published by the Free Software Foundation.
*/
#ifndef _EP93XX_SND_SOC_PCM_H
#define _EP93XX_SND_SOC_PCM_H
struct ep93xx_pcm_dma_params {
char *name;
int dma_port;
};
#endif /* _EP93XX_SND_SOC_PCM_H */
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include "ep93xx-pcm.h"
static struct snd_soc_dai_link simone_dai = { static struct snd_soc_dai_link simone_dai = {
.name = "AC97", .name = "AC97",
.stream_name = "AC97 HiFi", .stream_name = "AC97 HiFi",
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include "../codecs/tlv320aic23.h" #include "../codecs/tlv320aic23.h"
#include "ep93xx-pcm.h"
#define CODEC_CLOCK 5644800 #define CODEC_CLOCK 5644800
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "fsl_ssi.h" #include "fsl_ssi.h"
#include "imx-pcm.h" #include "imx-pcm.h"
...@@ -122,8 +123,10 @@ struct fsl_ssi_private { ...@@ -122,8 +123,10 @@ struct fsl_ssi_private {
bool ssi_on_imx; bool ssi_on_imx;
struct clk *clk; struct clk *clk;
struct platform_device *imx_pcm_pdev; struct platform_device *imx_pcm_pdev;
struct imx_pcm_dma_params dma_params_tx; struct snd_dmaengine_dai_dma_data dma_params_tx;
struct imx_pcm_dma_params dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_rx;
struct imx_dma_data filter_data_tx;
struct imx_dma_data filter_data_rx;
struct { struct {
unsigned int rfrc; unsigned int rfrc;
...@@ -653,6 +656,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -653,6 +656,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
const uint32_t *iprop; const uint32_t *iprop;
struct resource res; struct resource res;
char name[64]; char name[64];
bool shared;
/* SSIs that are not connected on the board should have a /* SSIs that are not connected on the board should have a
* status = "disabled" * status = "disabled"
...@@ -741,14 +745,18 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -741,14 +745,18 @@ static int fsl_ssi_probe(struct platform_device *pdev)
* We have burstsize be "fifo_depth - 2" to match the SSI * We have burstsize be "fifo_depth - 2" to match the SSI
* watermark setting in fsl_ssi_startup(). * watermark setting in fsl_ssi_startup().
*/ */
ssi_private->dma_params_tx.burstsize = ssi_private->dma_params_tx.maxburst =
ssi_private->fifo_depth - 2; ssi_private->fifo_depth - 2;
ssi_private->dma_params_rx.burstsize = ssi_private->dma_params_rx.maxburst =
ssi_private->fifo_depth - 2; ssi_private->fifo_depth - 2;
ssi_private->dma_params_tx.dma_addr = ssi_private->dma_params_tx.addr =
ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
ssi_private->dma_params_rx.dma_addr = ssi_private->dma_params_rx.addr =
ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
ssi_private->dma_params_tx.filter_data =
&ssi_private->filter_data_tx;
ssi_private->dma_params_rx.filter_data =
&ssi_private->filter_data_rx;
/* /*
* TODO: This is a temporary solution and should be changed * TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helplers get in. * to use generic DMA binding later when the helplers get in.
...@@ -759,14 +767,14 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -759,14 +767,14 @@ static int fsl_ssi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "could not get dma events\n"); dev_err(&pdev->dev, "could not get dma events\n");
goto error_clk; goto error_clk;
} }
ssi_private->dma_params_tx.dma = dma_events[0];
ssi_private->dma_params_rx.dma = dma_events[1];
ssi_private->dma_params_tx.shared_peripheral = shared = of_device_is_compatible(of_get_parent(np),
of_device_is_compatible(of_get_parent(np),
"fsl,spba-bus"); "fsl,spba-bus");
ssi_private->dma_params_rx.shared_peripheral =
ssi_private->dma_params_tx.shared_peripheral; imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
dma_events[0], shared);
imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
dma_events[1], shared);
} }
/* Initialize the the device_attribute structure */ /* Initialize the the device_attribute structure */
......
...@@ -30,16 +30,16 @@ ...@@ -30,16 +30,16 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include <linux/platform_data/dma-imx.h>
#include "imx-pcm.h" #include "imx-pcm.h"
static bool filter(struct dma_chan *chan, void *param) static bool filter(struct dma_chan *chan, void *param)
{ {
struct snd_dmaengine_dai_dma_data *dma_data = param;
if (!imx_dma_is_general_purpose(chan)) if (!imx_dma_is_general_purpose(chan))
return false; return false;
chan->private = param; chan->private = dma_data->filter_data;
return true; return true;
} }
...@@ -49,25 +49,16 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -49,25 +49,16 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct imx_pcm_dma_params *dma_params;
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
int ret; int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
if (ret) if (ret)
return ret; return ret;
slave_config.device_fc = false; snd_dmaengine_pcm_set_config_from_dai_data(substream,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { &slave_config);
slave_config.dst_addr = dma_params->dma_addr;
slave_config.dst_maxburst = dma_params->burstsize;
} else {
slave_config.src_addr = dma_params->dma_addr;
slave_config.src_maxburst = dma_params->burstsize;
}
ret = dmaengine_slave_config(chan, &slave_config); ret = dmaengine_slave_config(chan, &slave_config);
if (ret) if (ret)
...@@ -100,47 +91,16 @@ static struct snd_pcm_hardware snd_imx_hardware = { ...@@ -100,47 +91,16 @@ static struct snd_pcm_hardware snd_imx_hardware = {
static int snd_imx_open(struct snd_pcm_substream *substream) static int snd_imx_open(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params;
struct imx_dma_data *dma_data;
int ret;
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); return snd_dmaengine_pcm_open(substream, filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
if (!dma_data)
return -ENOMEM;
dma_data->peripheral_type = dma_params->shared_peripheral ?
IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI;
dma_data->priority = DMA_PRIO_HIGH;
dma_data->dma_request = dma_params->dma;
ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
if (ret) {
kfree(dma_data);
return ret;
}
snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
{
struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
snd_dmaengine_pcm_close(substream);
kfree(dma_data);
return 0;
} }
static struct snd_pcm_ops imx_pcm_ops = { static struct snd_pcm_ops imx_pcm_ops = {
.open = snd_imx_open, .open = snd_imx_open,
.close = snd_imx_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params, .hw_params = snd_imx_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger, .trigger = snd_dmaengine_pcm_trigger,
......
...@@ -299,8 +299,8 @@ int imx_pcm_fiq_init(struct platform_device *pdev) ...@@ -299,8 +299,8 @@ int imx_pcm_fiq_init(struct platform_device *pdev)
imx_ssi_fiq_base = (unsigned long)ssi->base; imx_ssi_fiq_base = (unsigned long)ssi->base;
ssi->dma_params_tx.burstsize = 4; ssi->dma_params_tx.maxburst = 4;
ssi->dma_params_rx.burstsize = 6; ssi->dma_params_rx.maxburst = 6;
ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
if (ret) if (ret)
......
...@@ -13,17 +13,24 @@ ...@@ -13,17 +13,24 @@
#ifndef _IMX_PCM_H #ifndef _IMX_PCM_H
#define _IMX_PCM_H #define _IMX_PCM_H
#include <linux/platform_data/dma-imx.h>
/* /*
* Do not change this as the FIQ handler depends on this size * Do not change this as the FIQ handler depends on this size
*/ */
#define IMX_SSI_DMABUF_SIZE (64 * 1024) #define IMX_SSI_DMABUF_SIZE (64 * 1024)
struct imx_pcm_dma_params { static inline void
int dma; imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
unsigned long dma_addr; int dma, bool shared)
int burstsize; {
bool shared_peripheral; /* The peripheral is on SPBA bus */ dma_data->dma_request = dma;
}; dma_data->priority = DMA_PRIO_HIGH;
if (shared)
dma_data->peripheral_type = IMX_DMATYPE_SSI_SP;
else
dma_data->peripheral_type = IMX_DMATYPE_SSI;
}
int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma); struct vm_area_struct *vma);
......
...@@ -236,7 +236,7 @@ static int imx_ssi_startup(struct snd_pcm_substream *substream, ...@@ -236,7 +236,7 @@ static int imx_ssi_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
struct imx_pcm_dma_params *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
/* Tx/Rx config */ /* Tx/Rx config */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
...@@ -369,8 +369,8 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) ...@@ -369,8 +369,8 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
snd_soc_dai_set_drvdata(dai, ssi); snd_soc_dai_set_drvdata(dai, ssi);
val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.maxburst) |
SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst);
writel(val, ssi->base + SSI_SFCSR); writel(val, ssi->base + SSI_SFCSR);
return 0; return 0;
...@@ -579,19 +579,26 @@ static int imx_ssi_probe(struct platform_device *pdev) ...@@ -579,19 +579,26 @@ static int imx_ssi_probe(struct platform_device *pdev)
writel(0x0, ssi->base + SSI_SIER); writel(0x0, ssi->base + SSI_SIER);
ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; ssi->dma_params_rx.addr = res->start + SSI_SRX0;
ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; ssi->dma_params_tx.addr = res->start + SSI_STX0;
ssi->dma_params_tx.burstsize = 6; ssi->dma_params_tx.maxburst = 6;
ssi->dma_params_rx.burstsize = 4; ssi->dma_params_rx.maxburst = 4;
ssi->dma_params_tx.filter_data = &ssi->filter_data_tx;
ssi->dma_params_rx.filter_data = &ssi->filter_data_rx;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
if (res) if (res) {
ssi->dma_params_tx.dma = res->start; imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start,
false);
}
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
if (res) if (res) {
ssi->dma_params_rx.dma = res->start; imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start,
false);
}
platform_set_drvdata(pdev, ssi); platform_set_drvdata(pdev, ssi);
......
...@@ -187,6 +187,7 @@ ...@@ -187,6 +187,7 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/platform_data/dma-imx.h> #include <linux/platform_data/dma-imx.h>
#include <sound/dmaengine_pcm.h>
#include "imx-pcm.h" #include "imx-pcm.h"
struct imx_ssi { struct imx_ssi {
...@@ -204,8 +205,10 @@ struct imx_ssi { ...@@ -204,8 +205,10 @@ struct imx_ssi {
void (*ac97_reset) (struct snd_ac97 *ac97); void (*ac97_reset) (struct snd_ac97 *ac97);
void (*ac97_warm_reset)(struct snd_ac97 *ac97); void (*ac97_warm_reset)(struct snd_ac97 *ac97);
struct imx_pcm_dma_params dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_rx;
struct imx_pcm_dma_params dma_params_tx; struct snd_dmaengine_dai_dma_data dma_params_tx;
struct imx_dma_data filter_data_tx;
struct imx_dma_data filter_data_rx;
int enabled; int enabled;
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/fsl/mxs-dma.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
...@@ -39,11 +38,6 @@ ...@@ -39,11 +38,6 @@
#include "mxs-pcm.h" #include "mxs-pcm.h"
struct mxs_pcm_dma_data {
struct mxs_dma_data dma_data;
struct mxs_pcm_dma_params *dma_params;
};
static struct snd_pcm_hardware snd_mxs_hardware = { static struct snd_pcm_hardware snd_mxs_hardware = {
.info = SNDRV_PCM_INFO_MMAP | .info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
...@@ -66,8 +60,7 @@ static struct snd_pcm_hardware snd_mxs_hardware = { ...@@ -66,8 +60,7 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
static bool filter(struct dma_chan *chan, void *param) static bool filter(struct dma_chan *chan, void *param)
{ {
struct mxs_pcm_dma_data *pcm_dma_data = param; struct mxs_pcm_dma_params *dma_params = param;
struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
if (!mxs_dma_is_apbx(chan)) if (!mxs_dma_is_apbx(chan))
return false; return false;
...@@ -75,7 +68,7 @@ static bool filter(struct dma_chan *chan, void *param) ...@@ -75,7 +68,7 @@ static bool filter(struct dma_chan *chan, void *param)
if (chan->chan_id != dma_params->chan_num) if (chan->chan_id != dma_params->chan_num)
return false; return false;
chan->private = &pcm_dma_data->dma_data; chan->private = &dma_params->dma_data;
return true; return true;
} }
...@@ -91,37 +84,11 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -91,37 +84,11 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
static int snd_mxs_open(struct snd_pcm_substream *substream) static int snd_mxs_open(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mxs_pcm_dma_data *pcm_dma_data;
int ret;
pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
if (pcm_dma_data == NULL)
return -ENOMEM;
pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
if (ret) {
kfree(pcm_dma_data);
return ret;
}
snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
snd_dmaengine_pcm_set_data(substream, pcm_dma_data); return snd_dmaengine_pcm_open(substream, filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
return 0;
}
static int snd_mxs_close(struct snd_pcm_substream *substream)
{
struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
snd_dmaengine_pcm_close(substream);
kfree(pcm_dma_data);
return 0;
} }
static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
...@@ -137,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -137,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops mxs_pcm_ops = { static struct snd_pcm_ops mxs_pcm_ops = {
.open = snd_mxs_open, .open = snd_mxs_open,
.close = snd_mxs_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_mxs_pcm_hw_params, .hw_params = snd_mxs_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger, .trigger = snd_dmaengine_pcm_trigger,
......
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
#ifndef _MXS_PCM_H #ifndef _MXS_PCM_H
#define _MXS_PCM_H #define _MXS_PCM_H
#include <linux/fsl/mxs-dma.h>
struct mxs_pcm_dma_params { struct mxs_pcm_dma_params {
int chan_irq; struct mxs_dma_data dma_data;
int chan_num; int chan_num;
}; };
......
...@@ -757,9 +757,9 @@ static int mxs_saif_probe(struct platform_device *pdev) ...@@ -757,9 +757,9 @@ static int mxs_saif_probe(struct platform_device *pdev)
return ret; return ret;
} }
saif->dma_param.chan_irq = platform_get_irq(pdev, 1); saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1);
if (saif->dma_param.chan_irq < 0) { if (saif->dma_param.dma_data.chan_irq < 0) {
ret = saif->dma_param.chan_irq; ret = saif->dma_param.dma_data.chan_irq;
dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
ret); ret);
return ret; return ret;
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/tlv320aic23.h" #include "../codecs/tlv320aic23.h"
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/cx20442.h" #include "../codecs/cx20442.h"
......
...@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev) ...@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* RX DMA request number, and port address configuration */ /* RX DMA request number, and port address configuration */
mcbsp->dma_data[1].name = "Audio Capture"; mcbsp->dma_req[1] = res->start;
mcbsp->dma_data[1].dma_req = res->start; mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1];
mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
mcbsp->dma_data[1].maxburst = 4;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
if (!res) { if (!res) {
...@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev) ...@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* TX DMA request number, and port address configuration */ /* TX DMA request number, and port address configuration */
mcbsp->dma_data[0].name = "Audio Playback"; mcbsp->dma_req[0] = res->start;
mcbsp->dma_data[0].dma_req = res->start; mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0];
mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
mcbsp->dma_data[0].maxburst = 4;
mcbsp->fclk = clk_get(&pdev->dev, "fck"); mcbsp->fclk = clk_get(&pdev->dev, "fck");
if (IS_ERR(mcbsp->fclk)) { if (IS_ERR(mcbsp->fclk)) {
......
...@@ -24,14 +24,14 @@ ...@@ -24,14 +24,14 @@
#ifndef __ASOC_MCBSP_H #ifndef __ASOC_MCBSP_H
#define __ASOC_MCBSP_H #define __ASOC_MCBSP_H
#include "omap-pcm.h"
#ifdef CONFIG_ARCH_OMAP1 #ifdef CONFIG_ARCH_OMAP1
#define mcbsp_omap1() 1 #define mcbsp_omap1() 1
#else #else
#define mcbsp_omap1() 0 #define mcbsp_omap1() 0
#endif #endif
#include <sound/dmaengine_pcm.h>
/* McBSP register numbers. Register address offset = num * reg_step */ /* McBSP register numbers. Register address offset = num * reg_step */
enum { enum {
/* Common registers */ /* Common registers */
...@@ -312,7 +312,8 @@ struct omap_mcbsp { ...@@ -312,7 +312,8 @@ struct omap_mcbsp {
struct omap_mcbsp_platform_data *pdata; struct omap_mcbsp_platform_data *pdata;
struct omap_mcbsp_st_data *st_data; struct omap_mcbsp_st_data *st_data;
struct omap_mcbsp_reg_cfg cfg_regs; struct omap_mcbsp_reg_cfg cfg_regs;
struct omap_pcm_dma_data dma_data[2]; struct snd_dmaengine_dai_dma_data dma_data[2];
unsigned int dma_req[2];
int dma_op_mode; int dma_op_mode;
u16 max_tx_thres; u16 max_tx_thres;
u16 max_rx_thres; u16 max_rx_thres;
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#define N810_HEADSET_AMP_GPIO 10 #define N810_HEADSET_AMP_GPIO 10
#define N810_SPEAKER_AMP_GPIO 101 #define N810_SPEAKER_AMP_GPIO 101
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include "omap-dmic.h" #include "omap-dmic.h"
#include "omap-mcpdm.h" #include "omap-mcpdm.h"
#include "omap-pcm.h"
#include "../codecs/twl6040.h" #include "../codecs/twl6040.h"
struct abe_twl6040 { struct abe_twl6040 {
......
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "omap-pcm.h"
#include "omap-dmic.h" #include "omap-dmic.h"
struct omap_dmic { struct omap_dmic {
...@@ -55,13 +55,9 @@ struct omap_dmic { ...@@ -55,13 +55,9 @@ struct omap_dmic {
u32 ch_enabled; u32 ch_enabled;
bool active; bool active;
struct mutex mutex; struct mutex mutex;
};
/* struct snd_dmaengine_dai_dma_data dma_data;
* Stream DMA parameters unsigned int dma_req;
*/
static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
.name = "DMIC capture",
}; };
static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
...@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, ...@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
mutex_unlock(&dmic->mutex); mutex_unlock(&dmic->mutex);
snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); snd_soc_dai_set_dma_data(dai, substream, &dmic->dma_data);
return ret; return ret;
} }
...@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
struct omap_pcm_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
int channels; int channels;
dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
...@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
/* packet size is threshold * channels */ /* packet size is threshold * channels */
dma_data = snd_soc_dai_get_dma_data(dai, substream); dma_data = snd_soc_dai_get_dma_data(dai, substream);
dma_data->packet_size = dmic->threshold * channels; dma_data->maxburst = dmic->threshold * channels;
return 0; return 0;
} }
...@@ -480,7 +476,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) ...@@ -480,7 +476,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
ret = -ENODEV; ret = -ENODEV;
goto err_put_clk; goto err_put_clk;
} }
omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG; dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
res = platform_get_resource(pdev, IORESOURCE_DMA, 0); res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!res) { if (!res) {
...@@ -488,7 +484,9 @@ static int asoc_dmic_probe(struct platform_device *pdev) ...@@ -488,7 +484,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
ret = -ENODEV; ret = -ENODEV;
goto err_put_clk; goto err_put_clk;
} }
omap_dmic_dai_dma_params.dma_req = res->start;
dmic->dma_req = res->start;
dmic->dma_data.filter_data = &dmic->dma_req;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (!res) { if (!res) {
...@@ -497,19 +495,9 @@ static int asoc_dmic_probe(struct platform_device *pdev) ...@@ -497,19 +495,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
goto err_put_clk; goto err_put_clk;
} }
if (!devm_request_mem_region(&pdev->dev, res->start, dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
resource_size(res), pdev->name)) { if (IS_ERR(dmic->io_base))
dev_err(dmic->dev, "memory region already claimed\n"); return PTR_ERR(dmic->io_base);
ret = -ENODEV;
goto err_put_clk;
}
dmic->io_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!dmic->io_base) {
ret = -ENOMEM;
goto err_put_clk;
}
ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component,
&omap_dmic_dai, 1); &omap_dmic_dai, 1);
......
...@@ -32,15 +32,16 @@ ...@@ -32,15 +32,16 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/asound.h> #include <sound/asound.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include <sound/dmaengine_pcm.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include "omap-pcm.h"
#include "omap-hdmi.h" #include "omap-hdmi.h"
#define DRV_NAME "omap-hdmi-audio-dai" #define DRV_NAME "omap-hdmi-audio-dai"
struct hdmi_priv { struct hdmi_priv {
struct omap_pcm_dma_data dma_params; struct snd_dmaengine_dai_dma_data dma_data;
unsigned int dma_req;
struct omap_dss_audio dss_audio; struct omap_dss_audio dss_audio;
struct snd_aes_iec958 iec; struct snd_aes_iec958 iec;
struct snd_cea_861_aud_if cea; struct snd_cea_861_aud_if cea;
...@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, ...@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
return -ENODEV; return -ENODEV;
} }
snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data);
return 0; return 0;
} }
...@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
struct snd_aes_iec958 *iec = &priv->iec; struct snd_aes_iec958 *iec = &priv->iec;
struct snd_cea_861_aud_if *cea = &priv->cea; struct snd_cea_861_aud_if *cea = &priv->cea;
struct omap_pcm_dma_data *dma_data;
int err = 0; int err = 0;
dma_data = snd_soc_dai_get_dma_data(dai, substream);
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
dma_data->packet_size = 16; priv->dma_data.maxburst = 16;
break; break;
case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_LE:
dma_data->packet_size = 32; priv->dma_data.maxburst = 32;
break; break;
default: default:
dev_err(dai->dev, "format not supported!\n"); dev_err(dai->dev, "format not supported!\n");
return -EINVAL; return -EINVAL;
} }
dma_data->data_type = 32;
/* /*
* fill the IEC-60958 channel status word * fill the IEC-60958 channel status word
*/ */
...@@ -287,8 +283,7 @@ static int omap_hdmi_probe(struct platform_device *pdev) ...@@ -287,8 +283,7 @@ static int omap_hdmi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
hdmi_data->dma_params.port_addr = hdmi_rsrc->start hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT;
+ OMAP_HDMI_AUDIO_DMA_PORT;
hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!hdmi_rsrc) { if (!hdmi_rsrc) {
...@@ -296,8 +291,9 @@ static int omap_hdmi_probe(struct platform_device *pdev) ...@@ -296,8 +291,9 @@ static int omap_hdmi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
hdmi_data->dma_params.dma_req = hdmi_rsrc->start; hdmi_data->dma_req = hdmi_rsrc->start;
hdmi_data->dma_params.name = "HDMI playback"; hdmi_data->dma_data.filter_data = &hdmi_data->dma_req;
hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
/* /*
* TODO: We assume that there is only one DSS HDMI device. Future * TODO: We assume that there is only one DSS HDMI device. Future
......
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "mcbsp.h" #include "mcbsp.h"
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
...@@ -62,24 +62,22 @@ enum { ...@@ -62,24 +62,22 @@ enum {
* Stream DMA parameters. DMA request line and port address are set runtime * Stream DMA parameters. DMA request line and port address are set runtime
* since they are different between OMAP1 and later OMAPs * since they are different between OMAP1 and later OMAPs
*/ */
static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream,
unsigned int packet_size)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_pcm_dma_data *dma_data;
int words; int words;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
/* /*
* Configure McBSP threshold based on either: * Configure McBSP threshold based on either:
* packet_size, when the sDMA is in packet mode, or based on the * packet_size, when the sDMA is in packet mode, or based on the
* period size in THRESHOLD mode, otherwise use McBSP threshold = 1 * period size in THRESHOLD mode, otherwise use McBSP threshold = 1
* for mono streams. * for mono streams.
*/ */
if (dma_data->packet_size) if (packet_size)
words = dma_data->packet_size; words = packet_size;
else else
words = 1; words = 1;
...@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
{ {
struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
struct omap_pcm_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
int wlen, channels, wpf; int wlen, channels, wpf;
int pkt_size = 0; int pkt_size = 0;
unsigned int format, div, framesize, master; unsigned int format, div, framesize, master;
...@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
if (mcbsp->pdata->buffer_size) { if (mcbsp->pdata->buffer_size) {
dma_data->set_threshold = omap_mcbsp_set_threshold;
if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
int period_words, max_thrsh; int period_words, max_thrsh;
int divider = 0; int divider = 0;
...@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
/* Use packet mode for non mono streams */ /* Use packet mode for non mono streams */
pkt_size = channels; pkt_size = channels;
} }
omap_mcbsp_set_threshold(substream, pkt_size);
} }
dma_data->packet_size = pkt_size; dma_data->maxburst = pkt_size;
if (mcbsp->configured) { if (mcbsp->configured) {
/* McBSP already configured by another stream */ /* McBSP already configured by another stream */
......
...@@ -39,11 +39,14 @@ ...@@ -39,11 +39,14 @@
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "omap-mcpdm.h" #include "omap-mcpdm.h"
#include "omap-pcm.h"
#define OMAP44XX_MCPDM_L3_BASE 0x49032000 struct mcpdm_link_config {
u32 link_mask; /* channel mask for the direction */
u32 threshold; /* FIFO threshold */
};
struct omap_mcpdm { struct omap_mcpdm {
struct device *dev; struct device *dev;
...@@ -53,29 +56,22 @@ struct omap_mcpdm { ...@@ -53,29 +56,22 @@ struct omap_mcpdm {
struct mutex mutex; struct mutex mutex;
/* channel data */ /* Playback/Capture configuration */
u32 dn_channels; struct mcpdm_link_config config[2];
u32 up_channels;
/* McPDM FIFO thresholds */
u32 dn_threshold;
u32 up_threshold;
/* McPDM dn offsets for rx1, and 2 channels */ /* McPDM dn offsets for rx1, and 2 channels */
u32 dn_rx_offset; u32 dn_rx_offset;
/* McPDM needs to be restarted due to runtime reconfiguration */
bool restart;
struct snd_dmaengine_dai_dma_data dma_data[2];
unsigned int dma_req[2];
}; };
/* /*
* Stream DMA parameters * Stream DMA parameters
*/ */
static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
{
.name = "Audio playback",
},
{
.name = "Audio capture",
},
};
static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
{ {
...@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} ...@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
{ {
u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask;
ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
ctrl |= mcpdm->dn_channels | mcpdm->up_channels; ctrl |= link_mask;
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
...@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) ...@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
{ {
u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK;
ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); ctrl &= ~(link_mask);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
...@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) ...@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
} }
omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN,
omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold);
omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP,
mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold);
omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
...@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, ...@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
mutex_unlock(&mcpdm->mutex); mutex_unlock(&mcpdm->mutex);
snd_soc_dai_set_dma_data(dai, substream, snd_soc_dai_set_dma_data(dai, substream,
&omap_mcpdm_dai_dma_params[substream->stream]); &mcpdm->dma_data[substream->stream]);
return 0; return 0;
} }
...@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, ...@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
if (omap_mcpdm_active(mcpdm)) { if (omap_mcpdm_active(mcpdm)) {
omap_mcpdm_stop(mcpdm); omap_mcpdm_stop(mcpdm);
omap_mcpdm_close_streams(mcpdm); omap_mcpdm_close_streams(mcpdm);
mcpdm->config[0].link_mask = 0;
mcpdm->config[1].link_mask = 0;
} }
} }
...@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
{ {
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int stream = substream->stream; int stream = substream->stream;
struct omap_pcm_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
u32 threshold;
int channels; int channels;
int link_mask = 0; int link_mask = 0;
...@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
dma_data = snd_soc_dai_get_dma_data(dai, substream); dma_data = snd_soc_dai_get_dma_data(dai, substream);
threshold = mcpdm->config[stream].threshold;
/* Configure McPDM channels, and DMA packet size */ /* Configure McPDM channels, and DMA packet size */
if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mcpdm->dn_channels = link_mask << 3; link_mask <<= 3;
dma_data->packet_size =
(MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; /* If capture is not running assume a stereo stream to come */
if (!mcpdm->config[!stream].link_mask)
mcpdm->config[!stream].link_mask = 0x3;
dma_data->maxburst =
(MCPDM_DN_THRES_MAX - threshold) * channels;
} else { } else {
mcpdm->up_channels = link_mask << 0; /* If playback is not running assume a stereo stream to come */
dma_data->packet_size = mcpdm->up_threshold * channels; if (!mcpdm->config[!stream].link_mask)
mcpdm->config[!stream].link_mask = (0x3 << 3);
dma_data->maxburst = threshold * channels;
} }
/* Check if we need to restart McPDM with this stream */
if (mcpdm->config[stream].link_mask &&
mcpdm->config[stream].link_mask != link_mask)
mcpdm->restart = true;
mcpdm->config[stream].link_mask = link_mask;
return 0; return 0;
} }
...@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, ...@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
if (!omap_mcpdm_active(mcpdm)) { if (!omap_mcpdm_active(mcpdm)) {
omap_mcpdm_start(mcpdm); omap_mcpdm_start(mcpdm);
omap_mcpdm_reg_dump(mcpdm); omap_mcpdm_reg_dump(mcpdm);
} else if (mcpdm->restart) {
omap_mcpdm_stop(mcpdm);
omap_mcpdm_start(mcpdm);
mcpdm->restart = false;
omap_mcpdm_reg_dump(mcpdm);
} }
return 0; return 0;
...@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) ...@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
pm_runtime_get_sync(mcpdm->dev); pm_runtime_get_sync(mcpdm->dev);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler,
0, "McPDM", (void *)mcpdm); 0, "McPDM", (void *)mcpdm);
pm_runtime_put_sync(mcpdm->dev); pm_runtime_put_sync(mcpdm->dev);
...@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) ...@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
} }
/* Configure McPDM threshold values */ /* Configure McPDM threshold values */
mcpdm->dn_threshold = 2; mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2;
mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold =
MCPDM_UP_THRES_MAX - 3;
return ret; return ret;
} }
...@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) ...@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
{ {
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
free_irq(mcpdm->irq, (void *)mcpdm);
pm_runtime_disable(mcpdm->dev); pm_runtime_disable(mcpdm->dev);
return 0; return 0;
...@@ -450,33 +474,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) ...@@ -450,33 +474,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
if (res == NULL) if (res == NULL)
return -ENOMEM; return -ENOMEM;
omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA;
omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link");
if (!res) if (!res)
return -ENODEV; return -ENODEV;
omap_mcpdm_dai_dma_params[0].dma_req = res->start; 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"); res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link");
if (!res) if (!res)
return -ENODEV; return -ENODEV;
omap_mcpdm_dai_dma_params[1].dma_req = res->start; mcpdm->dma_req[1] = res->start;
mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1];
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (res == NULL) if (res == NULL)
return -ENOMEM; return -ENOMEM;
if (!devm_request_mem_region(&pdev->dev, res->start, mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res);
resource_size(res), "McPDM")) if (IS_ERR(mcpdm->io_base))
return -EBUSY; return PTR_ERR(mcpdm->io_base);
mcpdm->io_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!mcpdm->io_base)
return -ENOMEM;
mcpdm->irq = platform_get_irq(pdev, 0); mcpdm->irq = platform_get_irq(pdev, 0);
if (mcpdm->irq < 0) if (mcpdm->irq < 0)
......
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "omap-pcm.h"
#ifdef CONFIG_ARCH_OMAP1 #ifdef CONFIG_ARCH_OMAP1
#define pcm_omap1510() cpu_is_omap1510() #define pcm_omap1510() cpu_is_omap1510()
#else #else
...@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { ...@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
.buffer_bytes_max = 128 * 1024, .buffer_bytes_max = 128 * 1024,
}; };
static int omap_pcm_get_dma_buswidth(int num_bits)
{
int buswidth;
switch (num_bits) {
case 16:
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case 32:
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
buswidth = -EINVAL;
break;
}
return buswidth;
}
/* this may get called several times by oss emulation */ /* this may get called several times by oss emulation */
static int omap_pcm_hw_params(struct snd_pcm_substream *substream, static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
...@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
if (err) if (err)
return err; return err;
/* Override the *_dma addr_width if requested by the DAI driver */ snd_dmaengine_pcm_set_config_from_dai_data(substream,
if (dma_data->data_type) { snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); &config);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
config.dst_addr_width = buswidth;
else
config.src_addr_width = buswidth;
}
config.src_addr = dma_data->port_addr;
config.dst_addr = dma_data->port_addr;
config.src_maxburst = dma_data->packet_size;
config.dst_maxburst = dma_data->packet_size;
return dmaengine_slave_config(chan, &config); return dmaengine_slave_config(chan, &config);
} }
...@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct omap_pcm_dma_data *dma_data;
int ret = 0;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
/* Configure McBSP internal buffer usage */
if (dma_data->set_threshold)
dma_data->set_threshold(substream);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
break;
default:
ret = -EINVAL;
}
if (ret == 0)
ret = snd_dmaengine_pcm_trigger(substream, cmd);
return ret;
}
static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
{ {
snd_pcm_uframes_t offset; snd_pcm_uframes_t offset;
...@@ -175,20 +112,14 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) ...@@ -175,20 +112,14 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
static int omap_pcm_open(struct snd_pcm_substream *substream) static int omap_pcm_open(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct omap_pcm_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
&dma_data->dma_req); dma_data->filter_data);
}
static int omap_pcm_close(struct snd_pcm_substream *substream)
{
snd_dmaengine_pcm_close(substream);
return 0;
} }
static int omap_pcm_mmap(struct snd_pcm_substream *substream, static int omap_pcm_mmap(struct snd_pcm_substream *substream,
...@@ -204,11 +135,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -204,11 +135,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops omap_pcm_ops = { static struct snd_pcm_ops omap_pcm_ops = {
.open = omap_pcm_open, .open = omap_pcm_open,
.close = omap_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = omap_pcm_hw_params, .hw_params = omap_pcm_hw_params,
.hw_free = omap_pcm_hw_free, .hw_free = omap_pcm_hw_free,
.trigger = omap_pcm_trigger, .trigger = snd_dmaengine_pcm_trigger,
.pointer = omap_pcm_pointer, .pointer = omap_pcm_pointer,
.mmap = omap_pcm_mmap, .mmap = omap_pcm_mmap,
}; };
......
/*
* omap-pcm.h
*
* Copyright (C) 2008 Nokia Corporation
*
* Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
* Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
struct snd_pcm_substream;
struct omap_pcm_dma_data {
char *name; /* stream identifier */
int dma_req; /* DMA request line */
unsigned long port_addr; /* transmit/receive register */
void (*set_threshold)(struct snd_pcm_substream *substream);
int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm
* to decide the sDMA data type */
int packet_size; /* packet size only in PACKET mode */
};
#endif
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <sound/jack.h> #include <sound/jack.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
struct omap_twl4030 { struct omap_twl4030 {
int jack_detect; /* board can detect jack events */ int jack_detect; /* board can detect jack events */
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#define OMAP3_PANDORA_DAC_POWER_GPIO 118 #define OMAP3_PANDORA_DAC_POWER_GPIO 118
#define OMAP3_PANDORA_AMP_POWER_GPIO 14 #define OMAP3_PANDORA_AMP_POWER_GPIO 14
...@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, ...@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event) struct snd_kcontrol *k, int event)
{ {
int ret;
/* /*
* The PCM1773 DAC datasheet requires 1ms delay between switching * The PCM1773 DAC datasheet requires 1ms delay between switching
* VCC power on/off and /PD pin high/low * VCC power on/off and /PD pin high/low
*/ */
if (SND_SOC_DAPM_EVENT_ON(event)) { if (SND_SOC_DAPM_EVENT_ON(event)) {
regulator_enable(omap3pandora_dac_reg); ret = regulator_enable(omap3pandora_dac_reg);
if (ret) {
dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret);
return ret;
}
mdelay(1); mdelay(1);
gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
} else { } else {
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/tlv320aic23.h" #include "../codecs/tlv320aic23.h"
#define CODEC_CLOCK 12000000 #define CODEC_CLOCK 12000000
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "omap-mcbsp.h" #include "omap-mcbsp.h"
#include "omap-pcm.h"
#define RX51_TVOUT_SEL_GPIO 40 #define RX51_TVOUT_SEL_GPIO 40
#define RX51_JACK_DETECT_GPIO 177 #define RX51_JACK_DETECT_GPIO 177
......
...@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream) ...@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct platform_device *pdev = to_platform_device(rtd->platform->dev); struct platform_device *pdev = to_platform_device(rtd->platform->dev);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct mmp_dma_data *dma_data; struct mmp_dma_data dma_data;
struct resource *r; struct resource *r;
int ret;
r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream);
if (!r) if (!r)
...@@ -128,33 +127,11 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream) ...@@ -128,33 +127,11 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
snd_soc_set_runtime_hwparams(substream, snd_soc_set_runtime_hwparams(substream,
&mmp_pcm_hardware[substream->stream]); &mmp_pcm_hardware[substream->stream]);
dma_data = devm_kzalloc(&pdev->dev,
sizeof(struct mmp_dma_data), GFP_KERNEL);
if (dma_data == NULL)
return -ENOMEM;
dma_data->dma_res = r; dma_data.dma_res = r;
dma_data->ssp_id = cpu_dai->id; dma_data.ssp_id = cpu_dai->id;
ret = snd_dmaengine_pcm_open(substream, filter, dma_data); return snd_dmaengine_pcm_open(substream, filter, &dma_data);
if (ret) {
devm_kfree(&pdev->dev, dma_data);
return ret;
}
snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int mmp_pcm_close(struct snd_pcm_substream *substream)
{
struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct platform_device *pdev = to_platform_device(rtd->platform->dev);
snd_dmaengine_pcm_close(substream);
devm_kfree(&pdev->dev, dma_data);
return 0;
} }
static int mmp_pcm_mmap(struct snd_pcm_substream *substream, static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
...@@ -171,7 +148,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -171,7 +148,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
struct snd_pcm_ops mmp_pcm_ops = { struct snd_pcm_ops mmp_pcm_ops = {
.open = mmp_pcm_open, .open = mmp_pcm_open,
.close = mmp_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = mmp_pcm_hw_params, .hw_params = mmp_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger, .trigger = snd_dmaengine_pcm_trigger,
......
...@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data { ...@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data {
dma_cookie_t cookie; dma_cookie_t cookie;
unsigned int pos; unsigned int pos;
void *data;
}; };
static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
...@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( ...@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
return substream->runtime->private_data; return substream->runtime->private_data;
} }
/**
* snd_dmaengine_pcm_set_data - Set dmaengine substream private data
* @substream: PCM substream
* @data: Data to set
*/
void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
prtd->data = data;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
/**
* snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
* @substream: PCM substream
*
* Returns the data previously set with snd_dmaengine_pcm_set_data
*/
void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
return prtd->data;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
{ {
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
...@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, ...@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
slave_config->src_addr_width = buswidth; slave_config->src_addr_width = buswidth;
} }
slave_config->device_fc = false;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); 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) static void dmaengine_pcm_dma_complete(void *arg)
{ {
struct snd_pcm_substream *substream = arg; struct snd_pcm_substream *substream = arg;
......
...@@ -64,21 +64,7 @@ static int spear_pcm_open(struct snd_pcm_substream *substream) ...@@ -64,21 +64,7 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
if (ret) if (ret)
return ret; return ret;
ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data); return 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, static int spear_pcm_mmap(struct snd_pcm_substream *substream,
...@@ -93,7 +79,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -93,7 +79,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops spear_pcm_ops = { static struct snd_pcm_ops spear_pcm_ops = {
.open = spear_pcm_open, .open = spear_pcm_open,
.close = spear_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = spear_pcm_hw_params, .hw_params = spear_pcm_hw_params,
.hw_free = spear_pcm_hw_free, .hw_free = spear_pcm_hw_free,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra_asoc_utils.h" #include "tegra_asoc_utils.h"
#include "tegra20_ac97.h" #include "tegra20_ac97.h"
...@@ -393,14 +394,14 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ...@@ -393,14 +394,14 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
} }
ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1;
ac97->capture_dma_data.wrap = 4; ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ac97->capture_dma_data.width = 32; ac97->capture_dma_data.maxburst = 4;
ac97->capture_dma_data.req_sel = of_dma[1]; ac97->capture_dma_data.slave_id = of_dma[1];
ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
ac97->playback_dma_data.wrap = 4; ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ac97->playback_dma_data.width = 32; ac97->capture_dma_data.maxburst = 4;
ac97->playback_dma_data.req_sel = of_dma[1]; ac97->capture_dma_data.slave_id = of_dma[0];
ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component,
&tegra20_ac97_dai, 1); &tegra20_ac97_dai, 1);
......
...@@ -85,8 +85,8 @@ ...@@ -85,8 +85,8 @@
struct tegra20_ac97 { struct tegra20_ac97 {
struct clk *clk_ac97; struct clk *clk_ac97;
struct tegra_pcm_dma_params capture_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap; struct regmap *regmap;
int reset_gpio; int reset_gpio;
int sync_gpio; int sync_gpio;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra20_i2s.h" #include "tegra20_i2s.h"
...@@ -407,14 +408,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) ...@@ -407,14 +408,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
} }
i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
i2s->capture_dma_data.wrap = 4; i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.width = 32; i2s->capture_dma_data.maxburst = 4;
i2s->capture_dma_data.req_sel = dma_ch; i2s->capture_dma_data.slave_id = dma_ch;
i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
i2s->playback_dma_data.wrap = 4; i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_dma_data.width = 32; i2s->playback_dma_data.maxburst = 4;
i2s->playback_dma_data.req_sel = dma_ch; i2s->playback_dma_data.slave_id = dma_ch;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev)) {
......
...@@ -155,8 +155,8 @@ ...@@ -155,8 +155,8 @@
struct tegra20_i2s { struct tegra20_i2s {
struct snd_soc_dai_driver dai; struct snd_soc_dai_driver dai;
struct clk *clk_i2s; struct clk *clk_i2s;
struct tegra_pcm_dma_params capture_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap; struct regmap *regmap;
}; };
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra20_spdif.h" #include "tegra20_spdif.h"
...@@ -322,9 +323,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) ...@@ -322,9 +323,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
} }
spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
spdif->playback_dma_data.wrap = 4; spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
spdif->playback_dma_data.width = 32; spdif->capture_dma_data.maxburst = 4;
spdif->playback_dma_data.req_sel = dmareq->start; spdif->playback_dma_data.slave_id = dmareq->start;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev)) {
......
...@@ -462,8 +462,8 @@ ...@@ -462,8 +462,8 @@
struct tegra20_spdif { struct tegra20_spdif {
struct clk *clk_spdif_out; struct clk *clk_spdif_out;
struct tegra_pcm_dma_params capture_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap; struct regmap *regmap;
}; };
......
...@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev) ...@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
} }
int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
unsigned long *fiforeg, dma_addr_t *fiforeg,
unsigned long *reqsel) unsigned int *reqsel)
{ {
int channel; int channel;
u32 reg, val; u32 reg, val;
...@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif) ...@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
unsigned long *fiforeg, dma_addr_t *fiforeg,
unsigned long *reqsel) unsigned int *reqsel)
{ {
int channel; int channel;
u32 reg, val; u32 reg, val;
......
...@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif { ...@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif {
}; };
extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
unsigned long *fiforeg, dma_addr_t *fiforeg,
unsigned long *reqsel); unsigned int *reqsel);
extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif); extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif); extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif); extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
unsigned long *fiforeg, dma_addr_t *fiforeg,
unsigned long *reqsel); unsigned int *reqsel);
extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif); extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif); extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif); extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra30_ahub.h" #include "tegra30_ahub.h"
#include "tegra30_i2s.h" #include "tegra30_i2s.h"
...@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream, ...@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif, ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
&i2s->playback_dma_data.addr, &i2s->playback_dma_data.addr,
&i2s->playback_dma_data.req_sel); &i2s->playback_dma_data.slave_id);
i2s->playback_dma_data.wrap = 4; i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_dma_data.width = 32; i2s->playback_dma_data.maxburst = 4;
tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif, tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
i2s->playback_fifo_cif); i2s->playback_fifo_cif);
} else { } else {
ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif, ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
&i2s->capture_dma_data.addr, &i2s->capture_dma_data.addr,
&i2s->capture_dma_data.req_sel); &i2s->capture_dma_data.slave_id);
i2s->capture_dma_data.wrap = 4; i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.width = 32; i2s->capture_dma_data.maxburst = 4;
tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif, tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
i2s->capture_i2s_cif); i2s->capture_i2s_cif);
} }
......
...@@ -231,10 +231,10 @@ struct tegra30_i2s { ...@@ -231,10 +231,10 @@ struct tegra30_i2s {
struct clk *clk_i2s; struct clk *clk_i2s;
enum tegra30_ahub_txcif capture_i2s_cif; enum tegra30_ahub_txcif capture_i2s_cif;
enum tegra30_ahub_rxcif capture_fifo_cif; enum tegra30_ahub_rxcif capture_fifo_cif;
struct tegra_pcm_dma_params capture_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data;
enum tegra30_ahub_rxcif playback_i2s_cif; enum tegra30_ahub_rxcif playback_i2s_cif;
enum tegra30_ahub_txcif playback_fifo_cif; enum tegra30_ahub_txcif playback_fifo_cif;
struct tegra_pcm_dma_params playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap; struct regmap *regmap;
}; };
......
...@@ -73,24 +73,15 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream) ...@@ -73,24 +73,15 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int tegra_pcm_close(struct snd_pcm_substream *substream)
{
snd_dmaengine_pcm_close(substream);
return 0;
}
static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->platform->dev; struct device *dev = rtd->platform->dev;
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct tegra_pcm_dma_params *dmap;
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
int ret; int ret;
dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
ret = snd_hwparams_to_dma_slave_config(substream, params, ret = snd_hwparams_to_dma_slave_config(substream, params,
&slave_config); &slave_config);
if (ret) { if (ret) {
...@@ -98,16 +89,9 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -98,16 +89,9 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { snd_dmaengine_pcm_set_config_from_dai_data(substream,
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
slave_config.dst_addr = dmap->addr; &slave_config);
slave_config.dst_maxburst = 4;
} else {
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.src_addr = dmap->addr;
slave_config.src_maxburst = 4;
}
slave_config.slave_id = dmap->req_sel;
ret = dmaengine_slave_config(chan, &slave_config); ret = dmaengine_slave_config(chan, &slave_config);
if (ret < 0) { if (ret < 0) {
...@@ -138,7 +122,7 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -138,7 +122,7 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops tegra_pcm_ops = { static struct snd_pcm_ops tegra_pcm_ops = {
.open = tegra_pcm_open, .open = tegra_pcm_open,
.close = tegra_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = tegra_pcm_hw_params, .hw_params = tegra_pcm_hw_params,
.hw_free = tegra_pcm_hw_free, .hw_free = tegra_pcm_hw_free,
......
...@@ -31,13 +31,6 @@ ...@@ -31,13 +31,6 @@
#ifndef __TEGRA_PCM_H__ #ifndef __TEGRA_PCM_H__
#define __TEGRA_PCM_H__ #define __TEGRA_PCM_H__
struct tegra_pcm_dma_params {
unsigned long addr;
unsigned long wrap;
unsigned long width;
unsigned long req_sel;
};
int tegra_pcm_platform_register(struct device *dev); int tegra_pcm_platform_register(struct device *dev);
void tegra_pcm_platform_unregister(struct device *dev); void tegra_pcm_platform_unregister(struct device *dev);
......
...@@ -28,28 +28,19 @@ ...@@ -28,28 +28,19 @@
#include "ux500_msp_i2s.h" #include "ux500_msp_i2s.h"
#include "ux500_pcm.h" #include "ux500_pcm.h"
static struct snd_pcm_hardware ux500_pcm_hw_playback = { #define UX500_PLATFORM_MIN_RATE 8000
.info = SNDRV_PCM_INFO_INTERLEAVED | #define UX500_PLATFORM_MAX_RATE 48000
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_RESUME | #define UX500_PLATFORM_MIN_CHANNELS 1
SNDRV_PCM_INFO_PAUSE, #define UX500_PLATFORM_MAX_CHANNELS 8
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U16_BE,
.rates = SNDRV_PCM_RATE_KNOT,
.rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK,
.rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK,
.channels_min = UX500_PLATFORM_MIN_CHANNELS,
.channels_max = UX500_PLATFORM_MAX_CHANNELS,
.buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
.period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
.period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
.periods_min = UX500_PLATFORM_PERIODS_MIN,
.periods_max = UX500_PLATFORM_PERIODS_MAX,
};
static struct snd_pcm_hardware ux500_pcm_hw_capture = { #define UX500_PLATFORM_PERIODS_BYTES_MIN 128
#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
#define UX500_PLATFORM_PERIODS_MIN 2
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
static struct snd_pcm_hardware ux500_pcm_hw = {
.info = SNDRV_PCM_INFO_INTERLEAVED | .info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_RESUME |
...@@ -59,8 +50,8 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = { ...@@ -59,8 +50,8 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U16_BE, SNDRV_PCM_FMTBIT_U16_BE,
.rates = SNDRV_PCM_RATE_KNOT, .rates = SNDRV_PCM_RATE_KNOT,
.rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, .rate_min = UX500_PLATFORM_MIN_RATE,
.rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, .rate_max = UX500_PLATFORM_MAX_RATE,
.channels_min = UX500_PLATFORM_MIN_CHANNELS, .channels_min = UX500_PLATFORM_MIN_CHANNELS,
.channels_max = UX500_PLATFORM_MAX_CHANNELS, .channels_max = UX500_PLATFORM_MAX_CHANNELS,
.buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
...@@ -90,8 +81,6 @@ static void ux500_pcm_dma_hw_free(struct device *dev, ...@@ -90,8 +81,6 @@ static void ux500_pcm_dma_hw_free(struct device *dev,
static int ux500_pcm_open(struct snd_pcm_substream *substream) static int ux500_pcm_open(struct snd_pcm_substream *substream)
{ {
int stream_id = substream->pstr->stream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *dai = rtd->cpu_dai; struct snd_soc_dai *dai = rtd->cpu_dai;
struct device *dev = dai->dev; struct device *dev = dai->dev;
...@@ -104,26 +93,7 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream) ...@@ -104,26 +93,7 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
snd_pcm_stream_str(substream)); snd_pcm_stream_str(substream));
dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__);
if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_set_runtime_hwparams(substream, &ux500_pcm_hw);
snd_soc_set_runtime_hwparams(substream,
&ux500_pcm_hw_playback);
else
snd_soc_set_runtime_hwparams(substream,
&ux500_pcm_hw_capture);
/* ensure that buffer size is a multiple of period size */
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0) {
dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n",
__func__, ret);
return ret;
}
dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__,
snd_pcm_stream_str(substream));
runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
ux500_pcm_hw_playback : ux500_pcm_hw_capture;
mem_data_width = STEDMA40_HALFWORD_WIDTH; mem_data_width = STEDMA40_HALFWORD_WIDTH;
...@@ -164,20 +134,6 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream) ...@@ -164,20 +134,6 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
return ret; return ret;
} }
snd_dmaengine_pcm_set_data(substream, dma_cfg);
return 0;
}
static int ux500_pcm_close(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *dai = rtd->cpu_dai;
dev_dbg(dai->dev, "%s: Enter\n", __func__);
snd_dmaengine_pcm_close(substream);
return 0; return 0;
} }
...@@ -255,7 +211,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream, ...@@ -255,7 +211,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops ux500_pcm_ops = { static struct snd_pcm_ops ux500_pcm_ops = {
.open = ux500_pcm_open, .open = ux500_pcm_open,
.close = ux500_pcm_close, .close = snd_dmaengine_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = ux500_pcm_hw_params, .hw_params = ux500_pcm_hw_params,
.hw_free = ux500_pcm_hw_free, .hw_free = ux500_pcm_hw_free,
......
...@@ -18,20 +18,6 @@ ...@@ -18,20 +18,6 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000
#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000
#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000
#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000
#define UX500_PLATFORM_MIN_CHANNELS 1
#define UX500_PLATFORM_MAX_CHANNELS 8
#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
#define UX500_PLATFORM_PERIODS_MIN 2
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
int ux500_pcm_register_platform(struct platform_device *pdev); int ux500_pcm_register_platform(struct platform_device *pdev);
int ux500_pcm_unregister_platform(struct platform_device *pdev); int ux500_pcm_unregister_platform(struct platform_device *pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment