diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index efe829919755..56746dcac40f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -7937,6 +7937,11 @@ intel_modeset_check_state(struct drm_device *dev) | |||
7937 | memset(&pipe_config, 0, sizeof(pipe_config)); | 7937 | memset(&pipe_config, 0, sizeof(pipe_config)); |
7938 | active = dev_priv->display.get_pipe_config(crtc, | 7938 | active = dev_priv->display.get_pipe_config(crtc, |
7939 | &pipe_config); | 7939 | &pipe_config); |
7940 | |||
7941 | /* hw state is inconsistent with the pipe A quirk */ | ||
7942 | if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) | ||
7943 | active = crtc->active; | ||
7944 | |||
7940 | WARN(crtc->active != active, | 7945 | WARN(crtc->active != active, |
7941 | "crtc active state doesn't match with hw state " | 7946 | "crtc active state doesn't match with hw state " |
7942 | "(expected %i, found %i)\n", crtc->active, active); | 7947 | "(expected %i, found %i)\n", crtc->active, active); |
@@ -8140,6 +8145,21 @@ static void intel_set_config_restore_state(struct drm_device *dev, | |||
8140 | } | 8145 | } |
8141 | } | 8146 | } |
8142 | 8147 | ||
8148 | static bool | ||
8149 | is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors, | ||
8150 | int num_connectors) | ||
8151 | { | ||
8152 | int i; | ||
8153 | |||
8154 | for (i = 0; i < num_connectors; i++) | ||
8155 | if (connectors[i].encoder && | ||
8156 | connectors[i].encoder->crtc == crtc && | ||
8157 | connectors[i].dpms != DRM_MODE_DPMS_ON) | ||
8158 | return true; | ||
8159 | |||
8160 | return false; | ||
8161 | } | ||
8162 | |||
8143 | static void | 8163 | static void |
8144 | intel_set_config_compute_mode_changes(struct drm_mode_set *set, | 8164 | intel_set_config_compute_mode_changes(struct drm_mode_set *set, |
8145 | struct intel_set_config *config) | 8165 | struct intel_set_config *config) |
@@ -8147,7 +8167,11 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, | |||
8147 | 8167 | ||
8148 | /* We should be able to check here if the fb has the same properties | 8168 | /* We should be able to check here if the fb has the same properties |
8149 | * and then just flip_or_move it */ | 8169 | * and then just flip_or_move it */ |
8150 | if (set->crtc->fb != set->fb) { | 8170 | if (set->connectors != NULL && |
8171 | is_crtc_connector_off(set->crtc, *set->connectors, | ||
8172 | set->num_connectors)) { | ||
8173 | config->mode_changed = true; | ||
8174 | } else if (set->crtc->fb != set->fb) { | ||
8151 | /* If we have no fb then treat it as a full mode set */ | 8175 | /* If we have no fb then treat it as a full mode set */ |
8152 | if (set->crtc->fb == NULL) { | 8176 | if (set->crtc->fb == NULL) { |
8153 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); | 8177 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); |
@@ -8157,8 +8181,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, | |||
8157 | } else if (set->fb->pixel_format != | 8181 | } else if (set->fb->pixel_format != |
8158 | set->crtc->fb->pixel_format) { | 8182 | set->crtc->fb->pixel_format) { |
8159 | config->mode_changed = true; | 8183 | config->mode_changed = true; |
8160 | } else | 8184 | } else { |
8161 | config->fb_changed = true; | 8185 | config->fb_changed = true; |
8186 | } | ||
8162 | } | 8187 | } |
8163 | 8188 | ||
8164 | if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y)) | 8189 | if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y)) |
@@ -8332,11 +8357,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set) | |||
8332 | 8357 | ||
8333 | ret = intel_set_mode(set->crtc, set->mode, | 8358 | ret = intel_set_mode(set->crtc, set->mode, |
8334 | set->x, set->y, set->fb); | 8359 | set->x, set->y, set->fb); |
8335 | if (ret) { | ||
8336 | DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n", | ||
8337 | set->crtc->base.id, ret); | ||
8338 | goto fail; | ||
8339 | } | ||
8340 | } else if (config->fb_changed) { | 8360 | } else if (config->fb_changed) { |
8341 | intel_crtc_wait_for_pending_flips(set->crtc); | 8361 | intel_crtc_wait_for_pending_flips(set->crtc); |
8342 | 8362 | ||
@@ -8344,18 +8364,18 @@ static int intel_crtc_set_config(struct drm_mode_set *set) | |||
8344 | set->x, set->y, set->fb); | 8364 | set->x, set->y, set->fb); |
8345 | } | 8365 | } |
8346 | 8366 | ||
8347 | intel_set_config_free(config); | 8367 | if (ret) { |
8348 | 8368 | DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n", | |
8349 | return 0; | 8369 | set->crtc->base.id, ret); |
8350 | |||
8351 | fail: | 8370 | fail: |
8352 | intel_set_config_restore_state(dev, config); | 8371 | intel_set_config_restore_state(dev, config); |
8353 | 8372 | ||
8354 | /* Try to restore the config */ | 8373 | /* Try to restore the config */ |
8355 | if (config->mode_changed && | 8374 | if (config->mode_changed && |
8356 | intel_set_mode(save_set.crtc, save_set.mode, | 8375 | intel_set_mode(save_set.crtc, save_set.mode, |
8357 | save_set.x, save_set.y, save_set.fb)) | 8376 | save_set.x, save_set.y, save_set.fb)) |
8358 | DRM_ERROR("failed to restore config after modeset failure\n"); | 8377 | DRM_ERROR("failed to restore config after modeset failure\n"); |
8378 | } | ||
8359 | 8379 | ||
8360 | out_config: | 8380 | out_config: |
8361 | intel_set_config_free(config); | 8381 | intel_set_config_free(config); |