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>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user