diff options
author | Dave Airlie <airlied@redhat.com> | 2010-05-07 01:02:30 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 03:40:22 -0400 |
commit | 1d42bbc8f7f9ce4d852692ef7aa336b133b0830a (patch) | |
tree | a0ea2d17508104ab681c829f0552e7f13512c8e2 /drivers/gpu/drm/drm_fb_helper.c | |
parent | eb1f8e4f3be898df808e2dfc131099f5831d491d (diff) |
drm/fbdev: fix cloning on fbcon
Simple cloning rules compared to server:
(a) single crtc
(b) > 1 connector active
(c) check command line mode
(d) try and find 1024x768 DMT mode if no command line.
(e) fail to clone
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 90 |
1 files changed, 85 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index f7b8fca4bbbc..b3779d243aef 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -1070,6 +1070,79 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, | |||
1070 | } | 1070 | } |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | static bool drm_target_cloned(struct drm_fb_helper *fb_helper, | ||
1074 | struct drm_display_mode **modes, | ||
1075 | bool *enabled, int width, int height) | ||
1076 | { | ||
1077 | int count, i, j; | ||
1078 | bool can_clone = false; | ||
1079 | struct drm_fb_helper_connector *fb_helper_conn; | ||
1080 | struct drm_display_mode *dmt_mode, *mode; | ||
1081 | |||
1082 | /* only contemplate cloning in the single crtc case */ | ||
1083 | if (fb_helper->crtc_count > 1) | ||
1084 | return false; | ||
1085 | |||
1086 | count = 0; | ||
1087 | for (i = 0; i < fb_helper->connector_count; i++) { | ||
1088 | if (enabled[i]) | ||
1089 | count++; | ||
1090 | } | ||
1091 | |||
1092 | /* only contemplate cloning if more than one connector is enabled */ | ||
1093 | if (count <= 1) | ||
1094 | return false; | ||
1095 | |||
1096 | /* check the command line or if nothing common pick 1024x768 */ | ||
1097 | can_clone = true; | ||
1098 | for (i = 0; i < fb_helper->connector_count; i++) { | ||
1099 | if (!enabled[i]) | ||
1100 | continue; | ||
1101 | fb_helper_conn = fb_helper->connector_info[i]; | ||
1102 | modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height); | ||
1103 | if (!modes[i]) { | ||
1104 | can_clone = false; | ||
1105 | break; | ||
1106 | } | ||
1107 | for (j = 0; j < i; j++) { | ||
1108 | if (!enabled[j]) | ||
1109 | continue; | ||
1110 | if (!drm_mode_equal(modes[j], modes[i])) | ||
1111 | can_clone = false; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | if (can_clone) { | ||
1116 | DRM_DEBUG_KMS("can clone using command line\n"); | ||
1117 | return true; | ||
1118 | } | ||
1119 | |||
1120 | /* try and find a 1024x768 mode on each connector */ | ||
1121 | can_clone = true; | ||
1122 | dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60); | ||
1123 | |||
1124 | for (i = 0; i < fb_helper->connector_count; i++) { | ||
1125 | |||
1126 | if (!enabled[i]) | ||
1127 | continue; | ||
1128 | |||
1129 | fb_helper_conn = fb_helper->connector_info[i]; | ||
1130 | list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { | ||
1131 | if (drm_mode_equal(mode, dmt_mode)) | ||
1132 | modes[i] = mode; | ||
1133 | } | ||
1134 | if (!modes[i]) | ||
1135 | can_clone = false; | ||
1136 | } | ||
1137 | |||
1138 | if (can_clone) { | ||
1139 | DRM_DEBUG_KMS("can clone using 1024x768\n"); | ||
1140 | return true; | ||
1141 | } | ||
1142 | DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); | ||
1143 | return false; | ||
1144 | } | ||
1145 | |||
1073 | static bool drm_target_preferred(struct drm_fb_helper *fb_helper, | 1146 | static bool drm_target_preferred(struct drm_fb_helper *fb_helper, |
1074 | struct drm_display_mode **modes, | 1147 | struct drm_display_mode **modes, |
1075 | bool *enabled, int width, int height) | 1148 | bool *enabled, int width, int height) |
@@ -1163,8 +1236,12 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, | |||
1163 | break; | 1236 | break; |
1164 | 1237 | ||
1165 | if (o < n) { | 1238 | if (o < n) { |
1166 | /* ignore cloning for now */ | 1239 | /* ignore cloning unless only a single crtc */ |
1167 | continue; | 1240 | if (fb_helper->crtc_count > 1) |
1241 | continue; | ||
1242 | |||
1243 | if (!drm_mode_equal(modes[o], modes[n])) | ||
1244 | continue; | ||
1168 | } | 1245 | } |
1169 | 1246 | ||
1170 | crtcs[n] = crtc; | 1247 | crtcs[n] = crtc; |
@@ -1214,9 +1291,12 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) | |||
1214 | 1291 | ||
1215 | drm_enable_connectors(fb_helper, enabled); | 1292 | drm_enable_connectors(fb_helper, enabled); |
1216 | 1293 | ||
1217 | ret = drm_target_preferred(fb_helper, modes, enabled, width, height); | 1294 | ret = drm_target_cloned(fb_helper, modes, enabled, width, height); |
1218 | if (!ret) | 1295 | if (!ret) { |
1219 | DRM_ERROR("Unable to find initial modes\n"); | 1296 | ret = drm_target_preferred(fb_helper, modes, enabled, width, height); |
1297 | if (!ret) | ||
1298 | DRM_ERROR("Unable to find initial modes\n"); | ||
1299 | } | ||
1220 | 1300 | ||
1221 | DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); | 1301 | DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); |
1222 | 1302 | ||