From a2e15b0e6c91a13d2219fba1f9e83ecd473a60db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 19 Mar 2021 16:34:45 -0400 Subject: drm/amdgpu: clean up non-DC suspend/resume handling Move the non-DC specific code into the DCE IP blocks similar to how we handle DC. This cleans up the common suspend and resume pathes. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b05301e1815c..9a2f811450ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1354,3 +1354,92 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc, return amdgpu_display_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos, stime, etime, mode); } + +int amdgpu_display_suspend_helper(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev_to_drm(adev); + struct drm_crtc *crtc; + struct drm_connector *connector; + struct drm_connector_list_iter iter; + int r; + + /* turn off display hw */ + drm_modeset_lock_all(dev); + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(connector, &iter) + drm_helper_connector_dpms(connector, + DRM_MODE_DPMS_OFF); + drm_connector_list_iter_end(&iter); + drm_modeset_unlock_all(dev); + /* unpin the front buffers and cursors */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = crtc->primary->fb; + struct amdgpu_bo *robj; + + if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) { + struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + r = amdgpu_bo_reserve(aobj, true); + if (r == 0) { + amdgpu_bo_unpin(aobj); + amdgpu_bo_unreserve(aobj); + } + } + + if (fb == NULL || fb->obj[0] == NULL) { + continue; + } + robj = gem_to_amdgpu_bo(fb->obj[0]); + /* don't unpin kernel fb objects */ + if (!amdgpu_fbdev_robj_is_fb(adev, robj)) { + r = amdgpu_bo_reserve(robj, true); + if (r == 0) { + amdgpu_bo_unpin(robj); + amdgpu_bo_unreserve(robj); + } + } + } + return r; +} + +int amdgpu_display_resume_helper(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev_to_drm(adev); + struct drm_connector *connector; + struct drm_connector_list_iter iter; + struct drm_crtc *crtc; + int r; + + /* pin cursors */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) { + struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + r = amdgpu_bo_reserve(aobj, true); + if (r == 0) { + r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM); + if (r != 0) + dev_err(adev->dev, "Failed to pin cursor BO (%d)\n", r); + amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj); + amdgpu_bo_unreserve(aobj); + } + } + } + + drm_helper_resume_force_mode(dev); + + /* turn on display hw */ + drm_modeset_lock_all(dev); + + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(connector, &iter) + drm_helper_connector_dpms(connector, + DRM_MODE_DPMS_ON); + drm_connector_list_iter_end(&iter); + + drm_modeset_unlock_all(dev); + + return 0; +} + -- cgit v1.2.3 From f4a9be998c8ee39a30a68cb775c91928fe10a384 Mon Sep 17 00:00:00 2001 From: Mark Yacoub Date: Wed, 24 Mar 2021 16:16:24 -0400 Subject: drm/amdgpu: Ensure that the modifier requested is supported by plane. On initializing the framebuffer, call drm_any_plane_has_format to do a check if the modifier is supported. drm_any_plane_has_format calls dm_plane_format_mod_supported which is extended to validate that the modifier is on the list of the plane's supported modifiers. The bug was caught using igt-gpu-tools test: kms_addfb_basic.addfb25-bad-modifier Tested on ChromeOS Zork by turning on the display, running an overlay test, and running a YT video. === Changes from v1 === Explicitly handle DRM_FORMAT_MOD_INVALID modifier. Cc: Alex Deucher Cc: Bas Nieuwenhuizen Signed-off-by: Mark Yacoub Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 9a2f811450ed..2e622c1675d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -908,6 +908,19 @@ int amdgpu_display_gem_fb_verify_and_init( &amdgpu_fb_funcs); if (ret) goto err; + /* Verify that the modifier is supported. */ + if (!drm_any_plane_has_format(dev, mode_cmd->pixel_format, + mode_cmd->modifier[0])) { + struct drm_format_name_buf format_name; + drm_dbg_kms(dev, + "unsupported pixel format %s / modifier 0x%llx\n", + drm_get_format_name(mode_cmd->pixel_format, + &format_name), + mode_cmd->modifier[0]); + + ret = -EINVAL; + goto err; + } ret = amdgpu_display_framebuffer_init(dev, rfb, mode_cmd, obj); if (ret) 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 281661f69ac5..81565e73c5c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4210,6 +4210,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, { struct amdgpu_device *adev = drm_to_adev(plane->dev); const struct drm_format_info *info = drm_format_info(format); + int i; enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; @@ -4217,11 +4218,22 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, return false; /* - * We always have to allow this modifier, because core DRM still - * checks LINEAR support if userspace does not provide modifers. + * We always have to allow these modifiers: + * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers. + * 2. Not passing any modifiers is the same as explicitly passing INVALID. */ - if (modifier == DRM_FORMAT_MOD_LINEAR) + if (modifier == DRM_FORMAT_MOD_LINEAR || + modifier == DRM_FORMAT_MOD_INVALID) { return true; + } + + /* Check that the modifier is on the list of the plane's supported modifiers. */ + for (i = 0; i < plane->modifier_count; i++) { + if (modifier == plane->modifiers[i]) + break; + } + if (i == plane->modifier_count) + return false; /* * The arbitrary tiling support for multiplane formats has not been hooked -- cgit v1.2.3 From 55fa622fe635bfc3f2587d784f6facc30f8fdf12 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Mon, 5 Apr 2021 10:28:02 -0400 Subject: Revert "drm/amdgpu: Ensure that the modifier requested is supported by plane." This reverts commit f4a9be998c8ee39a30a68cb775c91928fe10a384. The original commit was found to cause the following two issues on sienna cichlid: 1. Refresh rate locked during vrrdemo 2. Display sticks on flipped landscape mode after changing orientation, and cannot be changed back to regular landscape Signed-off-by: Qingqing Zhuo Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 13 ------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++--------------- 2 files changed, 3 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 2e622c1675d7..9a2f811450ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -908,19 +908,6 @@ int amdgpu_display_gem_fb_verify_and_init( &amdgpu_fb_funcs); if (ret) goto err; - /* Verify that the modifier is supported. */ - if (!drm_any_plane_has_format(dev, mode_cmd->pixel_format, - mode_cmd->modifier[0])) { - struct drm_format_name_buf format_name; - drm_dbg_kms(dev, - "unsupported pixel format %s / modifier 0x%llx\n", - drm_get_format_name(mode_cmd->pixel_format, - &format_name), - mode_cmd->modifier[0]); - - ret = -EINVAL; - goto err; - } ret = amdgpu_display_framebuffer_init(dev, rfb, mode_cmd, obj); if (ret) 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 29b30e7b631d..ec3c6d62a2b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4225,7 +4225,6 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, { struct amdgpu_device *adev = drm_to_adev(plane->dev); const struct drm_format_info *info = drm_format_info(format); - int i; enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; @@ -4233,22 +4232,11 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, return false; /* - * We always have to allow these modifiers: - * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers. - * 2. Not passing any modifiers is the same as explicitly passing INVALID. + * We always have to allow this modifier, because core DRM still + * checks LINEAR support if userspace does not provide modifers. */ - if (modifier == DRM_FORMAT_MOD_LINEAR || - modifier == DRM_FORMAT_MOD_INVALID) { + if (modifier == DRM_FORMAT_MOD_LINEAR) return true; - } - - /* Check that the modifier is on the list of the plane's supported modifiers. */ - for (i = 0; i < plane->modifier_count; i++) { - if (modifier == plane->modifiers[i]) - break; - } - if (i == plane->modifier_count) - return false; /* * The arbitrary tiling support for multiplane formats has not been hooked -- cgit v1.2.3