If a CRT doesn't deign to provide a preferred mode, we should try to pick a mode with a vaguely reasonable DPI instead of whatever happens to be biggest. Bugzilla: https://bugzilla.redhat.com/522155 Signed-off-by: Adam Jackson <ajax@xxxxxxxxxx> --- drivers/gpu/drm/drm_edid.c | 52 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 14 +++++++++- include/drm/drm_crtc.h | 3 ++ 3 files changed, 68 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ece03fc..7d7f4dc 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1810,3 +1810,55 @@ int drm_add_modes_noedid(struct drm_connector *connector, return num_modes; } EXPORT_SYMBOL(drm_add_modes_noedid); + +/** + * drm_edid_analog_mode_guess - guess a mode somewhere near 96dpi + * @connector: connector to inspect + * @max_width: maximum width + * @max_height: maximum height + * + * Some old (usually CRT) monitors do not specify a preferred mode. Usually + * they also expose very high resolutions, which leads to unreadably small + * text. Instead pick something reasonable. + * + * Returns the supported mode closest to 96dpi within some tolerance, if any. + * + * Only looks at horizontal DPI, but, whatever. + */ +struct drm_display_mode * +drm_edid_analog_mode_guess(struct drm_connector *connector, + int max_width, int max_height) +{ + struct drm_display_mode *mode, *best = NULL; + int best_dpi = 0; + struct edid *edid; + + edid = connector->edid_blob_ptr->data; + if (!edid) + return NULL; + + if ((edid->features & DRM_EDID_INPUT_DIGITAL)) + return NULL; + + if (!edid->width_cm || !edid->height_cm) + return NULL; + + list_for_each_entry(mode, &connector->probed_modes, head) { + int dpi = (mode->hdisplay * 254) / (edid->width_cm * 100); + + if (mode->hdisplay > max_width || mode->vdisplay > max_height) + continue; + + if (abs(96 - dpi) < abs(96 - best_dpi)) { + best_dpi = dpi; + best = mode; + } + } + + /* if we can't get anywhere near 96dpi, we probably shouldn't try */ + if (abs(96 - best_dpi) > 10) + return NULL; + + return best; +} +EXPORT_SYMBOL(drm_edid_analog_mode_guess); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index aada26f..14d544e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1177,15 +1177,27 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", fb_helper_conn->connector->base.id); - /* got for command line mode first */ + /* go for command line mode first */ modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height); + + /* then edid-preferred, if any */ if (!modes[i]) { DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", fb_helper_conn->connector->base.id); modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); } + + /* then something maybe near 96dpi if possible */ + if (!modes[i] && fb_helper_conn->connector->edid_blob_ptr) { + DRM_DEBUG_KMS("looking for 96dpi mode on connector %d\n", + fb_helper_conn->connector->base.id); + modes[i] = drm_edid_analog_mode_guess(fb_helper_conn->connector, width, height); + } + /* No preferred modes, pick one off the list */ if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { + DRM_DEBUG_KMS("guessing mode on connector %d\n", + fb_helper_conn->connector->base.id); list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) break; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4cd4be2..1d04589 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -993,6 +993,9 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, int GTF_2C, int GTF_K, int GTF_2J); extern int drm_add_modes_noedid(struct drm_connector *connector, int hdisplay, int vdisplay); +extern struct drm_display_mode *drm_edid_analog_mode_guess( + struct drm_connector *connector, + int max_width, int max_height); extern int drm_edid_header_is_valid(const u8 *raw_edid); extern bool drm_edid_is_valid(struct edid *edid); -- 1.7.7.6 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel