From: Alex Deucher <alexander.deuc...@amd.com>

When force == false, we don't do load detection in the connector
detect functions.  Unforunately, we also return the previous
connector state so we never get disconnect events for DVI-I, DVI-A,
or VGA.  Save whether we detected the monitor via load detection
previously and use that to determine whether we return the previous
state or not.

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

Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
Cc: stable at kernel.org
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   23 ++++++++++++++++++++---
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c 
b/drivers/gpu/drm/radeon/radeon_connectors.c
index 103eb1b..dec6cbe 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -724,6 +724,7 @@ radeon_vga_detect(struct drm_connector *connector, bool 
force)
                dret = radeon_ddc_probe(radeon_connector,
                                        
radeon_connector->requires_extended_probe);
        if (dret) {
+               radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
                        kfree(radeon_connector->edid);
                        radeon_connector->edid = NULL;
@@ -750,12 +751,21 @@ radeon_vga_detect(struct drm_connector *connector, bool 
force)
        } else {

                /* if we aren't forcing don't do destructive polling */
-               if (!force)
-                       return connector->status;
+               if (!force) {
+                       /* only return the previous status if we last
+                        * detected a monitor via load.
+                        */
+                       if (radeon_connector->detected_by_load)
+                               return connector->status;
+                       else
+                               return ret;
+               }

                if (radeon_connector->dac_load_detect && encoder) {
                        encoder_funcs = encoder->helper_private;
                        ret = encoder_funcs->detect(encoder, connector);
+                       if (ret == connector_status_connected)
+                               radeon_connector->detected_by_load = true;
                }
        }

@@ -897,6 +907,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool 
force)
                dret = radeon_ddc_probe(radeon_connector,
                                        
radeon_connector->requires_extended_probe);
        if (dret) {
+               radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
                        kfree(radeon_connector->edid);
                        radeon_connector->edid = NULL;
@@ -964,8 +975,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool 
force)
            (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
                goto out;

+       /* if we aren't forcing don't do destructive polling */
        if (!force) {
-               ret = connector->status;
+               /* only return the previous status if we last
+                * detected a monitor via load.
+                */
+               if (radeon_connector->detected_by_load)
+                       ret = connector->status;
                goto out;
        }

@@ -989,6 +1005,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool 
force)
                                        ret = encoder_funcs->detect(encoder, 
connector);
                                        if (ret == connector_status_connected) {
                                                radeon_connector->use_digital = 
false;
+                                               
radeon_connector->detected_by_load = true;
                                        }
                                }
                                break;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index 68820f5..ed0178f 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -447,6 +447,7 @@ struct radeon_connector {
        struct edid *edid;
        void *con_priv;
        bool dac_load_detect;
+       bool detected_by_load; /* if the connection status was determined by 
load */
        uint16_t connector_object_id;
        struct radeon_hpd hpd;
        struct radeon_router router;
-- 
1.7.1.1

Reply via email to