Loading drivers/gpu/drm/msm/msm_drv.c +69 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include "msm_gpu.h" #include "msm_kms.h" #include "sde_wb.h" #include "sde_dbg.h" /* * MSM driver version: Loading Loading @@ -823,6 +824,8 @@ static int msm_open(struct drm_device *dev, struct drm_file *file) if (!ctx) return -ENOMEM; mutex_init(&ctx->power_lock); file->driver_priv = ctx; if (dev && dev->dev_private) { Loading Loading @@ -859,6 +862,14 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) priv->lastctx = NULL; mutex_unlock(&dev->struct_mutex); mutex_lock(&ctx->power_lock); if (ctx->enable_refcnt) { SDE_EVT32(ctx->enable_refcnt); sde_power_resource_enable(&priv->phandle, priv->pclient, false); } mutex_unlock(&ctx->power_lock); kfree(ctx); } Loading Loading @@ -1573,6 +1584,62 @@ int msm_ioctl_rmfb2(struct drm_device *dev, void *data, } EXPORT_SYMBOL(msm_ioctl_rmfb2); /** * msm_ioctl_power_ctrl - enable/disable power vote on MDSS Hw * @dev: drm device for the ioctl * @data: data pointer for the ioctl * @file_priv: drm file for the ioctl call * */ static int msm_ioctl_power_ctrl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct msm_file_private *ctx = file_priv->driver_priv; struct msm_drm_private *priv; struct drm_msm_power_ctrl *power_ctrl = data; bool vote_req = false; int old_cnt; int rc = 0; if (unlikely(!power_ctrl)) { DRM_ERROR("invalid ioctl data\n"); return -EINVAL; } priv = dev->dev_private; mutex_lock(&ctx->power_lock); old_cnt = ctx->enable_refcnt; if (power_ctrl->enable) { if (!ctx->enable_refcnt) vote_req = true; ctx->enable_refcnt++; } else if (ctx->enable_refcnt) { ctx->enable_refcnt--; if (!ctx->enable_refcnt) vote_req = true; } else { pr_err("ignoring, unbalanced disable\n"); } if (vote_req) { rc = sde_power_resource_enable(&priv->phandle, priv->pclient, power_ctrl->enable); if (rc) ctx->enable_refcnt = old_cnt; } pr_debug("pid %d enable %d, refcnt %d, vote_req %d\n", current->pid, power_ctrl->enable, ctx->enable_refcnt, vote_req); SDE_EVT32(current->pid, power_ctrl->enable, ctx->enable_refcnt, vote_req); mutex_unlock(&ctx->power_lock); return rc; } static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), Loading @@ -1589,6 +1656,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_UNLOCKED|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF_DRV(MSM_RMFB2, msm_ioctl_rmfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(MSM_POWER_CTRL, msm_ioctl_power_ctrl, DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { Loading drivers/gpu/drm/msm/msm_drv.h +5 −5 Original line number Diff line number Diff line Loading @@ -74,11 +74,11 @@ struct msm_gem_vma; #define TEARDOWN_DEADLOCK_RETRY_MAX 5 struct msm_file_private { /* currently we don't do anything useful with this.. but when * per-context address spaces are supported we'd keep track of * the context's page-tables here. */ int dummy; /* update the refcount when user driver calls power_ctrl IOCTL */ unsigned short enable_refcnt; /* protects enable_refcnt */ struct mutex power_lock; }; enum msm_mdp_plane_property { Loading drivers/gpu/drm/msm/sde/sde_crtc.c +27 −1 Original line number Diff line number Diff line Loading @@ -941,6 +941,26 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc, return true; } static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc) { struct drm_encoder *encoder; int rc = 0; if (!crtc || !crtc->dev) return 0; list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) rc += sde_encoder_get_ctlstart_timeout_state(encoder); } return rc; } static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer, struct sde_plane_state *pstate, struct sde_format *format) { Loading Loading @@ -3714,7 +3734,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (unlikely(!sde_crtc->num_mixers)) goto end; if (_sde_crtc_get_ctlstart_timeout(crtc)) { _sde_crtc_blend_setup(crtc, old_state, false); SDE_ERROR("border fill only commit after ctlstart timeout\n"); } else { _sde_crtc_blend_setup(crtc, old_state, true); } _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ Loading drivers/gpu/drm/msm/sde/sde_encoder.c +17 −0 Original line number Diff line number Diff line Loading @@ -3545,6 +3545,23 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc) return 0; } int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = NULL; int i, count = 0; if (!drm_enc) return 0; sde_enc = to_sde_encoder_virt(drm_enc); for (i = 0; i < sde_enc->num_phys_encs; i++) { count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout); atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0); } return count; } /** * _sde_encoder_trigger_flush - trigger flush for a physical encoder * drm_enc: Pointer to drm encoder structure Loading drivers/gpu/drm/msm/sde/sde_encoder.h +7 −0 Original line number Diff line number Diff line Loading @@ -331,4 +331,11 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable); */ int sde_encoder_in_cont_splash(struct drm_encoder *enc); /** * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened * @drm_enc: Pointer to drm encoder structure * @Return: non zero value if ctl start timeout occurred */ int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc); #endif /* __SDE_ENCODER_H__ */ Loading
drivers/gpu/drm/msm/msm_drv.c +69 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include "msm_gpu.h" #include "msm_kms.h" #include "sde_wb.h" #include "sde_dbg.h" /* * MSM driver version: Loading Loading @@ -823,6 +824,8 @@ static int msm_open(struct drm_device *dev, struct drm_file *file) if (!ctx) return -ENOMEM; mutex_init(&ctx->power_lock); file->driver_priv = ctx; if (dev && dev->dev_private) { Loading Loading @@ -859,6 +862,14 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) priv->lastctx = NULL; mutex_unlock(&dev->struct_mutex); mutex_lock(&ctx->power_lock); if (ctx->enable_refcnt) { SDE_EVT32(ctx->enable_refcnt); sde_power_resource_enable(&priv->phandle, priv->pclient, false); } mutex_unlock(&ctx->power_lock); kfree(ctx); } Loading Loading @@ -1573,6 +1584,62 @@ int msm_ioctl_rmfb2(struct drm_device *dev, void *data, } EXPORT_SYMBOL(msm_ioctl_rmfb2); /** * msm_ioctl_power_ctrl - enable/disable power vote on MDSS Hw * @dev: drm device for the ioctl * @data: data pointer for the ioctl * @file_priv: drm file for the ioctl call * */ static int msm_ioctl_power_ctrl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct msm_file_private *ctx = file_priv->driver_priv; struct msm_drm_private *priv; struct drm_msm_power_ctrl *power_ctrl = data; bool vote_req = false; int old_cnt; int rc = 0; if (unlikely(!power_ctrl)) { DRM_ERROR("invalid ioctl data\n"); return -EINVAL; } priv = dev->dev_private; mutex_lock(&ctx->power_lock); old_cnt = ctx->enable_refcnt; if (power_ctrl->enable) { if (!ctx->enable_refcnt) vote_req = true; ctx->enable_refcnt++; } else if (ctx->enable_refcnt) { ctx->enable_refcnt--; if (!ctx->enable_refcnt) vote_req = true; } else { pr_err("ignoring, unbalanced disable\n"); } if (vote_req) { rc = sde_power_resource_enable(&priv->phandle, priv->pclient, power_ctrl->enable); if (rc) ctx->enable_refcnt = old_cnt; } pr_debug("pid %d enable %d, refcnt %d, vote_req %d\n", current->pid, power_ctrl->enable, ctx->enable_refcnt, vote_req); SDE_EVT32(current->pid, power_ctrl->enable, ctx->enable_refcnt, vote_req); mutex_unlock(&ctx->power_lock); return rc; } static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), Loading @@ -1589,6 +1656,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_UNLOCKED|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF_DRV(MSM_RMFB2, msm_ioctl_rmfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(MSM_POWER_CTRL, msm_ioctl_power_ctrl, DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { Loading
drivers/gpu/drm/msm/msm_drv.h +5 −5 Original line number Diff line number Diff line Loading @@ -74,11 +74,11 @@ struct msm_gem_vma; #define TEARDOWN_DEADLOCK_RETRY_MAX 5 struct msm_file_private { /* currently we don't do anything useful with this.. but when * per-context address spaces are supported we'd keep track of * the context's page-tables here. */ int dummy; /* update the refcount when user driver calls power_ctrl IOCTL */ unsigned short enable_refcnt; /* protects enable_refcnt */ struct mutex power_lock; }; enum msm_mdp_plane_property { Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +27 −1 Original line number Diff line number Diff line Loading @@ -941,6 +941,26 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc, return true; } static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc) { struct drm_encoder *encoder; int rc = 0; if (!crtc || !crtc->dev) return 0; list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) rc += sde_encoder_get_ctlstart_timeout_state(encoder); } return rc; } static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer, struct sde_plane_state *pstate, struct sde_format *format) { Loading Loading @@ -3714,7 +3734,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (unlikely(!sde_crtc->num_mixers)) goto end; if (_sde_crtc_get_ctlstart_timeout(crtc)) { _sde_crtc_blend_setup(crtc, old_state, false); SDE_ERROR("border fill only commit after ctlstart timeout\n"); } else { _sde_crtc_blend_setup(crtc, old_state, true); } _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +17 −0 Original line number Diff line number Diff line Loading @@ -3545,6 +3545,23 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc) return 0; } int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = NULL; int i, count = 0; if (!drm_enc) return 0; sde_enc = to_sde_encoder_virt(drm_enc); for (i = 0; i < sde_enc->num_phys_encs; i++) { count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout); atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0); } return count; } /** * _sde_encoder_trigger_flush - trigger flush for a physical encoder * drm_enc: Pointer to drm encoder structure Loading
drivers/gpu/drm/msm/sde/sde_encoder.h +7 −0 Original line number Diff line number Diff line Loading @@ -331,4 +331,11 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable); */ int sde_encoder_in_cont_splash(struct drm_encoder *enc); /** * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened * @drm_enc: Pointer to drm encoder structure * @Return: non zero value if ctl start timeout occurred */ int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc); #endif /* __SDE_ENCODER_H__ */