aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-30 01:34:15 -0400
committerDave Airlie <airlied@redhat.com>2010-04-06 20:28:01 -0400
commit0b4c0f3f0eceacb691e2b5570d9b16d751ce1b48 (patch)
tree708eecc3e3b86f4328df588400e2b7a3f6f2b32d /drivers
parent8be48d924c307e72e3797ab5bde81b07a1ccc52d (diff)
drm/kms/fb: separate fbdev connector list from core drm connectors
This breaks the connection between the core drm connector list and the fbdev connector usage, and allows them to become disjoint in the future. It also removes the untype void* that was in the connector struct to support this. All connectors are added to the fbdev now but this could be changed in the future. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_crtc.c1
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c196
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c50
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c5
6 files changed, 121 insertions, 134 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6a472d534522..e8cd6832f08e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -493,7 +493,6 @@ void drm_connector_cleanup(struct drm_connector *connector)
493 list_for_each_entry_safe(mode, t, &connector->user_modes, head) 493 list_for_each_entry_safe(mode, t, &connector->user_modes, head)
494 drm_mode_remove(connector, mode); 494 drm_mode_remove(connector, mode);
495 495
496 kfree(connector->fb_helper_private);
497 mutex_lock(&dev->mode_config.mutex); 496 mutex_lock(&dev->mode_config.mutex);
498 drm_mode_object_put(dev, &connector->base); 497 drm_mode_object_put(dev, &connector->base);
499 list_del(&connector->head); 498 list_del(&connector->head);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 2515563063ce..9808f6e37a9d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -41,15 +41,33 @@ MODULE_LICENSE("GPL and additional rights");
41 41
42static LIST_HEAD(kernel_fb_helper_list); 42static LIST_HEAD(kernel_fb_helper_list);
43 43
44int drm_fb_helper_add_connector(struct drm_connector *connector) 44/* simple single crtc case helper function */
45int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
45{ 46{
46 connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); 47 struct drm_device *dev = fb_helper->dev;
47 if (!connector->fb_helper_private) 48 struct drm_connector *connector;
48 return -ENOMEM; 49 int i;
50
51 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
52 struct drm_fb_helper_connector *fb_helper_connector;
53
54 fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
55 if (!fb_helper_connector)
56 goto fail;
49 57
58 fb_helper_connector->connector = connector;
59 fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
60 }
50 return 0; 61 return 0;
62fail:
63 for (i = 0; i < fb_helper->connector_count; i++) {
64 kfree(fb_helper->connector_info[i]);
65 fb_helper->connector_info[i] = NULL;
66 }
67 fb_helper->connector_count = 0;
68 return -ENOMEM;
51} 69}
52EXPORT_SYMBOL(drm_fb_helper_add_connector); 70EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
53 71
54/** 72/**
55 * drm_fb_helper_connector_parse_command_line - parse command line for connector 73 * drm_fb_helper_connector_parse_command_line - parse command line for connector
@@ -64,7 +82,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_connector);
64 * 82 *
65 * enable/enable Digital/disable bit at the end 83 * enable/enable Digital/disable bit at the end
66 */ 84 */
67static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector, 85static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn,
68 const char *mode_option) 86 const char *mode_option)
69{ 87{
70 const char *name; 88 const char *name;
@@ -74,13 +92,13 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con
74 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; 92 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
75 int i; 93 int i;
76 enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; 94 enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
77 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
78 struct drm_fb_helper_cmdline_mode *cmdline_mode; 95 struct drm_fb_helper_cmdline_mode *cmdline_mode;
96 struct drm_connector *connector = fb_helper_conn->connector;
79 97
80 if (!fb_help_conn) 98 if (!fb_helper_conn)
81 return false; 99 return false;
82 100
83 cmdline_mode = &fb_help_conn->cmdline_mode; 101 cmdline_mode = &fb_helper_conn->cmdline_mode;
84 if (!mode_option) 102 if (!mode_option)
85 mode_option = fb_mode_option; 103 mode_option = fb_mode_option;
86 104
@@ -203,18 +221,21 @@ done:
203 return true; 221 return true;
204} 222}
205 223
206int drm_fb_helper_parse_command_line(struct drm_device *dev) 224static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
207{ 225{
208 struct drm_connector *connector; 226 struct drm_fb_helper_connector *fb_helper_conn;
227 int i;
209 228
210 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 229 for (i = 0; i < fb_helper->connector_count; i++) {
211 char *option = NULL; 230 char *option = NULL;
212 231
232 fb_helper_conn = fb_helper->connector_info[i];
233
213 /* do something on return - turn off connector maybe */ 234 /* do something on return - turn off connector maybe */
214 if (fb_get_options(drm_get_connector_name(connector), &option)) 235 if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option))
215 continue; 236 continue;
216 237
217 drm_fb_helper_connector_parse_command_line(connector, option); 238 drm_fb_helper_connector_parse_command_line(fb_helper_conn, option);
218 } 239 }
219 return 0; 240 return 0;
220} 241}
@@ -391,6 +412,9 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
391{ 412{
392 int i; 413 int i;
393 414
415 for (i = 0; i < helper->connector_count; i++)
416 kfree(helper->connector_info[i]);
417 kfree(helper->connector_info);
394 for (i = 0; i < helper->crtc_count; i++) 418 for (i = 0; i < helper->crtc_count; i++)
395 kfree(helper->crtc_info[i].mode_set.connectors); 419 kfree(helper->crtc_info[i].mode_set.connectors);
396 kfree(helper->crtc_info); 420 kfree(helper->crtc_info);
@@ -411,6 +435,13 @@ int drm_fb_helper_init_crtc_count(struct drm_device *dev,
411 return -ENOMEM; 435 return -ENOMEM;
412 helper->crtc_count = crtc_count; 436 helper->crtc_count = crtc_count;
413 437
438 helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
439 if (!helper->connector_info) {
440 kfree(helper->crtc_info);
441 return -ENOMEM;
442 }
443 helper->connector_count = 0;
444
414 for (i = 0; i < crtc_count; i++) { 445 for (i = 0; i < crtc_count; i++) {
415 helper->crtc_info[i].mode_set.connectors = 446 helper->crtc_info[i].mode_set.connectors =
416 kcalloc(max_conn_count, 447 kcalloc(max_conn_count,
@@ -672,14 +703,10 @@ int drm_fb_helper_set_par(struct fb_info *info)
672 mutex_lock(&dev->mode_config.mutex); 703 mutex_lock(&dev->mode_config.mutex);
673 for (i = 0; i < fb_helper->crtc_count; i++) { 704 for (i = 0; i < fb_helper->crtc_count; i++) {
674 crtc = fb_helper->crtc_info[i].mode_set.crtc; 705 crtc = fb_helper->crtc_info[i].mode_set.crtc;
675 706 ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
676 if (crtc->fb != fb_helper->crtc_info[i].mode_set.fb) { 707 if (ret) {
677 ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set); 708 mutex_unlock(&dev->mode_config.mutex);
678 709 return ret;
679 if (ret) {
680 mutex_unlock(&dev->mode_config.mutex);
681 return ret;
682 }
683 } 710 }
684 } 711 }
685 mutex_unlock(&dev->mode_config.mutex); 712 mutex_unlock(&dev->mode_config.mutex);
@@ -722,8 +749,6 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display);
722int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, 749int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
723 int preferred_bpp) 750 int preferred_bpp)
724{ 751{
725 struct drm_device *dev = fb_helper->dev;
726 struct drm_connector *connector;
727 int new_fb = 0; 752 int new_fb = 0;
728 int crtc_count = 0; 753 int crtc_count = 0;
729 int ret, i; 754 int ret, i;
@@ -743,14 +768,11 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
743 sizes.surface_depth = sizes.surface_bpp = preferred_bpp; 768 sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
744 } 769 }
745 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 770 /* first up get a count of crtcs now in use and new min/maxes width/heights */
746 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 771 for (i = 0; i < fb_helper->connector_count; i++) {
747 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; 772 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
748 struct drm_fb_helper_cmdline_mode *cmdline_mode; 773 struct drm_fb_helper_cmdline_mode *cmdline_mode;
749 774
750 if (!fb_help_conn) 775 cmdline_mode = &fb_helper_conn->cmdline_mode;
751 continue;
752
753 cmdline_mode = &fb_help_conn->cmdline_mode;
754 776
755 if (cmdline_mode->bpp_specified) { 777 if (cmdline_mode->bpp_specified) {
756 switch (cmdline_mode->bpp) { 778 switch (cmdline_mode->bpp) {
@@ -954,24 +976,27 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
954} 976}
955EXPORT_SYMBOL(drm_fb_helper_fill_var); 977EXPORT_SYMBOL(drm_fb_helper_fill_var);
956 978
957static int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, 979static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
958 uint32_t maxY) 980 uint32_t maxX,
981 uint32_t maxY)
959{ 982{
960 struct drm_connector *connector; 983 struct drm_connector *connector;
961 int count = 0; 984 int count = 0;
985 int i;
962 986
963 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 987 for (i = 0; i < fb_helper->connector_count; i++) {
988 connector = fb_helper->connector_info[i]->connector;
964 count += connector->funcs->fill_modes(connector, maxX, maxY); 989 count += connector->funcs->fill_modes(connector, maxX, maxY);
965 } 990 }
966 991
967 return count; 992 return count;
968} 993}
969 994
970static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) 995static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
971{ 996{
972 struct drm_display_mode *mode; 997 struct drm_display_mode *mode;
973 998
974 list_for_each_entry(mode, &connector->modes, head) { 999 list_for_each_entry(mode, &fb_connector->connector->modes, head) {
975 if (drm_mode_width(mode) > width || 1000 if (drm_mode_width(mode) > width ||
976 drm_mode_height(mode) > height) 1001 drm_mode_height(mode) > height)
977 continue; 1002 continue;
@@ -981,28 +1006,20 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con
981 return NULL; 1006 return NULL;
982} 1007}
983 1008
984static bool drm_has_cmdline_mode(struct drm_connector *connector) 1009static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
985{ 1010{
986 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
987 struct drm_fb_helper_cmdline_mode *cmdline_mode; 1011 struct drm_fb_helper_cmdline_mode *cmdline_mode;
988 1012 cmdline_mode = &fb_connector->cmdline_mode;
989 if (!fb_help_conn)
990 return false;
991
992 cmdline_mode = &fb_help_conn->cmdline_mode;
993 return cmdline_mode->specified; 1013 return cmdline_mode->specified;
994} 1014}
995 1015
996static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height) 1016static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1017 int width, int height)
997{ 1018{
998 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
999 struct drm_fb_helper_cmdline_mode *cmdline_mode; 1019 struct drm_fb_helper_cmdline_mode *cmdline_mode;
1000 struct drm_display_mode *mode = NULL; 1020 struct drm_display_mode *mode = NULL;
1001 1021
1002 if (!fb_help_conn) 1022 cmdline_mode = &fb_helper_conn->cmdline_mode;
1003 return mode;
1004
1005 cmdline_mode = &fb_help_conn->cmdline_mode;
1006 if (cmdline_mode->specified == false) 1023 if (cmdline_mode->specified == false)
1007 return mode; 1024 return mode;
1008 1025
@@ -1012,7 +1029,7 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn
1012 if (cmdline_mode->rb || cmdline_mode->margins) 1029 if (cmdline_mode->rb || cmdline_mode->margins)
1013 goto create_mode; 1030 goto create_mode;
1014 1031
1015 list_for_each_entry(mode, &connector->modes, head) { 1032 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
1016 /* check width/height */ 1033 /* check width/height */
1017 if (mode->hdisplay != cmdline_mode->xres || 1034 if (mode->hdisplay != cmdline_mode->xres ||
1018 mode->vdisplay != cmdline_mode->yres) 1035 mode->vdisplay != cmdline_mode->yres)
@@ -1031,13 +1048,13 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn
1031 } 1048 }
1032 1049
1033create_mode: 1050create_mode:
1034 mode = drm_cvt_mode(connector->dev, cmdline_mode->xres, 1051 mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
1035 cmdline_mode->yres, 1052 cmdline_mode->yres,
1036 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, 1053 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1037 cmdline_mode->rb, cmdline_mode->interlace, 1054 cmdline_mode->rb, cmdline_mode->interlace,
1038 cmdline_mode->margins); 1055 cmdline_mode->margins);
1039 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1056 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1040 list_add(&mode->head, &connector->modes); 1057 list_add(&mode->head, &fb_helper_conn->connector->modes);
1041 return mode; 1058 return mode;
1042} 1059}
1043 1060
@@ -1053,62 +1070,60 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
1053 return enable; 1070 return enable;
1054} 1071}
1055 1072
1056static void drm_enable_connectors(struct drm_device *dev, bool *enabled) 1073static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
1074 bool *enabled)
1057{ 1075{
1058 bool any_enabled = false; 1076 bool any_enabled = false;
1059 struct drm_connector *connector; 1077 struct drm_connector *connector;
1060 int i = 0; 1078 int i = 0;
1061 1079
1062 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1080 for (i = 0; i < fb_helper->connector_count; i++) {
1081 connector = fb_helper->connector_info[i]->connector;
1063 enabled[i] = drm_connector_enabled(connector, true); 1082 enabled[i] = drm_connector_enabled(connector, true);
1064 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, 1083 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
1065 enabled[i] ? "yes" : "no"); 1084 enabled[i] ? "yes" : "no");
1066 any_enabled |= enabled[i]; 1085 any_enabled |= enabled[i];
1067 i++;
1068 } 1086 }
1069 1087
1070 if (any_enabled) 1088 if (any_enabled)
1071 return; 1089 return;
1072 1090
1073 i = 0; 1091 for (i = 0; i < fb_helper->connector_count; i++) {
1074 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1092 connector = fb_helper->connector_info[i]->connector;
1075 enabled[i] = drm_connector_enabled(connector, false); 1093 enabled[i] = drm_connector_enabled(connector, false);
1076 i++;
1077 } 1094 }
1078} 1095}
1079 1096
1080static bool drm_target_preferred(struct drm_device *dev, 1097static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
1081 struct drm_display_mode **modes, 1098 struct drm_display_mode **modes,
1082 bool *enabled, int width, int height) 1099 bool *enabled, int width, int height)
1083{ 1100{
1084 struct drm_connector *connector; 1101 struct drm_fb_helper_connector *fb_helper_conn;
1085 int i = 0; 1102 int i;
1086 1103
1087 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1104 for (i = 0; i < fb_helper->connector_count; i++) {
1105 fb_helper_conn = fb_helper->connector_info[i];
1088 1106
1089 if (enabled[i] == false) { 1107 if (enabled[i] == false)
1090 i++;
1091 continue; 1108 continue;
1092 }
1093 1109
1094 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", 1110 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
1095 connector->base.id); 1111 fb_helper_conn->connector->base.id);
1096 1112
1097 /* got for command line mode first */ 1113 /* got for command line mode first */
1098 modes[i] = drm_pick_cmdline_mode(connector, width, height); 1114 modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
1099 if (!modes[i]) { 1115 if (!modes[i]) {
1100 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", 1116 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
1101 connector->base.id); 1117 fb_helper_conn->connector->base.id);
1102 modes[i] = drm_has_preferred_mode(connector, width, height); 1118 modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
1103 } 1119 }
1104 /* No preferred modes, pick one off the list */ 1120 /* No preferred modes, pick one off the list */
1105 if (!modes[i] && !list_empty(&connector->modes)) { 1121 if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
1106 list_for_each_entry(modes[i], &connector->modes, head) 1122 list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
1107 break; 1123 break;
1108 } 1124 }
1109 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : 1125 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
1110 "none"); 1126 "none");
1111 i++;
1112 } 1127 }
1113 return true; 1128 return true;
1114} 1129}
@@ -1126,15 +1141,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
1126 struct drm_fb_helper_crtc *best_crtc; 1141 struct drm_fb_helper_crtc *best_crtc;
1127 int my_score, best_score, score; 1142 int my_score, best_score, score;
1128 struct drm_fb_helper_crtc **crtcs, *crtc; 1143 struct drm_fb_helper_crtc **crtcs, *crtc;
1144 struct drm_fb_helper_connector *fb_helper_conn;
1129 1145
1130 if (n == fb_helper->dev->mode_config.num_connector) 1146 if (n == fb_helper->connector_count)
1131 return 0; 1147 return 0;
1132 c = 0; 1148
1133 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1149 fb_helper_conn = fb_helper->connector_info[n];
1134 if (c == n) 1150 connector = fb_helper_conn->connector;
1135 break;
1136 c++;
1137 }
1138 1151
1139 best_crtcs[n] = NULL; 1152 best_crtcs[n] = NULL;
1140 best_crtc = NULL; 1153 best_crtc = NULL;
@@ -1150,9 +1163,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
1150 my_score = 1; 1163 my_score = 1;
1151 if (connector->status == connector_status_connected) 1164 if (connector->status == connector_status_connected)
1152 my_score++; 1165 my_score++;
1153 if (drm_has_cmdline_mode(connector)) 1166 if (drm_has_cmdline_mode(fb_helper_conn))
1154 my_score++; 1167 my_score++;
1155 if (drm_has_preferred_mode(connector, width, height)) 1168 if (drm_has_preferred_mode(fb_helper_conn, width, height))
1156 my_score++; 1169 my_score++;
1157 1170
1158 connector_funcs = connector->helper_private; 1171 connector_funcs = connector->helper_private;
@@ -1201,7 +1214,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1201 struct drm_fb_helper_crtc **crtcs; 1214 struct drm_fb_helper_crtc **crtcs;
1202 struct drm_display_mode **modes; 1215 struct drm_display_mode **modes;
1203 struct drm_encoder *encoder; 1216 struct drm_encoder *encoder;
1204 struct drm_connector *connector;
1205 struct drm_mode_set *modeset; 1217 struct drm_mode_set *modeset;
1206 bool *enabled; 1218 bool *enabled;
1207 int width, height; 1219 int width, height;
@@ -1224,9 +1236,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1224 enabled = kcalloc(dev->mode_config.num_connector, 1236 enabled = kcalloc(dev->mode_config.num_connector,
1225 sizeof(bool), GFP_KERNEL); 1237 sizeof(bool), GFP_KERNEL);
1226 1238
1227 drm_enable_connectors(dev, enabled); 1239 drm_enable_connectors(fb_helper, enabled);
1228 1240
1229 ret = drm_target_preferred(dev, modes, enabled, width, height); 1241 ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
1230 if (!ret) 1242 if (!ret)
1231 DRM_ERROR("Unable to find initial modes\n"); 1243 DRM_ERROR("Unable to find initial modes\n");
1232 1244
@@ -1241,8 +1253,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1241 modeset->num_connectors = 0; 1253 modeset->num_connectors = 0;
1242 } 1254 }
1243 1255
1244 i = 0; 1256 for (i = 0; i < fb_helper->connector_count; i++) {
1245 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1246 struct drm_display_mode *mode = modes[i]; 1257 struct drm_display_mode *mode = modes[i];
1247 struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; 1258 struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
1248 modeset = &fb_crtc->mode_set; 1259 modeset = &fb_crtc->mode_set;
@@ -1255,9 +1266,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1255 drm_mode_destroy(dev, modeset->mode); 1266 drm_mode_destroy(dev, modeset->mode);
1256 modeset->mode = drm_mode_duplicate(dev, 1267 modeset->mode = drm_mode_duplicate(dev,
1257 fb_crtc->desired_mode); 1268 fb_crtc->desired_mode);
1258 modeset->connectors[modeset->num_connectors++] = connector; 1269 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
1259 } 1270 }
1260 i++;
1261 } 1271 }
1262 1272
1263 kfree(crtcs); 1273 kfree(crtcs);
@@ -1287,11 +1297,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper)
1287 /* disable all the possible outputs/crtcs before entering KMS mode */ 1297 /* disable all the possible outputs/crtcs before entering KMS mode */
1288 drm_helper_disable_unused_functions(fb_helper->dev); 1298 drm_helper_disable_unused_functions(fb_helper->dev);
1289 1299
1290 drm_fb_helper_parse_command_line(fb_helper->dev); 1300 drm_fb_helper_parse_command_line(fb_helper);
1291 1301
1292 count = drm_helper_probe_connector_modes(dev, 1302 count = drm_fb_helper_probe_connector_modes(fb_helper,
1293 dev->mode_config.max_width, 1303 dev->mode_config.max_width,
1294 dev->mode_config.max_height); 1304 dev->mode_config.max_height);
1295 1305
1296 /* 1306 /*
1297 * we shouldn't end up with no modes here. 1307 * we shouldn't end up with no modes here.
@@ -1310,8 +1320,8 @@ bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper,
1310{ 1320{
1311 DRM_DEBUG_KMS("\n"); 1321 DRM_DEBUG_KMS("\n");
1312 1322
1313 drm_helper_probe_connector_modes(fb_helper->dev, max_width, 1323 drm_fb_helper_probe_connector_modes(fb_helper, max_width,
1314 max_height); 1324 max_height);
1315 1325
1316 drm_setup_crtcs(fb_helper); 1326 drm_setup_crtcs(fb_helper);
1317 1327
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index ff6912edf0c6..8f7a7c476098 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -249,6 +249,7 @@ int intel_fbdev_init(struct drm_device *dev)
249 249
250 drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2, 250 drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2,
251 INTELFB_CONN_LIMIT); 251 INTELFB_CONN_LIMIT);
252 drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
252 ifbdev->helper.fb_probe = intel_fb_find_or_create_single; 253 ifbdev->helper.fb_probe = intel_fb_find_or_create_single;
253 drm_fb_helper_initial_config(&ifbdev->helper); 254 drm_fb_helper_initial_config(&ifbdev->helper);
254 intelfb_probe(ifbdev); 255 intelfb_probe(ifbdev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 90843b62d9b1..fd5d3cde0a07 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -435,6 +435,8 @@ int nouveau_fbcon_init(struct drm_device *dev)
435 drm_fb_helper_init_crtc_count(dev, &nfbdev->helper, 435 drm_fb_helper_init_crtc_count(dev, &nfbdev->helper,
436 2, 4); 436 2, 4);
437 nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single; 437 nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single;
438 drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
439
438 drm_fb_helper_initial_config(&nfbdev->helper); 440 drm_fb_helper_initial_config(&nfbdev->helper);
439 nouveau_fbcon_probe(nfbdev); 441 nouveau_fbcon_probe(nfbdev);
440 return 0; 442 return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 3fba50540f72..47bd98521bec 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1032,7 +1032,6 @@ radeon_add_atom_connector(struct drm_device *dev,
1032 struct radeon_connector_atom_dig *radeon_dig_connector; 1032 struct radeon_connector_atom_dig *radeon_dig_connector;
1033 uint32_t subpixel_order = SubPixelNone; 1033 uint32_t subpixel_order = SubPixelNone;
1034 bool shared_ddc = false; 1034 bool shared_ddc = false;
1035 int ret;
1036 1035
1037 /* fixme - tv/cv/din */ 1036 /* fixme - tv/cv/din */
1038 if (connector_type == DRM_MODE_CONNECTOR_Unknown) 1037 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -1067,9 +1066,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1067 switch (connector_type) { 1066 switch (connector_type) {
1068 case DRM_MODE_CONNECTOR_VGA: 1067 case DRM_MODE_CONNECTOR_VGA:
1069 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1068 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
1070 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); 1069 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
1071 if (ret)
1072 goto failed;
1073 if (i2c_bus->valid) { 1070 if (i2c_bus->valid) {
1074 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); 1071 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
1075 if (!radeon_connector->ddc_bus) 1072 if (!radeon_connector->ddc_bus)
@@ -1082,9 +1079,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1082 break; 1079 break;
1083 case DRM_MODE_CONNECTOR_DVIA: 1080 case DRM_MODE_CONNECTOR_DVIA:
1084 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1081 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
1085 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); 1082 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
1086 if (ret)
1087 goto failed;
1088 if (i2c_bus->valid) { 1083 if (i2c_bus->valid) {
1089 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); 1084 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
1090 if (!radeon_connector->ddc_bus) 1085 if (!radeon_connector->ddc_bus)
@@ -1104,9 +1099,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1104 radeon_dig_connector->igp_lane_info = igp_lane_info; 1099 radeon_dig_connector->igp_lane_info = igp_lane_info;
1105 radeon_connector->con_priv = radeon_dig_connector; 1100 radeon_connector->con_priv = radeon_dig_connector;
1106 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); 1101 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
1107 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); 1102 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
1108 if (ret)
1109 goto failed;
1110 if (i2c_bus->valid) { 1103 if (i2c_bus->valid) {
1111 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); 1104 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
1112 if (!radeon_connector->ddc_bus) 1105 if (!radeon_connector->ddc_bus)
@@ -1132,9 +1125,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1132 radeon_dig_connector->igp_lane_info = igp_lane_info; 1125 radeon_dig_connector->igp_lane_info = igp_lane_info;
1133 radeon_connector->con_priv = radeon_dig_connector; 1126 radeon_connector->con_priv = radeon_dig_connector;
1134 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); 1127 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
1135 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); 1128 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
1136 if (ret)
1137 goto failed;
1138 if (i2c_bus->valid) { 1129 if (i2c_bus->valid) {
1139 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); 1130 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
1140 if (!radeon_connector->ddc_bus) 1131 if (!radeon_connector->ddc_bus)
@@ -1154,9 +1145,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1154 radeon_dig_connector->igp_lane_info = igp_lane_info; 1145 radeon_dig_connector->igp_lane_info = igp_lane_info;
1155 radeon_connector->con_priv = radeon_dig_connector; 1146 radeon_connector->con_priv = radeon_dig_connector;
1156 drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); 1147 drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
1157 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); 1148 drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
1158 if (ret)
1159 goto failed;
1160 if (i2c_bus->valid) { 1149 if (i2c_bus->valid) {
1161 /* add DP i2c bus */ 1150 /* add DP i2c bus */
1162 if (connector_type == DRM_MODE_CONNECTOR_eDP) 1151 if (connector_type == DRM_MODE_CONNECTOR_eDP)
@@ -1182,9 +1171,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1182 case DRM_MODE_CONNECTOR_9PinDIN: 1171 case DRM_MODE_CONNECTOR_9PinDIN:
1183 if (radeon_tv == 1) { 1172 if (radeon_tv == 1) {
1184 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); 1173 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
1185 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); 1174 drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
1186 if (ret)
1187 goto failed;
1188 radeon_connector->dac_load_detect = true; 1175 radeon_connector->dac_load_detect = true;
1189 drm_connector_attach_property(&radeon_connector->base, 1176 drm_connector_attach_property(&radeon_connector->base,
1190 rdev->mode_info.load_detect_property, 1177 rdev->mode_info.load_detect_property,
@@ -1202,9 +1189,7 @@ radeon_add_atom_connector(struct drm_device *dev,
1202 radeon_dig_connector->igp_lane_info = igp_lane_info; 1189 radeon_dig_connector->igp_lane_info = igp_lane_info;
1203 radeon_connector->con_priv = radeon_dig_connector; 1190 radeon_connector->con_priv = radeon_dig_connector;
1204 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); 1191 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
1205 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); 1192 drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
1206 if (ret)
1207 goto failed;
1208 if (i2c_bus->valid) { 1193 if (i2c_bus->valid) {
1209 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); 1194 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
1210 if (!radeon_connector->ddc_bus) 1195 if (!radeon_connector->ddc_bus)
@@ -1241,7 +1226,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
1241 struct drm_connector *connector; 1226 struct drm_connector *connector;
1242 struct radeon_connector *radeon_connector; 1227 struct radeon_connector *radeon_connector;
1243 uint32_t subpixel_order = SubPixelNone; 1228 uint32_t subpixel_order = SubPixelNone;
1244 int ret;
1245 1229
1246 /* fixme - tv/cv/din */ 1230 /* fixme - tv/cv/din */
1247 if (connector_type == DRM_MODE_CONNECTOR_Unknown) 1231 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -1269,9 +1253,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
1269 switch (connector_type) { 1253 switch (connector_type) {
1270 case DRM_MODE_CONNECTOR_VGA: 1254 case DRM_MODE_CONNECTOR_VGA:
1271 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1255 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
1272 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); 1256 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
1273 if (ret)
1274 goto failed;
1275 if (i2c_bus->valid) { 1257 if (i2c_bus->valid) {
1276 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); 1258 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
1277 if (!radeon_connector->ddc_bus) 1259 if (!radeon_connector->ddc_bus)
@@ -1284,9 +1266,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
1284 break; 1266 break;
1285 case DRM_MODE_CONNECTOR_DVIA: 1267 case DRM_MODE_CONNECTOR_DVIA:
1286 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1268 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
1287 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); 1269 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
1288 if (ret)
1289 goto failed;
1290 if (i2c_bus->valid) { 1270 if (i2c_bus->valid) {
1291 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); 1271 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
1292 if (!radeon_connector->ddc_bus) 1272 if (!radeon_connector->ddc_bus)
@@ -1300,9 +1280,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
1300 case DRM_MODE_CONNECTOR_DVII: 1280 case DRM_MODE_CONNECTOR_DVII:
1301 case DRM_MODE_CONNECTOR_DVID: 1281 case DRM_MODE_CONNECTOR_DVID:
1302 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); 1282 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
1303 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); 1283 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
1304 if (ret)
1305 goto failed;
1306 if (i2c_bus->valid) { 1284 if (i2c_bus->valid) {
1307 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); 1285 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
1308 if (!radeon_connector->ddc_bus) 1286 if (!radeon_connector->ddc_bus)
@@ -1319,9 +1297,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
1319 case DRM_MODE_CONNECTOR_9PinDIN: 1297 case DRM_MODE_CONNECTOR_9PinDIN:
1320 if (radeon_tv == 1) { 1298 if (radeon_tv == 1) {
1321 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); 1299 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
1322 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); 1300 drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
1323 if (ret)
1324 goto failed;
1325 radeon_connector->dac_load_detect = true; 1301 radeon_connector->dac_load_detect = true;
1326 /* RS400,RC410,RS480 chipset seems to report a lot 1302 /* RS400,RC410,RS480 chipset seems to report a lot
1327 * of false positive on load detect, we haven't yet 1303 * of false positive on load detect, we haven't yet
@@ -1340,9 +1316,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
1340 break; 1316 break;
1341 case DRM_MODE_CONNECTOR_LVDS: 1317 case DRM_MODE_CONNECTOR_LVDS:
1342 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); 1318 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
1343 ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); 1319 drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
1344 if (ret)
1345 goto failed;
1346 if (i2c_bus->valid) { 1320 if (i2c_bus->valid) {
1347 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); 1321 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
1348 if (!radeon_connector->ddc_bus) 1322 if (!radeon_connector->ddc_bus)
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 705425defba0..7275b2e09444 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -274,8 +274,6 @@ out_unref:
274 drm_framebuffer_cleanup(fb); 274 drm_framebuffer_cleanup(fb);
275 kfree(fb); 275 kfree(fb);
276 } 276 }
277
278out:
279 return ret; 277 return ret;
280} 278}
281 279
@@ -380,6 +378,9 @@ int radeon_fbdev_init(struct radeon_device *rdev)
380 rdev->num_crtc, 378 rdev->num_crtc,
381 RADEONFB_CONN_LIMIT); 379 RADEONFB_CONN_LIMIT);
382 rfbdev->helper.fb_probe = radeon_fb_find_or_create_single; 380 rfbdev->helper.fb_probe = radeon_fb_find_or_create_single;
381
382 drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
383
383 drm_fb_helper_initial_config(&rfbdev->helper); 384 drm_fb_helper_initial_config(&rfbdev->helper);
384 radeonfb_probe(rfbdev); 385 radeonfb_probe(rfbdev);
385 return 0; 386 return 0;