Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c0ae2ab authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: properly handle crtc powergating



Need to make sure the crtc is gated on before modesetting.
Explicitly gate the crtc on in prepare() and set a flag
so that the dpms functions don't gate it off during
mode set.

Noticed by sylware on IRC.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 3838f46e
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
		/* adjust pm to dpms changes BEFORE enabling crtcs */
		radeon_pm_compute_clocks(rdev);
		/* disable crtc pair power gating before programming */
		if (ASIC_IS_DCE6(rdev))
		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
			atombios_powergate_crtc(crtc, ATOM_DISABLE);
		atombios_enable_crtc(crtc, ATOM_ENABLE);
		if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
		atombios_enable_crtc(crtc, ATOM_DISABLE);
		radeon_crtc->enabled = false;
		/* power gating is per-pair */
		if (ASIC_IS_DCE6(rdev)) {
		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) {
			struct drm_crtc *other_crtc;
			struct radeon_crtc *other_radeon_crtc;
			list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) {
@@ -1635,18 +1635,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
static void atombios_crtc_prepare(struct drm_crtc *crtc)
{
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
	struct drm_device *dev = crtc->dev;
	struct radeon_device *rdev = dev->dev_private;

	radeon_crtc->in_mode_set = true;
	/* pick pll */
	radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);

	/* disable crtc pair power gating before programming */
	if (ASIC_IS_DCE6(rdev))
		atombios_powergate_crtc(crtc, ATOM_DISABLE);

	atombios_lock_crtc(crtc, ATOM_ENABLE);
	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}

static void atombios_crtc_commit(struct drm_crtc *crtc)
{
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);

	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
	atombios_lock_crtc(crtc, ATOM_DISABLE);
	radeon_crtc->in_mode_set = false;
}

static void atombios_crtc_disable(struct drm_crtc *crtc)
+4 −0
Original line number Diff line number Diff line
@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,

static void radeon_crtc_prepare(struct drm_crtc *crtc)
{
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
	struct drm_device *dev = crtc->dev;
	struct drm_crtc *crtci;

	radeon_crtc->in_mode_set = true;
	/*
	* The hardware wedges sometimes if you reconfigure one CRTC
	* whilst another is running (see fdo bug #24611).
@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)

static void radeon_crtc_commit(struct drm_crtc *crtc)
{
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
	struct drm_device *dev = crtc->dev;
	struct drm_crtc *crtci;

@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
		if (crtci->enabled)
			radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
	}
	radeon_crtc->in_mode_set = false;
}

static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
+1 −0
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@ struct radeon_crtc {
	u16 lut_r[256], lut_g[256], lut_b[256];
	bool enabled;
	bool can_tile;
	bool in_mode_set;
	uint32_t crtc_offset;
	struct drm_gem_object *cursor_bo;
	uint64_t cursor_addr;