summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorNicolin Chen <b42378@freescale.com>2013-10-08 16:39:39 +0800
committerJason Liu <r64343@freescale.com>2013-10-30 09:55:52 +0800
commit0c7a25933a30ed812fe91ba28ca0ae5d3b76dac8 (patch)
tree68640af80bfeb53012d01735763051ec0f0ec5a5 /sound
parent9d531128378a75e927f9f1f24a2b2af502d4bdec (diff)
ENGR00281859-3 ASoC: fsl: Prepare dmaengine before submit it
ASRC and HDMI audio might meet unexpected stop, 'ctrl+z' for example, and then disable its sdma channel. But after 'fg' resume, because sdma channel's status has already been set into DMA_ERROR, we need to prepare dmaengine again to clear its error state, otherwise sdma driver would bypass its channel enabling and 'Input/Output error' would happen to ALSA lib. The combined prepare and submit are also being used in soc-dmaengine, the common ASoC dmaengine driver. And since we already use a proper way to handle sdma channel status, there's no need to make an exception for HDMI any more, so drop it. Signed-off-by: Nicolin Chen <b42378@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/fsl_asrc.c31
-rw-r--r--sound/soc/fsl/imx-hdmi-dma.c35
2 files changed, 47 insertions, 19 deletions
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index dc230ffee9dd..d91484f236c9 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -133,13 +133,6 @@ static int asrc_p2p_request_channel(struct snd_pcm_substream *substream)
dev_err(rtd->card->dev, "can not config dma channel\n");
goto error;
}
- asrc_p2p->asrc_p2p_desc = dmaengine_prep_dma_cyclic(chan, 0xffff, 64,
- 64, DMA_DEV_TO_DEV, 0);
- if (!asrc_p2p->asrc_p2p_desc) {
- dev_err(&chan->dev->device,
- "cannot prepare slave dma\n");
- goto error;
- }
return 0;
error:
@@ -274,16 +267,38 @@ static int fsl_asrc_p2p_hw_free(struct snd_pcm_substream *substream,
return 0;
}
+static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream,
+ struct fsl_asrc_p2p *asrc_p2p)
+{
+ struct dma_async_tx_descriptor *desc = asrc_p2p->asrc_p2p_desc;
+ struct dma_chan *chan = asrc_p2p->asrc_p2p_dma_chan;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+
+ desc = dmaengine_prep_dma_cyclic(chan, 0xffff, 64, 64, DMA_DEV_TO_DEV, 0);
+ if (!desc) {
+ dev_err(dev, "failed to prepare slave dma\n");
+ return -EINVAL;
+ }
+
+ dmaengine_submit(desc);
+
+ return 0;
+}
+
static int fsl_asrc_p2p_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
+ int ret;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(asrc_p2p->asrc_p2p_desc);
+ ret = fsl_asrc_dma_prepare_and_submit(substream, asrc_p2p);
+ if (ret)
+ return ret;
dma_async_issue_pending(asrc_p2p->asrc_p2p_dma_chan);
asrc_p2p->asrc_ops.asrc_p2p_start_conv(asrc_p2p->asrc_index);
break;
diff --git a/sound/soc/fsl/imx-hdmi-dma.c b/sound/soc/fsl/imx-hdmi-dma.c
index 0dc32dcf98b5..4155122f8d0e 100644
--- a/sound/soc/fsl/imx-hdmi-dma.c
+++ b/sound/soc/fsl/imx-hdmi-dma.c
@@ -697,16 +697,6 @@ static int hdmi_sdma_config(struct snd_pcm_substream *substream,
return -EINVAL;
}
- priv->desc = dmaengine_prep_dma_cyclic(priv->dma_channel, 0, 0, 0,
- DMA_TRANS_NONE, 0);
- if (!priv->desc) {
- dev_err(dev, "failed to prepare slave dma\n");
- return -EINVAL;
- }
-
- priv->desc->callback = hdmi_sdma_callback;
- priv->desc->callback_param = (void *)priv;
-
return 0;
}
@@ -810,12 +800,33 @@ static void hdmi_dma_trigger_init(struct snd_pcm_substream *substream,
hdmi_writeb(status, HDMI_IH_AHBDMAAUD_STAT0);
}
+static int hdmi_dma_prepare_and_submit(struct snd_pcm_substream *substream,
+ struct hdmi_dma_priv *priv)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+
+ priv->desc = dmaengine_prep_dma_cyclic(priv->dma_channel, 0, 0, 0,
+ DMA_TRANS_NONE, 0);
+ if (!priv->desc) {
+ dev_err(dev, "failed to prepare slave dma\n");
+ return -EINVAL;
+ }
+
+ priv->desc->callback = hdmi_sdma_callback;
+ priv->desc->callback_param = (void *)priv;
+ dmaengine_submit(priv->desc);
+
+ return 0;
+}
+
static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct hdmi_dma_priv *priv = runtime->private_data;
struct device *dev = rtd->platform->dev;
+ int ret;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -831,7 +842,9 @@ static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
hdmi_audio_writeb(AHB_DMA_START, START, 0x1);
hdmi_dma_irq_set(false);
hdmi_set_dma_mode(1);
- dmaengine_submit(priv->desc);
+ ret = hdmi_dma_prepare_and_submit(substream, priv);
+ if (ret)
+ return ret;
dma_async_issue_pending(priv->desc->chan);
break;
case SNDRV_PCM_TRIGGER_STOP: