Commit a948216d authored by Adam Jackson's avatar Adam Jackson 💣

EDID 1.4: Decode CVT 3-byte codes and add them to the mode pool.

Section 3.10.3.8: CVT 3 Byte Code Descriptor Definition.
parent f6df66cc
......@@ -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 {
......
......@@ -174,6 +174,34 @@ get_established_timing_section(Uchar *c, struct established_timings *r)
r->t_manu = T_MANU;
}
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;
......
......@@ -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,
......
......@@ -354,6 +354,36 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
return Mode;
}
static DisplayModePtr
DDCModesFromCVT(int scrnIndex, struct cvt_timings *t)
{
DisplayModePtr modes = NULL;
int i;
for (i = 0; i < 4; i++) {
if (t[i].height) {
if (t[i].rates & 0x10)
modes = xf86ModesAdd(modes,
xf86CVTMode(t[i].width, t[i].height, 50, 0, 0));
if (t[i].rates & 0x08)
modes = xf86ModesAdd(modes,
xf86CVTMode(t[i].width, t[i].height, 60, 0, 0));
if (t[i].rates & 0x04)
modes = xf86ModesAdd(modes,
xf86CVTMode(t[i].width, t[i].height, 75, 0, 0));
if (t[i].rates & 0x02)
modes = xf86ModesAdd(modes,
xf86CVTMode(t[i].width, t[i].height, 85, 0, 0));
if (t[i].rates & 0x01)
modes = xf86ModesAdd(modes,
xf86CVTMode(t[i].width, t[i].height, 60, 1, 0));
} else break;
}
return modes;
}
/*
*
*/
......@@ -527,6 +557,10 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
quirks);
Modes = xf86ModesAdd(Modes, Mode);
break;
case DS_CVT:
Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt);
Modes = xf86ModesAdd(Modes, Mode);
break;
default:
break;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment