diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index f2366440b73..d2619d72cec 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -29,6 +29,9 @@ | |||
29 | * Jesse Barnes <jesse.barnes@intel.com> | 29 | * Jesse Barnes <jesse.barnes@intel.com> |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/export.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | |||
32 | #include "drmP.h" | 35 | #include "drmP.h" |
33 | #include "drm_crtc.h" | 36 | #include "drm_crtc.h" |
34 | #include "drm_crtc_helper.h" | 37 | #include "drm_crtc_helper.h" |
@@ -453,6 +456,30 @@ done: | |||
453 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); | 456 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
454 | 457 | ||
455 | 458 | ||
459 | static int | ||
460 | drm_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 | |||
456 | /** | 483 | /** |
457 | * drm_crtc_helper_set_config - set a new config from userspace | 484 | * drm_crtc_helper_set_config - set a new config from userspace |
458 | * @crtc: CRTC to setup | 485 | * @crtc: CRTC to setup |
@@ -481,6 +508,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
481 | struct drm_connector *save_connectors, *connector; | 508 | struct drm_connector *save_connectors, *connector; |
482 | int count = 0, ro, fail = 0; | 509 | int count = 0, ro, fail = 0; |
483 | struct drm_crtc_helper_funcs *crtc_funcs; | 510 | struct drm_crtc_helper_funcs *crtc_funcs; |
511 | struct drm_mode_set save_set; | ||
484 | int ret = 0; | 512 | int ret = 0; |
485 | int i; | 513 | int i; |
486 | 514 | ||
@@ -506,8 +534,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
506 | (int)set->num_connectors, set->x, set->y); | 534 | (int)set->num_connectors, set->x, set->y); |
507 | } else { | 535 | } else { |
508 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); | 536 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
509 | set->mode = NULL; | 537 | return drm_crtc_helper_disable(set->crtc); |
510 | set->num_connectors = 0; | ||
511 | } | 538 | } |
512 | 539 | ||
513 | dev = set->crtc->dev; | 540 | dev = set->crtc->dev; |
@@ -553,6 +580,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
553 | save_connectors[count++] = *connector; | 580 | save_connectors[count++] = *connector; |
554 | } | 581 | } |
555 | 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 | |||
556 | /* 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 |
557 | * and then just flip_or_move it */ | 590 | * and then just flip_or_move it */ |
558 | if (set->crtc->fb != set->fb) { | 591 | if (set->crtc->fb != set->fb) { |
@@ -718,6 +751,12 @@ fail: | |||
718 | *connector = save_connectors[count++]; | 751 | *connector = save_connectors[count++]; |
719 | } | 752 | } |
720 | 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 | |||
721 | kfree(save_connectors); | 760 | kfree(save_connectors); |
722 | kfree(save_encoders); | 761 | kfree(save_encoders); |
723 | kfree(save_crtcs); | 762 | kfree(save_crtcs); |