diff options
author | Chris Fries <C.Fries@motorola.com> | 2010-12-02 14:37:47 -0600 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2010-12-02 14:08:50 -0800 |
commit | 3d8c542754a0ac192eba87726aa4462fbde43853 (patch) | |
tree | 7bfdea27e42551f88be4c6590dd93ce4434293d7 | |
parent | 66feb38823706e829aae1df59afb506e26fd58db (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>
-rw-r--r-- | arch/arm/mach-tegra/tegra_i2s_audio.c | 21 |
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__); |