summaryrefslogtreecommitdiff
path: root/hw/xfree86/ddc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/ddc')
-rw-r--r--hw/xfree86/ddc/edid.h26
-rw-r--r--hw/xfree86/ddc/interpret_edid.c29
-rw-r--r--hw/xfree86/ddc/print_edid.c21
3 files changed, 70 insertions, 6 deletions
diff --git a/hw/xfree86/ddc/edid.h b/hw/xfree86/ddc/edid.h
index 2e3e7df4f..6708eaaa5 100644
--- a/hw/xfree86/ddc/edid.h
+++ b/hw/xfree86/ddc/edid.h
@@ -449,17 +449,33 @@ struct whitePoints{
float white_gamma;
};
+struct cvt_timings {
+ int width;
+ int height;
+ int rate;
+ int rates;
+};
+
+/*
+ * Be careful when adding new sections; this structure can't grow, it's
+ * embedded in the middle of xf86Monitor which is ABI. Sizes below are
+ * in bytes, for ILP32 systems. If all else fails just copy the section
+ * literally like serial and friends.
+ */
struct detailed_monitor_section {
int type;
union {
- struct detailed_timings d_timings;
+ struct detailed_timings d_timings; /* 56 */
Uchar serial[13];
Uchar ascii_data[13];
Uchar name[13];
- struct monitor_ranges ranges;
- struct std_timings std_t[5];
- struct whitePoints wp[2];
- } section;
+ struct monitor_ranges ranges; /* 40 */
+ struct std_timings std_t[5]; /* 80 */
+ struct whitePoints wp[2]; /* 32 */
+ /* color management data */
+ struct cvt_timings cvt[4]; /* 64 */
+ /* established timings III */
+ } section; /* max: 80 */
};
typedef struct {
diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index ecec2b039..982a502fd 100644
--- a/hw/xfree86/ddc/interpret_edid.c
+++ b/hw/xfree86/ddc/interpret_edid.c
@@ -175,6 +175,34 @@ get_established_timing_section(Uchar *c, struct established_timings *r)
}
static void
+get_cvt_timing_section(Uchar *c, struct cvt_timings *r)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (c[0] && c[1] && c[2]) {
+ r[i].height = (c[0] + ((c[1] & 0xF0) << 8) + 1) * 2;
+ switch (c[1] & 0xc0) {
+ case 0x00: r[i].width = r[i].height * 4 / 3; break;
+ case 0x40: r[i].width = r[i].height * 16 / 9; break;
+ case 0x80: r[i].width = r[i].height * 16 / 10; break;
+ case 0xc0: r[i].width = r[i].height * 15 / 9; break;
+ }
+ switch (c[2] & 0x60) {
+ case 0x00: r[i].rate = 50; break;
+ case 0x20: r[i].rate = 60; break;
+ case 0x40: r[i].rate = 75; break;
+ case 0x60: r[i].rate = 85; break;
+ }
+ r[i].rates = c[2] & 0x1f;
+ } else {
+ return;
+ }
+ c += 3;
+ }
+}
+
+static void
get_std_timing_section(Uchar *c, struct std_timings *r,
struct edid_version *v)
{
@@ -232,6 +260,7 @@ get_dt_md_section(Uchar *c, struct edid_version *ver,
break;
case CVT_3BYTE_DATA:
det_mon[i].type = DS_CVT;
+ get_cvt_timing_section(c, det_mon[i].section.cvt);
break;
case ADD_EST_TIMINGS:
det_mon[i].type = DS_EST_III;
diff --git a/hw/xfree86/ddc/print_edid.c b/hw/xfree86/ddc/print_edid.c
index 17e21aca8..5aebc6e74 100644
--- a/hw/xfree86/ddc/print_edid.c
+++ b/hw/xfree86/ddc/print_edid.c
@@ -235,6 +235,24 @@ print_std_timings(int scrnIndex, struct std_timings *t)
}
}
}
+
+static void
+print_cvt_timings(int si, struct cvt_timings *t)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (t[i].height) {
+ xf86DrvMsg(si, X_INFO, "%dx%d @ %s%s%s%s%s Hz\n",
+ t[i].width, t[i].height,
+ t[i].rates & 0x10 ? "50," : "",
+ t[i].rates & 0x08 ? "60," : "",
+ t[i].rates & 0x04 ? "75," : "",
+ t[i].rates & 0x02 ? "85," : "",
+ t[i].rates & 0x01 ? "60RB" : "");
+ } else break;
+ }
+}
static void
print_detailed_monitor_section(int scrnIndex,
@@ -296,7 +314,8 @@ print_detailed_monitor_section(int scrnIndex,
break;
case DS_CVT:
xf86DrvMsg(scrnIndex, X_INFO,
- "CVT 3-byte-code modes: (not decoded)\n");
+ "CVT 3-byte-code modes:\n");
+ print_cvt_timings(scrnIndex, m[i].section.cvt);
break;
case DS_EST_III:
xf86DrvMsg(scrnIndex, X_INFO,