summaryrefslogtreecommitdiff
path: root/hw/xfree86/ddc/interpret_edid.c
diff options
context:
space:
mode:
authorAdam Jackson <ajax@benzedrine.nwnk.net>2006-09-14 18:56:34 -0400
committerAdam Jackson <ajax@benzedrine.nwnk.net>2006-09-14 18:56:34 -0400
commit72af975f9c8de0ff6796f1ce4b76dcf841d21e99 (patch)
tree298eb9e20196811cc4895c9ff6f7578a5eed19c3 /hw/xfree86/ddc/interpret_edid.c
parentd05e0a97bb704a4986cf638487205da759c4ce17 (diff)
Fix up EDID blocks where the max pixclock exceeds the preferred mode clock.
Base EDID only lets you specify the maximum dotclock in tens of MHz, which is too fuzzy for some monitors. 1600x1200@60 is just over 160MHz, but if the monitor really can't handle any mode at 170MHz, then 160 is more correct. Fix up the EDID block before the driver can see it in this case, so we don't spuriously reject modes.
Diffstat (limited to 'hw/xfree86/ddc/interpret_edid.c')
-rw-r--r--hw/xfree86/ddc/interpret_edid.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index a16055491..c58bb2fe1 100644
--- a/hw/xfree86/ddc/interpret_edid.c
+++ b/hw/xfree86/ddc/interpret_edid.c
@@ -31,6 +31,41 @@ static void get_whitepoint_section(Uchar *, struct whitePoints *);
static void get_detailed_timing_section(Uchar*, struct detailed_timings *);
static Bool validate_version(int scrnIndex, struct edid_version *);
+static void
+handle_edid_quirks(xf86MonPtr m)
+{
+ int i, j;
+ struct detailed_timings *preferred_timing;
+ struct monitor_ranges *ranges;
+
+ /*
+ * max_clock is only encoded in EDID in tens of MHz, so occasionally we
+ * find a monitor claiming a max of 160 with a mode requiring 162, or
+ * similar. Strictly we should refuse to round up too far, but let's
+ * see how well this works.
+ */
+ for (i = 0; i < 4; i++) {
+ if (m->det_mon[i].type == DS_RANGES) {
+ ranges = &m->det_mon[i].section.ranges;
+ for (j = 0; j < 4; j++) {
+ if (m->det_mon[j].type == DT) {
+ preferred_timing = &m->det_mon[j].section.d_timings;
+ if (!ranges->max_clock) continue; /* zero is legal */
+ if (ranges->max_clock * 1000000 < preferred_timing->clock) {
+ xf86Msg(X_WARNING,
+ "EDID preferred timing clock %.2fMHz exceeds "
+ "claimed max %dMHz, fixing\n",
+ preferred_timing->clock / 1.0e6,
+ ranges->max_clock);
+ ranges->max_clock =
+ (preferred_timing->clock+999999)/1000000;
+ return;
+ }
+ }
+ }
+ }
+ }
+}
xf86MonPtr
xf86InterpretEDID(int scrnIndex, Uchar *block)
@@ -53,7 +88,9 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
&m->ver);
get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
-
+
+ handle_edid_quirks(m);
+
return (m);
error: