drm/radeon/kms: reduce probe latency on digital connectors
authorTvrtko Ursulin <tvrtko.ursulin@onelan.co.uk>
Fri, 16 Mar 2012 16:22:11 +0000 (12:22 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 20 Mar 2012 08:45:42 +0000 (08:45 +0000)
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>
drivers/gpu/drm/radeon/radeon_connectors.c

index d2e6144..64774ac 100644 (file)
@@ -827,6 +827,27 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
        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
@@ -851,6 +872,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        enum drm_connector_status ret = connector_status_disconnected;
        bool dret = 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) {
@@ -1254,6 +1278,9 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
        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;