diff options
author | Roland Mainz <roland.mainz@nrubsig.org> | 2004-12-17 01:28:14 +0000 |
---|---|---|
committer | Roland Mainz <roland.mainz@nrubsig.org> | 2004-12-17 01:28:14 +0000 |
commit | 73fe0ac04ec814590f9e5860659b6cacbf5cb16b (patch) | |
tree | 5c7f09ff741d626e233c66f95e2b58d8be7630a0 | |
parent | d4a26aea280890079e9898a2da4fccf3e1c9e63f (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.h | 57 | ||||
-rw-r--r-- | hw/xfree86/ddc/interpret_edid.c | 80 | ||||
-rw-r--r-- | hw/xfree86/ddc/print_edid.c | 73 |
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); +} + |