summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorChris Fries <C.Fries@motorola.com>2010-12-02 14:37:47 -0600
committerIliyan Malchev <malchev@google.com>2010-12-02 14:08:50 -0800
commit3d8c542754a0ac192eba87726aa4462fbde43853 (patch)
tree7bfdea27e42551f88be4c6590dd93ce4434293d7 /arch
parent66feb38823706e829aae1df59afb506e26fd58db (diff)
[ARM] tegra_i2s_audio: don't turn off hardware during over/underflow
-- Leave I2S running during underflow, for a couple of reasons. First, the I2S buffers a few samples, and if we get a new write before those samples are flushed, we will keep continuous audio Second, we burn CPU time stopping and restarting the HW frequently. -- Fix TEGRA_AUDIO_IN/OUT_GET/SET_NUM_BUFS, was causing DMA to read/write to null HW address. Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra_i2s_audio.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c
index 900ac042c9fa..c36fe3b5671f 100644
--- a/arch/arm/mach-tegra/tegra_i2s_audio.c
+++ b/arch/arm/mach-tegra/tegra_i2s_audio.c
@@ -821,13 +821,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\n", __func__);
+ complete(&aos->stop_completion);
}
}
@@ -846,6 +842,9 @@ static void dma_rx_complete_callback(struct tegra_dma_req *req)
complete(&ais->comp[req_num]);
+ if (!pending_buffer_requests(ais))
+ pr_debug("%s: Capture overflow\n", __func__);
+
spin_unlock_irqrestore(&ais->dma_req_lock, flags);
}
@@ -1083,6 +1082,8 @@ static long tegra_audio_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: {
@@ -1106,6 +1107,7 @@ static long tegra_audio_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:
@@ -1260,10 +1262,11 @@ static long tegra_audio_in_ioctl(struct file *file,
if (rc < 0)
break;
ais->num_bufs = num;
+ sound_ops->setup(ads);
}
break;
case TEGRA_AUDIO_IN_GET_NUM_BUFS:
- if (copy_from_user((void __user *)arg,
+ if (copy_to_user((void __user *)arg,
&ais->num_bufs, sizeof(ais->num_bufs)))
rc = -EFAULT;
break;
@@ -1399,6 +1402,8 @@ static int tegra_audio_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__);