From 7de73e0bb036ab1c0aa69170eec99fdddca92634 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Thu, 6 Apr 2023 12:31:06 -0400 Subject: [PATCH] drm/amd/display: fix flickering caused by S/G mode Currently, we allow the framebuffer for a given plane to move between memory domains, however when that happens it causes the screen to flicker, it is even possible for the framebuffer to change memory domains on every plane update (causing a continuous flicker effect). So, to fix this, make it so that we always pin a plane's framebuffer to the same memory domain in dm_plane_helper_prepare_fb(). Fixes: 81d0bcf99009 ("drm/amdgpu: make display pinning more flexible (v2)") Signed-off-by: Hamza Mahfooz --- .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 322668973747..921b028d5b34 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -826,9 +826,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct amdgpu_framebuffer *afb; - struct drm_gem_object *obj; struct amdgpu_device *adev; - struct amdgpu_bo *rbo; + struct amdgpu_bo *abo, *rbo; struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; uint32_t domain; int r; @@ -839,8 +838,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, } afb = to_amdgpu_framebuffer(new_state->fb); - obj = new_state->fb->obj[0]; - rbo = gem_to_amdgpu_bo(obj); + rbo = gem_to_amdgpu_bo(new_state->fb->obj[0]); adev = amdgpu_ttm_adev(rbo->tbo.bdev); r = amdgpu_bo_reserve(rbo, true); @@ -855,15 +853,32 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, goto error_unlock; } - if (plane->type != DRM_PLANE_TYPE_CURSOR) - domain = amdgpu_display_supported_domains(adev, rbo->flags); - else + if (plane->type == DRM_PLANE_TYPE_CURSOR) domain = AMDGPU_GEM_DOMAIN_VRAM; + else { + domain = amdgpu_display_supported_domains(adev, rbo->flags); + + if (!plane->state->fb || rbo->tbo.pin_count || + !(domain & AMDGPU_GEM_DOMAIN_GTT)) + goto skip; + + abo = gem_to_amdgpu_bo(plane->state->fb->obj[0]); + + if (amdgpu_bo_reserve(abo, true) || + dma_resv_reserve_fences(abo->tbo.base.resv, 1)) + goto err; + + domain = amdgpu_mem_type_to_domain(abo->tbo.resource->mem_type); +err: + amdgpu_bo_unreserve(abo); + } +skip: r = amdgpu_bo_pin(rbo, domain); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) - DRM_ERROR("Failed to pin framebuffer with error %d\n", r); + drm_err(plane->dev, + "failed to pin framebuffer with error %d\n", r); goto error_unlock; } -- 2.40.0