Commit a3621485 authored by Andrey Grodzovsky's avatar Andrey Grodzovsky Committed by Alex Deucher
Browse files

drm/amd/display: Switch to DRM helpers in s3.

parent 268cadbd
Loading
Loading
Loading
Loading
+14 −143
Original line number Diff line number Diff line
@@ -451,28 +451,17 @@ static int dm_suspend(void *handle)
	struct amdgpu_device *adev = handle;
	struct amdgpu_display_manager *dm = &adev->dm;
	int ret = 0;
	struct drm_crtc *crtc;

	s3_handle_mst(adev->ddev, true);

	/* flash all pending vblank events and turn interrupt off
	 * before disabling CRTCs. They will be enabled back in
	 * dm_display_resume
	 */
	drm_modeset_lock_all(adev->ddev);
	list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) {
		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
		if (acrtc->stream)
				drm_crtc_vblank_off(crtc);
	}
	drm_modeset_unlock_all(adev->ddev);

	amdgpu_dm_irq_suspend(adev);

	adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);

	dc_set_power_state(
		dm->dc,
		DC_ACPI_CM_POWER_STATE_D3,
		DC_VIDEO_POWER_SUSPEND);
		DC_ACPI_CM_POWER_STATE_D3
		);

	return ret;
}
@@ -504,120 +493,6 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector(
	return NULL;
}

static int dm_display_resume(struct drm_device *ddev)
{
	int ret = 0;
	struct drm_connector *connector;

	struct drm_atomic_state *state = drm_atomic_state_alloc(ddev);
	struct drm_plane *plane;
	struct drm_crtc *crtc;
	struct amdgpu_connector *aconnector;
	struct drm_connector_state *conn_state;

	if (!state)
		return ENOMEM;

	state->acquire_ctx = ddev->mode_config.acquire_ctx;

	/* Construct an atomic state to restore previous display setting */

	/*
	 * Attach connectors to drm_atomic_state
	 * Should be done in the first place in order to make connectors
	 * available in state during crtc state processing. It is used for
	 * making decision if crtc should be disabled in case sink got
	 * disconnected.
	 *
	 * Connectors state crtc with NULL dc_sink should be cleared, because it
	 * will fail validation during commit
	 */
	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
		aconnector = to_amdgpu_connector(connector);
		conn_state = drm_atomic_get_connector_state(state, connector);

		ret = PTR_ERR_OR_ZERO(conn_state);
		if (ret)
			goto err;
	}

	/* Attach crtcs to drm_atomic_state*/
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		struct drm_crtc_state *crtc_state =
			drm_atomic_get_crtc_state(state, crtc);

		ret = PTR_ERR_OR_ZERO(crtc_state);
		if (ret)
			goto err;

		/* force a restore */
		crtc_state->mode_changed = true;
	}


	/* Attach planes to drm_atomic_state */
	list_for_each_entry(plane, &ddev->mode_config.plane_list, head) {

		struct drm_crtc *crtc;
		struct drm_gem_object *obj;
		struct drm_framebuffer *fb;
		struct amdgpu_framebuffer *afb;
		struct amdgpu_bo *rbo;
		int r;
		struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane);

		ret = PTR_ERR_OR_ZERO(plane_state);
		if (ret)
			goto err;

		crtc = plane_state->crtc;
		fb = plane_state->fb;

		if (!crtc || !crtc->state || !crtc->state->active)
			continue;

		if (!fb) {
			DRM_DEBUG_KMS("No FB bound\n");
			return 0;
		}

		/*
		 * Pin back the front buffers, cursor buffer was already pinned
		 * back in amdgpu_resume_kms
		 */

		afb = to_amdgpu_framebuffer(fb);

		obj = afb->obj;
		rbo = gem_to_amdgpu_bo(obj);
		r = amdgpu_bo_reserve(rbo, false);
		if (unlikely(r != 0))
		       return r;

		r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL);

		amdgpu_bo_unreserve(rbo);

		if (unlikely(r != 0)) {
			DRM_ERROR("Failed to pin framebuffer\n");
			return r;
		}

	}


	/* Call commit internally with the state we just constructed */
	ret = drm_atomic_commit(state);
	if (!ret)
		return 0;

err:
	DRM_ERROR("Restoring old state failed with %i\n", ret);
	drm_atomic_state_put(state);

	return ret;
}

static int dm_resume(void *handle)
{
	struct amdgpu_device *adev = handle;
@@ -626,8 +501,8 @@ static int dm_resume(void *handle)
	/* power on hardware */
	dc_set_power_state(
		dm->dc,
		DC_ACPI_CM_POWER_STATE_D0,
		DC_VIDEO_POWER_ON);
		DC_ACPI_CM_POWER_STATE_D0
		);

	return 0;
}
@@ -638,8 +513,10 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev )
	struct amdgpu_display_manager *dm = &adev->dm;
	struct amdgpu_connector *aconnector;
	struct drm_connector *connector;
	int ret = 0;
	struct drm_crtc *crtc;
	struct drm_crtc_state *crtc_state;
	int ret = 0;
	int i;

	/* program HPD filter */
	dc_resume(dm->dc);
@@ -653,14 +530,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev )
	 */
	amdgpu_dm_irq_resume_early(adev);

	drm_modeset_lock_all(ddev);
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
		if (acrtc->stream)
				drm_crtc_vblank_on(crtc);
	}
	drm_modeset_unlock_all(ddev);

	/* Do detection*/
	list_for_each_entry(connector,
			&ddev->mode_config.connector_list, head) {
@@ -678,9 +547,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev )
		amdgpu_dm_update_connector_after_detect(aconnector);
	}

	drm_modeset_lock_all(ddev);
	ret = dm_display_resume(ddev);
	drm_modeset_unlock_all(ddev);
	/* Force mode set in atomic comit */
	for_each_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i)
			crtc_state->active_changed = true;

	ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state);

	amdgpu_dm_irq_resume(adev);

+5 −0
Original line number Diff line number Diff line
@@ -128,6 +128,11 @@ struct amdgpu_display_manager {
	struct work_struct mst_hotplug_work;

	struct mod_freesync *freesync_module;

	/**
	 * Caches device atomic state for suspend/resume
	 */
	struct drm_atomic_state *cached_state;
};

/* basic init/fini API */
+1 −7
Original line number Diff line number Diff line
@@ -1589,21 +1589,15 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)

void dc_set_power_state(
	struct dc *dc,
	enum dc_acpi_cm_power_state power_state,
	enum dc_video_power_state video_power_state)
	enum dc_acpi_cm_power_state power_state)
{
	struct core_dc *core_dc = DC_TO_CORE(dc);

	core_dc->previous_power_state = core_dc->current_power_state;
	core_dc->current_power_state = video_power_state;

	switch (power_state) {
	case DC_ACPI_CM_POWER_STATE_D0:
		core_dc->hwss.init_hw(core_dc);
		break;
	default:
		/* NULL means "reset/release all DC streams" */
		dc_commit_streams(dc, NULL, 0);

		core_dc->hwss.power_down(core_dc);

+1 −2
Original line number Diff line number Diff line
@@ -705,8 +705,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index(

void dc_set_power_state(
		struct dc *dc,
		enum dc_acpi_cm_power_state power_state,
		enum dc_video_power_state video_power_state);
		enum dc_acpi_cm_power_state power_state);
void dc_resume(const struct dc *dc);

/*******************************************************************************
+0 −4
Original line number Diff line number Diff line
@@ -26,10 +26,6 @@ struct core_dc {
	struct validate_context *scratch_val_ctx;
	struct resource_pool *res_pool;

	/*Power State*/
	enum dc_video_power_state previous_power_state;
	enum dc_video_power_state current_power_state;

	/* Display Engine Clock levels */
	struct dm_pp_clock_levels sclk_lvls;