From 6a4f1880fdd114ea413f57ae395daf7373bb8588 Mon Sep 17 00:00:00 2001
From: Elws. Starnight <elws@elstel.org>
From: Elws. Starnight <elws@elstel.org>
Date: Tue, 27 Nov 2018 17:52:32 +0100
Subject: [PATCH] radeon.hdmimhz parameter introduced * proven to work for a
 radeon XFX R5 230 card with radeon.hdmimhz=297   3840x2160@30 is offered
 automatically and can be set successfully   with an AOC u2868pqu as well as
 an iiyama X4071UHSU monitor;   no heat issues in the long term (cooler
 moderately warm after running half a day) * radeon_encoders.c:
 radeon_dig_monitor_is_duallink must always return   false otherwise screen
 stays black for the settings described above

---
 drivers/gpu/drm/radeon/radeon.h            |  1 +
 drivers/gpu/drm/radeon/radeon_connectors.c | 16 ++++++++++------
 drivers/gpu/drm/radeon/radeon_drv.c        |  4 ++++
 drivers/gpu/drm/radeon/radeon_encoders.c   |  3 +++
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 1a6f6edb3515..843e051e526d 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -112,6 +112,7 @@ extern int radeon_use_pflipirq;
 extern int radeon_bapm;
 extern int radeon_backlight;
 extern int radeon_auxch;
+extern int radeon_hdmimhz;
 extern int radeon_mst;
 extern int radeon_uvd;
 extern int radeon_vce;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 414642e5b7a3..1930ba7c35c1 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1480,6 +1480,7 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto
 	struct drm_device *dev = connector->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int mode_valid = MODE_OK;
 
 	/* XXX check mode bandwidth */
 
@@ -1487,7 +1488,7 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto
 	if (radeon_connector->use_digital &&
 	    (rdev->family == CHIP_RV100) &&
 	    (mode->clock > 135000))
-		return MODE_CLOCK_HIGH;
+		return MODE_CLOCK_HIGH;	    // never override since this is a known issue
 
 	if (radeon_connector->use_digital && (mode->clock > 165000)) {
 		if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
@@ -1497,19 +1498,22 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto
 		else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 			/* HDMI 1.3+ supports max clock of 340 Mhz */
 			if (mode->clock > 340000)
-				return MODE_CLOCK_HIGH;
+				mode_valid = MODE_CLOCK_HIGH;
 			else
 				return MODE_OK;
 		} else {
-			return MODE_CLOCK_HIGH;
+			mode_valid = MODE_CLOCK_HIGH;
 		}
 	}
 
+	if ( radeon_hdmimhz > 0 && ( mode->clock <= radeon_hdmimhz * 1000 ) )
+	        mode_valid = MODE_OK;
+
 	/* check against the max pixel clock */
-	if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
-		return MODE_CLOCK_HIGH;
+	if ( mode_valid == MODE_OK && (mode->clock / 10) > rdev->clock.max_pixel_clock )
+		mode_valid = MODE_CLOCK_HIGH;
 
-	return MODE_OK;
+	return mode_valid;
 }
 
 static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 99c63eeb2866..b62ac35c7eb4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -198,6 +198,7 @@ int radeon_use_pflipirq = 2;
 int radeon_bapm = -1;
 int radeon_backlight = -1;
 int radeon_auxch = -1;
+int radeon_hdmimhz = 0;
 int radeon_mst = 0;
 int radeon_uvd = 1;
 int radeon_vce = 1;
@@ -289,6 +290,9 @@ module_param_named(backlight, radeon_backlight, int, 0444);
 MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(auxch, radeon_auxch, int, 0444);
 
+MODULE_PARM_DESC(hdmimhz, "Force a maximum HDMI pixel clock (in MHz); try 165/225/297/330 to overclock your TMDS for gaining a higher resolution.");
+module_param_named(hdmimhz, radeon_hdmimhz, int, 0444);
+
 MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
 module_param_named(mst, radeon_mst, int, 0444);
 
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index c341fb2a5b56..219b2dc038bc 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -372,6 +372,9 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector_atom_dig *dig_connector;
 
+	if(radeon_hdmimhz > 0)
+	  return false;
+
 	connector = radeon_get_connector_for_encoder(encoder);
 	/* if we don't have an active device yet, just use one of
 	 * the connectors tied to the encoder.
-- 
2.11.0

