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.
This commit is contained in:
parent
f6df66cc89
commit
a948216dcc
|
@ -449,17 +449,33 @@ struct whitePoints{
|
||||||
float white_gamma;
|
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 {
|
struct detailed_monitor_section {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
struct detailed_timings d_timings;
|
struct detailed_timings d_timings; /* 56 */
|
||||||
Uchar serial[13];
|
Uchar serial[13];
|
||||||
Uchar ascii_data[13];
|
Uchar ascii_data[13];
|
||||||
Uchar name[13];
|
Uchar name[13];
|
||||||
struct monitor_ranges ranges;
|
struct monitor_ranges ranges; /* 40 */
|
||||||
struct std_timings std_t[5];
|
struct std_timings std_t[5]; /* 80 */
|
||||||
struct whitePoints wp[2];
|
struct whitePoints wp[2]; /* 32 */
|
||||||
} section;
|
/* color management data */
|
||||||
|
struct cvt_timings cvt[4]; /* 64 */
|
||||||
|
/* established timings III */
|
||||||
|
} section; /* max: 80 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -174,6 +174,34 @@ get_established_timing_section(Uchar *c, struct established_timings *r)
|
||||||
r->t_manu = T_MANU;
|
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
|
static void
|
||||||
get_std_timing_section(Uchar *c, struct std_timings *r,
|
get_std_timing_section(Uchar *c, struct std_timings *r,
|
||||||
struct edid_version *v)
|
struct edid_version *v)
|
||||||
|
@ -232,6 +260,7 @@ get_dt_md_section(Uchar *c, struct edid_version *ver,
|
||||||
break;
|
break;
|
||||||
case CVT_3BYTE_DATA:
|
case CVT_3BYTE_DATA:
|
||||||
det_mon[i].type = DS_CVT;
|
det_mon[i].type = DS_CVT;
|
||||||
|
get_cvt_timing_section(c, det_mon[i].section.cvt);
|
||||||
break;
|
break;
|
||||||
case ADD_EST_TIMINGS:
|
case ADD_EST_TIMINGS:
|
||||||
det_mon[i].type = DS_EST_III;
|
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
|
static void
|
||||||
print_detailed_monitor_section(int scrnIndex,
|
print_detailed_monitor_section(int scrnIndex,
|
||||||
|
@ -296,7 +314,8 @@ print_detailed_monitor_section(int scrnIndex,
|
||||||
break;
|
break;
|
||||||
case DS_CVT:
|
case DS_CVT:
|
||||||
xf86DrvMsg(scrnIndex, X_INFO,
|
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;
|
break;
|
||||||
case DS_EST_III:
|
case DS_EST_III:
|
||||||
xf86DrvMsg(scrnIndex, X_INFO,
|
xf86DrvMsg(scrnIndex, X_INFO,
|
||||||
|
|
|
@ -354,6 +354,36 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
|
||||||
return Mode;
|
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);
|
quirks);
|
||||||
Modes = xf86ModesAdd(Modes, Mode);
|
Modes = xf86ModesAdd(Modes, Mode);
|
||||||
break;
|
break;
|
||||||
|
case DS_CVT:
|
||||||
|
Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt);
|
||||||
|
Modes = xf86ModesAdd(Modes, Mode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue