From 17245f2ba90fe9242041dd0626a570a8becce5c1 Mon Sep 17 00:00:00 2001
From: Elws. Starnight <elws@elstel.org>
From: Elws. Starnight <elws@elstel.org>
Date: Mon, 22 Aug 2016 10:27:53 +0200
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 5633ee3..5451a43 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -113,6 +113,7 @@ extern int radeon_bapm;
 extern int radeon_backlight;
 extern int radeon_auxch;
 extern int radeon_mst;
+extern int radeon_hdmimhz;
 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 b79f3b0..88736ac 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1476,6 +1476,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
 	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 */
 
@@ -1483,7 +1484,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
 	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) ||
@@ -1493,19 +1494,22 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
 		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 c01a7c6..85cf798 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -202,6 +202,7 @@ int radeon_bapm = -1;
 int radeon_backlight = -1;
 int radeon_auxch = -1;
 int radeon_mst = 0;
+int radeon_hdmimhz = 0;
 int radeon_uvd = 1;
 int radeon_vce = 1;
 
@@ -295,6 +296,9 @@ module_param_named(auxch, radeon_auxch, int, 0444);
 MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
 module_param_named(mst, radeon_mst, 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(uvd, "uvd enable/disable uvd support (1 = enable, 0 = disable)");
 module_param_named(uvd, radeon_uvd, int, 0444);
 
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index c6ee802..0d06e12 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.9.3

