summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorIsaac Richards <irichards@nvidia.com>2012-01-24 12:13:05 -0500
committerVarun Colbert <vcolbert@nvidia.com>2012-01-30 12:31:41 -0800
commita97621dc0ddf4983cdb9a17af3caffe2903abea7 (patch)
tree3d7d8e65011e4feb44fe75deb8cf49959ee5ae15 /drivers/media
parenta882618b895bfad07b59f97e70964fc3adda82e0 (diff)
media: video: tegra: nvavp: Fix suspend/resume
Mark host1x as busy only when clocks are enabled, instead of unconditionally at load/unload and suspend/resume time. Shutdown the avp device entirely during suspend, and restart it on resume if if necessary. Bug 929279 Reviewed-on: http://git-master/r/77054 Change-Id: I0c66c26302fe307bea396e1c547a67b3417e26ec Signed-off-by: Isaac Richards <irichards@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/77749 Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index bf4bac987677..58c9f8059a4c 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -89,6 +89,7 @@ struct nvavp_info {
struct mutex open_lock;
int refcount;
+ int initialized;
struct work_struct clock_disable_work;
@@ -145,6 +146,7 @@ static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id)
static void nvavp_clk_ctrl(struct nvavp_info *nvavp, u32 clk_en)
{
if (clk_en && !nvavp->clk_enabled) {
+ nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
clk_enable(nvavp->bsev_clk);
clk_enable(nvavp->vde_clk);
clk_set_rate(nvavp->emc_clk, nvavp->emc_clk_rate);
@@ -159,6 +161,7 @@ static void nvavp_clk_ctrl(struct nvavp_info *nvavp, u32 clk_en)
clk_disable(nvavp->vde_clk);
clk_set_rate(nvavp->emc_clk, 0);
clk_set_rate(nvavp->sclk, 0);
+ nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
nvavp->clk_enabled = 0;
dev_dbg(&nvavp->nvhost_dev->dev, "%s: resetting emc_clk "
"and sclk\n", __func__);
@@ -289,12 +292,16 @@ static void nvavp_halt_vde(struct nvavp_info *nvavp)
clk_disable(nvavp->bsev_clk);
tegra_periph_reset_assert(nvavp->vde_clk);
clk_disable(nvavp->vde_clk);
+ nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
nvavp->clk_enabled = 0;
}
}
static int nvavp_reset_vde(struct nvavp_info *nvavp)
{
+ if (!nvavp->clk_enabled)
+ nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
+
clk_enable(nvavp->bsev_clk);
tegra_periph_reset_assert(nvavp->bsev_clk);
udelay(2);
@@ -696,6 +703,9 @@ static int nvavp_init(struct nvavp_info *nvavp)
char fw_os_file[32];
int ret = 0;
+ if (nvavp->initialized)
+ return ret;
+
#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
/* paddr is any address returned from nvmap_pin */
/* vaddr is AVP_KERNEL_VIRT_BASE */
@@ -767,12 +777,17 @@ static int nvavp_init(struct nvavp_info *nvavp)
nvavp_reset_avp(nvavp, nvavp->os_info.reset_addr);
enable_irq(nvavp->mbox_from_avp_pend_irq);
+ nvavp->initialized = 1;
+
err_exit:
return ret;
}
static void nvavp_uninit(struct nvavp_info *nvavp)
{
+ if (!nvavp->initialized)
+ return;
+
disable_irq(nvavp->mbox_from_avp_pend_irq);
cancel_work_sync(&nvavp->clock_disable_work);
@@ -784,6 +799,8 @@ static void nvavp_uninit(struct nvavp_info *nvavp)
clk_disable(nvavp->sclk);
clk_disable(nvavp->emc_clk);
+
+ nvavp->initialized = 0;
}
static int nvavp_set_clock_ioctl(struct file *filp, unsigned int cmd,
@@ -1024,7 +1041,6 @@ static int tegra_nvavp_open(struct inode *inode, struct file *filp)
filp->private_data = clientctx;
- nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
mutex_unlock(&nvavp->open_lock);
return ret;
@@ -1039,7 +1055,6 @@ static int tegra_nvavp_release(struct inode *inode, struct file *filp)
dev_dbg(&nvavp->nvhost_dev->dev, "%s: ++\n", __func__);
filp->private_data = NULL;
- nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
mutex_lock(&nvavp->open_lock);
@@ -1357,18 +1372,33 @@ static int tegra_nvavp_remove(struct nvhost_device *ndev)
static int tegra_nvavp_suspend(struct nvhost_device *ndev, pm_message_t state)
{
struct nvavp_info *nvavp = nvhost_get_drvdata(ndev);
+ int ret = 0;
- if (nvavp->refcount)
- nvhost_module_idle(ndev);
- return 0;
+ mutex_lock(&nvavp->open_lock);
+
+ if (nvavp->refcount) {
+ if (nvavp_check_idle(nvavp))
+ nvavp_uninit(nvavp);
+ else
+ ret = -EBUSY;
+ }
+
+ mutex_unlock(&nvavp->open_lock);
+
+ return ret;
}
static int tegra_nvavp_resume(struct nvhost_device *ndev)
{
struct nvavp_info *nvavp = nvhost_get_drvdata(ndev);
+ mutex_lock(&nvavp->open_lock);
+
if (nvavp->refcount)
- nvhost_module_busy(ndev);
+ nvavp_init(nvavp);
+
+ mutex_unlock(&nvavp->open_lock);
+
return 0;
}
#endif