aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch98
1 files changed, 98 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch
new file mode 100644
index 00000000..c6e3513d
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1710-drm-amd-display-Prevent-vblank-irq-disable-while-VRR.patch
@@ -0,0 +1,98 @@
+From ba6f989ba71e003ead3067fea61302b7b8fac147 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 29 Mar 2019 13:00:54 +0100
+Subject: [PATCH 1710/2940] drm/amd/display: Prevent vblank irq disable while
+ VRR is active. (v3)
+
+During VRR mode we can not allow vblank irq dis-/enable
+transitions, as an enable after a disable can happen at
+an arbitrary time during the video refresh cycle, e.g.,
+with a high likelyhood inside vblank front-porch. An
+enable during front-porch would cause vblank timestamp
+updates/calculations which are completely bogus, given
+the code can't know when the vblank will end as long
+as we are in front-porch with no page flip completed.
+
+Hold a permanent vblank reference on the crtc while
+in active VRR mode to prevent a vblank disable, and
+drop the reference again when switching back to fixed
+refresh rate non-VRR mode.
+
+v2: Make sure transition is also handled if vrr is
+ disabled and stream gets disabled in the same
+ atomic commit by moving the call to the transition
+ function outside of plane commit.
+ Suggested by Nicholas.
+
+v3: Trivial rebase onto previous patch.
+
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 65da7ed1bd38..ed37a368d4fd 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -252,6 +252,12 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev,
+ return NULL;
+ }
+
++static inline bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state)
++{
++ return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE ||
++ dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
++}
++
+ static void dm_pflip_high_irq(void *interrupt_params)
+ {
+ struct amdgpu_crtc *amdgpu_crtc;
+@@ -4865,6 +4871,31 @@ static void pre_update_freesync_state_on_stream(
+ new_crtc_state->vrr_params = vrr_params;
+ }
+
++static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
++ struct dm_crtc_state *new_state)
++{
++ bool old_vrr_active = amdgpu_dm_vrr_active(old_state);
++ bool new_vrr_active = amdgpu_dm_vrr_active(new_state);
++
++ if (!old_vrr_active && new_vrr_active) {
++ /* Transition VRR inactive -> active:
++ * While VRR is active, we must not disable vblank irq, as a
++ * reenable after disable would compute bogus vblank/pflip
++ * timestamps if it likely happened inside display front-porch.
++ */
++ drm_crtc_vblank_get(new_state->base.crtc);
++ DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n",
++ __func__, new_state->base.crtc->base.id);
++ } else if (old_vrr_active && !new_vrr_active) {
++ /* Transition VRR active -> inactive:
++ * Allow vblank irq disable again for fixed refresh rate.
++ */
++ drm_crtc_vblank_put(new_state->base.crtc);
++ DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n",
++ __func__, new_state->base.crtc->base.id);
++ }
++}
++
+ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ struct dc_state *dc_state,
+ struct drm_device *dev,
+@@ -5400,6 +5431,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
+
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
++
++ /* Handle vrr on->off / off->on transitions */
++ amdgpu_dm_handle_vrr_transition(dm_old_crtc_state,
++ dm_new_crtc_state);
++
+ modeset_needed = modeset_required(
+ new_crtc_state,
+ dm_new_crtc_state->stream,
+--
+2.17.1
+