diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2021-03-19 16:34:45 -0400 | 
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2021-04-09 16:36:40 -0400 | 
| commit | a2e15b0e6c91a13d2219fba1f9e83ecd473a60db (patch) | |
| tree | 2df8109d190d4066866a6de016c6f904e3801f7b /drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
| parent | 48ccbf730c945c7fc86e8790a8246247a2c0478b (diff) | |
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 <evan.quan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 89 | 
1 files changed, 89 insertions, 0 deletions
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; +} +  | 
