All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/edid: Strengthen the algorithm for CRT default resolution
@ 2012-02-09 20:08 Adam Jackson
  0 siblings, 0 replies; only message in thread
From: Adam Jackson @ 2012-02-09 20:08 UTC (permalink / raw)
  To: dri-devel

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@redhat.com>
---
 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

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-02-09 20:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-09 20:08 [PATCH] drm/edid: Strengthen the algorithm for CRT default resolution Adam Jackson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.