aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 2957636161e..d2619d72cec 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -456,6 +456,30 @@ done:
456EXPORT_SYMBOL(drm_crtc_helper_set_mode); 456EXPORT_SYMBOL(drm_crtc_helper_set_mode);
457 457
458 458
459static int
460drm_crtc_helper_disable(struct drm_crtc *crtc)
461{
462 struct drm_device *dev = crtc->dev;
463 struct drm_connector *connector;
464 struct drm_encoder *encoder;
465
466 /* Decouple all encoders and their attached connectors from this crtc */
467 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
468 if (encoder->crtc != crtc)
469 continue;
470
471 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
472 if (connector->encoder != encoder)
473 continue;
474
475 connector->encoder = NULL;
476 }
477 }
478
479 drm_helper_disable_unused_functions(dev);
480 return 0;
481}
482
459/** 483/**
460 * drm_crtc_helper_set_config - set a new config from userspace 484 * drm_crtc_helper_set_config - set a new config from userspace
461 * @crtc: CRTC to setup 485 * @crtc: CRTC to setup
@@ -484,6 +508,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
484 struct drm_connector *save_connectors, *connector; 508 struct drm_connector *save_connectors, *connector;
485 int count = 0, ro, fail = 0; 509 int count = 0, ro, fail = 0;
486 struct drm_crtc_helper_funcs *crtc_funcs; 510 struct drm_crtc_helper_funcs *crtc_funcs;
511 struct drm_mode_set save_set;
487 int ret = 0; 512 int ret = 0;
488 int i; 513 int i;
489 514
@@ -509,8 +534,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
509 (int)set->num_connectors, set->x, set->y); 534 (int)set->num_connectors, set->x, set->y);
510 } else { 535 } else {
511 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); 536 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
512 set->mode = NULL; 537 return drm_crtc_helper_disable(set->crtc);
513 set->num_connectors = 0;
514 } 538 }
515 539
516 dev = set->crtc->dev; 540 dev = set->crtc->dev;
@@ -556,6 +580,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
556 save_connectors[count++] = *connector; 580 save_connectors[count++] = *connector;
557 } 581 }
558 582
583 save_set.crtc = set->crtc;
584 save_set.mode = &set->crtc->mode;
585 save_set.x = set->crtc->x;
586 save_set.y = set->crtc->y;
587 save_set.fb = set->crtc->fb;
588
559 /* We should be able to check here if the fb has the same properties 589 /* We should be able to check here if the fb has the same properties
560 * and then just flip_or_move it */ 590 * and then just flip_or_move it */
561 if (set->crtc->fb != set->fb) { 591 if (set->crtc->fb != set->fb) {
@@ -721,6 +751,12 @@ fail:
721 *connector = save_connectors[count++]; 751 *connector = save_connectors[count++];
722 } 752 }
723 753
754 /* Try to restore the config */
755 if (mode_changed &&
756 !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
757 save_set.y, save_set.fb))
758 DRM_ERROR("failed to restore config after modeset failure\n");
759
724 kfree(save_connectors); 760 kfree(save_connectors);
725 kfree(save_encoders); 761 kfree(save_encoders);
726 kfree(save_crtcs); 762 kfree(save_crtcs);