From e929f231fb47ae745934386f53cfb7ea5b5a257b Mon Sep 17 00:00:00 2001 From: Hyung Taek Ryoo Date: Mon, 16 Apr 2012 11:33:49 -0700 Subject: video: tegra: nvavp: Add force clock stay on API Add nvavp_force_clock_stay_on ioctl which provides way for user-mode driver to stay on AVP clock state. This change is to fix LP0 resume fail during Widevine playback. Since VDE/BSEV clocks are used by OTF driver in secure world during closing sesssion, the change makes VDE/BSEV clocks running while entering LP0. Bug 960130 Bug 961015 Change-Id: I7eaaa9a33537a72b6ae0a016372bc513fef532e2 Reviewed-on: http://git-master/r/96302 Reviewed-by: Hyung Taek Ryoo Tested-by: Hyung Taek Ryoo Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Karan Jhavar Reviewed-by: Dan Willemsen --- drivers/media/video/tegra/nvavp/nvavp_dev.c | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c index d692be54c538..3741043eb1d2 100644 --- a/drivers/media/video/tegra/nvavp/nvavp_dev.c +++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c @@ -117,6 +117,7 @@ struct nvavp_info { struct nvhost_device *nvhost_dev; struct miscdevice misc_dev; + atomic_t clock_stay_on_refcount; }; struct nvavp_clientctx { @@ -126,6 +127,7 @@ struct nvavp_clientctx { struct nvmap_handle_ref *gather_mem; int num_relocs; struct nvavp_info *nvavp; + int clock_stay_on; }; static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id) @@ -171,7 +173,8 @@ static void nvavp_clk_ctrl(struct nvavp_info *nvavp, u32 clk_en) static u32 nvavp_check_idle(struct nvavp_info *nvavp) { struct nv_e276_control *control = nvavp->os_control; - return (control->put == control->get) ? 1 : 0; + return ((control->put == control->get) + && (!atomic_read(&nvavp->clock_stay_on_refcount))) ? 1 : 0; } static void clock_disable_handler(struct work_struct *work) @@ -1022,6 +1025,39 @@ 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; + } + + if (clientctx->clock_stay_on == clock.state) + return 0; + + clientctx->clock_stay_on = clock.state; + + if (clientctx->clock_stay_on == NVAVP_CLOCK_STAY_ON_ENABLED) + atomic_inc(&nvavp->clock_stay_on_refcount); + else if (clientctx->clock_stay_on == NVAVP_CLOCK_STAY_ON_DISABLED) + atomic_dec(&nvavp->clock_stay_on_refcount); + + return 0; +} static int tegra_nvavp_open(struct inode *inode, struct file *filp) { @@ -1048,6 +1084,7 @@ static int tegra_nvavp_open(struct inode *inode, struct file *filp) clientctx->nvmap = nvavp->nvmap; clientctx->nvavp = nvavp; + clientctx->clock_stay_on = NVAVP_CLOCK_STAY_ON_DISABLED; filp->private_data = clientctx; @@ -1075,6 +1112,8 @@ static int tegra_nvavp_release(struct inode *inode, struct file *filp) goto out; } + if (clientctx->clock_stay_on == NVAVP_CLOCK_STAY_ON_ENABLED) + atomic_dec(&nvavp->clock_stay_on_refcount); if (nvavp->refcount > 0) nvavp->refcount--; if (!nvavp->refcount) @@ -1116,6 +1155,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; -- cgit v1.2.3