[PATCH 4/9] handle detailed timing operation in xf86EdidModes.c

Ma Ling ling.ma at intel.com
Wed Feb 11 01:15:40 PST 2009


handle detailed timing quirks and insert detailed timing modes into mode list 

---
 hw/xfree86/ddc/xf86DDC.h         |   39 +++++
 hw/xfree86/modes/xf86EdidModes.c |  284 ++++++++++++++++++++------------------
 2 files changed, 190 insertions(+), 133 deletions(-)

diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h
index b865e1a..0f4f65f 100644
--- a/hw/xfree86/ddc/xf86DDC.h
+++ b/hw/xfree86/ddc/xf86DDC.h
@@ -62,9 +62,48 @@ extern _X_EXPORT DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
 extern _X_EXPORT Bool
 xf86MonitorIsHDMI(xf86MonPtr mon);
 
+/*
+ * Quirks to work around broken EDID data from various monitors.
+ */
+typedef enum {
+    DDC_QUIRK_NONE = 0,
+    /* First detailed mode is bogus, prefer largest mode at 60hz */
+    DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
+    /* 135MHz clock is too high, drop a bit */
+    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
+    /* Prefer the largest mode at 75 Hz */
+    DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
+    /* Convert detailed timing's horizontal from units of cm to mm */
+    DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
+    /* Convert detailed timing's vertical from units of cm to mm */
+    DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
+    /* Detailed timing descriptors have bogus size values, so just take the
+     * maximum size and use that.
+     */
+    DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
+    /* Monitor forgot to set the first detailed is preferred bit. */
+    DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
+    /* use +hsync +vsync for detailed mode */
+    DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
+    /* Force single-link DVI bandwidth limit */
+    DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
+} ddc_quirk_t;
+
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+
+extern Bool
+xf86MonitorIsHDMI(xf86MonPtr mon);
+
 typedef void (* handle_detailed_fn)(struct detailed_monitor_section *,void *);
 
 void xf86ForEachDetailedBlock(xf86MonPtr mon,
                               handle_detailed_fn,
                               void *data);
+
+ddc_quirk_t
+xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose);
+
+void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
+                              ddc_quirk_t quirks, int hsize, int vsize);
+
 #endif
diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 1413e87..97c40bf 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -45,20 +45,23 @@
 #include <string.h>
 #include <math.h>
 
+static void handle_detailed_rblank(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    if (det_mon->type == DS_RANGES)
+        if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
+            *(Bool*)data = TRUE;
+}
+
 static Bool
 xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
 {
     /* EDID 1.4 explicitly defines RB support */
     if (DDC->ver.revision >= 4) {
-	int i;
-	for (i = 0; i < DET_TIMINGS; i++) {
-	    struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-	    if (det_mon->type == DS_RANGES)
-		if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
-		    return TRUE;
-	}
-	
-	return FALSE;
+        Bool ret = FALSE;
+
+        xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret);
+        return ret;
     }
 
     /* For anything older, assume digital means RB support. Boo. */
@@ -68,34 +71,6 @@ xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
     return FALSE;
 }
 
-/*
- * Quirks to work around broken EDID data from various monitors.
- */
-
-typedef enum {
-    DDC_QUIRK_NONE = 0,
-    /* First detailed mode is bogus, prefer largest mode at 60hz */
-    DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
-    /* 135MHz clock is too high, drop a bit */
-    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
-    /* Prefer the largest mode at 75 Hz */
-    DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
-    /* Convert detailed timing's horizontal from units of cm to mm */
-    DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
-    /* Convert detailed timing's vertical from units of cm to mm */
-    DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
-    /* Detailed timing descriptors have bogus size values, so just take the
-     * maximum size and use that.
-     */
-    DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
-    /* Monitor forgot to set the first detailed is preferred bit. */
-    DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
-    /* use +hsync +vsync for detailed mode */
-    DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
-    /* Force single-link DVI bandwidth limit */
-    DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
-} ddc_quirk_t;
-
 static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
 {
     /* Belinea 10 15 55 */
@@ -667,7 +642,7 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
     }
 }
 
-static ddc_quirk_t
+ddc_quirk_t
 xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
 {
     ddc_quirk_t	quirks;
@@ -687,6 +662,25 @@ xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
     return quirks;
 }
 
+void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
+                              ddc_quirk_t quirks,
+                              int hsize, int vsize)  
+{
+    if (det_mon->type != DT)
+        return;
+
+    if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
+        det_mon->section.d_timings.h_size *= 10;
+
+    if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
+        det_mon->section.d_timings.v_size *= 10;
+
+    if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
+        det_mon->section.d_timings.h_size = 10 * hsize;
+        det_mon->section.d_timings.v_size = 10 * vsize;
+    }
+}
+
 /**
  * Applies monitor-specific quirks to the decoded EDID information.
  *
@@ -700,21 +694,9 @@ xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC)
     int i;
 
     for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-	if (det_mon->type != DT)
-	    continue;
-
-	if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
-	    det_mon->section.d_timings.h_size *= 10;
-
-	if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
-	    det_mon->section.d_timings.v_size *= 10;
-
-	if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
-	    det_mon->section.d_timings.h_size = 10 * DDC->features.hsize;
-	    det_mon->section.d_timings.v_size = 10 * DDC->features.vsize;
-	}
+        xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks,
+                                 DDC->features.hsize,
+                                 DDC->features.vsize);
     }
 }
 
@@ -759,14 +741,58 @@ xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes,
 	    best->type |= M_T_PREFERRED;
 }
 
+struct det_modes_parameter {
+    xf86MonPtr DDC;
+    ddc_quirk_t quirks;
+    DisplayModePtr * Modes;
+    Bool rb;
+    Bool preferred;
+    int timing_level;
+};
+
+static void handle_detailed_modes(struct detailed_monitor_section *det_mon,
+	                          void *data)
+{
+    DisplayModePtr  Mode;
+    struct det_modes_parameter *p = (struct det_modes_parameter *)data;
+
+    xf86DetTimingApplyQuirks(det_mon,p->quirks,
+                             p->DDC->features.hsize,
+                             p->DDC->features.vsize);
+
+    switch (det_mon->type) {
+    case DT:
+        Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex,
+                                         &det_mon->section.d_timings,
+                                         p->preferred,
+                                         p->quirks);
+        p->preferred = FALSE;
+        *p->Modes = xf86ModesAdd(*p->Modes, Mode);
+        break;
+    case DS_STD_TIMINGS:
+        Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
+                                          p->quirks, p->timing_level,p->rb);
+        *p->Modes = xf86ModesAdd(*p->Modes, Mode);
+        break;
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
+    case DS_CVT:
+        Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt);
+        *p->Modes = xf86ModesAdd(*p->Modes, Mode);
+        break;
+#endif
+    default:
+        break;
+    }
+}
+
 DisplayModePtr
 xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 {
-    int		    i;
     DisplayModePtr  Modes = NULL, Mode;
     ddc_quirk_t	    quirks;
     Bool	    preferred, rb;
     int		    timing_level;
+    struct det_modes_parameter p;
 
     xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
 		DDC->vendor.name, DDC->vendor.prod_id);
@@ -785,33 +811,13 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 
     timing_level = MonitorStandardTimingLevel(DDC);
 
-    for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-        switch (det_mon->type) {
-        case DT:
-            Mode = DDCModeFromDetailedTiming(scrnIndex,
-                                             &det_mon->section.d_timings,
-					     preferred,
-					     quirks);
-	    preferred = FALSE;
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-        case DS_STD_TIMINGS:
-            Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
-					      quirks, timing_level, rb);
-            Modes = xf86ModesAdd(Modes, Mode);
-            break;
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
-	case DS_CVT:
-	    Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt);
-	    Modes = xf86ModesAdd(Modes, Mode);
-	    break;
-#endif
-        default:
-            break;
-        }
-    }
+    p.quirks = quirks;
+    p.DDC = DDC;
+    p.Modes = &Modes;
+    p.rb = rb;
+    p.preferred = preferred;
+    p.timing_level = timing_level;
+    xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p);
 
     /* Add established timings */
     Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
@@ -830,6 +836,63 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
     return Modes;
 }
 
+struct det_mon_parameter {
+    MonPtr Monitor;
+    ddc_quirk_t quirks;
+    Bool have_hsync;
+    Bool have_vrefresh;
+    Bool have_maxpixclock;
+};
+
+static void handle_detailed_monset(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    int clock;
+    struct det_mon_parameter *p = (struct det_mon_parameter *)data;
+    int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex;
+
+    switch (det_mon->type) {
+    case DS_RANGES:
+        if (!p->have_hsync) {
+            if (!p->Monitor->nHsync)
+                xf86DrvMsg(scrnIndex, X_INFO,
+                    "Using EDID range info for horizontal sync\n");
+                p->Monitor->hsync[p->Monitor->nHsync].lo =
+                    det_mon->section.ranges.min_h;
+                p->Monitor->hsync[p->Monitor->nHsync].hi =
+                    det_mon->section.ranges.max_h;
+                p->Monitor->nHsync++;
+        } else {
+            xf86DrvMsg(scrnIndex, X_INFO,
+                "Using hsync ranges from config file\n");
+        }
+
+        if (!p->have_vrefresh) {
+            if (!p->Monitor->nVrefresh)
+                xf86DrvMsg(scrnIndex, X_INFO,
+                    "Using EDID range info for vertical refresh\n");
+            p->Monitor->vrefresh[p->Monitor->nVrefresh].lo =
+                det_mon->section.ranges.min_v;
+            p->Monitor->vrefresh[p->Monitor->nVrefresh].hi =
+                det_mon->section.ranges.max_v;
+            p->Monitor->nVrefresh++;
+        } else {
+            xf86DrvMsg(scrnIndex, X_INFO,
+                "Using vrefresh ranges from config file\n");
+        }
+
+        clock = det_mon->section.ranges.max_clock * 1000;
+        if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK)
+            clock = min(clock, 165000);
+        if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock)
+            p->Monitor->maxPixClock = clock;
+
+        break;
+    default:
+        break;
+    }
+}
+
 /*
  * Fill out MonPtr with xf86MonPtr information.
  */
@@ -837,17 +900,13 @@ void
 xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 {
     DisplayModePtr Modes = NULL, Mode;
-    int i, clock;
-    Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE;
-    ddc_quirk_t quirks;
+    struct det_mon_parameter p; 
 
     if (!Monitor || !DDC)
         return;
 
     Monitor->DDC = DDC;
 
-    quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE);
-
     if (Monitor->widthmm <= 0 && Monitor->heightmm <= 0) {
 	Monitor->widthmm = 10 * DDC->features.hsize;
 	Monitor->heightmm = 10 * DDC->features.vsize;
@@ -857,54 +916,13 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 
     Modes = xf86DDCGetModes(scrnIndex, DDC);
 
-    /* Skip EDID ranges if they were specified in the config file */
-    have_hsync = (Monitor->nHsync != 0);
-    have_vrefresh = (Monitor->nVrefresh != 0);
-    have_maxpixclock = (Monitor->maxPixClock != 0);
-
     /* Go through the detailed monitor sections */
-    for (i = 0; i < DET_TIMINGS; i++) {
-        switch (DDC->det_mon[i].type) {
-        case DS_RANGES:
-	    if (!have_hsync) {
-		if (!Monitor->nHsync)
-		    xf86DrvMsg(scrnIndex, X_INFO,
-			    "Using EDID range info for horizontal sync\n");
-		Monitor->hsync[Monitor->nHsync].lo =
-		    DDC->det_mon[i].section.ranges.min_h;
-		Monitor->hsync[Monitor->nHsync].hi =
-		    DDC->det_mon[i].section.ranges.max_h;
-		Monitor->nHsync++;
-	    } else {
-		xf86DrvMsg(scrnIndex, X_INFO,
-			"Using hsync ranges from config file\n");
-	    }
-
-	    if (!have_vrefresh) {
-		if (!Monitor->nVrefresh)
-		    xf86DrvMsg(scrnIndex, X_INFO,
-			    "Using EDID range info for vertical refresh\n");
-		Monitor->vrefresh[Monitor->nVrefresh].lo =
-		    DDC->det_mon[i].section.ranges.min_v;
-		Monitor->vrefresh[Monitor->nVrefresh].hi =
-		    DDC->det_mon[i].section.ranges.max_v;
-		Monitor->nVrefresh++;
-	    } else {
-		xf86DrvMsg(scrnIndex, X_INFO,
-			"Using vrefresh ranges from config file\n");
-	    }
-
-	    clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
-	    if (quirks & DDC_QUIRK_DVI_SINGLE_LINK)
-		clock = min(clock, 165000);
-	    if (!have_maxpixclock && clock > Monitor->maxPixClock)
-		Monitor->maxPixClock = clock;
-
-            break;
-        default:
-            break;
-        }
-    }
+    p.Monitor = Monitor;
+    p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE);
+    p.have_hsync = (Monitor->nHsync != 0);
+    p.have_vrefresh = (Monitor->nVrefresh != 0);
+    p.have_maxpixclock = (Monitor->maxPixClock != 0);
+    xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p);
 
     if (Modes) {
         /* Print Modes */
-- 
1.5.4.4






More information about the xorg mailing list