drm/i915: check connector hw/sw state
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 2 Jul 2012 19:54:27 +0000 (21:54 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 6 Sep 2012 05:59:42 +0000 (07:59 +0200)
Atm we can only check the connector state after a dpms call - while
doing modeset with the copy&pasted crtc helper code things are too
ill-defined for proper checking. But the idea is very much to call
this check from the modeset code, too.

v2: Fix dpms check and don't presume that if the hw isn't on that it
must not be linked up with an encoder (it could simply be switched off
with the dpms state).

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_sdvo.c

index b0fadd00a4dca58a5cffde4fc056b518e1d3c8c1..c002d260c1a4f56e97b574343e47d2ff413d9ffb 100644 (file)
@@ -176,6 +176,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
 
                intel_crtc_update_dpms(crtc);
        }
+
+       intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
index 8c8dbc90faf1de04140babbad5e624303a638f7b..15e4a652dee6048e9fea4390784cf03aa0bd8f5f 100644 (file)
@@ -3562,6 +3562,41 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
        }
 }
 
+/* Cross check the actual hw state with our own modeset state tracking (and it's
+ * internal consistency). */
+void intel_connector_check_state(struct intel_connector *connector)
+{
+       if (connector->get_hw_state(connector)) {
+               struct intel_encoder *encoder = connector->encoder;
+               struct drm_crtc *crtc;
+               bool encoder_enabled;
+               enum pipe pipe;
+
+               DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                             connector->base.base.id,
+                             drm_get_connector_name(&connector->base));
+
+               WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
+                    "wrong connector dpms state\n");
+               WARN(connector->base.encoder != &encoder->base,
+                    "active connector not linked to encoder\n");
+               WARN(!encoder->connectors_active,
+                    "encoder->connectors_active not set\n");
+
+               encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+               WARN(!encoder_enabled, "encoder not enabled\n");
+               if (WARN_ON(!encoder->base.crtc))
+                       return;
+
+               crtc = encoder->base.crtc;
+
+               WARN(!crtc->enabled, "crtc not enabled\n");
+               WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
+               WARN(pipe != to_intel_crtc(crtc)->pipe,
+                    "encoder active on the wrong pipe\n");
+       }
+}
+
 /* Even simpler default implementation, if there's really no special case to
  * consider. */
 void intel_connector_dpms(struct drm_connector *connector, int mode)
@@ -3582,6 +3617,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
                intel_encoder_dpms(encoder, mode);
        else
                encoder->connectors_active = false;
+
+       intel_connector_check_state(to_intel_connector(connector));
 }
 
 /* Simple connector->get_hw_state implementation for encoders that support only
index e3928b922825753b2ba5852339a90f22a96345a5..96fd1e7ff02e58ff9800072bb8880142b443a03b 100644 (file)
@@ -1367,6 +1367,8 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
                intel_encoder_dpms(&intel_dp->base, mode);
                WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
        }
+
+       intel_connector_check_state(to_intel_connector(connector));
 }
 
 /*
index 4daa7e65b04a6b64023e9fc49f9a6f536e7d2333..e2116d96bd6f01f5ea6087b9842690f37e994e25 100644 (file)
@@ -434,6 +434,7 @@ extern void intel_encoder_destroy(struct drm_encoder *encoder);
 extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode);
 extern void intel_connector_dpms(struct drm_connector *, int mode);
 extern bool intel_connector_get_hw_state(struct intel_connector *connector);
+extern void intel_connector_check_state(struct intel_connector *);
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
 {
index e9397b72b4f36ae2e61012561696453aaac7306a..17dc8bebf8f24078e44fbd7fc29311b0766a594f 100644 (file)
@@ -188,6 +188,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 
                intel_crtc_update_dpms(crtc);
        }
+
+       intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_dvo_mode_valid(struct drm_connector *connector,
index 4a735a50f47192f244a20e5b4c6f1a3ea99dfe99..198bb8965b8dcc30038dfc14359f92d314ac200f 100644 (file)
@@ -1274,6 +1274,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
                        intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
                intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
        }
+
+       intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,