summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/nv50_kms_wrapper.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/linux-core/nv50_kms_wrapper.c b/linux-core/nv50_kms_wrapper.c
index e93a2668..739704b5 100644
--- a/linux-core/nv50_kms_wrapper.c
+++ b/linux-core/nv50_kms_wrapper.c
@@ -303,7 +303,7 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
goto out;
}
- if (!set->crtc || !set->connectors) {
+ if (!set->crtc) {
NV50_DEBUG("Sanity check failed\n");
goto out;
}
@@ -323,6 +323,11 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
blank = true;
}
+ if (!set->connectors && modeset) {
+ NV50_DEBUG("Sanity check failed\n");
+ goto out;
+ }
+
if (!modeset && !switch_fb && !blank) {
DRM_ERROR("There is nothing to do, bad input.\n");
goto out;
@@ -439,28 +444,15 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
}
/**
- * Unwire encoders and connectors, etc.
+ * Disable crtc.
*/
if (blank) {
- crtc = to_nv50_crtc(drm_crtc);
+ crtc = to_nv50_crtc(set->crtc);
+ /* keeping the encoders and connectors attached, so they can be tracked */
crtc->active = false;
set->crtc->enabled = false;
-
- /* find encoders that use this crtc. */
- list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
- if (drm_encoder->crtc == set->crtc) {
- /* find the connector that goes with it */
- list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
- if (drm_connector->encoder == drm_encoder) {
- drm_connector->encoder = NULL;
- break;
- }
- }
- drm_encoder->crtc = NULL;
- }
- }
}
/**
@@ -517,13 +509,26 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
DRM_ERROR("blanking failed\n");
goto out;
}
+
+ /* detach any outputs that are currently running on this crtc */
+ list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+ if (drm_encoder->crtc == set->crtc) {
+ output = to_nv50_output(drm_encoder);
+
+ rval = output->execute_mode(output, TRUE);
+ if (rval != 0) {
+ DRM_ERROR("detaching output failed\n");
+ goto out;
+ }
+ }
+ }
}
/**
* Change framebuffer, without changing mode.
*/
- if (switch_fb && !modeset) {
+ if (switch_fb && !modeset && !blank) {
crtc = to_nv50_crtc(set->crtc);
rval = crtc->blank(crtc, TRUE);
@@ -553,10 +558,15 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
if (modeset) {
/* disconnect unused outputs */
list_for_each_entry(output, &display->outputs, head) {
- if (output->crtc)
+ if (output->crtc) {
crtc_mask |= 1 << output->crtc->index;
- else
- output->execute_mode(output, TRUE);
+ } else {
+ rval = output->execute_mode(output, TRUE);
+ if (rval != 0) {
+ DRM_ERROR("detaching output failed\n");
+ goto out;
+ }
+ }
}
rval = crtc->set_mode(crtc, hw_mode);
@@ -627,7 +637,8 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
return 0;
out:
- display->update(display);
+ if (display)
+ display->update(display);
kfree(hw_mode);