diff options
author | Hyung Taek Ryoo <hryoo@nvidia.com> | 2012-05-11 11:19:00 -0700 |
---|---|---|
committer | Lokesh Pathak <lpathak@nvidia.com> | 2012-05-14 03:35:02 -0700 |
commit | fa2c352e1c7430f525265ea78301f41210555dcf (patch) | |
tree | 0e0146045784d102dd0eae1f5ff1dcbd622ed8b3 /drivers/media | |
parent | dfa3daebbc8dbe3ccc8e72400359dfce29053222 (diff) |
video: tegra: nvavp: Add a clock request ioctl
Add nvavp_force_clock_stay_on ioctl which provides way for user-mode driver
to request the VDE/BSEV clocks. This change is to fix a hang during DRM
session close. The AVP driver may have already turned
the clocks off since playback was paused prior to session teardown. This
situation can cause the OTF driver on secure side to hang if the VDE/BSEV
clocks are not explicitly enabled prior to calling session terminate.
Bug 960130
Bug 961015
Bug 979102
Change-Id: I3c09a6766f50a01ed04fbfd03e723ad9e978909f
Reviewed-on: http://git-master/r/102024
Reviewed-by: Prajakta Gudadhe <pgudadhe@nvidia.com>
Tested-by: Prajakta Gudadhe <pgudadhe@nvidia.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/tegra/nvavp/nvavp_dev.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c index 14e4dc218241..4627c514622a 100644 --- a/drivers/media/video/tegra/nvavp/nvavp_dev.c +++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c @@ -127,6 +127,7 @@ struct nvavp_clientctx { struct nvmap_handle_ref *gather_mem; int num_relocs; struct nvavp_info *nvavp; + u32 clk_reqs; }; static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id) @@ -1039,6 +1040,38 @@ static int nvavp_wake_avp_ioctl(struct file *filp, unsigned int cmd, return 0; } +static int nvavp_force_clock_stay_on_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct nvavp_clientctx *clientctx = filp->private_data; + struct nvavp_info *nvavp = clientctx->nvavp; + struct nvavp_clock_stay_on_state_args clock; + + if (copy_from_user(&clock, (void __user *)arg, + sizeof(struct nvavp_clock_stay_on_state_args))) + return -EFAULT; + + dev_dbg(&nvavp->nvhost_dev->dev, "%s: state=%d\n", + __func__, clock.state); + + if (clock.state != NVAVP_CLOCK_STAY_ON_DISABLED && + clock.state != NVAVP_CLOCK_STAY_ON_ENABLED) { + dev_err(&nvavp->nvhost_dev->dev, "%s: invalid argument=%d\n", + __func__, clock.state); + return -EINVAL; + } + + mutex_lock(&nvavp->open_lock); + if (clock.state) { + if (clientctx->clk_reqs++ == 0) + nvavp_clks_enable(nvavp); + } else { + if (--clientctx->clk_reqs == 0) + nvavp_clks_disable(nvavp); + } + mutex_unlock(&nvavp->open_lock); + return 0; +} static int tegra_nvavp_open(struct inode *inode, struct file *filp) { @@ -1092,6 +1125,10 @@ static int tegra_nvavp_release(struct inode *inode, struct file *filp) goto out; } + /* if this client had any requests, drop our clk ref */ + if (clientctx->clk_reqs) + nvavp_clks_disable(nvavp); + if (nvavp->refcount > 0) nvavp->refcount--; if (!nvavp->refcount) @@ -1133,6 +1170,9 @@ static long tegra_nvavp_ioctl(struct file *filp, unsigned int cmd, case NVAVP_IOCTL_WAKE_AVP: ret = nvavp_wake_avp_ioctl(filp, cmd, arg); break; + case NVAVP_IOCTL_FORCE_CLOCK_STAY_ON: + ret = nvavp_force_clock_stay_on_ioctl(filp, cmd, arg); + break; default: ret = -EINVAL; break; |