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.c43
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:
453EXPORT_SYMBOL(drm_crtc_helper_set_mode); 456EXPORT_SYMBOL(drm_crtc_helper_set_mode);
454 457
455 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
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);