[ARM] tegra_i2s/spdif_audio: move allow_suspend to a work queue

Since pm_qos_update_request() may block, we need to make sure that
allow_suspend is always called in process context.

Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
Iliyan Malchev
2010-11-05 13:03:35 -07:00
parent dbe75d43f5
commit 86d007b0f8
2 changed files with 30 additions and 4 deletions

View File

@@ -44,6 +44,8 @@
#include <linux/delay.h>
#include <linux/tegra_audio.h>
#include <linux/pm.h>
#include <linux/workqueue.h>
#include <mach/dma.h>
#include <mach/iomap.h>
#include <mach/i2s.h>
@@ -90,6 +92,7 @@ struct audio_stream {
struct tegra_dma_req dma_req;
struct pm_qos_request_list pm_qos;
struct work_struct allow_suspend_work;
};
struct i2s_pio_stats {
@@ -218,13 +221,22 @@ static inline struct audio_driver_state *ads_from_in(
static inline void prevent_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
cancel_work_sync(&as->allow_suspend_work);
pm_qos_update_request(&as->pm_qos, 0);
}
static void allow_suspend_worker(struct work_struct *w)
{
struct audio_stream *as = container_of(w,
struct audio_stream, allow_suspend_work);
pr_debug("%s\n", __func__);
pm_qos_update_request(&as->pm_qos, PM_QOS_DEFAULT_VALUE);
}
static inline void allow_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
pm_qos_update_request(&as->pm_qos, PM_QOS_DEFAULT_VALUE);
schedule_work(&as->allow_suspend_work);
}
#define I2S_I2S_FIFO_TX_BUSY I2S_I2S_STATUS_FIFO1_BSY
@@ -2451,6 +2463,7 @@ static int tegra_audio_probe(struct platform_device *pdev)
if (rc < 0)
return rc;
INIT_WORK(&state->out.allow_suspend_work, allow_suspend_worker);
pm_qos_add_request(&state->out.pm_qos, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
@@ -2488,6 +2501,7 @@ static int tegra_audio_probe(struct platform_device *pdev)
if (rc < 0)
return rc;
INIT_WORK(&state->in.allow_suspend_work, allow_suspend_worker);
pm_qos_add_request(&state->in.pm_qos, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);

View File

@@ -46,6 +46,7 @@
#include <linux/pm_qos_params.h>
#include <linux/delay.h>
#include <linux/tegra_audio.h>
#include <linux/workqueue.h>
#include <mach/dma.h>
#include <mach/iomap.h>
@@ -88,6 +89,7 @@ struct audio_stream {
struct tegra_dma_req dma_req;
struct pm_qos_request_list pm_qos;
struct work_struct allow_suspend_work;
};
struct spdif_pio_stats {
@@ -162,13 +164,22 @@ static inline struct audio_driver_state *ads_from_out(
static inline void prevent_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
cancel_work_sync(&as->allow_suspend_work);
pm_qos_update_request(&as->pm_qos, 0);
}
static void allow_suspend_worker(struct work_struct *w)
{
struct audio_stream *as = container_of(w,
struct audio_stream, allow_suspend_work);
pr_debug("%s\n", __func__);
pm_qos_update_request(&as->pm_qos, PM_QOS_DEFAULT_VALUE);
}
static inline void allow_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
pm_qos_update_request(&as->pm_qos, PM_QOS_DEFAULT_VALUE);
schedule_work(&as->allow_suspend_work);
}
#define I2S_I2S_FIFO_TX_BUSY I2S_I2S_STATUS_FIFO1_BSY
@@ -1337,6 +1348,7 @@ static int tegra_spdif_probe(struct platform_device *pdev)
if (rc < 0)
return rc;
INIT_WORK(&state->out.allow_suspend_work, allow_suspend_worker);
pm_qos_add_request(&state->out.pm_qos, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);