msm: 8660: audio: HDMI: Fix the HDMI DMA stop issue
LPA_IF dma channel is disabled without checking the per count value.
Because of this dma channel is not functional after few iterations
of continuous playback. Fix this issue by checking the dma per count
value to stop before disabling the LPA_IF dma channel.
Change-Id: Ie9e9a9337ca2c4b76cebd99cd3eb98137be85b89
Signed-off-by: Deepa Madiregama <dmadireg@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
index 5c9bfb5..1970d0b 100644
--- a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
+++ b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -202,6 +202,11 @@
#define LPAIF_DMA_SET_BUFF_CNT(x) DMA_CTRL_ADDR(x, 0x20)
#define LPAIF_DMA_SET_PER_CNT(x) DMA_CTRL_ADDR(x, 0x24)
+#define LPAIF_DMA_PER_CNT_PER_CNT_MASK 0x000FFFFF
+#define LPAIF_DMA_PER_CNT_PER_CNT_SHIFT 0
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK 0x00F00000
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT 20
+
/* channel assignments */
#define DMA_CH_0 0
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 97dad67..3965a75 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -14,5 +14,6 @@
#define __MSM_HDMI_AUDIO_H
int hdmi_audio_enable(bool on , u32 fifo_water_mark);
+int hdmi_audio_packet_enable(bool on);
#endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index 11d5d05..16258eb 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -74,8 +74,6 @@
pending = (intrsrc
& (UNDER_CH(dma_ch) | PER_CH(dma_ch) | ERR_CH(dma_ch)));
- pr_debug("pending = 0x%08x\n", pending);
-
if (pending & UNDER_CH(dma_ch))
pr_err("under run\n");
if (pending & ERR_CH(dma_ch))
@@ -104,10 +102,9 @@
dai_start_hdmi(lpa_if->dma_ch);
- mb();
-
hdmi_audio_enable(1, HDMI_AUDIO_FIFO_WATER_MARK);
- mb();
+
+ hdmi_audio_packet_enable(1);
return 0;
}
@@ -121,7 +118,7 @@
dma_params.period_size = lpa_if->dma_period_sz;
dma_params.channels = 2;
- lpa_if->dma_ch = 0;
+ lpa_if->dma_ch = 4;
dai_set_params(lpa_if->dma_ch, &dma_params);
register_dma_irq_handler(lpa_if->dma_ch, lpa_if_irq, (void *)lpa_if);
@@ -232,6 +229,7 @@
lpa_if_ptr->dma_buf = 0;
core_req_bus_bandwith(AUDIO_IF_BUS_ID, 100000, 0);
+ mb();
return 0;
}
@@ -244,9 +242,6 @@
const char __user *start = buf;
int xfer, rc;
- pr_debug("count %u cpu_buf %d dma_buf %d\n",
- (unsigned int)count, lpa_if->cpu_buf, lpa_if->dma_buf);
-
mutex_lock(&lpa_if->lock);
if (dma_buf_index < 2) {
@@ -259,6 +254,7 @@
goto end;
}
+ mb();
pr_debug("prefill: count %u audio_buf[%u].size %u\n",
count, dma_buf_index, ab->size);
@@ -315,15 +311,20 @@
static int lpa_if_release(struct inode *inode, struct file *file)
{
struct lpa_if *lpa_if = file->private_data;
- hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
- smp_mb();
+ hdmi_audio_packet_enable(0);
+
+ wait_for_dma_cnt_stop(lpa_if->dma_ch);
+
+ hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
if (lpa_if->config) {
unregister_dma_irq_handler(lpa_if->dma_ch);
dai_stop_hdmi(lpa_if->dma_ch);
lpa_if->config = 0;
}
+ core_req_bus_bandwith(AUDIO_IF_BUS_ID, 0, 0);
+
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
index 4eeb654..9b8346d 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
@@ -102,7 +102,7 @@
snddev_hdmi_active = 0;
if (snddev_hdmi_data->on_apps) {
- pr_debug("%s open done\n", dev_info->name);
+ pr_debug("%s Closed\n", dev_info->name);
mutex_unlock(&snddev_hdmi_lock);
return 0;