diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-10 03:50:11 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-09-06 02:21:30 -0400 |
commit | 8af6cf88a5ad7fa41d4eb700cc97f01d0bcd2a69 (patch) | |
tree | 97475031324a623e4f46fd8ce8a4db706d26b116 /drivers/gpu/drm/i915/intel_display.c | |
parent | 9dc10f37e326d5d789929e1886b5a8089ccee5a7 (diff) |
drm/i915: add tons of modeset state checks
... let's see whether this catches anything earlier and I can track
down a few bugs.
v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...
v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...
v4: Properly add a short explanation for each WARN, to avoid the need
to correlate dmesg lines with source lines accurately. Suggested by
Chris Wilson.
v5: Also dump (expected, found) for state checks (or wherever it's not
apparent from the test what exactly mismatches with expectations).
Again suggested by Chris Wilson.
v6: Due to an issue reported by Paulo Zanoni I've noticed that the
encoder checking is by far not as strict as it could and should be.
Improve this.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4c0ec180564f..d15fa0c6ae88 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) | |||
3637 | if (encoder->base.crtc) | 3637 | if (encoder->base.crtc) |
3638 | intel_encoder_dpms(encoder, mode); | 3638 | intel_encoder_dpms(encoder, mode); |
3639 | else | 3639 | else |
3640 | encoder->connectors_active = false; | 3640 | WARN_ON(encoder->connectors_active != false); |
3641 | 3641 | ||
3642 | intel_connector_check_state(to_intel_connector(connector)); | 3642 | intel_connector_check_state(to_intel_connector(connector)); |
3643 | } | 3643 | } |
@@ -6872,6 +6872,104 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) | |||
6872 | base.head) \ | 6872 | base.head) \ |
6873 | if (mask & (1 <<(intel_crtc)->pipe)) \ | 6873 | if (mask & (1 <<(intel_crtc)->pipe)) \ |
6874 | 6874 | ||
6875 | static void | ||
6876 | intel_modeset_check_state(struct drm_device *dev) | ||
6877 | { | ||
6878 | struct intel_crtc *crtc; | ||
6879 | struct intel_encoder *encoder; | ||
6880 | struct intel_connector *connector; | ||
6881 | |||
6882 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
6883 | base.head) { | ||
6884 | /* This also checks the encoder/connector hw state with the | ||
6885 | * ->get_hw_state callbacks. */ | ||
6886 | intel_connector_check_state(connector); | ||
6887 | |||
6888 | WARN(&connector->new_encoder->base != connector->base.encoder, | ||
6889 | "connector's staged encoder doesn't match current encoder\n"); | ||
6890 | } | ||
6891 | |||
6892 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, | ||
6893 | base.head) { | ||
6894 | bool enabled = false; | ||
6895 | bool active = false; | ||
6896 | enum pipe pipe, tracked_pipe; | ||
6897 | |||
6898 | DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", | ||
6899 | encoder->base.base.id, | ||
6900 | drm_get_encoder_name(&encoder->base)); | ||
6901 | |||
6902 | WARN(&encoder->new_crtc->base != encoder->base.crtc, | ||
6903 | "encoder's stage crtc doesn't match current crtc\n"); | ||
6904 | WARN(encoder->connectors_active && !encoder->base.crtc, | ||
6905 | "encoder's active_connectors set, but no crtc\n"); | ||
6906 | |||
6907 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
6908 | base.head) { | ||
6909 | if (connector->base.encoder != &encoder->base) | ||
6910 | continue; | ||
6911 | enabled = true; | ||
6912 | if (connector->base.dpms != DRM_MODE_DPMS_OFF) | ||
6913 | active = true; | ||
6914 | } | ||
6915 | WARN(!!encoder->base.crtc != enabled, | ||
6916 | "encoder's enabled state mismatch " | ||
6917 | "(expected %i, found %i)\n", | ||
6918 | !!encoder->base.crtc, enabled); | ||
6919 | WARN(active && !encoder->base.crtc, | ||
6920 | "active encoder with no crtc\n"); | ||
6921 | |||
6922 | WARN(encoder->connectors_active != active, | ||
6923 | "encoder's computed active state doesn't match tracked active state " | ||
6924 | "(expected %i, found %i)\n", active, encoder->connectors_active); | ||
6925 | |||
6926 | active = encoder->get_hw_state(encoder, &pipe); | ||
6927 | WARN(active != encoder->connectors_active, | ||
6928 | "encoder's hw state doesn't match sw tracking " | ||
6929 | "(expected %i, found %i)\n", | ||
6930 | encoder->connectors_active, active); | ||
6931 | |||
6932 | if (!encoder->base.crtc) | ||
6933 | continue; | ||
6934 | |||
6935 | tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe; | ||
6936 | WARN(active && pipe != tracked_pipe, | ||
6937 | "active encoder's pipe doesn't match" | ||
6938 | "(expected %i, found %i)\n", | ||
6939 | tracked_pipe, pipe); | ||
6940 | |||
6941 | } | ||
6942 | |||
6943 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, | ||
6944 | base.head) { | ||
6945 | bool enabled = false; | ||
6946 | bool active = false; | ||
6947 | |||
6948 | DRM_DEBUG_KMS("[CRTC:%d]\n", | ||
6949 | crtc->base.base.id); | ||
6950 | |||
6951 | WARN(crtc->active && !crtc->base.enabled, | ||
6952 | "active crtc, but not enabled in sw tracking\n"); | ||
6953 | |||
6954 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, | ||
6955 | base.head) { | ||
6956 | if (encoder->base.crtc != &crtc->base) | ||
6957 | continue; | ||
6958 | enabled = true; | ||
6959 | if (encoder->connectors_active) | ||
6960 | active = true; | ||
6961 | } | ||
6962 | WARN(active != crtc->active, | ||
6963 | "crtc's computed active state doesn't match tracked active state " | ||
6964 | "(expected %i, found %i)\n", active, crtc->active); | ||
6965 | WARN(enabled != crtc->base.enabled, | ||
6966 | "crtc's computed enabled state doesn't match tracked enabled state " | ||
6967 | "(expected %i, found %i)\n", enabled, crtc->base.enabled); | ||
6968 | |||
6969 | assert_pipe(dev->dev_private, crtc->pipe, crtc->active); | ||
6970 | } | ||
6971 | } | ||
6972 | |||
6875 | bool intel_set_mode(struct drm_crtc *crtc, | 6973 | bool intel_set_mode(struct drm_crtc *crtc, |
6876 | struct drm_display_mode *mode, | 6974 | struct drm_display_mode *mode, |
6877 | int x, int y, struct drm_framebuffer *fb) | 6975 | int x, int y, struct drm_framebuffer *fb) |
@@ -6969,6 +7067,8 @@ done: | |||
6969 | if (!ret && crtc->enabled) { | 7067 | if (!ret && crtc->enabled) { |
6970 | crtc->hwmode = saved_hwmode; | 7068 | crtc->hwmode = saved_hwmode; |
6971 | crtc->mode = saved_mode; | 7069 | crtc->mode = saved_mode; |
7070 | } else { | ||
7071 | intel_modeset_check_state(dev); | ||
6972 | } | 7072 | } |
6973 | 7073 | ||
6974 | return ret; | 7074 | return ret; |
@@ -8147,6 +8247,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev) | |||
8147 | } | 8247 | } |
8148 | 8248 | ||
8149 | intel_modeset_update_staged_output_state(dev); | 8249 | intel_modeset_update_staged_output_state(dev); |
8250 | |||
8251 | intel_modeset_check_state(dev); | ||
8150 | } | 8252 | } |
8151 | 8253 | ||
8152 | void intel_modeset_gem_init(struct drm_device *dev) | 8254 | void intel_modeset_gem_init(struct drm_device *dev) |