diff mbox

[1/3,v2] fbdev: sh_mobile_hdmi: add command line option to use the preferred EDID mode

Message ID Pine.LNX.4.64.1101071253330.32550@axis700.grange (mailing list archive)
State Accepted
Commit c7321d6f88e1f962d605923a93f9c255e4d0b8c9
Headers show

Commit Message

Guennadi Liakhovetski Jan. 7, 2011, 11:57 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 8c59cc8..571bd9f 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -737,7 +737,7 @@  static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
 	struct fb_modelist *modelist = NULL;
 	unsigned int f_width = 0, f_height = 0, f_refresh = 0;
 	unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
-	bool exact_match = false;
+	bool scanning = false, preferred_bad = false;
 	u8 edid[128];
 	char *forced;
 	int i;
@@ -800,6 +800,9 @@  static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
 		if (i < 2) {
 			f_width = 0;
 			f_height = 0;
+		} else {
+			/* The user wants us to use the EDID data */
+			scanning = true;
 		}
 		dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
 			f_width, f_height, f_refresh);
@@ -807,37 +810,56 @@  static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
 
 	/* Walk monitor modes to find the best or the exact match */
 	for (i = 0, mode = hdmi->monspec.modedb;
-	     f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
+	     i < hdmi->monspec.modedb_len && scanning;
 	     i++, mode++) {
 		unsigned long rate_error;
 
-		/* No interest in unmatching modes */
-		if (f_width != mode->xres || f_height != mode->yres)
+		if (!f_width && !f_height) {
+			/*
+			 * A parameter string "video=sh_mobile_lcdc:0x0" means
+			 * use the preferred EDID mode. If it is rejected by
+			 * .fb_check_var(), keep looking, until an acceptable
+			 * one is found.
+			 */
+			if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad)
+				scanning = false;
+			else
+				continue;
+		} else if (f_width != mode->xres || f_height != mode->yres) {
+			/* No interest in unmatching modes */
 			continue;
+		}
 
 		rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
 
-		if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
-			/*
-			 * Exact match if either the refresh rate matches or it
-			 * hasn't been specified and we've found a mode, for
-			 * which we can configure the clock precisely
-			 */
-			exact_match = true;
-		else if (found && found_rate_error <= rate_error)
-			/*
-			 * We otherwise search for the closest matching clock
-			 * rate - either if no refresh rate has been specified
-			 * or we cannot find an exactly matching one
-			 */
-			continue;
+		if (scanning) {
+			if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
+				/*
+				 * Exact match if either the refresh rate
+				 * matches or it hasn't been specified and we've
+				 * found a mode, for which we can configure the
+				 * clock precisely
+				 */
+				scanning = false;
+			else if (found && found_rate_error <= rate_error)
+				/*
+				 * We otherwise search for the closest matching
+				 * clock rate - either if no refresh rate has
+				 * been specified or we cannot find an exactly
+				 * matching one
+				 */
+				continue;
+		}
 
 		/* Check if supported: sufficient fb memory, supported clock-rate */
 		fb_videomode_to_var(var, mode);
 
+		var->bits_per_pixel = info->var.bits_per_pixel;
+
 		if (info && info->fbops->fb_check_var &&
 		    info->fbops->fb_check_var(var, info)) {
-			exact_match = false;
+			scanning = true;
+			preferred_bad = true;
 			continue;
 		}