From 11fe1266253a96c4d4ac9c07918372a98248c62e Mon Sep 17 00:00:00 2001
From: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk>
Date: Fri, 16 Mar 2012 12:22:11 -0400
Subject: drm/radeon/kms: reduce probe latency on digital connectors
Git-commit: 11fe1266253a96c4d4ac9c07918372a98248c62e
Patch-mainline: v3.4-rc1

On a system with one HDMI and one VGA connector the latter
causes output polling to run every ten seconds. This causes
full EDID re-fetch on every poll and approx. 100ms rendering
stalls are experienced by full screen page-flipping applications.
Optimisation is to trust HPD sense on R600+ ASICs and to skip
doing these expensive probes unless HPD sense has changed.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=47007

agd5f: fix patch and message formatting.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Acked-by: Michal Srb <msrb@suse.com>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

Index: linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_connectors.c
===================================================================
--- linux-3.0-SLE11-SP3.orig/drivers/gpu/drm/radeon/radeon_connectors.c
+++ linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -846,6 +846,27 @@ static int radeon_dvi_get_modes(struct d
 	return ret;
 }
 
+static bool radeon_check_hpd_status_unchanged(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);
+	enum drm_connector_status status;
+
+	/* We only trust HPD on R600 and newer ASICS. */
+	if (rdev->family >= CHIP_R600
+	  && radeon_connector->hpd.hpd != RADEON_HPD_NONE) {
+		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+			status = connector_status_connected;
+		else
+			status = connector_status_disconnected;
+		if (connector->status == status)
+			return true;
+	}
+
+	return false;
+}
+
 /*
  * DVI is complicated
  * Do a DDC probe, if DDC probe passes, get the full EDID so
@@ -870,6 +891,9 @@ radeon_dvi_detect(struct drm_connector *
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false, broken_edid = false;
 
+	if (!force && radeon_check_hpd_status_unchanged(connector))
+		return connector->status;
+
 	if (radeon_connector->ddc_bus)
 		dret = radeon_ddc_probe(radeon_connector);
 	if (dret) {
@@ -1287,6 +1311,9 @@ radeon_dp_detect(struct drm_connector *c
 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 
+	if (!force && radeon_check_hpd_status_unchanged(connector))
+		return connector->status;
+
 	if (radeon_connector->edid) {
 		kfree(radeon_connector->edid);
 		radeon_connector->edid = NULL;
