diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index e490e69db21e..964c5eb1fada 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -480,6 +480,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
480 | int saved_x, saved_y; | 480 | int saved_x, saved_y; |
481 | struct drm_encoder *encoder; | 481 | struct drm_encoder *encoder; |
482 | bool ret = true; | 482 | bool ret = true; |
483 | bool depth_changed, bpp_changed; | ||
483 | 484 | ||
484 | adjusted_mode = drm_mode_duplicate(dev, mode); | 485 | adjusted_mode = drm_mode_duplicate(dev, mode); |
485 | 486 | ||
@@ -488,6 +489,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
488 | if (!crtc->enabled) | 489 | if (!crtc->enabled) |
489 | return true; | 490 | return true; |
490 | 491 | ||
492 | if (old_fb && crtc->fb) { | ||
493 | depth_changed = (old_fb->depth != crtc->fb->depth); | ||
494 | bpp_changed = (old_fb->bits_per_pixel != | ||
495 | crtc->fb->bits_per_pixel); | ||
496 | } else { | ||
497 | depth_changed = true; | ||
498 | bpp_changed = true; | ||
499 | } | ||
500 | |||
491 | saved_mode = crtc->mode; | 501 | saved_mode = crtc->mode; |
492 | saved_x = crtc->x; | 502 | saved_x = crtc->x; |
493 | saved_y = crtc->y; | 503 | saved_y = crtc->y; |
@@ -500,7 +510,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
500 | crtc->y = y; | 510 | crtc->y = y; |
501 | 511 | ||
502 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { | 512 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { |
503 | if (saved_x != crtc->x || saved_y != crtc->y) { | 513 | if (saved_x != crtc->x || saved_y != crtc->y || |
514 | depth_changed || bpp_changed) { | ||
504 | crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, | 515 | crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, |
505 | old_fb); | 516 | old_fb); |
506 | goto done; | 517 | goto done; |
@@ -606,8 +617,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
606 | struct drm_encoder **save_encoders, *new_encoder; | 617 | struct drm_encoder **save_encoders, *new_encoder; |
607 | struct drm_framebuffer *old_fb; | 618 | struct drm_framebuffer *old_fb; |
608 | bool save_enabled; | 619 | bool save_enabled; |
609 | bool changed = false; | 620 | bool mode_changed = false; |
610 | bool flip_or_move = false; | 621 | bool fb_changed = false; |
611 | struct drm_connector *connector; | 622 | struct drm_connector *connector; |
612 | int count = 0, ro, fail = 0; | 623 | int count = 0, ro, fail = 0; |
613 | struct drm_crtc_helper_funcs *crtc_funcs; | 624 | struct drm_crtc_helper_funcs *crtc_funcs; |
@@ -635,7 +646,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
635 | /* save previous config */ | 646 | /* save previous config */ |
636 | save_enabled = set->crtc->enabled; | 647 | save_enabled = set->crtc->enabled; |
637 | 648 | ||
638 | /* this is meant to be num_connector not num_crtc */ | 649 | /* |
650 | * We do mode_config.num_connectors here since we'll look at the | ||
651 | * CRTC and encoder associated with each connector later. | ||
652 | */ | ||
639 | save_crtcs = kzalloc(dev->mode_config.num_connector * | 653 | save_crtcs = kzalloc(dev->mode_config.num_connector * |
640 | sizeof(struct drm_crtc *), GFP_KERNEL); | 654 | sizeof(struct drm_crtc *), GFP_KERNEL); |
641 | if (!save_crtcs) | 655 | if (!save_crtcs) |
@@ -651,21 +665,25 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
651 | /* We should be able to check here if the fb has the same properties | 665 | /* We should be able to check here if the fb has the same properties |
652 | * and then just flip_or_move it */ | 666 | * and then just flip_or_move it */ |
653 | if (set->crtc->fb != set->fb) { | 667 | if (set->crtc->fb != set->fb) { |
654 | /* if we have no fb then its a change not a flip */ | 668 | /* If we have no fb then treat it as a full mode set */ |
655 | if (set->crtc->fb == NULL) | 669 | if (set->crtc->fb == NULL) |
656 | changed = true; | 670 | mode_changed = true; |
671 | else if ((set->fb->bits_per_pixel != | ||
672 | set->crtc->fb->bits_per_pixel) || | ||
673 | set->fb->depth != set->crtc->fb->depth) | ||
674 | fb_changed = true; | ||
657 | else | 675 | else |
658 | flip_or_move = true; | 676 | fb_changed = true; |
659 | } | 677 | } |
660 | 678 | ||
661 | if (set->x != set->crtc->x || set->y != set->crtc->y) | 679 | if (set->x != set->crtc->x || set->y != set->crtc->y) |
662 | flip_or_move = true; | 680 | fb_changed = true; |
663 | 681 | ||
664 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { | 682 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
665 | DRM_DEBUG("modes are different\n"); | 683 | DRM_DEBUG("modes are different\n"); |
666 | drm_mode_debug_printmodeline(&set->crtc->mode); | 684 | drm_mode_debug_printmodeline(&set->crtc->mode); |
667 | drm_mode_debug_printmodeline(set->mode); | 685 | drm_mode_debug_printmodeline(set->mode); |
668 | changed = true; | 686 | mode_changed = true; |
669 | } | 687 | } |
670 | 688 | ||
671 | /* a) traverse passed in connector list and get encoders for them */ | 689 | /* a) traverse passed in connector list and get encoders for them */ |
@@ -688,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
688 | } | 706 | } |
689 | 707 | ||
690 | if (new_encoder != connector->encoder) { | 708 | if (new_encoder != connector->encoder) { |
691 | changed = true; | 709 | mode_changed = true; |
692 | connector->encoder = new_encoder; | 710 | connector->encoder = new_encoder; |
693 | } | 711 | } |
694 | } | 712 | } |
@@ -715,16 +733,16 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
715 | new_crtc = set->crtc; | 733 | new_crtc = set->crtc; |
716 | } | 734 | } |
717 | if (new_crtc != connector->encoder->crtc) { | 735 | if (new_crtc != connector->encoder->crtc) { |
718 | changed = true; | 736 | mode_changed = true; |
719 | connector->encoder->crtc = new_crtc; | 737 | connector->encoder->crtc = new_crtc; |
720 | } | 738 | } |
721 | } | 739 | } |
722 | 740 | ||
723 | /* mode_set_base is not a required function */ | 741 | /* mode_set_base is not a required function */ |
724 | if (flip_or_move && !crtc_funcs->mode_set_base) | 742 | if (fb_changed && !crtc_funcs->mode_set_base) |
725 | changed = true; | 743 | mode_changed = true; |
726 | 744 | ||
727 | if (changed) { | 745 | if (mode_changed) { |
728 | old_fb = set->crtc->fb; | 746 | old_fb = set->crtc->fb; |
729 | set->crtc->fb = set->fb; | 747 | set->crtc->fb = set->fb; |
730 | set->crtc->enabled = (set->mode != NULL); | 748 | set->crtc->enabled = (set->mode != NULL); |
@@ -743,7 +761,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
743 | set->crtc->desired_mode = set->mode; | 761 | set->crtc->desired_mode = set->mode; |
744 | } | 762 | } |
745 | drm_helper_disable_unused_functions(dev); | 763 | drm_helper_disable_unused_functions(dev); |
746 | } else if (flip_or_move) { | 764 | } else if (fb_changed) { |
747 | old_fb = set->crtc->fb; | 765 | old_fb = set->crtc->fb; |
748 | if (set->crtc->fb != set->fb) | 766 | if (set->crtc->fb != set->fb) |
749 | set->crtc->fb = set->fb; | 767 | set->crtc->fb = set->fb; |