aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc_helper.c
diff options
context:
space:
mode:
authorMaarten Maathuis <madman2003@gmail.com>2009-08-27 04:18:29 -0400
committerDave Airlie <airlied@redhat.com>2009-08-30 19:09:29 -0400
commite67aae79f93d9584aaa24d2a2c76383e9d588f98 (patch)
tree436ea43c3fdf3b99ae76b61dff47998c765a9cd4 /drivers/gpu/drm/drm_crtc_helper.c
parent689d7c2a1127378854c7d7ea8d7c81238a824240 (diff)
drm/crtc_helper: replace modeset fail path with something simpler
- The previous system was not very transparent, nor flexible. - This is needed to be able to fix a few bugs in the mechanism. Signed-off-by: Maarten Maathuis <madman2003@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index a06c5f52c289..a3837b39bb8f 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -704,13 +704,12 @@ EXPORT_SYMBOL(drm_crtc_helper_set_mode);
704int drm_crtc_helper_set_config(struct drm_mode_set *set) 704int drm_crtc_helper_set_config(struct drm_mode_set *set)
705{ 705{
706 struct drm_device *dev; 706 struct drm_device *dev;
707 struct drm_crtc **save_crtcs, *new_crtc; 707 struct drm_crtc *save_crtcs, *new_crtc, *crtc;
708 struct drm_encoder **save_encoders, *new_encoder; 708 struct drm_encoder *save_encoders, *new_encoder, *encoder;
709 struct drm_framebuffer *old_fb = NULL; 709 struct drm_framebuffer *old_fb = NULL;
710 bool save_enabled;
711 bool mode_changed = false; /* if true do a full mode set */ 710 bool mode_changed = false; /* if true do a full mode set */
712 bool fb_changed = false; /* if true and !mode_changed just do a flip */ 711 bool fb_changed = false; /* if true and !mode_changed just do a flip */
713 struct drm_connector *connector; 712 struct drm_connector *save_connectors, *connector;
714 int count = 0, ro, fail = 0; 713 int count = 0, ro, fail = 0;
715 struct drm_crtc_helper_funcs *crtc_funcs; 714 struct drm_crtc_helper_funcs *crtc_funcs;
716 int ret = 0; 715 int ret = 0;
@@ -735,25 +734,47 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
735 734
736 dev = set->crtc->dev; 735 dev = set->crtc->dev;
737 736
738 /* save previous config */ 737 /* Allocate space for the backup of all (non-pointer) crtc, encoder and
739 save_enabled = set->crtc->enabled; 738 * connector data. */
740 739 save_crtcs = kzalloc(dev->mode_config.num_crtc *
741 /* 740 sizeof(struct drm_crtc), GFP_KERNEL);
742 * We do mode_config.num_connectors here since we'll look at the
743 * CRTC and encoder associated with each connector later.
744 */
745 save_crtcs = kzalloc(dev->mode_config.num_connector *
746 sizeof(struct drm_crtc *), GFP_KERNEL);
747 if (!save_crtcs) 741 if (!save_crtcs)
748 return -ENOMEM; 742 return -ENOMEM;
749 743
750 save_encoders = kzalloc(dev->mode_config.num_connector * 744 save_encoders = kzalloc(dev->mode_config.num_encoder *
751 sizeof(struct drm_encoders *), GFP_KERNEL); 745 sizeof(struct drm_encoder), GFP_KERNEL);
752 if (!save_encoders) { 746 if (!save_encoders) {
753 kfree(save_crtcs); 747 kfree(save_crtcs);
754 return -ENOMEM; 748 return -ENOMEM;
755 } 749 }
756 750
751 save_connectors = kzalloc(dev->mode_config.num_connector *
752 sizeof(struct drm_connector), GFP_KERNEL);
753 if (!save_connectors) {
754 kfree(save_crtcs);
755 kfree(save_encoders);
756 return -ENOMEM;
757 }
758
759 /* Copy data. Note that driver private data is not affected.
760 * Should anything bad happen only the expected state is
761 * restored, not the drivers personal bookkeeping.
762 */
763 count = 0;
764 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
765 save_crtcs[count++] = *crtc;
766 }
767
768 count = 0;
769 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
770 save_encoders[count++] = *encoder;
771 }
772
773 count = 0;
774 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
775 save_connectors[count++] = *connector;
776 }
777
757 /* We should be able to check here if the fb has the same properties 778 /* We should be able to check here if the fb has the same properties
758 * and then just flip_or_move it */ 779 * and then just flip_or_move it */
759 if (set->crtc->fb != set->fb) { 780 if (set->crtc->fb != set->fb) {
@@ -786,7 +807,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
786 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 807 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
787 struct drm_connector_helper_funcs *connector_funcs = 808 struct drm_connector_helper_funcs *connector_funcs =
788 connector->helper_private; 809 connector->helper_private;
789 save_encoders[count++] = connector->encoder;
790 new_encoder = connector->encoder; 810 new_encoder = connector->encoder;
791 for (ro = 0; ro < set->num_connectors; ro++) { 811 for (ro = 0; ro < set->num_connectors; ro++) {
792 if (set->connectors[ro] == connector) { 812 if (set->connectors[ro] == connector) {
@@ -809,7 +829,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
809 829
810 if (fail) { 830 if (fail) {
811 ret = -EINVAL; 831 ret = -EINVAL;
812 goto fail_no_encoder; 832 goto fail;
813 } 833 }
814 834
815 count = 0; 835 count = 0;
@@ -817,8 +837,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
817 if (!connector->encoder) 837 if (!connector->encoder)
818 continue; 838 continue;
819 839
820 save_crtcs[count++] = connector->encoder->crtc;
821
822 if (connector->encoder->crtc == set->crtc) 840 if (connector->encoder->crtc == set->crtc)
823 new_crtc = NULL; 841 new_crtc = NULL;
824 else 842 else
@@ -833,7 +851,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
833 if (new_crtc && 851 if (new_crtc &&
834 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { 852 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
835 ret = -EINVAL; 853 ret = -EINVAL;
836 goto fail_set_mode; 854 goto fail;
837 } 855 }
838 if (new_crtc != connector->encoder->crtc) { 856 if (new_crtc != connector->encoder->crtc) {
839 DRM_DEBUG_KMS("crtc changed, full mode switch\n"); 857 DRM_DEBUG_KMS("crtc changed, full mode switch\n");
@@ -862,7 +880,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
862 DRM_ERROR("failed to set mode on crtc %p\n", 880 DRM_ERROR("failed to set mode on crtc %p\n",
863 set->crtc); 881 set->crtc);
864 ret = -EINVAL; 882 ret = -EINVAL;
865 goto fail_set_mode; 883 goto fail;
866 } 884 }
867 /* TODO are these needed? */ 885 /* TODO are these needed? */
868 set->crtc->desired_x = set->x; 886 set->crtc->desired_x = set->x;
@@ -877,30 +895,34 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
877 ret = crtc_funcs->mode_set_base(set->crtc, 895 ret = crtc_funcs->mode_set_base(set->crtc,
878 set->x, set->y, old_fb); 896 set->x, set->y, old_fb);
879 if (ret != 0) 897 if (ret != 0)
880 goto fail_set_mode; 898 goto fail;
881 } 899 }
882 900
901 kfree(save_connectors);
883 kfree(save_encoders); 902 kfree(save_encoders);
884 kfree(save_crtcs); 903 kfree(save_crtcs);
885 return 0; 904 return 0;
886 905
887fail_set_mode: 906fail:
888 set->crtc->enabled = save_enabled; 907 /* Restore all previous data. */
889 set->crtc->fb = old_fb;
890 count = 0; 908 count = 0;
891 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 909 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
892 if (!connector->encoder) 910 *crtc = save_crtcs[count++];
893 continue; 911 }
894 912
895 connector->encoder->crtc = save_crtcs[count++]; 913 count = 0;
914 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
915 *encoder = save_encoders[count++];
896 } 916 }
897fail_no_encoder: 917
898 kfree(save_crtcs);
899 count = 0; 918 count = 0;
900 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 919 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
901 connector->encoder = save_encoders[count++]; 920 *connector = save_connectors[count++];
902 } 921 }
922
923 kfree(save_connectors);
903 kfree(save_encoders); 924 kfree(save_encoders);
925 kfree(save_crtcs);
904 return ret; 926 return ret;
905} 927}
906EXPORT_SYMBOL(drm_crtc_helper_set_config); 928EXPORT_SYMBOL(drm_crtc_helper_set_config);