drm/amd/display: Rework vrr flip throttling for late vblank irq.
authorMario Kleiner <mario.kleiner.de@gmail.com>
Tue, 2 Apr 2019 22:00:06 +0000 (17:00 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 3 Apr 2019 15:00:33 +0000 (10:00 -0500)
For throttling to work correctly, we always need a baseline vblank
count last_flip_vblank that increments at start of front-porch.

This is the case for drm_crtc_vblank_count() in non-VRR mode, where
the vblank irq fires at start of front-porch and triggers DRM core
vblank handling, but it is no longer the case in VRR mode, where
core vblank handling is done later, after end of front-porch.

Therefore drm_crtc_vblank_count() is no longer useful for this.
We also can't use drm_crtc_accurate_vblank_count(), as that would
screw up vblank timestamps in VRR mode when called in front-porch.

To solve this, use the cooked hardware vblank counter returned by
amdgpu_get_vblank_counter_kms() instead, as that one is cooked to
always increment at start of front-porch, independent of when
vblank related irq's fire.

This patch allows vblank irq handling to happen anywhere within
vblank of even after it, without a negative impact on flip
throttling, so followup patches can shift the vblank core
handling trigger point wherever they need it.

Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 889e443..add238f 100644 (file)
@@ -406,7 +406,7 @@ struct amdgpu_crtc {
        struct amdgpu_flip_work *pflip_works;
        enum amdgpu_flip_status pflip_status;
        int deferred_flip_completion;
-       u64 last_flip_vblank;
+       u32 last_flip_vblank;
        /* pll sharing */
        struct amdgpu_atom_ss ss;
        bool ss_enabled;
index 467fa4d..4c27e68 100644 (file)
@@ -286,7 +286,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
        }
 
        /* Update to correct count(s) if racing with vblank irq */
-       amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
+       drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
 
        /* wake up userspace */
        if (amdgpu_crtc->event) {
@@ -298,6 +298,14 @@ static void dm_pflip_high_irq(void *interrupt_params)
        } else
                WARN_ON(1);
 
+       /* Keep track of vblank of this flip for flip throttling. We use the
+        * cooked hw counter, as that one incremented at start of this vblank
+        * of pageflip completion, so last_flip_vblank is the forbidden count
+        * for queueing new pageflips if vsync + VRR is enabled.
+        */
+       amdgpu_crtc->last_flip_vblank = amdgpu_get_vblank_counter_kms(adev->ddev,
+                                                       amdgpu_crtc->crtc_id);
+
        amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
@@ -4790,11 +4798,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
        unsigned long flags;
        struct amdgpu_bo *abo;
        uint64_t tiling_flags;
-       uint32_t target, target_vblank;
-       uint64_t last_flip_vblank;
-       bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
+       uint32_t target_vblank, last_flip_vblank;
+       bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
        bool pflip_present = false;
-
        struct {
                struct dc_surface_update surface_updates[MAX_SURFACES];
                struct dc_plane_info plane_infos[MAX_SURFACES];
@@ -4936,7 +4942,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                         * clients using the GLX_OML_sync_control extension or
                         * DRI3/Present extension with defined target_msc.
                         */
-                       last_flip_vblank = drm_crtc_vblank_count(pcrtc);
+                       last_flip_vblank = amdgpu_get_vblank_counter_kms(dm->ddev, acrtc_attach->crtc_id);
                }
                else {
                        /* For variable refresh rate mode only:
@@ -4952,11 +4958,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
                }
 
-               target = (uint32_t)last_flip_vblank + wait_for_vblank;
-
-               /* Prepare wait for target vblank early - before the fence-waits */
-               target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) +
-                               amdgpu_get_vblank_counter_kms(pcrtc->dev, acrtc_attach->crtc_id);
+               target_vblank = last_flip_vblank + wait_for_vblank;
 
                /*
                 * Wait until we're out of the vertical blank period before the one