diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/1824-drm-amd-display-Refactor-CRTC-interrupt-toggling-log.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/1824-drm-amd-display-Refactor-CRTC-interrupt-toggling-log.patch | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/1824-drm-amd-display-Refactor-CRTC-interrupt-toggling-log.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/1824-drm-amd-display-Refactor-CRTC-interrupt-toggling-log.patch new file mode 100644 index 00000000..c43d619e --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/1824-drm-amd-display-Refactor-CRTC-interrupt-toggling-log.patch @@ -0,0 +1,234 @@ +From b8576a2773e4fdc8aed1dfe6ae0954ba53245da1 Mon Sep 17 00:00:00 2001 +From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> +Date: Fri, 5 Apr 2019 09:35:14 -0400 +Subject: [PATCH 1824/2940] drm/amd/display: Refactor CRTC interrupt toggling + logic + +[Why] +The vblank and pageflip interrupts should only be enabled for a CRTC +that's enabled and has active planes. + +The current logic takes care of this, but isn't setup to handle the case +where the active plane count goes to zero but the stream remains +enabled. + +We currently block this case since we don't allow commits that enable a +CRTC with no active planes, but shouldn't be any reason we can't support +this from a hardware perspective and many userspace applications expect +to be able to do it (like IGT). + +[How] +The count_crtc_active_planes function fills in the number of +"active_planes" on the dm_crtc_state. This should be the same as +DC's plane_count on the stream_status but easier to access since we +don't need to lock the private atomic state with the DC context. + +Add the "interrupts_enabled" flag to the dm_crtc_state and set it based +on whether the stream exists and if there are active planes on the +stream. + +Update the disable and enable logic to make use of this new flag. + +There shouldn't be any functional change (yet) with this patch. + +Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> +Reviewed-by: David Francis <David.Francis@amd.com> +Acked-by: Leo Li <sunpeng.li@amd.com> +Signed-off-by: Chaudhary Amit Kumar <Chaudharyamit.Kumar@amd.com> +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 104 +++++++++++++----- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 + + 2 files changed, 80 insertions(+), 27 deletions(-) + +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 ac3ac629d4cb..65c15ae620bd 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -3525,6 +3525,8 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) + dc_stream_retain(state->stream); + } + ++ state->active_planes = cur->active_planes; ++ state->interrupts_enabled = cur->interrupts_enabled; + state->vrr_params = cur->vrr_params; + state->vrr_infopacket = cur->vrr_infopacket; + state->abm_level = cur->abm_level; +@@ -3974,7 +3976,7 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc) + { + } + +-static bool does_crtc_have_active_plane(struct drm_crtc_state *new_crtc_state) ++static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state) + { + struct drm_atomic_state *state = new_crtc_state->state; + struct drm_plane *plane; +@@ -4003,7 +4005,32 @@ static bool does_crtc_have_active_plane(struct drm_crtc_state *new_crtc_state) + num_active += (new_plane_state->fb != NULL); + } + +- return num_active > 0; ++ return num_active; ++} ++ ++/* ++ * Sets whether interrupts should be enabled on a specific CRTC. ++ * We require that the stream be enabled and that there exist active ++ * DC planes on the stream. ++ */ ++static void ++dm_update_crtc_interrupt_state(struct drm_crtc *crtc, ++ struct drm_crtc_state *new_crtc_state) ++{ ++ struct dm_crtc_state *dm_new_crtc_state = ++ to_dm_crtc_state(new_crtc_state); ++ ++ dm_new_crtc_state->active_planes = 0; ++ dm_new_crtc_state->interrupts_enabled = false; ++ ++ if (!dm_new_crtc_state->stream) ++ return; ++ ++ dm_new_crtc_state->active_planes = ++ count_crtc_active_planes(new_crtc_state); ++ ++ dm_new_crtc_state->interrupts_enabled = ++ dm_new_crtc_state->active_planes > 0; + } + + static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, +@@ -4014,6 +4041,14 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); + int ret = -EINVAL; + ++ /* ++ * Update interrupt state for the CRTC. This needs to happen whenever ++ * the CRTC has changed or whenever any of its planes have changed. ++ * Atomic check satisfies both of these requirements since the CRTC ++ * is added to the state by DRM during drm_atomic_helper_check_planes. ++ */ ++ dm_update_crtc_interrupt_state(crtc, state); ++ + if (unlikely(!dm_crtc_state->stream && + modeset_required(state, NULL, dm_crtc_state->stream))) { + WARN_ON(1); +@@ -4026,7 +4061,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, + + /* We want at least one hardware plane enabled to use the stream. */ + if (state->enable && state->active && +- !does_crtc_have_active_plane(state)) ++ dm_crtc_state->active_planes == 0) + return -EINVAL; + + if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK) +@@ -5510,28 +5545,43 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct amdgpu_device *adev = dev->dev_private; + int i; + +- /* +- * We evade vblanks and pflips on crtc that +- * should be changed. We do it here to flush & disable +- * interrupts before drm_swap_state is called in drm_atomic_helper_commit +- * it will update crtc->dm_crtc_state->stream pointer which is used in +- * the ISRs. ++ /* ++ * We evade vblank and pflip interrupts on CRTCs that are undergoing ++ * a modeset, being disabled, or have no active planes. ++ * ++ * It's done in atomic commit rather than commit tail for now since ++ * some of these interrupt handlers access the current CRTC state and ++ * potentially the stream pointer itself. ++ * ++ * Since the atomic state is swapped within atomic commit and not within ++ * commit tail this would leave to new state (that hasn't been committed yet) ++ * being accesssed from within the handlers. ++ * ++ * TODO: Fix this so we can do this in commit tail and not have to block ++ * in atomic check. + */ + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + +- if (drm_atomic_crtc_needs_modeset(new_crtc_state) +- && dm_old_crtc_state->stream) { ++ if (dm_old_crtc_state->interrupts_enabled && ++ (!dm_new_crtc_state->interrupts_enabled || ++ drm_atomic_crtc_needs_modeset(new_crtc_state))) { + /* +- * CRC capture was enabled but not disabled. +- * Release the vblank reference. +- */ +- if (dm_new_crtc_state->crc_enabled) { +- drm_crtc_vblank_put(crtc); +- dm_new_crtc_state->crc_enabled = false; +- } ++ * Drop the extra vblank reference added by CRC ++ * capture if applicable. ++ */ ++ if (dm_new_crtc_state->crc_enabled) ++ drm_crtc_vblank_put(crtc); ++ ++ /* ++ * Only keep CRC capture enabled if there's ++ * still a stream for the CRTC. ++ */ ++ if (!dm_new_crtc_state->stream) ++ dm_new_crtc_state->crc_enabled = false; ++ + + manage_dm_interrupts(adev, acrtc, false); + } +@@ -5751,13 +5801,14 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + pre_update_freesync_state_on_stream(dm, dm_new_crtc_state); + } + ++ /* ++ * Enable interrupts on CRTCs that are newly active, undergone ++ * a modeset, or have active planes again. ++ */ + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { +- /* +- * loop to enable interrupts on newly arrived crtc +- */ + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); +- bool modeset_needed; ++ bool enable; + + if (old_crtc_state->active && !new_crtc_state->active) + crtc_disable_count++; +@@ -5769,12 +5820,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + 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, +- dm_old_crtc_state->stream); ++ enable = dm_new_crtc_state->interrupts_enabled && ++ (!dm_old_crtc_state->interrupts_enabled || ++ drm_atomic_crtc_needs_modeset(new_crtc_state)); + +- if (dm_new_crtc_state->stream == NULL || !modeset_needed) ++ if (!enable) + continue; + + manage_dm_interrupts(adev, acrtc, true); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index e194bf79ca90..715a2d66a0a7 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -268,6 +268,9 @@ struct dm_crtc_state { + struct drm_crtc_state base; + struct dc_stream_state *stream; + ++ int active_planes; ++ bool interrupts_enabled; ++ + int crc_skip_count; + bool crc_enabled; + +-- +2.17.1 + |