diff options
author | Dave Airlie <airlied@redhat.com> | 2010-05-07 05:02:30 +0000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 17:40:22 +1000 |
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, } } +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); |