Loading drivers/gpu/drm/msm/sde/sde_crtc.c +53 −48 Original line number Diff line number Diff line Loading @@ -976,8 +976,10 @@ end: * _sde_crtc_vblank_enable_nolock - update power resource and vblank request * @sde_crtc: Pointer to sde crtc structure * @enable: Whether to enable/disable vblanks * * @Return: error code */ static void _sde_crtc_vblank_enable_nolock( static int _sde_crtc_vblank_enable_no_lock( struct sde_crtc *sde_crtc, bool enable) { struct drm_device *dev; Loading @@ -985,10 +987,11 @@ static void _sde_crtc_vblank_enable_nolock( struct drm_encoder *enc; struct msm_drm_private *priv; struct sde_kms *sde_kms; int ret = 0; if (!sde_crtc) { SDE_ERROR("invalid crtc\n"); return; return -EINVAL; } crtc = &sde_crtc->base; Loading @@ -997,13 +1000,16 @@ static void _sde_crtc_vblank_enable_nolock( if (!priv->kms) { SDE_ERROR("invalid kms\n"); return; return -EINVAL; } sde_kms = to_sde_kms(priv->kms); if (enable) { sde_power_resource_enable(&priv->phandle, ret = sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true); if (ret) return ret; list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { if (enc->crtc != crtc) continue; Loading @@ -1022,9 +1028,11 @@ static void _sde_crtc_vblank_enable_nolock( sde_encoder_register_vblank_callback(enc, NULL, NULL); } sde_power_resource_enable(&priv->phandle, ret = sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); } return ret; } /** Loading Loading @@ -1070,8 +1078,8 @@ static void _sde_crtc_set_suspend(struct drm_crtc *crtc, bool enable) if (sde_crtc->suspend == enable) SDE_DEBUG("crtc%d suspend already set to %d, ignoring update\n", crtc->base.id, enable); else if (atomic_read(&sde_crtc->vblank_refcount) != 0) _sde_crtc_vblank_enable_nolock(sde_crtc, !enable); else if (sde_crtc->enabled && sde_crtc->vblank_requested) _sde_crtc_vblank_enable_no_lock(sde_crtc, !enable); sde_crtc->suspend = enable; Loading Loading @@ -1155,39 +1163,13 @@ static void sde_crtc_reset(struct drm_crtc *crtc) crtc->state = &cstate->base; } static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en) { if (!sde_crtc) { SDE_ERROR("invalid crtc\n"); return -EINVAL; } else if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) { SDE_DEBUG("crtc%d vblank enable\n", sde_crtc->base.base.id); if (!sde_crtc->suspend) _sde_crtc_vblank_enable_nolock(sde_crtc, true); } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) { SDE_ERROR("crtc%d invalid vblank disable\n", sde_crtc->base.base.id); return -EINVAL; } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) { SDE_DEBUG("crtc%d vblank disable\n", sde_crtc->base.base.id); if (!sde_crtc->suspend) _sde_crtc_vblank_enable_nolock(sde_crtc, false); } else { SDE_DEBUG("crtc%d vblank %s refcount:%d\n", sde_crtc->base.base.id, en ? "enable" : "disable", atomic_read(&sde_crtc->vblank_refcount)); } return 0; } static void sde_crtc_disable(struct drm_crtc *crtc) { struct drm_encoder *encoder; struct sde_crtc *sde_crtc; struct sde_kms *sde_kms; struct msm_drm_private *priv; int ret = 0; if (!crtc || !crtc->dev || !crtc->state) { SDE_ERROR("invalid crtc\n"); Loading @@ -1207,17 +1189,19 @@ static void sde_crtc_disable(struct drm_crtc *crtc) _sde_crtc_set_suspend(crtc, true); mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc)); SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (atomic_read(&sde_crtc->vblank_refcount) && !sde_crtc->suspend) { SDE_ERROR("crtc%d invalid vblank refcount\n", crtc->base.id); SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->vblank_refcount)); while (atomic_read(&sde_crtc->vblank_refcount)) if (_sde_crtc_vblank_no_lock(sde_crtc, false)) break; if (sde_crtc->enabled && !sde_crtc->suspend && sde_crtc->vblank_requested) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, false); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->enabled = false; if (atomic_read(&sde_crtc->frame_pending)) { /* release bandwidth and other resources */ SDE_ERROR("crtc%d invalid frame pending\n", Loading Loading @@ -1252,6 +1236,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc) struct sde_hw_mixer_cfg cfg; struct drm_encoder *encoder; int i; int ret = 0; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading Loading @@ -1280,6 +1265,19 @@ static void sde_crtc_enable(struct drm_crtc *crtc) sde_crtc_request_flip_cb, (void *)crtc); } mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (!sde_crtc->enabled && !sde_crtc->suspend && sde_crtc->vblank_requested) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, true); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->enabled = true; mutex_unlock(&sde_crtc->crtc_lock); for (i = 0; i < sde_crtc->num_mixers; i++) { lm = mixer[i].hw_lm; cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode); Loading Loading @@ -1435,7 +1433,7 @@ end: int sde_crtc_vblank(struct drm_crtc *crtc, bool en) { struct sde_crtc *sde_crtc; int rc; int ret; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading @@ -1444,10 +1442,19 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) sde_crtc = to_sde_crtc(crtc); mutex_lock(&sde_crtc->crtc_lock); rc = _sde_crtc_vblank_no_lock(sde_crtc, en); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (sde_crtc->enabled && !sde_crtc->suspend) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->vblank_requested = en; mutex_unlock(&sde_crtc->crtc_lock); return rc; return 0; } void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, Loading Loading @@ -1760,8 +1767,7 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data) sde_crtc->vblank_cb_time = ktime_set(0, 0); } seq_printf(s, "vblank_refcount:%d\n", atomic_read(&sde_crtc->vblank_refcount)); seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_requested); mutex_unlock(&sde_crtc->crtc_lock); Loading Loading @@ -1889,7 +1895,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, crtc = &sde_crtc->base; crtc->dev = dev; atomic_set(&sde_crtc->vblank_refcount, 0); mutex_init(&sde_crtc->crtc_lock); spin_lock_init(&sde_crtc->spin_lock); Loading drivers/gpu/drm/msm/sde/sde_crtc.h +6 −2 Original line number Diff line number Diff line Loading @@ -81,8 +81,11 @@ struct sde_crtc_frame_event { * @debugfs_root : Parent of debugfs node * @vblank_cb_count : count of vblank callback since last reset * @vblank_cb_time : ktime at vblank count reset * @vblank_refcount : reference count for vblank enable request * @vblank_requested : whether the user has requested vblank events * @suspend : whether or not a suspend operation is in progress * @enabled : whether the SDE CRTC is currently enabled. updated in the * commit-thread, not state-swap time which is earlier, so * safe to make decisions on during VBLANK on/off work * @feature_list : list of color processing features supported on a crtc * @active_list : list of color processing features are active * @dirty_list : list of color processing features are dirty Loading Loading @@ -117,8 +120,9 @@ struct sde_crtc { u32 vblank_cb_count; ktime_t vblank_cb_time; atomic_t vblank_refcount; bool vblank_requested; bool suspend; bool enabled; struct list_head feature_list; struct list_head active_list; Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +53 −48 Original line number Diff line number Diff line Loading @@ -976,8 +976,10 @@ end: * _sde_crtc_vblank_enable_nolock - update power resource and vblank request * @sde_crtc: Pointer to sde crtc structure * @enable: Whether to enable/disable vblanks * * @Return: error code */ static void _sde_crtc_vblank_enable_nolock( static int _sde_crtc_vblank_enable_no_lock( struct sde_crtc *sde_crtc, bool enable) { struct drm_device *dev; Loading @@ -985,10 +987,11 @@ static void _sde_crtc_vblank_enable_nolock( struct drm_encoder *enc; struct msm_drm_private *priv; struct sde_kms *sde_kms; int ret = 0; if (!sde_crtc) { SDE_ERROR("invalid crtc\n"); return; return -EINVAL; } crtc = &sde_crtc->base; Loading @@ -997,13 +1000,16 @@ static void _sde_crtc_vblank_enable_nolock( if (!priv->kms) { SDE_ERROR("invalid kms\n"); return; return -EINVAL; } sde_kms = to_sde_kms(priv->kms); if (enable) { sde_power_resource_enable(&priv->phandle, ret = sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true); if (ret) return ret; list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { if (enc->crtc != crtc) continue; Loading @@ -1022,9 +1028,11 @@ static void _sde_crtc_vblank_enable_nolock( sde_encoder_register_vblank_callback(enc, NULL, NULL); } sde_power_resource_enable(&priv->phandle, ret = sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); } return ret; } /** Loading Loading @@ -1070,8 +1078,8 @@ static void _sde_crtc_set_suspend(struct drm_crtc *crtc, bool enable) if (sde_crtc->suspend == enable) SDE_DEBUG("crtc%d suspend already set to %d, ignoring update\n", crtc->base.id, enable); else if (atomic_read(&sde_crtc->vblank_refcount) != 0) _sde_crtc_vblank_enable_nolock(sde_crtc, !enable); else if (sde_crtc->enabled && sde_crtc->vblank_requested) _sde_crtc_vblank_enable_no_lock(sde_crtc, !enable); sde_crtc->suspend = enable; Loading Loading @@ -1155,39 +1163,13 @@ static void sde_crtc_reset(struct drm_crtc *crtc) crtc->state = &cstate->base; } static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en) { if (!sde_crtc) { SDE_ERROR("invalid crtc\n"); return -EINVAL; } else if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) { SDE_DEBUG("crtc%d vblank enable\n", sde_crtc->base.base.id); if (!sde_crtc->suspend) _sde_crtc_vblank_enable_nolock(sde_crtc, true); } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) { SDE_ERROR("crtc%d invalid vblank disable\n", sde_crtc->base.base.id); return -EINVAL; } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) { SDE_DEBUG("crtc%d vblank disable\n", sde_crtc->base.base.id); if (!sde_crtc->suspend) _sde_crtc_vblank_enable_nolock(sde_crtc, false); } else { SDE_DEBUG("crtc%d vblank %s refcount:%d\n", sde_crtc->base.base.id, en ? "enable" : "disable", atomic_read(&sde_crtc->vblank_refcount)); } return 0; } static void sde_crtc_disable(struct drm_crtc *crtc) { struct drm_encoder *encoder; struct sde_crtc *sde_crtc; struct sde_kms *sde_kms; struct msm_drm_private *priv; int ret = 0; if (!crtc || !crtc->dev || !crtc->state) { SDE_ERROR("invalid crtc\n"); Loading @@ -1207,17 +1189,19 @@ static void sde_crtc_disable(struct drm_crtc *crtc) _sde_crtc_set_suspend(crtc, true); mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc)); SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (atomic_read(&sde_crtc->vblank_refcount) && !sde_crtc->suspend) { SDE_ERROR("crtc%d invalid vblank refcount\n", crtc->base.id); SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->vblank_refcount)); while (atomic_read(&sde_crtc->vblank_refcount)) if (_sde_crtc_vblank_no_lock(sde_crtc, false)) break; if (sde_crtc->enabled && !sde_crtc->suspend && sde_crtc->vblank_requested) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, false); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->enabled = false; if (atomic_read(&sde_crtc->frame_pending)) { /* release bandwidth and other resources */ SDE_ERROR("crtc%d invalid frame pending\n", Loading Loading @@ -1252,6 +1236,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc) struct sde_hw_mixer_cfg cfg; struct drm_encoder *encoder; int i; int ret = 0; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading Loading @@ -1280,6 +1265,19 @@ static void sde_crtc_enable(struct drm_crtc *crtc) sde_crtc_request_flip_cb, (void *)crtc); } mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (!sde_crtc->enabled && !sde_crtc->suspend && sde_crtc->vblank_requested) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, true); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->enabled = true; mutex_unlock(&sde_crtc->crtc_lock); for (i = 0; i < sde_crtc->num_mixers; i++) { lm = mixer[i].hw_lm; cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode); Loading Loading @@ -1435,7 +1433,7 @@ end: int sde_crtc_vblank(struct drm_crtc *crtc, bool en) { struct sde_crtc *sde_crtc; int rc; int ret; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading @@ -1444,10 +1442,19 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) sde_crtc = to_sde_crtc(crtc); mutex_lock(&sde_crtc->crtc_lock); rc = _sde_crtc_vblank_no_lock(sde_crtc, en); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled, sde_crtc->suspend, sde_crtc->vblank_requested); if (sde_crtc->enabled && !sde_crtc->suspend) { ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); if (ret) SDE_ERROR("%s vblank enable failed: %d\n", sde_crtc->name, ret); } sde_crtc->vblank_requested = en; mutex_unlock(&sde_crtc->crtc_lock); return rc; return 0; } void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, Loading Loading @@ -1760,8 +1767,7 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data) sde_crtc->vblank_cb_time = ktime_set(0, 0); } seq_printf(s, "vblank_refcount:%d\n", atomic_read(&sde_crtc->vblank_refcount)); seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_requested); mutex_unlock(&sde_crtc->crtc_lock); Loading Loading @@ -1889,7 +1895,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, crtc = &sde_crtc->base; crtc->dev = dev; atomic_set(&sde_crtc->vblank_refcount, 0); mutex_init(&sde_crtc->crtc_lock); spin_lock_init(&sde_crtc->spin_lock); Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +6 −2 Original line number Diff line number Diff line Loading @@ -81,8 +81,11 @@ struct sde_crtc_frame_event { * @debugfs_root : Parent of debugfs node * @vblank_cb_count : count of vblank callback since last reset * @vblank_cb_time : ktime at vblank count reset * @vblank_refcount : reference count for vblank enable request * @vblank_requested : whether the user has requested vblank events * @suspend : whether or not a suspend operation is in progress * @enabled : whether the SDE CRTC is currently enabled. updated in the * commit-thread, not state-swap time which is earlier, so * safe to make decisions on during VBLANK on/off work * @feature_list : list of color processing features supported on a crtc * @active_list : list of color processing features are active * @dirty_list : list of color processing features are dirty Loading Loading @@ -117,8 +120,9 @@ struct sde_crtc { u32 vblank_cb_count; ktime_t vblank_cb_time; atomic_t vblank_refcount; bool vblank_requested; bool suspend; bool enabled; struct list_head feature_list; struct list_head active_list; Loading