diff options
| author | Dhaval Patel <pdhaval@quicinc.com> | 2016-11-11 12:11:24 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-11-11 12:11:24 -0800 |
| commit | 113b255bab6f2030a40753203a268c882aa2cd48 (patch) | |
| tree | b4409c366da9015478a82b5167d49c64b52e5028 /drivers/gpu | |
| parent | 3516a5609517fbbdd1451dd9c25062a5f82596e4 (diff) | |
| parent | 023f3af0e93b058c2480e4cd56564be8b1a15019 (diff) | |
Merge "drm/msm/sde: add vblank reference counting to crtc" into dev/msm-4.4-drm_kms
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_crtc.c | 59 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_crtc.h | 7 |
2 files changed, 65 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 2ef5dc62c6c2..a610f4b8d2a3 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -365,6 +365,13 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc, static void sde_crtc_vblank_cb(void *data) { struct drm_crtc *crtc = (struct drm_crtc *)data; + struct sde_crtc *sde_crtc = to_sde_crtc(crtc); + + /* keep statistics on vblank callback - with auto reset via debugfs */ + if (ktime_equal(sde_crtc->vblank_cb_time, ktime_set(0, 0))) + sde_crtc->vblank_cb_time = ktime_get(); + else + sde_crtc->vblank_cb_count++; drm_crtc_handle_vblank(crtc); DRM_DEBUG_VBL("crtc%d\n", crtc->base.id); @@ -759,6 +766,7 @@ static void sde_crtc_reset(struct drm_crtc *crtc) static void sde_crtc_disable(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; + struct drm_encoder *encoder; if (!crtc) { SDE_ERROR("invalid crtc\n"); @@ -769,6 +777,19 @@ static void sde_crtc_disable(struct drm_crtc *crtc) SDE_DEBUG("\n"); mutex_lock(&sde_crtc->crtc_lock); + if (atomic_read(&sde_crtc->vblank_refcount)) { + SDE_ERROR("crtc%d invalid vblank refcount %d\n", + crtc->base.id, + atomic_read(&sde_crtc->vblank_refcount)); + drm_for_each_encoder(encoder, crtc->dev) { + if (encoder->crtc != crtc) + continue; + sde_encoder_register_vblank_callback(encoder, NULL, + NULL); + } + atomic_set(&sde_crtc->vblank_refcount, 0); + } + memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers)); sde_crtc->num_mixers = 0; mutex_unlock(&sde_crtc->crtc_lock); @@ -947,10 +968,24 @@ end: int sde_crtc_vblank(struct drm_crtc *crtc, bool en) { + struct sde_crtc *sde_crtc = to_sde_crtc(crtc); struct drm_encoder *encoder; struct drm_device *dev = crtc->dev; - SDE_DEBUG("%d", en); + if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) { + SDE_DEBUG("crtc%d vblank enable\n", crtc->base.id); + } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) { + SDE_ERROR("crtc%d invalid vblank disable\n", crtc->base.id); + return -EINVAL; + } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) { + SDE_DEBUG("crtc%d vblank disable\n", crtc->base.id); + } else { + SDE_DEBUG("crtc%d vblank %s refcount:%d\n", + crtc->base.id, + en ? "enable" : "disable", + atomic_read(&sde_crtc->vblank_refcount)); + return 0; + } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) @@ -1224,6 +1259,27 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data) state->crtc_h); seq_puts(s, "\n"); } + + if (sde_crtc->vblank_cb_count) { + ktime_t diff = ktime_sub(ktime_get(), sde_crtc->vblank_cb_time); + s64 diff_ms = ktime_to_ms(diff); + s64 fps = diff_ms ? DIV_ROUND_CLOSEST( + sde_crtc->vblank_cb_count * 1000, diff_ms) : 0; + + seq_printf(s, + "vblank fps:%lld count:%u total:%llums\n", + fps, + sde_crtc->vblank_cb_count, + ktime_to_ms(diff)); + + /* reset time & count for next measurement */ + sde_crtc->vblank_cb_count = 0; + sde_crtc->vblank_cb_time = ktime_set(0, 0); + } + + seq_printf(s, "vblank_refcount:%d\n", + atomic_read(&sde_crtc->vblank_refcount)); + mutex_unlock(&sde_crtc->crtc_lock); return 0; @@ -1305,6 +1361,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) crtc = &sde_crtc->base; crtc->dev = dev; + atomic_set(&sde_crtc->vblank_refcount, 0); drm_crtc_init_with_planes(dev, crtc, plane, NULL, &sde_crtc_funcs); diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 4d1bb3c98329..c58bb097e8e6 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -54,6 +54,9 @@ struct sde_crtc_mixer { * @property_defaults : Array of default values for generic property support * @stage_cfg : H/w mixer stage configuration * @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 * @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 @@ -81,6 +84,10 @@ struct sde_crtc { struct sde_hw_stage_cfg stage_cfg; struct dentry *debugfs_root; + u32 vblank_cb_count; + ktime_t vblank_cb_time; + atomic_t vblank_refcount; + struct list_head feature_list; struct list_head active_list; struct list_head dirty_list; |
