diff options
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/nv50_kms_wrapper.c | 55 |
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); |