|
@@ -1070,6 +1070,79 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
|
|
|
+ struct drm_display_mode **modes,
|
|
|
+ bool *enabled, int width, int height)
|
|
|
+{
|
|
|
+ int count, i, j;
|
|
|
+ bool can_clone = false;
|
|
|
+ struct drm_fb_helper_connector *fb_helper_conn;
|
|
|
+ struct drm_display_mode *dmt_mode, *mode;
|
|
|
+
|
|
|
+ /* only contemplate cloning in the single crtc case */
|
|
|
+ if (fb_helper->crtc_count > 1)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ count = 0;
|
|
|
+ for (i = 0; i < fb_helper->connector_count; i++) {
|
|
|
+ if (enabled[i])
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* only contemplate cloning if more than one connector is enabled */
|
|
|
+ if (count <= 1)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* check the command line or if nothing common pick 1024x768 */
|
|
|
+ can_clone = true;
|
|
|
+ for (i = 0; i < fb_helper->connector_count; i++) {
|
|
|
+ if (!enabled[i])
|
|
|
+ continue;
|
|
|
+ fb_helper_conn = fb_helper->connector_info[i];
|
|
|
+ modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
|
|
|
+ if (!modes[i]) {
|
|
|
+ can_clone = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ for (j = 0; j < i; j++) {
|
|
|
+ if (!enabled[j])
|
|
|
+ continue;
|
|
|
+ if (!drm_mode_equal(modes[j], modes[i]))
|
|
|
+ can_clone = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (can_clone) {
|
|
|
+ DRM_DEBUG_KMS("can clone using command line\n");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* try and find a 1024x768 mode on each connector */
|
|
|
+ can_clone = true;
|
|
|
+ dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60);
|
|
|
+
|
|
|
+ for (i = 0; i < fb_helper->connector_count; i++) {
|
|
|
+
|
|
|
+ if (!enabled[i])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ fb_helper_conn = fb_helper->connector_info[i];
|
|
|
+ list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
|
|
|
+ if (drm_mode_equal(mode, dmt_mode))
|
|
|
+ modes[i] = mode;
|
|
|
+ }
|
|
|
+ if (!modes[i])
|
|
|
+ can_clone = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (can_clone) {
|
|
|
+ DRM_DEBUG_KMS("can clone using 1024x768\n");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
|
|
|
struct drm_display_mode **modes,
|
|
|
bool *enabled, int width, int height)
|
|
@@ -1163,8 +1236,12 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|
|
break;
|
|
|
|
|
|
if (o < n) {
|
|
|
- /* ignore cloning for now */
|
|
|
- continue;
|
|
|
+ /* ignore cloning unless only a single crtc */
|
|
|
+ if (fb_helper->crtc_count > 1)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!drm_mode_equal(modes[o], modes[n]))
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
crtcs[n] = crtc;
|
|
@@ -1214,9 +1291,12 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
|
|
|
|
|
|
drm_enable_connectors(fb_helper, enabled);
|
|
|
|
|
|
- ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
|
|
|
- if (!ret)
|
|
|
- DRM_ERROR("Unable to find initial modes\n");
|
|
|
+ ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
|
|
|
+ if (!ret) {
|
|
|
+ ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
|
|
|
+ if (!ret)
|
|
|
+ DRM_ERROR("Unable to find initial modes\n");
|
|
|
+ }
|
|
|
|
|
|
DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
|
|
|
|