summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/tegra_i2s_audio.c7
-rw-r--r--arch/arm/mach-tegra/tegra_spdif_audio.c22
2 files changed, 20 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c
index c36fe3b5671f..56857beae63a 100644
--- a/arch/arm/mach-tegra/tegra_i2s_audio.c
+++ b/arch/arm/mach-tegra/tegra_i2s_audio.c
@@ -690,12 +690,17 @@ static void request_stop_nosync(struct audio_stream *as)
pr_debug("%s\n", __func__);
if (!as->stop) {
as->stop = true;
- wait_till_stopped(as);
+ if (pending_buffer_requests(as))
+ wait_till_stopped(as);
for (i = 0; i < as->num_bufs; i++) {
init_completion(&as->comp[i]);
complete(&as->comp[i]);
}
}
+ if (!tegra_dma_is_empty(as->dma_chan))
+ pr_err("%s: DMA not empty!\n", __func__);
+ /* Stop the DMA then dequeue anything that's in progress. */
+ tegra_dma_cancel(as->dma_chan);
as->active = false; /* applies to recording only */
pr_debug("%s: done\n", __func__);
}
diff --git a/arch/arm/mach-tegra/tegra_spdif_audio.c b/arch/arm/mach-tegra/tegra_spdif_audio.c
index 3fb90905bc87..64a85c28efaa 100644
--- a/arch/arm/mach-tegra/tegra_spdif_audio.c
+++ b/arch/arm/mach-tegra/tegra_spdif_audio.c
@@ -455,12 +455,17 @@ static void request_stop_nosync(struct audio_stream *as)
pr_debug("%s\n", __func__);
if (!as->stop) {
as->stop = true;
- wait_till_stopped(as);
+ if (pending_buffer_requests(as))
+ wait_till_stopped(as);
for (i = 0; i < as->num_bufs; i++) {
init_completion(&as->comp[i]);
complete(&as->comp[i]);
}
}
+ if (!tegra_dma_is_empty(as->dma_chan))
+ pr_err("%s: DMA not empty!\n", __func__);
+ /* Stop the DMA then dequeue anything that's in progress. */
+ tegra_dma_cancel(as->dma_chan);
as->active = false; /* applies to recording only */
pr_debug("%s: done\n", __func__);
}
@@ -538,13 +543,9 @@ static void dma_tx_complete_callback(struct tegra_dma_req *req)
complete(&aos->comp[req_num]);
- if (stop_playback_if_necessary(aos)) {
- pr_debug("%s: done (stopped)\n", __func__);
- if (!completion_done(&aos->stop_completion)) {
- pr_debug("%s: signalling stop completion\n", __func__);
- complete(&aos->stop_completion);
- }
- return;
+ if (!pending_buffer_requests(aos)) {
+ pr_debug("%s: Playback underflow", __func__);
+ complete(&aos->stop_completion);
}
}
@@ -724,6 +725,8 @@ static long tegra_spdif_out_ioctl(struct file *file,
request_stop_nosync(aos);
pr_debug("%s: flushed\n", __func__);
}
+ if (stop_playback_if_necessary(aos))
+ pr_debug("%s: done (stopped)\n", __func__);
aos->stop = false;
break;
case TEGRA_AUDIO_OUT_SET_NUM_BUFS: {
@@ -747,6 +750,7 @@ static long tegra_spdif_out_ioctl(struct file *file,
if (rc < 0)
break;
aos->num_bufs = num;
+ sound_ops->setup(ads);
}
break;
case TEGRA_AUDIO_OUT_GET_NUM_BUFS:
@@ -801,6 +805,8 @@ static int tegra_spdif_out_release(struct inode *inode, struct file *file)
mutex_lock(&ads->out.lock);
ads->out.opened = 0;
request_stop_nosync(&ads->out);
+ if (stop_playback_if_necessary(&ads->out))
+ pr_debug("%s: done (stopped)\n", __func__);
allow_suspend(&ads->out);
mutex_unlock(&ads->out.lock);
pr_debug("%s: done\n", __func__);