summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Mainz <roland.mainz@nrubsig.org>2004-12-17 01:28:14 +0000
committerRoland Mainz <roland.mainz@nrubsig.org>2004-12-17 01:28:14 +0000
commit73fe0ac04ec814590f9e5860659b6cacbf5cb16b (patch)
tree5c7f09ff741d626e233c66f95e2b58d8be7630a0
parentd4a26aea280890079e9898a2da4fccf3e1c9e63f (diff)
xc/programs/Xserver/hw/xfree86/ddc/edid.h
xc/programs/Xserver/hw/xfree86/ddc/interpret_edid.c //bugs.freedesktop.org/show_bug.cgi?id=1490) attachment #1122 (https://bugs.freedesktop.org/attachment.cgi?id=1122): Updating to EDID 1.3. Patch by Jay Cotton <jay.cotton@sun.com> and Egbert Eich <eich@freedesktop.org>.
-rw-r--r--hw/xfree86/ddc/edid.h57
-rw-r--r--hw/xfree86/ddc/interpret_edid.c80
-rw-r--r--hw/xfree86/ddc/print_edid.c73
3 files changed, 172 insertions, 38 deletions
diff --git a/hw/xfree86/ddc/edid.h b/hw/xfree86/ddc/edid.h
index ccf9d9280..e40492c4c 100644
--- a/hw/xfree86/ddc/edid.h
+++ b/hw/xfree86/ddc/edid.h
@@ -11,7 +11,7 @@
*/
#ifndef _EDID_H_
-#define _EDID_H_ 1
+#define _EDID_H_
#include "vdif.h"
@@ -126,7 +126,9 @@
#define SETUP _SETUP(GET(D_INPUT))
#define _SYNC(x) (x & 0x0F)
#define SYNC _SYNC(GET(D_INPUT))
-#define _GAMMA(x) ((x + 100.0)/100.0)
+#define _DFP(x) (x & 0x01)
+#define DFP _DFP(GET(D_INPUT))
+#define _GAMMA(x) (x == 0xff ? 1.0 : ((x + 100.0)/100.0))
#define GAMMA _GAMMA(GET(D_GAMMA))
#define HSIZE_MAX GET(D_HSIZE)
#define VSIZE_MAX GET(D_VSIZE)
@@ -158,20 +160,27 @@
#define T_MANU GET(E_TMANU)
/* extract information from estabished timing section */
+#define _VALID_TIMING(x) ((x[0] != 0x01 && x[1] != 0x01) \
+ && (x[0] != 0x00 && x[1] != 0x00) \
+ && (x[0] != 0x20 && x[1] != 0x20) )
+#define VALID_TIMING _VALID_TIMING(c)
#define _HSIZE1(x) ((x[0] + 31) * 8)
#define HSIZE1 _HSIZE1(c)
#define RATIO(x) ((x[1] & 0xC0) >> 6)
#define RATIO1_1 0
+/* EDID Ver. 1.3 redefined this */
+#define RATIO16_10 RATIO1_1
#define RATIO4_3 1
#define RATIO5_4 2
#define RATIO16_9 3
-#define _VSIZE1(x,y) switch(RATIO(x)){ \
- case RATIO1_1: y = _HSIZE1(x); break; \
+#define _VSIZE1(x,y,r) switch(RATIO(x)){ \
+ case RATIO1_1: y = _HSIZE1(x) * ((v->version>1||v->revision>2) ? 10/16 : 1); \
+ break; \
case RATIO4_3: y = _HSIZE1(x) * 3 / 4; break; \
case RATIO5_4: y = _HSIZE1(x) * 4 / 5; break; \
case RATIO16_9: y = _HSIZE1(x) * 9 / 16; break; \
}
-#define VSIZE1(x) _VSIZE1(c,x)
+#define VSIZE1(x) _VSIZE1(c,x,v)
#define _REFRESH_R(x) (x[1] & 0x3F) + 60
#define REFRESH_R _REFRESH_R(c)
#define _ID_LOW(x) x[0]
@@ -183,7 +192,7 @@
#define NEXT_STD_TIMING _NEXT_STD_TIMING(c)
-/* EDID Ver. > 1.2 */
+/* EDID Ver. >= 1.2 */
#define _IS_MONITOR_DESC(x) (x[0] == 0 && x[1] == 0 && x[2] == 0 && x[4] == 0)
#define IS_MONITOR_DESC _IS_MONITOR_DESC(c)
#define _PIXEL_CLOCK(x) (x[0] + (x[1] << 8)) * 10000
@@ -214,8 +223,10 @@
#define V_BORDER _V_BORDER(c)
#define _INTERLACED(x) ((x[17] & 0x80) >> 7)
#define INTERLACED _INTERLACED(c)
-#define _STEREO(x) ((x[17] & 0x60) >> 6)
+#define _STEREO(x) ((x[17] & 0x60) >> 5)
#define STEREO _STEREO(c)
+#define _STEREO1(x) (x[17] & 0x1)
+#define STEREO1 _STEREO(c)
#define _SYNC_T(x) ((x[17] & 0x18) >> 4)
#define SYNC_T _SYNC_T(c)
#define _MISC(x) ((x[17] & 0x06) >> 2)
@@ -236,6 +247,18 @@
#define MAX_H _MAX_H(c)
#define _MAX_CLOCK(x) x[9]
#define MAX_CLOCK _MAX_CLOCK(c)
+#define _HAVE_2ND_GTF(x) (x[10] == 0x02)
+#define HAVE_2ND_GTF _HAVE_2ND_GTF(c)
+#define _F_2ND_GTF(x) (x[12] * 2)
+#define F_2ND_GTF _F_2ND_GTF(c)
+#define _C_2ND_GTF(x) (x[13] / 2)
+#define C_2ND_GTF _C_2ND_GTF(c)
+#define _M_2ND_GTF(x) (x[14] + (x[15] << 8))
+#define M_2ND_GTF _M_2ND_GTF(c)
+#define _K_2ND_GTF(x) (x[16])
+#define K_2ND_GTF _K_2ND_GTF(c)
+#define _J_2ND_GTF(x) (x[17] / 2)
+#define J_2ND_GTF _J_2ND_GTF(c)
#define MONITOR_NAME 0xFC
#define ADD_COLOR_POINT 0xFB
#define WHITEX F_CC(I_CC((GET(D_BW_LOW)),(GET(D_WHITEX)),2))
@@ -255,6 +278,7 @@
#define _WHITE_GAMMA2(x) _GAMMA(x[14])
#define WHITE_GAMMA2 _WHITE_GAMMA2(c)
#define ADD_STD_TIMINGS 0xFA
+#define ADD_DUMMY 0x10
#define _NEXT_DT_MD_SECTION(x) (x = (x + DET_TIMING_INFO_LEN))
#define NEXT_DT_MD_SECTION _NEXT_DT_MD_SECTION(c)
@@ -264,6 +288,9 @@
/* input type */
#define DIGITAL(x) x
+/* DFP */
+#define DFP1(x) x
+
/* input voltage level */
#define V070 0 /* 0.700V/0.300V */
#define V071 1 /* 0.714V/0.286V */
@@ -297,8 +324,12 @@
/* detailed timing misc */
#define IS_INTERLACED(x) (x)
#define IS_STEREO(x) (x)
-#define IS_RIGHT_ON_SYNC(x) (x & 0x01)
-#define IS_LEFT_ON_SYNC(x) (x & 0x02)
+#define IS_RIGHT_STEREO(x) (x & 0x01)
+#define IS_LEFT_STEREO(x) (x & 0x02)
+#define IS_4WAY_STEREO(x) (x & 0x03)
+#define IS_RIGHT_ON_SYNC(x) IS_RIGHT_STEREO(x)
+#define IS_LEFT_ON_SYNC(x) IS_LEFT_STEREO(x)
+
typedef unsigned int Uint;
typedef unsigned char Uchar;
@@ -321,6 +352,7 @@ struct disp_features {
unsigned int input_voltage:2;
unsigned int input_setup:1;
unsigned int input_sync:5;
+ unsigned int input_dfp:1;
int hsize;
int vsize;
float gamma;
@@ -368,6 +400,7 @@ struct detailed_timings {
unsigned int stereo:2;
unsigned int sync:2;
unsigned int misc:2;
+ unsigned int stereo_1:1;
};
#define DT 0
@@ -377,6 +410,7 @@ struct detailed_timings {
#define DS_RANGES 0xFD
#define DS_WHITE_P 0xFB
#define DS_STD_TIMINGS 0xFA
+#define DS_DUMMY 0x10
struct monitor_ranges {
int min_v;
@@ -384,6 +418,11 @@ struct monitor_ranges {
int min_h;
int max_h;
int max_clock;
+ int gtf_2nd_f;
+ int gtf_2nd_c;
+ int gtf_2nd_m;
+ int gtf_2nd_k;
+ int gtf_2nd_j;
};
struct whitePoints{
diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index d5a791570..36bb10cda 100644
--- a/hw/xfree86/ddc/interpret_edid.c
+++ b/hw/xfree86/ddc/interpret_edid.c
@@ -13,16 +13,21 @@
static void get_vendor_section(Uchar*, struct vendor *);
static void get_version_section(Uchar*, struct edid_version *);
-static void get_display_section(Uchar*, struct disp_features *);
+static void get_display_section(Uchar*, struct disp_features *,
+ struct edid_version *);
static void get_established_timing_section(Uchar*, struct established_timings *);
-static void get_std_timing_section(Uchar*, struct std_timings *);
+static void get_std_timing_section(Uchar*, struct std_timings *,
+ struct edid_version *);
static void get_dt_md_section(Uchar *, struct edid_version *,
struct detailed_monitor_section *det_mon);
static void copy_string(Uchar *, Uchar *);
-static void get_dst_timing_section(Uchar *, struct std_timings *);
+static void get_dst_timing_section(Uchar *, struct std_timings *,
+ struct edid_version *);
static void get_monitor_ranges(Uchar *, struct monitor_ranges *);
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 *);
+
xf86MonPtr
xf86InterpretEDID(int scrnIndex, Uchar *block)
@@ -33,15 +38,24 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
if (! (m = xnfcalloc(sizeof(xf86Monitor),1))) return NULL;
m->scrnIndex = scrnIndex;
m->rawData = block;
+
get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor);
get_version_section(SECTION(VERSION_SECTION,block),&m->ver);
- get_display_section(SECTION(DISPLAY_SECTION,block),&m->features);
+ if (!validate_version(scrnIndex, &m->ver)) goto error;
+ get_display_section(SECTION(DISPLAY_SECTION,block),&m->features,
+ &m->ver);
get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block),
&m->timings1);
- get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2);
+ get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
+ &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);
+
return (m);
+
+ error:
+ xfree(m);
+ return NULL;
}
static void
@@ -66,12 +80,16 @@ get_version_section(Uchar *c, struct edid_version *r)
}
static void
-get_display_section(Uchar *c, struct disp_features *r)
+get_display_section(Uchar *c, struct disp_features *r,
+ struct edid_version *v)
{
r->input_type = INPUT_TYPE;
- r->input_voltage = INPUT_VOLTAGE;
- r->input_setup = SETUP;
- r->input_sync = SYNC;
+ if (!DIGITAL(r->input_type)) {
+ r->input_voltage = INPUT_VOLTAGE;
+ r->input_setup = SETUP;
+ r->input_sync = SYNC;
+ } else if (v->version > 1 || v->revision > 2)
+ r->input_dfp = DFP;
r->hsize = HSIZE_MAX;
r->vsize = VSIZE_MAX;
r->gamma = GAMMA;
@@ -97,15 +115,20 @@ get_established_timing_section(Uchar *c, struct established_timings *r)
}
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)
{
int i;
for (i=0;i<STD_TIMINGS;i++){
- r[i].hsize = HSIZE1;
- VSIZE1(r[i].vsize);
- r[i].refresh = REFRESH_R;
- r[i].id = STD_TIMING_ID;
+ if (VALID_TIMING) {
+ r[i].hsize = HSIZE1;
+ VSIZE1(r[i].vsize);
+ r[i].refresh = REFRESH_R;
+ r[i].id = STD_TIMING_ID;
+ } else {
+ r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0;
+ }
NEXT_STD_TIMING;
}
}
@@ -142,8 +165,11 @@ get_dt_md_section(Uchar *c, struct edid_version *ver,
break;
case ADD_STD_TIMINGS:
det_mon[i].type = DS_STD_TIMINGS;
- get_dst_timing_section(c,det_mon[i].section.std_t);
+ get_dst_timing_section(c,det_mon[i].section.std_t, ver);
break;
+ case ADD_DUMMY:
+ det_mon[i].type = DS_DUMMY;
+ break;
}
} else {
det_mon[i].type = DT;
@@ -165,7 +191,8 @@ copy_string(Uchar *c, Uchar *s)
}
static void
-get_dst_timing_section(Uchar *c, struct std_timings *t)
+get_dst_timing_section(Uchar *c, struct std_timings *t,
+ struct edid_version *v)
{
int j;
c = c + 5;
@@ -188,6 +215,14 @@ get_monitor_ranges(Uchar *c, struct monitor_ranges *r)
r->max_clock = 0;
if(MAX_CLOCK != 0xff) /* is specified? */
r->max_clock = MAX_CLOCK * 10;
+ if (HAVE_2ND_GTF) {
+ r->gtf_2nd_f = F_2ND_GTF;
+ r->gtf_2nd_c = C_2ND_GTF;
+ r->gtf_2nd_m = M_2ND_GTF;
+ r->gtf_2nd_k = K_2ND_GTF;
+ r->gtf_2nd_j = J_2ND_GTF;
+ } else
+ r->gtf_2nd_f = 0;
}
static void
@@ -221,8 +256,21 @@ get_detailed_timing_section(Uchar *c, struct detailed_timings *r)
r->v_border = V_BORDER;
r->interlaced = INTERLACED;
r->stereo = STEREO;
+ r->stereo_1 = STEREO1;
r->sync = SYNC_T;
r->misc = MISC;
}
+static Bool
+validate_version(int scrnIndex, struct edid_version *r)
+{
+ if (r->version != 1)
+ return FALSE;
+ if (r->revision > 3) {
+ xf86DrvMsg(scrnIndex, X_ERROR,"EDID Version 1.%i not yet supported\n",
+ r->revision);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/hw/xfree86/ddc/print_edid.c b/hw/xfree86/ddc/print_edid.c
index 29f418398..8af7702d8 100644
--- a/hw/xfree86/ddc/print_edid.c
+++ b/hw/xfree86/ddc/print_edid.c
@@ -12,7 +12,8 @@
static void print_vendor(int scrnIndex, struct vendor *);
static void print_version(int scrnIndex, struct edid_version *);
-static void print_display(int scrnIndex, struct disp_features *);
+static void print_display(int scrnIndex, struct disp_features *,
+ struct edid_version *);
static void print_established_timings(int scrnIndex,
struct established_timings *);
static void print_std_timings(int scrnIndex, struct std_timings *);
@@ -21,19 +22,23 @@ static void print_detailed_monitor_section(int scrnIndex,
static void print_detailed_timings(int scrnIndex, struct detailed_timings *);
static void print_input_features(int scrnIndex, struct disp_features *);
-static void print_dpms_features(int scrnIndex, struct disp_features *);
+static void print_dpms_features(int scrnIndex, struct disp_features *,
+ struct edid_version *v);
static void print_whitepoint(int scrnIndex, struct disp_features *);
-
+static void print_number_sections(int scrnIndex, int);
+
xf86MonPtr
xf86PrintEDID(xf86MonPtr m)
{
if (!(m)) return NULL;
print_vendor(m->scrnIndex,&m->vendor);
print_version(m->scrnIndex,&m->ver);
- print_display(m->scrnIndex,&m->features);
+ print_display(m->scrnIndex,&m->features, &m->ver);
print_established_timings(m->scrnIndex,&m->timings1);
print_std_timings(m->scrnIndex,m->timings2);
print_detailed_monitor_section(m->scrnIndex,m->det_mon);
+ print_number_sections(m->scrnIndex,m->no_sections);
+
return m;
}
@@ -53,7 +58,8 @@ print_version(int scrnIndex, struct edid_version *c)
}
static void
-print_display(int scrnIndex, struct disp_features *disp)
+print_display(int scrnIndex, struct disp_features *disp,
+ struct edid_version *version)
{
print_input_features(scrnIndex,disp);
xf86DrvMsg(scrnIndex,X_INFO,"Max H-Image Size [cm]: ");
@@ -66,16 +72,18 @@ print_display(int scrnIndex, struct disp_features *disp)
else
xf86ErrorF("V-Size may change\n");
xf86DrvMsg(scrnIndex,X_INFO,"Gamma: %.2f\n", disp->gamma);
- print_dpms_features(scrnIndex,disp);
+ print_dpms_features(scrnIndex,disp,version);
print_whitepoint(scrnIndex,disp);
}
static void
print_input_features(int scrnIndex, struct disp_features *c)
{
- if (DIGITAL(c->input_type))
+ if (DIGITAL(c->input_type)) {
xf86DrvMsg(scrnIndex,X_INFO,"Digital Display Input\n");
- else {
+ if (DFP1(c->input_dfp))
+ xf86DrvMsg(scrnIndex,X_INFO,"DFP 1.x compatible TMDS\n");
+ } else {
xf86DrvMsg(scrnIndex,X_INFO,"Analog Display Input, ");
xf86ErrorF("Input Voltage Level: ");
switch (c->input_voltage){
@@ -111,7 +119,8 @@ print_input_features(int scrnIndex, struct disp_features *c)
}
static void
-print_dpms_features(int scrnIndex, struct disp_features *c)
+print_dpms_features(int scrnIndex, struct disp_features *c,
+ struct edid_version *v)
{
if (c->dpms) {
xf86DrvMsg(scrnIndex,X_INFO,"DPMS capabilities:");
@@ -140,6 +149,10 @@ print_dpms_features(int scrnIndex, struct disp_features *c)
if (PREFERRED_TIMING_MODE(c->msc))
xf86DrvMsg(scrnIndex,X_INFO,
"First detailed timing is preferred mode\n");
+ else if (v->version == 1 && v->revision >= 3)
+ xf86DrvMsg(scrnIndex,X_INFO,
+ "First detailed timing not preferred "
+ "mode in violation of standard!");
if (GFT_SUPPORTED(c->msc))
xf86DrvMsg(scrnIndex,X_INFO,
"GTF timings supported\n");
@@ -234,7 +247,15 @@ print_detailed_monitor_section(int scrnIndex,
if (m[i].section.ranges.max_clock != 0)
xf86ErrorF(" PixClock max %i MHz\n",m[i].section.ranges.max_clock);
else
- xf86DrvMsg(scrnIndex,X_INFO,"\n");
+ xf86ErrorF("\n");
+ if (m[i].section.ranges.gtf_2nd_f > 0)
+ xf86DrvMsg(scrnIndex,X_INFO," 2nd GTF parameters: f: %i kHz "
+ "c: %i m: %i k %i j %i\n",
+ m[i].section.ranges.gtf_2nd_f,
+ m[i].section.ranges.gtf_2nd_c,
+ m[i].section.ranges.gtf_2nd_m,
+ m[i].section.ranges.gtf_2nd_k,
+ m[i].section.ranges.gtf_2nd_j);
break;
case DS_STD_TIMINGS:
for (j = 0; j<5; j++)
@@ -252,6 +273,9 @@ print_detailed_monitor_section(int scrnIndex,
m[i].section.wp[j].white_y,
m[i].section.wp[j].white_gamma);
break;
+ case DS_DUMMY:
+ default:
+ break;
}
}
}
@@ -278,9 +302,32 @@ print_detailed_timings(int scrnIndex, struct detailed_timings *t)
xf86ErrorF("v_border: %i\n",t->v_border);
if (IS_STEREO(t->stereo)) {
xf86DrvMsg(scrnIndex,X_INFO,"Stereo: ");
- if (IS_RIGHT_ON_SYNC(t->stereo))
- xf86ErrorF("right channel on sync\n");
- else xf86ErrorF("right channel on sync\n");
+ if (IS_RIGHT_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("right channel on sync\n");
+ else
+ xf86ErrorF("left channel on sync\n");
+ } else if (IS_LEFT_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("right channel on even line\n");
+ else
+ xf86ErrorF("left channel on evel line\n");
+ }
+ if (IS_4WAY_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("4-way interleaved\n");
+ else
+ xf86ErrorF("side-by-side interleaved");
+ }
}
}
}
+
+static void
+print_number_sections(int scrnIndex, int num)
+{
+ if (num)
+ xf86DrvMsg(scrnIndex,X_INFO,"Number of EDID sections to follow: %i\n",
+ num);
+}
+