[PATCH] [RFC] xf86Crtc: Trust the drivers to report the correct output modes

Chris Wilson chris at chris-wilson.co.uk
Thu Aug 5 10:59:59 PDT 2010


In the absence of the user specifying an overriding monitor
configuration, trust the KMS drivers to have correctly probed the output
modes.

This avoids duplicating work already done by the kernel (when using KMS)
and secondly avoids disagreements (which admittedly shouldn't exist in
an ideal world) between the kernel and X over valid modes.

References:

  Bug 23833 - X uses different refresh rate to that set by kernel module
  https://bugs.freedesktop.org/show_bug.cgi?id=23833

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 hw/xfree86/modes/xf86Crtc.c |  264 ++++++++++++++++++++++---------------------
 1 files changed, 136 insertions(+), 128 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index b2daec7..d9672bb 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1554,23 +1554,14 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
     }
 
     /* Probe the list of modes for each output. */
-    for (o = 0; o < config->num_output; o++) 
+    for (o = 0; o < config->num_output; o++)
     {
 	xf86OutputPtr	    output = config->output[o];
-	DisplayModePtr	    mode;
 	DisplayModePtr	    config_modes = NULL, output_modes, default_modes = NULL;
+	DisplayModePtr	    mode;
 	char		    *preferred_mode;
-	xf86MonPtr	    edid_monitor;
 	XF86ConfMonitorPtr  conf_monitor;
-	MonRec		    mon_rec;
-	int		    min_clock = 0;
-	int		    max_clock = 0;
-	double		    clock;
-	Bool		    add_default_modes = xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
-	Bool		    debug_modes = config->debug_modes ||
-					  xf86Initialising;
-	enum det_monrec_source sync_source = sync_default;
-	
+
 	while (output->probed_modes != NULL)
 	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
 
@@ -1586,148 +1577,165 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 	    continue;
 	}
 
-	memset (&mon_rec, '\0', sizeof (mon_rec));
-	
+	output_modes = (*output->funcs->get_modes) (output);
+
 	conf_monitor = output->conf_monitor;
-	
-	if (conf_monitor)
+	if (output_modes == NULL || conf_monitor)
 	{
+	    xf86MonPtr	    edid_monitor;
+	    MonRec	    mon_rec;
+	    int		    min_clock = 0;
+	    int		    max_clock = 0;
+	    double	    clock;
+	    Bool	    add_default_modes = xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
+	    Bool	    debug_modes = config->debug_modes ||
+		    xf86Initialising;
+	    enum det_monrec_source sync_source = sync_default;
 	    int	i;
-	    
-	    for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+
+	    memset (&mon_rec, '\0', sizeof (mon_rec));
+
+	    if (conf_monitor)
 	    {
-		mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
-		mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
-		mon_rec.nHsync++;
-		sync_source = sync_config;
+		    for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+		    {
+			    mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
+			    mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
+			    mon_rec.nHsync++;
+			    sync_source = sync_config;
+		    }
+		    for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+		    {
+			    mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
+			    mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
+			    mon_rec.nVrefresh++;
+			    sync_source = sync_config;
+		    }
+		    config_modes = xf86GetMonitorModes (scrn, conf_monitor);
 	    }
-	    for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+
+	    edid_monitor = output->MonInfo;
+	    if (edid_monitor)
 	    {
-		mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
-		mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
-		mon_rec.nVrefresh++;
-		sync_source = sync_config;
+		struct det_monrec_parameter p;
+		struct disp_features    *features = &edid_monitor->features;
+
+		/* if display is not continuous-frequency, don't add default modes */
+		if (!GTF_SUPPORTED(features->msc))
+		    add_default_modes = FALSE;
+
+		p.mon_rec = &mon_rec;
+		p.max_clock = &max_clock;
+		p.set_hsync = mon_rec.nHsync == 0;
+		p.set_vrefresh = mon_rec.nVrefresh == 0;
+		p.sync_source = &sync_source;
+
+		xf86ForEachDetailedBlock(edid_monitor,
+					 handle_detailed_monrec,
+					 &p);
 	    }
-	    config_modes = xf86GetMonitorModes (scrn, conf_monitor);
-	}
-	
-	output_modes = (*output->funcs->get_modes) (output);
-	
-	edid_monitor = output->MonInfo;
-	
-        if (edid_monitor)
-        {
-            struct det_monrec_parameter p;
-            struct disp_features    *features = &edid_monitor->features;
-
-	    /* if display is not continuous-frequency, don't add default modes */
-	    if (!GTF_SUPPORTED(features->msc))
-		add_default_modes = FALSE;
-
-	    p.mon_rec = &mon_rec;
-	    p.max_clock = &max_clock;
-	    p.set_hsync = mon_rec.nHsync == 0;
-	    p.set_vrefresh = mon_rec.nVrefresh == 0;
-	    p.sync_source = &sync_source;
-
-	    xf86ForEachDetailedBlock(edid_monitor,
-			             handle_detailed_monrec,
-			             &p);
-	}
 
-	if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
-			       OPTUNITS_KHZ, &clock))
-	    min_clock = (int) clock;
-	if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
-			       OPTUNITS_KHZ, &clock))
-	    max_clock = (int) clock;
+	    if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+				   OPTUNITS_KHZ, &clock))
+		min_clock = (int) clock;
+	    if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+				   OPTUNITS_KHZ, &clock))
+		max_clock = (int) clock;
 
-	/* If we still don't have a sync range, guess wildly */
-	if (!mon_rec.nHsync || !mon_rec.nVrefresh)
-	    GuessRangeFromModes(&mon_rec, output_modes);
+	    /* If we still don't have a sync range, guess wildly */
+	    if (!mon_rec.nHsync || !mon_rec.nVrefresh)
+		GuessRangeFromModes(&mon_rec, output_modes);
 
-	/*
-	 * These limits will end up setting a 1024x768 at 60Hz mode by default,
-	 * which seems like a fairly good mode to use when nothing else is
-	 * specified
-	 */
-	if (mon_rec.nHsync == 0)
-	{
-	    mon_rec.hsync[0].lo = 31.0;
-	    mon_rec.hsync[0].hi = 55.0;
-	    mon_rec.nHsync = 1;
-	}
-	if (mon_rec.nVrefresh == 0)
-	{
-	    mon_rec.vrefresh[0].lo = 58.0;
-	    mon_rec.vrefresh[0].hi = 62.0;
-	    mon_rec.nVrefresh = 1;
-	}
+	    /*
+	     * These limits will end up setting a 1024x768 at 60Hz mode by default,
+	     * which seems like a fairly good mode to use when nothing else is
+	     * specified
+	     */
+	    if (mon_rec.nHsync == 0)
+	    {
+		mon_rec.hsync[0].lo = 31.0;
+		mon_rec.hsync[0].hi = 55.0;
+		mon_rec.nHsync = 1;
+	    }
+	    if (mon_rec.nVrefresh == 0)
+	    {
+		mon_rec.vrefresh[0].lo = 58.0;
+		mon_rec.vrefresh[0].hi = 62.0;
+		mon_rec.nVrefresh = 1;
+	    }
 
-	if (add_default_modes)
-	    default_modes = xf86GetDefaultModes ();
+	    if (add_default_modes)
+		default_modes = xf86GetDefaultModes ();
 
-	/*
-	 * If this is not an RB monitor, remove RB modes from the default
-	 * pool.  RB modes from the config or the monitor itself are fine.
-	 */
-	if (!mon_rec.reducedblanking)
-	    xf86ValidateModesReducedBlanking (scrn, default_modes);
+	    /*
+	     * If this is not an RB monitor, remove RB modes from the default
+	     * pool.  RB modes from the config or the monitor itself are fine.
+	     */
+	    if (!mon_rec.reducedblanking)
+		xf86ValidateModesReducedBlanking (scrn, default_modes);
 
-	if (sync_source == sync_config)
-	{
-	    /* 
-	     * Check output and config modes against sync range from config file
+	    if (sync_source == sync_config)
+	    {
+		/*
+		 * Check output and config modes against sync range from
+		 * config file
+		 */
+		xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+		xf86ValidateModesSync (scrn, config_modes, &mon_rec);
+	    }
+	    /*
+	     * Check default modes against sync range
 	     */
-	    xf86ValidateModesSync (scrn, output_modes, &mon_rec);
-	    xf86ValidateModesSync (scrn, config_modes, &mon_rec);
-	}
-	/*
-	 * Check default modes against sync range
-	 */
-        xf86ValidateModesSync (scrn, default_modes, &mon_rec);
-	/*
-	 * Check default modes against monitor max clock
-	 */
-	if (max_clock) {
-	    xf86ValidateModesClocks(scrn, default_modes,
-				    &min_clock, &max_clock, 1);
-	    xf86ValidateModesClocks(scrn, output_modes,
-				    &min_clock, &max_clock, 1);
-	}
-	
-	output->probed_modes = NULL;
-	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
-	output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
-	output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
-	
-	/*
-	 * Check all modes against max size, interlace, and doublescan
-	 */
-	if (maxX && maxY)
-	    xf86ValidateModesSize (scrn, output->probed_modes,
+	    xf86ValidateModesSync (scrn, default_modes, &mon_rec);
+	    /*
+	     * Check default modes against monitor max clock
+	     */
+	    if (max_clock) {
+		xf86ValidateModesClocks(scrn, default_modes,
+					&min_clock, &max_clock, 1);
+		xf86ValidateModesClocks(scrn, output_modes,
+					&min_clock, &max_clock, 1);
+	    }
+
+	    output->probed_modes = NULL;
+	    output->probed_modes = xf86ModesAdd(output->probed_modes,
+						config_modes);
+	    output->probed_modes = xf86ModesAdd(output->probed_modes,
+						output_modes);
+	    output->probed_modes = xf86ModesAdd(output->probed_modes,
+						default_modes);
+
+	    /*
+	     * Check all modes against max size, interlace, and doublescan
+	     */
+	    if (maxX && maxY)
+		xf86ValidateModesSize (scrn, output->probed_modes,
 				       maxX, maxY, 0);
 
+	    {
+		int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
+		    (output->doubleScanAllowed ? V_DBLSCAN : 0);
+		xf86ValidateModesFlags (scrn, output->probed_modes, flags);
+	    }
+	}
+	else
 	{
-	    int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
-			(output->doubleScanAllowed ? V_DBLSCAN : 0);
-	    xf86ValidateModesFlags (scrn, output->probed_modes, flags);
+	    output->probed_modes = output_modes;
 	}
-	 
+
 	/*
 	 * Check all modes against output
 	 */
-	for (mode = output->probed_modes; mode != NULL; mode = mode->next) 
+	for (mode = output->probed_modes; mode != NULL; mode = mode->next)
 	    if (mode->status == MODE_OK)
 		mode->status = (*output->funcs->mode_valid)(output, mode);
-	
+
 	xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes);
-	
+
 	output->probed_modes = xf86SortModes (output->probed_modes);
-	
+
 	/* Check for a configured preference for a particular mode */
 	preferred_mode = preferredMode(scrn, output);
-
 	if (preferred_mode)
 	{
 	    for (mode = output->probed_modes; mode; mode = mode->next)
@@ -1750,7 +1758,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 		}
 	    }
 	}
-	
+
 	output->initial_rotation = xf86OutputInitialRotation (output);
 
 	if (debug_modes) {
-- 
1.7.1



More information about the xorg-devel mailing list