Takashi Iwai fd6a88
From 227545b9a08c68778ddd89428f99c351fc9315ac Mon Sep 17 00:00:00 2001
Takashi Iwai fd6a88
From: Kai-Heng Feng <kai.heng.feng@canonical.com>
Takashi Iwai fd6a88
Date: Fri, 30 Apr 2021 12:56:56 +0800
Takashi Iwai fd6a88
Subject: [PATCH] drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors are connected
Takashi Iwai fd6a88
Git-commit: 227545b9a08c68778ddd89428f99c351fc9315ac
Takashi Iwai fd6a88
Patch-mainline: v5.13-rc2
Takashi Iwai fd6a88
References: git-fixes
Takashi Iwai fd6a88
Takashi Iwai fd6a88
Screen flickers rapidly when two 4K 60Hz monitors are in use. This issue
Takashi Iwai fd6a88
doesn't happen when one monitor is 4K 60Hz (pixelclock 594MHz) and
Takashi Iwai fd6a88
another one is 4K 30Hz (pixelclock 297MHz).
Takashi Iwai fd6a88
Takashi Iwai fd6a88
The issue is gone after setting "power_dpm_force_performance_level" to
Takashi Iwai fd6a88
"high". Following the indication, we found that the issue occurs when
Takashi Iwai fd6a88
sclk is too low.
Takashi Iwai fd6a88
Takashi Iwai fd6a88
So resolve the issue by disabling sclk switching when there are two
Takashi Iwai fd6a88
monitors requires high pixelclock (> 297MHz).
Takashi Iwai fd6a88
Takashi Iwai fd6a88
V2: - Only apply the fix to Oland.
Takashi Iwai fd6a88
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Takashi Iwai fd6a88
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Takashi Iwai fd6a88
Cc: stable@vger.kernel.org
Takashi Iwai fd6a88
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai fd6a88
Takashi Iwai fd6a88
---
Takashi Iwai fd6a88
 drivers/gpu/drm/radeon/radeon.h    | 1 +
Takashi Iwai fd6a88
 drivers/gpu/drm/radeon/radeon_pm.c | 8 ++++++++
Takashi Iwai fd6a88
 drivers/gpu/drm/radeon/si_dpm.c    | 3 +++
Takashi Iwai fd6a88
 3 files changed, 12 insertions(+)
Takashi Iwai fd6a88
Takashi Iwai fd6a88
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
Takashi Iwai fd6a88
index 42281fce552e..56ed5634cebe 100644
Takashi Iwai fd6a88
--- a/drivers/gpu/drm/radeon/radeon.h
Takashi Iwai fd6a88
+++ b/drivers/gpu/drm/radeon/radeon.h
Takashi Iwai fd6a88
@@ -1549,6 +1549,7 @@ struct radeon_dpm {
Takashi Iwai fd6a88
 	void                    *priv;
Takashi Iwai fd6a88
 	u32			new_active_crtcs;
Takashi Iwai fd6a88
 	int			new_active_crtc_count;
Takashi Iwai fd6a88
+	int			high_pixelclock_count;
Takashi Iwai fd6a88
 	u32			current_active_crtcs;
Takashi Iwai fd6a88
 	int			current_active_crtc_count;
Takashi Iwai fd6a88
 	bool single_display;
Takashi Iwai fd6a88
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
Takashi Iwai fd6a88
index 0c1950f4e146..3861c0b98fcf 100644
Takashi Iwai fd6a88
--- a/drivers/gpu/drm/radeon/radeon_pm.c
Takashi Iwai fd6a88
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
Takashi Iwai fd6a88
@@ -1767,6 +1767,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
Takashi Iwai fd6a88
 	struct drm_device *ddev = rdev->ddev;
Takashi Iwai fd6a88
 	struct drm_crtc *crtc;
Takashi Iwai fd6a88
 	struct radeon_crtc *radeon_crtc;
Takashi Iwai fd6a88
+	struct radeon_connector *radeon_connector;
Takashi Iwai fd6a88
 
Takashi Iwai fd6a88
 	if (!rdev->pm.dpm_enabled)
Takashi Iwai fd6a88
 		return;
Takashi Iwai fd6a88
@@ -1776,6 +1777,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
Takashi Iwai fd6a88
 	/* update active crtc counts */
Takashi Iwai fd6a88
 	rdev->pm.dpm.new_active_crtcs = 0;
Takashi Iwai fd6a88
 	rdev->pm.dpm.new_active_crtc_count = 0;
Takashi Iwai fd6a88
+	rdev->pm.dpm.high_pixelclock_count = 0;
Takashi Iwai fd6a88
 	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
Takashi Iwai fd6a88
 		list_for_each_entry(crtc,
Takashi Iwai fd6a88
 				    &ddev->mode_config.crtc_list, head) {
Takashi Iwai fd6a88
@@ -1783,6 +1785,12 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
Takashi Iwai fd6a88
 			if (crtc->enabled) {
Takashi Iwai fd6a88
 				rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
Takashi Iwai fd6a88
 				rdev->pm.dpm.new_active_crtc_count++;
Takashi Iwai fd6a88
+				if (!radeon_crtc->connector)
Takashi Iwai fd6a88
+					continue;
Takashi Iwai fd6a88
+
Takashi Iwai fd6a88
+				radeon_connector = to_radeon_connector(radeon_crtc->connector);
Takashi Iwai fd6a88
+				if (radeon_connector->pixelclock_for_modeset > 297000)
Takashi Iwai fd6a88
+					rdev->pm.dpm.high_pixelclock_count++;
Takashi Iwai fd6a88
 			}
Takashi Iwai fd6a88
 		}
Takashi Iwai fd6a88
 	}
Takashi Iwai fd6a88
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
Takashi Iwai fd6a88
index 2c54c0d7ca5b..3add39c1a689 100644
Takashi Iwai fd6a88
--- a/drivers/gpu/drm/radeon/si_dpm.c
Takashi Iwai fd6a88
+++ b/drivers/gpu/drm/radeon/si_dpm.c
Takashi Iwai fd6a88
@@ -2979,6 +2979,9 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
Takashi Iwai fd6a88
 		    (rdev->pdev->device == 0x6605)) {
Takashi Iwai fd6a88
 			max_sclk = 75000;
Takashi Iwai fd6a88
 		}
Takashi Iwai fd6a88
+
Takashi Iwai fd6a88
+		if (rdev->pm.dpm.high_pixelclock_count > 1)
Takashi Iwai fd6a88
+			disable_sclk_switching = true;
Takashi Iwai fd6a88
 	}
Takashi Iwai fd6a88
 
Takashi Iwai fd6a88
 	if (rps->vce_active) {
Takashi Iwai fd6a88
-- 
Takashi Iwai fd6a88
2.26.2
Takashi Iwai fd6a88