diff options
author | Iliyan Malchev <malchev@google.com> | 2010-10-02 17:31:54 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2010-10-06 16:29:09 -0700 |
commit | d25a67d8d27f5ac796ceeade975d08350786b01c (patch) | |
tree | d1e8da36a949f811ada7101c43c0e7c71bfcec80 /arch/arm/mach-tegra/tegra_i2s_audio.c | |
parent | d7675db7251e3d121cb0ef418285c5552e6707fa (diff) |
[ARM] tegra_i2s_audio: use pm_qos to prevent DMA-callback delays
Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_i2s_audio.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra_i2s_audio.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c index 0df7ef033fe5..4cbcf9897095 100644 --- a/arch/arm/mach-tegra/tegra_i2s_audio.c +++ b/arch/arm/mach-tegra/tegra_i2s_audio.c @@ -40,6 +40,7 @@ #include <linux/io.h> #include <linux/ktime.h> #include <linux/sysfs.h> +#include <linux/pm_qos_params.h> #include <linux/tegra_audio.h> @@ -81,6 +82,8 @@ struct audio_stream { spinlock_t dma_req_lock; /* guards dma_has_it */ int dma_has_it; struct tegra_dma_req dma_req; + + struct pm_qos_request_list *pm_qos; }; struct i2s_pio_stats { @@ -527,6 +530,8 @@ static int start_playback(struct audio_stream *aos) pr_debug("%s: starting playback\n", __func__); rc = sound_ops->start_playback(aos); spin_unlock_irqrestore(&aos->dma_req_lock, flags); + if (!rc) + pm_qos_update_request(aos->pm_qos, 0); return rc; } @@ -542,6 +547,8 @@ static int start_recording_if_necessary(struct audio_stream *ais) rc = sound_ops->start_recording(ais); } spin_unlock_irqrestore(&ais->dma_req_lock, flags); + if (!rc) + pm_qos_update_request(ais->pm_qos, 0); return rc; } @@ -554,6 +561,7 @@ static bool stop_playback_if_necessary(struct audio_stream *aos) if (aos->active) aos->errors++; spin_unlock_irqrestore(&aos->dma_req_lock, flags); + pm_qos_update_request(aos->pm_qos, PM_QOS_DEFAULT_VALUE); return true; } spin_unlock_irqrestore(&aos->dma_req_lock, flags); @@ -582,6 +590,7 @@ static bool stop_recording(struct audio_stream *ais) rc = wait_for_completion_interruptible( &ais->stop_completion); pr_debug("%s: done: %d\n", __func__, rc); + pm_qos_update_request(ais->pm_qos, PM_QOS_DEFAULT_VALUE); return true; } @@ -2175,6 +2184,24 @@ static int tegra_audio_probe(struct platform_device *pdev) if (rc < 0) return rc; + state->in.pm_qos = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + if (!state->in.pm_qos) { + dev_err(&pdev->dev, + "%s: could not register pm_qos handle for input\n", + __func__); + return -EIO; + } + + state->out.pm_qos = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + if (!state->out.pm_qos) { + dev_err(&pdev->dev, + "%s: could not register pm_qos handle for output\n", + __func__); + return -EIO; + } + if (request_irq(state->irq, i2s_interrupt, IRQF_DISABLED, state->pdev->name, state) < 0) { dev_err(&pdev->dev, |