diff options
Diffstat (limited to 'xorg-server/hw/xfree86/ddc')
-rw-r--r-- | xorg-server/hw/xfree86/ddc/ddc.c | 351 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/ddcProperty.c | 31 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/edid.h | 327 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/interpret_edid.c | 1399 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/print_edid.c | 644 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/xf86DDC.h | 64 |
6 files changed, 1444 insertions, 1372 deletions
diff --git a/xorg-server/hw/xfree86/ddc/ddc.c b/xorg-server/hw/xfree86/ddc/ddc.c index 179f42ccd..a1281d735 100644 --- a/xorg-server/hw/xfree86/ddc/ddc.c +++ b/xorg-server/hw/xfree86/ddc/ddc.c @@ -29,10 +29,10 @@ typedef enum { } DDCOpts; static const OptionInfoRec DDCOptions[] = { - { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE }, + {DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE}, + {DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE}, + {DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, OPTV_NONE, {0}, FALSE}, }; /* DDC1 */ @@ -41,19 +41,20 @@ static int find_start(unsigned int *ptr) { unsigned int comp[9], test[9]; - int i,j; - - for (i=0;i<9;i++){ - comp[i] = *(ptr++); - test[i] = 1; + int i, j; + + for (i = 0; i < 9; i++) { + comp[i] = *(ptr++); + test[i] = 1; } - for (i=0;i<127;i++){ - for (j=0;j<9;j++){ - test[j] = test[j] & !(comp[j] ^ *(ptr++)); - } + for (i = 0; i < 127; i++) { + for (j = 0; j < 9; j++) { + test[j] = test[j] & !(comp[j] ^ *(ptr++)); + } } - for (i=0;i<9;i++) - if (test[i]) return i+1; + for (i = 0; i < 9; i++) + if (test[i]) + return i + 1; return -1; } @@ -61,21 +62,26 @@ static unsigned char * find_header(unsigned char *block) { unsigned char *ptr, *head_ptr, *end; - unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; - + unsigned char header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + ptr = block; end = block + EDID1_LEN; - while (ptr<end) { - int i; - head_ptr = ptr; - for (i=0;i<8;i++){ - if (header[i] != *(head_ptr++)) break; - if (head_ptr == end) head_ptr = block; - } - if (i==8) break; - ptr++; + while (ptr < end) { + int i; + + head_ptr = ptr; + for (i = 0; i < 8; i++) { + if (header[i] != *(head_ptr++)) + break; + if (head_ptr == end) + head_ptr = block; + } + if (i == 8) + break; + ptr++; } - if (ptr == end) return NULL; + if (ptr == end) + return NULL; return ptr; } @@ -87,15 +93,18 @@ resort(unsigned char *s_block) s_end = s_block + EDID1_LEN; d_new = malloc(EDID1_LEN); - if (!d_new) return NULL; + if (!d_new) + return NULL; d_end = d_new + EDID1_LEN; s_ptr = find_header(s_block); - if (!s_ptr) return NULL; - for (d_ptr=d_new;d_ptr<d_end;d_ptr++){ - tmp = *(s_ptr++); - *d_ptr = tmp; - if (s_ptr == s_end) s_ptr = s_block; + if (!s_ptr) + return NULL; + for (d_ptr = d_new; d_ptr < d_end; d_ptr++) { + tmp = *(s_ptr++); + *d_ptr = tmp; + if (s_ptr == s_end) + s_ptr = s_block; } free(s_block); return d_new; @@ -106,21 +115,24 @@ DDC_checksum(const unsigned char *block, int len) { int i, result = 0; int not_null = 0; - - for (i=0;i<len;i++) { - not_null |= block[i]; - result += block[i]; + + for (i = 0; i < len; i++) { + not_null |= block[i]; + result += block[i]; } - + #ifdef DEBUG - if (result & 0xFF) ErrorF("DDC checksum not correct\n"); - if (!not_null) ErrorF("DDC read all Null\n"); + if (result & 0xFF) + ErrorF("DDC checksum not correct\n"); + if (!not_null) + ErrorF("DDC read all Null\n"); #endif /* catch the trivial case where all bytes are 0 */ - if (!not_null) return 1; + if (!not_null) + return 1; - return result&0xFF; + return result & 0xFF; } static unsigned char * @@ -129,64 +141,73 @@ GetEDID_DDC1(unsigned int *s_ptr) unsigned char *d_block, *d_pos; unsigned int *s_pos, *s_end; int s_start; - int i,j; + int i, j; + s_start = find_start(s_ptr); - if (s_start==-1) return NULL; + if (s_start == -1) + return NULL; s_end = s_ptr + NUM; s_pos = s_ptr + s_start; - d_block=malloc(EDID1_LEN); - if (!d_block) return NULL; + d_block = malloc(EDID1_LEN); + if (!d_block) + return NULL; d_pos = d_block; - for (i=0;i<EDID1_LEN;i++) { - for (j=0;j<8;j++) { - *d_pos <<= 1; - if (*s_pos) { - *d_pos |= 0x01; - } - s_pos++; if (s_pos == s_end) s_pos=s_ptr; - }; - s_pos++; if (s_pos == s_end) s_pos=s_ptr; - d_pos++; + for (i = 0; i < EDID1_LEN; i++) { + for (j = 0; j < 8; j++) { + *d_pos <<= 1; + if (*s_pos) { + *d_pos |= 0x01; + } + s_pos++; + if (s_pos == s_end) + s_pos = s_ptr; + }; + s_pos++; + if (s_pos == s_end) + s_pos = s_ptr; + d_pos++; } free(s_ptr); - if (d_block && DDC_checksum(d_block,EDID1_LEN)) { - free(d_block); - return NULL; + if (d_block && DDC_checksum(d_block, EDID1_LEN)) { + free(d_block); + return NULL; } return (resort(d_block)); } /* fetch entire EDID record; DDC bit needs to be masked */ -static unsigned int * +static unsigned int * FetchEDID_DDC1(register ScrnInfoPtr pScrn, - register unsigned int (*read_DDC)(ScrnInfoPtr)) + register unsigned int (*read_DDC) (ScrnInfoPtr)) { int count = NUM; unsigned int *ptr, *xp; - ptr=xp=malloc(sizeof(int)*NUM); + ptr = xp = malloc(sizeof(int) * NUM); - if (!ptr) return NULL; + if (!ptr) + return NULL; do { - /* wait for next retrace */ - *xp = read_DDC(pScrn); - xp++; - } while(--count); + /* wait for next retrace */ + *xp = read_DDC(pScrn); + xp++; + } while (--count); return ptr; } /* test if DDC1 return 0 if not */ static Bool -TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr)) +TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC) (ScrnInfoPtr)) { int old, count; old = read_DDC(pScrn); count = HEADER * BITS_PER_BYTE; do { - /* wait for next retrace */ - if (old != read_DDC(pScrn)) break; - } while(count--); + /* wait for next retrace */ + if (old != read_DDC(pScrn)) + break; + } while (count--); return count; } @@ -196,29 +217,31 @@ TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr)) * function; it will also decide if we need to reread it */ static unsigned char * -EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, - unsigned int (*read_DDC)(ScrnInfoPtr)) +EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, + unsigned int (*read_DDC) (ScrnInfoPtr)) { unsigned char *EDID_block = NULL; int count = RETRIES; - if (!read_DDC) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "chipset doesn't support DDC1\n"); - return NULL; + if (!read_DDC) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "chipset doesn't support DDC1\n"); + return NULL; }; - if (TestDDC1(pScrn,read_DDC)==-1) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); - return NULL; + if (TestDDC1(pScrn, read_DDC) == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); + return NULL; }; - if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); + if (DDCSpeed) + DDCSpeed(pScrn, DDC_FAST); do { - EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); - count --; + EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn, read_DDC)); + count--; } while (!EDID_block && count); - if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); + if (DDCSpeed) + DDCSpeed(pScrn, DDC_SLOW); return EDID_block; } @@ -235,40 +258,42 @@ EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, * @return NULL if no monitor attached or failure to interpret the EDID. */ xf86MonPtr -xf86DoEDID_DDC1(int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, - unsigned int (*DDC1Read)(ScrnInfoPtr)) +xf86DoEDID_DDC1(int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, + unsigned int (*DDC1Read) (ScrnInfoPtr)) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; unsigned char *EDID_block = NULL; xf86MonPtr tmp = NULL; + /* Default DDC and DDC1 to enabled. */ Bool noddc = FALSE, noddc1 = FALSE; OptionInfoPtr options; options = xnfalloc(sizeof(DDCOptions)); - (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + (void) memcpy(options, DDCOptions, sizeof(DDCOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); free(options); - + if (noddc || noddc1) - return NULL; - + return NULL; + OsBlockSignals(); - EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); + EDID_block = EDIDRead_DDC1(pScrn, DDC1SetSpeed, DDC1Read); OsReleaseSignals(); - if (EDID_block){ - tmp = xf86InterpretEDID(scrnIndex,EDID_block); + if (EDID_block) { + tmp = xf86InterpretEDID(scrnIndex, EDID_block); } #ifdef DEBUG - else ErrorF("No EDID block returned\n"); + else + ErrorF("No EDID block returned\n"); if (!tmp) - ErrorF("Cannot interpret EDID block\n"); + ErrorF("Cannot interpret EDID block\n"); #endif - return tmp; + return tmp; } /* DDC2 */ @@ -279,19 +304,19 @@ DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) I2CDevPtr dev = NULL; if (!(dev = xf86I2CFindDev(pBus, address))) { - dev = xf86CreateI2CDevRec(); - dev->DevName = name; - dev->SlaveAddr = address; - dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ - dev->StartTimeout = 550; - dev->BitTimeout = 40; - dev->AcknTimeout = 40; - - dev->pI2CBus = pBus; - if (!xf86I2CDevInit(dev)) { - xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); - return NULL; - } + dev = xf86CreateI2CDevRec(); + dev->DevName = name; + dev->SlaveAddr = address; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->AcknTimeout = 40; + + dev->pI2CBus = pBus; + if (!xf86I2CDevInit(dev)) { + xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); + return NULL; + } } return dev; @@ -307,10 +332,10 @@ DDC2Init(int scrnIndex, I2CBusPtr pBus) * miss things. */ pBus->RiseFallTime = 20; - + dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); if (xf86I2CProbeAddress(pBus, 0x0060)) - DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); + DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); return dev; } @@ -328,39 +353,39 @@ DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) unsigned char W_Buffer[1]; int i, segment; I2CDevPtr seg; - void (*stop)(I2CDevPtr); + void (*stop) (I2CDevPtr); for (i = 0; i < RETRIES; i++) { - /* Stop bits reset the segment pointer to 0, so be careful here. */ - segment = block >> 1; - if (segment) { - Bool b; - - if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) - return FALSE; - - W_Buffer[0] = segment; - - stop = dev->pI2CBus->I2CStop; - dev->pI2CBus->I2CStop = EEDIDStop; - - b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); - - dev->pI2CBus->I2CStop = stop; - if (!b) { - dev->pI2CBus->I2CStop(dev); - continue; - } - } - - W_Buffer[0] = (block & 0x01) * EDID1_LEN; - - if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { - if (!DDC_checksum(R_Buffer, EDID1_LEN)) - return TRUE; - } + /* Stop bits reset the segment pointer to 0, so be careful here. */ + segment = block >> 1; + if (segment) { + Bool b; + + if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) + return FALSE; + + W_Buffer[0] = segment; + + stop = dev->pI2CBus->I2CStop; + dev->pI2CBus->I2CStop = EEDIDStop; + + b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); + + dev->pI2CBus->I2CStop = stop; + if (!b) { + dev->pI2CBus->I2CStop(dev); + continue; + } + } + + W_Buffer[0] = (block & 0x01) * EDID1_LEN; + + if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { + if (!DDC_checksum(R_Buffer, EDID1_LEN)) + return TRUE; + } } - + return FALSE; } @@ -384,13 +409,14 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) unsigned char *EDID_block = NULL; xf86MonPtr tmp = NULL; I2CDevPtr dev = NULL; + /* Default DDC and DDC2 to enabled. */ Bool noddc = FALSE, noddc2 = FALSE; OptionInfoPtr options; options = malloc(sizeof(DDCOptions)); if (!options) - return NULL; + return NULL; memcpy(options, DDCOptions, sizeof(DDCOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); @@ -399,30 +425,30 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) free(options); if (noddc || noddc2) - return NULL; + return NULL; if (!(dev = DDC2Init(scrnIndex, pBus))) - return NULL; + return NULL; EDID_block = calloc(1, EDID1_LEN); if (!EDID_block) - return NULL; + return NULL; if (DDC2Read(dev, 0, EDID_block)) { - int i, n = EDID_block[0x7e]; + int i, n = EDID_block[0x7e]; - if (complete && n) { - EDID_block = realloc(EDID_block, EDID1_LEN * (1+n)); + if (complete && n) { + EDID_block = realloc(EDID_block, EDID1_LEN * (1 + n)); - for (i = 0; i < n; i++) - DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); - } + for (i = 0; i < n; i++) + DDC2Read(dev, i + 1, EDID_block + (EDID1_LEN * (1 + i))); + } - tmp = xf86InterpretEEDID(scrnIndex, EDID_block); + tmp = xf86InterpretEEDID(scrnIndex, EDID_block); } if (tmp && complete) - tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; + tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; return tmp; } @@ -469,13 +495,14 @@ xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) unsigned char *did = NULL; xf86MonPtr tmp = NULL; I2CDevPtr dev = NULL; + /* Default DDC and DDC2 to enabled. */ Bool noddc = FALSE, noddc2 = FALSE; OptionInfoPtr options; options = malloc(sizeof(DDCOptions)); if (!options) - return NULL; + return NULL; memcpy(options, DDCOptions, sizeof(DDCOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); @@ -484,19 +511,19 @@ xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) free(options); if (noddc || noddc2) - return NULL; + return NULL; if (!(dev = DDC2Init(scrnIndex, pBus))) - return NULL; + return NULL; if ((did = DDC2ReadDisplayID())) { - tmp = calloc(1, sizeof(*tmp)); - if (!tmp) - return NULL; + tmp = calloc(1, sizeof(*tmp)); + if (!tmp) + return NULL; - tmp->scrnIndex = scrnIndex; - tmp->flags |= MONITOR_DISPLAYID; - tmp->rawData = did; + tmp->scrnIndex = scrnIndex; + tmp->flags |= MONITOR_DISPLAYID; + tmp->rawData = did; } return tmp; diff --git a/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c index c3aced5c2..fc63f0e8a 100644 --- a/xorg-server/hw/xfree86/ddc/ddcProperty.c +++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c @@ -40,8 +40,8 @@ edidMakeAtom(int i, const char *name, CARD8 *data, int size) Atom atom; unsigned char *atom_data; - if (!(atom_data = malloc(size*sizeof(CARD8)))) - return; + if (!(atom_data = malloc(size * sizeof(CARD8)))) + return; atom = MakeAtom(name, strlen(name), TRUE); memcpy(atom_data, data, size); @@ -54,17 +54,19 @@ addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) int scrnIndex = pScrn->scrnIndex; if (DDC->flags & MONITOR_DISPLAYID) { - /* Don't bother, use RANDR already */ - return; - } else if (DDC->ver.version == 1) { - int size = 128 + - (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); + /* Don't bother, use RANDR already */ + return; + } + else if (DDC->ver.version == 1) { + int size = 128 + + (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); - edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); - } else { - xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", - DDC->ver.version, DDC->ver.revision); - return; + edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); + } + else { + xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", + DDC->ver.version, DDC->ver.revision); + return; } } @@ -74,10 +76,9 @@ xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) if (!pScrn || !pScrn->monitor || !DDC) return FALSE; - if (DDC->flags & MONITOR_DISPLAYID) - ; + if (DDC->flags & MONITOR_DISPLAYID); else - xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); + xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); addRootWindowProperties(pScrn, DDC); diff --git a/xorg-server/hw/xfree86/ddc/edid.h b/xorg-server/hw/xfree86/ddc/edid.h index cc4bd02ea..91565a2cf 100644 --- a/xorg-server/hw/xfree86/ddc/edid.h +++ b/xorg-server/hw/xfree86/ddc/edid.h @@ -10,12 +10,12 @@ */ #ifndef _EDID_H_ -#define _EDID_H_ +#define _EDID_H_ #include <X11/Xmd.h> #ifndef _X_EXPORT -# include <X11/Xfuncproto.h> +#include <X11/Xfuncproto.h> #endif /* read complete EDID record */ @@ -72,7 +72,7 @@ #define E_T1 0 #define E_T2 (E_T1 + 1) #define E_TMANU (E_T2 + 1) -#define E_TIMING_LENGTH (E_TMANU + 1) +#define E_TIMING_LENGTH (E_TMANU + 1) /* non predefined standard timings supported by display */ #define STD_TIMING_SECTION (ESTABLISHED_TIMING_SECTION + E_TIMING_LENGTH) @@ -90,13 +90,12 @@ /* number of EDID sections to follow */ #define NO_EDID (DET_TIMING_SECTION + DET_TIMING_LENGTH) /* one byte checksum */ -#define CHECKSUM (NO_EDID + 1) +#define CHECKSUM (NO_EDID + 1) #if (CHECKSUM != (EDID1_LEN - 1)) -# error "EDID1 length != 128!" +#error "EDID1 length != 128!" #endif - #define SECTION(x,y) (Uchar *)(x + y) #define GET_ARRAY(y) ((Uchar *)(c + y)) #define GET(y) *(Uchar *)(c + y) @@ -146,7 +145,6 @@ #define _MSC(x) (x & 0x7) #define MSC _MSC(GET(FEAT_S)) - /* color characteristics */ #define CC_L(x,y) ((x & (0x03 << y)) >> y) #define CC_H(x) (x << 2) @@ -198,7 +196,6 @@ #define _NEXT_STD_TIMING(x) (x = (x + STD_TIMING_INFO_LEN)) #define NEXT_STD_TIMING _NEXT_STD_TIMING(c) - /* EDID Ver. >= 1.2 */ /** * Returns true if the pointer is the start of a monitor descriptor block @@ -264,7 +261,7 @@ #define _MAX_H(x) x[8] #define MAX_H (_MAX_H(c) + _MAX_H_OFFSET(c)) #define _MAX_CLOCK(x) x[9] -#define MAX_CLOCK _MAX_CLOCK(c) +#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) @@ -325,7 +322,7 @@ #define WHITEX2 _WHITEX_ADD(c,12) #define WHITEY2 _WHITEY_ADD(c,12) #define _WHITE_GAMMA1(x) _GAMMA(x[9]) -#define WHITE_GAMMA1 _WHITE_GAMMA1(c) +#define WHITE_GAMMA1 _WHITE_GAMMA1(c) #define _WHITE_GAMMA2(x) _GAMMA(x[14]) #define WHITE_GAMMA2 _WHITE_GAMMA2(c) #define ADD_STD_TIMINGS 0xFA @@ -337,7 +334,7 @@ #define _NEXT_DT_MD_SECTION(x) (x = (x + DET_TIMING_INFO_LEN)) #define NEXT_DT_MD_SECTION _NEXT_DT_MD_SECTION(c) -#endif /* _PARSE_EDID_ */ +#endif /* _PARSE_EDID_ */ /* input type */ #define DIGITAL(x) x @@ -346,10 +343,10 @@ #define DFP1(x) x /* input voltage level */ -#define V070 0 /* 0.700V/0.300V */ -#define V071 1 /* 0.714V/0.286V */ -#define V100 2 /* 1.000V/0.400V */ -#define V007 3 /* 0.700V/0.000V */ +#define V070 0 /* 0.700V/0.300V */ +#define V071 1 /* 0.714V/0.286V */ +#define V100 2 /* 1.000V/0.400V */ +#define V007 3 /* 0.700V/0.000V */ /* Signal level setup */ #define SIG_SETUP(x) (x) @@ -382,88 +379,87 @@ #define CVT_SUPPORTED(x) (x & 0x1) /* detailed timing misc */ -#define IS_INTERLACED(x) (x) -#define IS_STEREO(x) (x) +#define IS_INTERLACED(x) (x) +#define IS_STEREO(x) (x) #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; struct vendor { - char name[4]; - int prod_id; - Uint serial; - int week; - int year; + char name[4]; + int prod_id; + Uint serial; + int week; + int year; }; struct edid_version { - int version; - int revision; + int version; + int revision; }; struct disp_features { - unsigned int input_type:1; - unsigned int input_voltage:2; - unsigned int input_setup:1; - unsigned int input_sync:5; - unsigned int input_dfp:1; - unsigned int input_bpc:3; - unsigned int input_interface:4; - /* 15 bit hole */ - int hsize; - int vsize; - float gamma; - unsigned int dpms:3; - unsigned int display_type:2; - unsigned int msc:3; - float redx; - float redy; - float greenx; - float greeny; - float bluex; - float bluey; - float whitex; - float whitey; + unsigned int input_type:1; + unsigned int input_voltage:2; + unsigned int input_setup:1; + unsigned int input_sync:5; + unsigned int input_dfp:1; + unsigned int input_bpc:3; + unsigned int input_interface:4; + /* 15 bit hole */ + int hsize; + int vsize; + float gamma; + unsigned int dpms:3; + unsigned int display_type:2; + unsigned int msc:3; + float redx; + float redy; + float greenx; + float greeny; + float bluex; + float bluey; + float whitex; + float whitey; }; struct established_timings { - Uchar t1; - Uchar t2; - Uchar t_manu; + Uchar t1; + Uchar t2; + Uchar t_manu; }; struct std_timings { - int hsize; - int vsize; - int refresh; - CARD16 id; + int hsize; + int vsize; + int refresh; + CARD16 id; }; struct detailed_timings { - int clock; - int h_active; - int h_blanking; - int v_active; - int v_blanking; - int h_sync_off; - int h_sync_width; - int v_sync_off; - int v_sync_width; - int h_size; - int v_size; - int h_border; - int v_border; - unsigned int interlaced:1; - unsigned int stereo:2; - unsigned int sync:2; - unsigned int misc:2; - unsigned int stereo_1:1; + int clock; + int h_active; + int h_blanking; + int v_active; + int v_blanking; + int h_sync_off; + int h_sync_width; + int v_sync_off; + int v_sync_width; + int h_size; + int v_size; + int h_border; + int v_border; + unsigned int interlaced:1; + unsigned int stereo:2; + unsigned int sync:2; + unsigned int misc:2; + unsigned int stereo_1:1; }; #define DT 0 @@ -477,35 +473,35 @@ struct detailed_timings { #define DS_CVT 0xF8 #define DS_EST_III 0xF7 #define DS_DUMMY 0x10 -#define DS_UNKOWN 0x100 /* type is an int */ +#define DS_UNKOWN 0x100 /* type is an int */ #define DS_VENDOR 0x101 #define DS_VENDOR_MAX 0x110 struct monitor_ranges { - int min_v; - int max_v; - int min_h; - int max_h; - int max_clock; /* in mhz */ - int gtf_2nd_f; - int gtf_2nd_c; - int gtf_2nd_m; - int gtf_2nd_k; - int gtf_2nd_j; - int max_clock_khz; - int maxwidth; /* in pixels */ - char supported_aspect; - char preferred_aspect; - char supported_blanking; - char supported_scaling; - int preferred_refresh; /* in hz */ + int min_v; + int max_v; + int min_h; + int max_h; + int max_clock; /* in mhz */ + int gtf_2nd_f; + int gtf_2nd_c; + int gtf_2nd_m; + int gtf_2nd_k; + int gtf_2nd_j; + int max_clock_khz; + int maxwidth; /* in pixels */ + char supported_aspect; + char preferred_aspect; + char supported_blanking; + char supported_scaling; + int preferred_refresh; /* in hz */ }; -struct whitePoints{ - int index; - float white_x; - float white_y; - float white_gamma; +struct whitePoints { + int index; + float white_x; + float white_y; + float white_gamma; }; struct cvt_timings { @@ -522,19 +518,19 @@ struct cvt_timings { * literally like serial and friends. */ struct detailed_monitor_section { - int type; - union { - struct detailed_timings d_timings; /* 56 */ - Uchar serial[13]; - Uchar ascii_data[13]; - Uchar name[13]; - struct monitor_ranges ranges; /* 56 */ - struct std_timings std_t[5]; /* 80 */ - struct whitePoints wp[2]; /* 32 */ - /* color management data */ - struct cvt_timings cvt[4]; /* 64 */ - Uchar est_iii[6]; /* 6 */ - } section; /* max: 80 */ + int type; + union { + struct detailed_timings d_timings; /* 56 */ + Uchar serial[13]; + Uchar ascii_data[13]; + Uchar name[13]; + struct monitor_ranges ranges; /* 56 */ + struct std_timings std_t[5]; /* 80 */ + struct whitePoints wp[2]; /* 32 */ + /* color management data */ + struct cvt_timings cvt[4]; /* 64 */ + Uchar est_iii[6]; /* 6 */ + } section; /* max: 80 */ }; /* flags */ @@ -548,16 +544,16 @@ struct detailed_monitor_section { * are meaningful. For EDID, they all are. */ typedef struct { - int scrnIndex; - struct vendor vendor; - struct edid_version ver; - struct disp_features features; - struct established_timings timings1; - struct std_timings timings2[8]; - struct detailed_monitor_section det_mon[4]; - unsigned long flags; - int no_sections; - Uchar *rawData; + int scrnIndex; + struct vendor vendor; + struct edid_version ver; + struct disp_features features; + struct established_timings timings1; + struct std_timings timings2[8]; + struct detailed_monitor_section det_mon[4]; + unsigned long flags; + int no_sections; + Uchar *rawData; } xf86Monitor, *xf86MonPtr; extern _X_EXPORT xf86MonPtr ConfiguredMonitor; @@ -590,73 +586,72 @@ extern _X_EXPORT xf86MonPtr ConfiguredMonitor; #define HDMI_MAX_TMDS_UNIT (5000) struct cea_video_block { - Uchar video_code; + Uchar video_code; }; struct cea_audio_block_descriptor { - Uchar audio_code[3]; + Uchar audio_code[3]; }; struct cea_audio_block { - struct cea_audio_block_descriptor descriptor[10]; + struct cea_audio_block_descriptor descriptor[10]; }; struct cea_vendor_block_hdmi { - Uchar portB:4; - Uchar portA:4; - Uchar portD:4; - Uchar portC:4; - Uchar support_flags; - Uchar max_tmds_clock; - Uchar latency_present; - Uchar video_latency; - Uchar audio_latency; - Uchar interlaced_video_latency; - Uchar interlaced_audio_latency; + Uchar portB:4; + Uchar portA:4; + Uchar portD:4; + Uchar portC:4; + Uchar support_flags; + Uchar max_tmds_clock; + Uchar latency_present; + Uchar video_latency; + Uchar audio_latency; + Uchar interlaced_video_latency; + Uchar interlaced_audio_latency; }; struct cea_vendor_block { - unsigned char ieee_id[3]; - union { - struct cea_vendor_block_hdmi hdmi; - /* any other vendor blocks we know about */ - }; + unsigned char ieee_id[3]; + union { + struct cea_vendor_block_hdmi hdmi; + /* any other vendor blocks we know about */ + }; }; -struct cea_speaker_block -{ - Uchar FLR:1; - Uchar LFE:1; - Uchar FC:1; - Uchar RLR:1; - Uchar RC:1; - Uchar FLRC:1; - Uchar RLRC:1; - Uchar FLRW:1; - Uchar FLRH:1; - Uchar TC:1; - Uchar FCH:1; - Uchar Resv:5; - Uchar ResvByte; +struct cea_speaker_block { + Uchar FLR:1; + Uchar LFE:1; + Uchar FC:1; + Uchar RLR:1; + Uchar RC:1; + Uchar FLRC:1; + Uchar RLRC:1; + Uchar FLRW:1; + Uchar FLRH:1; + Uchar TC:1; + Uchar FCH:1; + Uchar Resv:5; + Uchar ResvByte; }; struct cea_data_block { - Uchar len:5; - Uchar tag:3; - union{ - struct cea_video_block video; - struct cea_audio_block audio; - struct cea_vendor_block vendor; - struct cea_speaker_block speaker; - }u; + Uchar len:5; + Uchar tag:3; + union { + struct cea_video_block video; + struct cea_audio_block audio; + struct cea_vendor_block vendor; + struct cea_speaker_block speaker; + } u; }; struct cea_ext_body { - Uchar tag; - Uchar rev; - Uchar dt_offset; - Uchar flags; - struct cea_data_block data_collection; + Uchar tag; + Uchar rev; + Uchar dt_offset; + Uchar flags; + struct cea_data_block data_collection; }; -#endif /* _EDID_H_ */ +#endif /* _EDID_H_ */ diff --git a/xorg-server/hw/xfree86/ddc/interpret_edid.c b/xorg-server/hw/xfree86/ddc/interpret_edid.c index d1001a21f..882a6b201 100644 --- a/xorg-server/hw/xfree86/ddc/interpret_edid.c +++ b/xorg-server/hw/xfree86/ddc/interpret_edid.c @@ -1,685 +1,714 @@ -/*
- * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
- * Copyright 2007 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * interpret_edid.c: interpret a primary EDID block
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "misc.h"
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#define _PARSE_EDID_
-#include "xf86DDC.h"
-#include <string.h>
-
-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 *,
- struct edid_version *);
-static void get_established_timing_section(Uchar*, struct established_timings *);
-static void get_std_timing_section(Uchar*, struct std_timings *,
- struct edid_version *);
-static void fetch_detailed_block(Uchar *c, struct edid_version *ver,
- struct detailed_monitor_section *det_mon);
-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 *,
- 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 *);
-
-static void
-find_ranges_section(struct detailed_monitor_section *det, void *ranges)
-{
- if (det->type == DS_RANGES && det->section.ranges.max_clock)
- *(struct monitor_ranges **)ranges = &det->section.ranges;
-}
-
-static void
-find_max_detailed_clock(struct detailed_monitor_section *det, void *ret)
-{
- if (det->type == DT) {
- *(int *)ret = max(*((int *)ret),
- det->section.d_timings.clock);
- }
-}
-
-static void
-handle_edid_quirks(xf86MonPtr m)
-{
- struct monitor_ranges *ranges = NULL;
-
- /*
- * max_clock is only encoded in EDID in tens of MHz, so occasionally we
- * find a monitor claiming a max of 160 with a mode requiring 162, or
- * similar. Strictly we should refuse to round up too far, but let's
- * see how well this works.
- */
-
- /* Try to find Monitor Range and max clock, then re-set range value*/
- xf86ForEachDetailedBlock(m, find_ranges_section, &ranges);
- if (ranges && ranges->max_clock) {
- int clock = 0;
- xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock);
- if (clock && (ranges->max_clock * 1e6 < clock)) {
- xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max "
- "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock);
- ranges->max_clock = (clock+999999)/1e6;
- }
- }
-}
-
-struct det_hv_parameter {
- int real_hsize;
- int real_vsize;
- float target_aspect;
-};
-
-static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon,
- void *data)
-{
- struct det_hv_parameter *p = (struct det_hv_parameter *)data;
- float timing_aspect;
-
- if (det_mon->type == DT) {
- struct detailed_timings *timing;
- timing = &det_mon->section.d_timings;
-
- if (!timing->v_size)
- return;
-
- timing_aspect = (float)timing->h_size / timing->v_size;
- if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) {
- p->real_hsize = max(p->real_hsize, timing->h_size);
- p->real_vsize = max(p->real_vsize, timing->v_size);
- }
- }
-}
-
-static void encode_aspect_ratio(xf86MonPtr m)
-{
- /*
- * some monitors encode the aspect ratio instead of the physical size.
- * try to find the largest detailed timing that matches that aspect
- * ratio and use that to fill in the feature section.
- */
- if ((m->features.hsize == 16 && m->features.vsize == 9) ||
- (m->features.hsize == 16 && m->features.vsize == 10) ||
- (m->features.hsize == 4 && m->features.vsize == 3) ||
- (m->features.hsize == 5 && m->features.vsize == 4)) {
-
- struct det_hv_parameter p;
- p.real_hsize = 0;
- p.real_vsize = 0;
- p.target_aspect = (float)m->features.hsize /m->features.vsize;
-
- xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p);
-
- if (!p.real_hsize || !p.real_vsize) {
- m->features.hsize = m->features.vsize = 0;
- } else if ((m->features.hsize * 10 == p.real_hsize) &&
- (m->features.vsize * 10 == p.real_vsize)) {
- /* exact match is just unlikely, should do a better check though */
- m->features.hsize = m->features.vsize = 0;
- } else {
- /* convert mm to cm */
- m->features.hsize = (p.real_hsize + 5) / 10;
- m->features.vsize = (p.real_vsize + 5) / 10;
- }
-
- xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n",
- m->features.hsize, m->features.vsize);
- }
-}
-
-xf86MonPtr
-xf86InterpretEDID(int scrnIndex, Uchar *block)
-{
- xf86MonPtr m;
-
- if (!block) return NULL;
- 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);
- 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,
- &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);
-
- handle_edid_quirks(m);
- encode_aspect_ratio(m);
-
- return m;
-
- error:
- free(m);
- return NULL;
-}
-
-static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon,
- struct detailed_monitor_section *det_mon)
-{
- int dt_num;
- int dt_offset = ((struct cea_ext_body *)blk)->dt_offset;
-
- dt_num = 0;
-
- if (dt_offset < CEA_EXT_MIN_DATA_OFFSET)
- return dt_num;
-
- for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) &&
- dt_num < CEA_EXT_DET_TIMING_NUM;
- _NEXT_DT_MD_SECTION(dt_offset)) {
-
- fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num);
- dt_num = dt_num + 1 ;
- }
-
- return dt_num;
-}
-
-static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon,
- handle_detailed_fn fn,
- void *data)
-{
- int i;
- struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM];
- int det_mon_num;
-
- det_mon_num = get_cea_detail_timing(ext, mon, det_mon);
-
- for (i = 0; i < det_mon_num; i++)
- fn(det_mon + i, data);
-}
-
-void xf86ForEachDetailedBlock(xf86MonPtr mon,
- handle_detailed_fn fn,
- void *data)
-{
- int i;
- Uchar *ext;
-
- if (mon == NULL)
- return;
-
- for (i = 0; i < DET_TIMINGS; i++)
- fn(mon->det_mon + i, data);
-
- for (i = 0; i < mon->no_sections; i++) {
- ext = mon->rawData + EDID1_LEN * (i + 1);
- switch (ext[EXT_TAG]){
- case CEA_EXT:
- handle_cea_detail_block(ext, mon, fn, data);
- break;
- case VTB_EXT:
- case DI_EXT:
- case LS_EXT:
- case MI_EXT:
- break;
- }
- }
-}
-
-static struct cea_data_block *
-extract_cea_data_block(Uchar *ext, int data_type)
-{
- struct cea_ext_body *cea;
- struct cea_data_block *data_collection;
- struct cea_data_block *data_end;
-
- cea = (struct cea_ext_body *)ext;
-
- if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET)
- return NULL;
-
- data_collection = &cea->data_collection;
- data_end = (struct cea_data_block *)(cea->dt_offset + ext);
-
- for ( ;data_collection < data_end;) {
-
- if (data_type == data_collection->tag) {
- return data_collection;
- }
- data_collection = (void *)((unsigned char *)data_collection +
- data_collection->len + 1);
- }
-
- return NULL;
-}
-
-static void handle_cea_video_block(Uchar *ext, handle_video_fn fn, void *data)
-{
- struct cea_video_block *video;
- struct cea_video_block *video_end;
- struct cea_data_block *data_collection;
-
- data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK);
- if (data_collection == NULL)
- return;
-
- video = &data_collection->u.video;
- video_end = (struct cea_video_block *)
- ((Uchar *)video + data_collection->len);
-
- for (; video < video_end; video = video + 1) {
- fn(video, data);
- }
-}
-
-void xf86ForEachVideoBlock(xf86MonPtr mon,
- handle_video_fn fn,
- void *data)
-{
- int i;
- Uchar *ext;
-
- if (mon == NULL)
- return;
-
- for (i = 0; i < mon->no_sections; i++) {
- ext = mon->rawData + EDID1_LEN * (i + 1);
- switch (ext[EXT_TAG]) {
- case CEA_EXT:
- handle_cea_video_block(ext, fn, data);
- break;
- case VTB_EXT:
- case DI_EXT:
- case LS_EXT:
- case MI_EXT:
- break;
- }
- }
-}
-
-xf86MonPtr
-xf86InterpretEEDID(int scrnIndex, Uchar *block)
-{
- xf86MonPtr m;
-
- m = xf86InterpretEDID(scrnIndex, block);
- if (!m)
- return NULL;
-
- /* extension parse */
-
- return m;
-}
-
-static void
-get_vendor_section(Uchar *c, struct vendor *r)
-{
- r->name[0] = L1;
- r->name[1] = L2;
- r->name[2] = L3;
- r->name[3] = '\0';
-
- r->prod_id = PROD_ID;
- r->serial = SERIAL_NO;
- r->week = WEEK;
- r->year = YEAR;
-}
-
-static void
-get_version_section(Uchar *c, struct edid_version *r)
-{
- r->version = VERSION;
- r->revision = REVISION;
-}
-
-static void
-get_display_section(Uchar *c, struct disp_features *r,
- struct edid_version *v)
-{
- r->input_type = INPUT_TYPE;
- if (!DIGITAL(r->input_type)) {
- r->input_voltage = INPUT_VOLTAGE;
- r->input_setup = SETUP;
- r->input_sync = SYNC;
- } else if (v->revision == 2 || v->revision == 3) {
- r->input_dfp = DFP;
- } else if (v->revision >= 4) {
- r->input_bpc = BPC;
- r->input_interface = DIGITAL_INTERFACE;
- }
- r->hsize = HSIZE_MAX;
- r->vsize = VSIZE_MAX;
- r->gamma = GAMMA;
- r->dpms = DPMS;
- r->display_type = DISPLAY_TYPE;
- r->msc = MSC;
- r->redx = REDX;
- r->redy = REDY;
- r->greenx = GREENX;
- r->greeny = GREENY;
- r->bluex = BLUEX;
- r->bluey = BLUEY;
- r->whitex = WHITEX;
- r->whitey = WHITEY;
-}
-
-static void
-get_established_timing_section(Uchar *c, struct established_timings *r)
-{
- r->t1 = T1;
- r->t2 = T2;
- 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)
-{
- int i;
-
- for (i=0;i<STD_TIMINGS;i++){
- 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;
- }
-}
-
-static const unsigned char empty_block[18];
-
-static void
-fetch_detailed_block(Uchar *c, struct edid_version *ver,
- struct detailed_monitor_section *det_mon)
-{
- if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) {
- switch (MONITOR_DESC_TYPE) {
- case SERIAL_NUMBER:
- det_mon->type = DS_SERIAL;
- copy_string(c,det_mon->section.serial);
- break;
- case ASCII_STR:
- det_mon->type = DS_ASCII_STR;
- copy_string(c,det_mon->section.ascii_data);
- break;
- case MONITOR_RANGES:
- det_mon->type = DS_RANGES;
- get_monitor_ranges(c,&det_mon->section.ranges);
- break;
- case MONITOR_NAME:
- det_mon->type = DS_NAME;
- copy_string(c,det_mon->section.name);
- break;
- case ADD_COLOR_POINT:
- det_mon->type = DS_WHITE_P;
- get_whitepoint_section(c,det_mon->section.wp);
- break;
- case ADD_STD_TIMINGS:
- det_mon->type = DS_STD_TIMINGS;
- get_dst_timing_section(c,det_mon->section.std_t, ver);
- break;
- case COLOR_MANAGEMENT_DATA:
- det_mon->type = DS_CMD;
- break;
- case CVT_3BYTE_DATA:
- det_mon->type = DS_CVT;
- get_cvt_timing_section(c, det_mon->section.cvt);
- break;
- case ADD_EST_TIMINGS:
- det_mon->type = DS_EST_III;
- memcpy(det_mon->section.est_iii, c + 6, 6);
- break;
- case ADD_DUMMY:
- det_mon->type = DS_DUMMY;
- break;
- default:
- det_mon->type = DS_UNKOWN;
- break;
- }
- if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) {
- det_mon->type = DS_VENDOR + c[3];
- }
- } else {
- det_mon->type = DT;
- get_detailed_timing_section(c, &det_mon->section.d_timings);
- }
-}
-
-static void
-get_dt_md_section(Uchar *c, struct edid_version *ver,
- struct detailed_monitor_section *det_mon)
-{
- int i;
-
- for (i=0; i < DET_TIMINGS; i++) {
- fetch_detailed_block(c, ver, det_mon + i);
- NEXT_DT_MD_SECTION;
- }
-}
-
-static void
-copy_string(Uchar *c, Uchar *s)
-{
- int i;
- c = c + 5;
- for (i = 0; (i < 13 && *c != 0x0A); i++)
- *(s++) = *(c++);
- *s = 0;
- while (i-- && (*--s == 0x20)) *s = 0;
-}
-
-static void
-get_dst_timing_section(Uchar *c, struct std_timings *t,
- struct edid_version *v)
-{
- int j;
- c = c + 5;
- for (j = 0; j < 5; j++) {
- t[j].hsize = HSIZE1;
- VSIZE1(t[j].vsize);
- t[j].refresh = REFRESH_R;
- t[j].id = STD_TIMING_ID;
- NEXT_STD_TIMING;
- }
-}
-
-static void
-get_monitor_ranges(Uchar *c, struct monitor_ranges *r)
-{
- r->min_v = MIN_V;
- r->max_v = MAX_V;
- r->min_h = MIN_H;
- r->max_h = MAX_H;
- r->max_clock = 0;
- if(MAX_CLOCK != 0xff) /* is specified? */
- r->max_clock = MAX_CLOCK * 10 + 5;
- 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;
- }
- if (HAVE_CVT) {
- r->max_clock_khz = MAX_CLOCK_KHZ;
- r->max_clock = r->max_clock_khz / 1000;
- r->maxwidth = MAXWIDTH;
- r->supported_aspect = SUPPORTED_ASPECT;
- r->preferred_aspect = PREFERRED_ASPECT;
- r->supported_blanking = SUPPORTED_BLANKING;
- r->supported_scaling = SUPPORTED_SCALING;
- r->preferred_refresh = PREFERRED_REFRESH;
- } else {
- r->max_clock_khz = 0;
- }
-}
-
-static void
-get_whitepoint_section(Uchar *c, struct whitePoints *wp)
-{
- wp[0].white_x = WHITEX1;
- wp[0].white_y = WHITEY1;
- wp[1].white_x = WHITEX2;
- wp[1].white_y = WHITEY2;
- wp[0].index = WHITE_INDEX1;
- wp[1].index = WHITE_INDEX2;
- wp[0].white_gamma = WHITE_GAMMA1;
- wp[1].white_gamma = WHITE_GAMMA2;
-}
-
-static void
-get_detailed_timing_section(Uchar *c, struct detailed_timings *r)
-{
- r->clock = PIXEL_CLOCK;
- r->h_active = H_ACTIVE;
- r->h_blanking = H_BLANK;
- r->v_active = V_ACTIVE;
- r->v_blanking = V_BLANK;
- r->h_sync_off = H_SYNC_OFF;
- r->h_sync_width = H_SYNC_WIDTH;
- r->v_sync_off = V_SYNC_OFF;
- r->v_sync_width = V_SYNC_WIDTH;
- r->h_size = H_SIZE;
- r->v_size = V_SIZE;
- r->h_border = H_BORDER;
- r->v_border = V_BORDER;
- r->interlaced = INTERLACED;
- r->stereo = STEREO;
- r->stereo_1 = STEREO1;
- r->sync = SYNC_T;
- r->misc = MISC;
-}
-
-#define MAX_EDID_MINOR 4
-
-static Bool
-validate_version(int scrnIndex, struct edid_version *r)
-{
- if (r->version != 1) {
- xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n",
- r->version);
- return FALSE;
- }
-
- if (r->revision > MAX_EDID_MINOR)
- xf86DrvMsg(scrnIndex, X_WARNING,
- "Assuming version 1.%d is compatible with 1.%d\n",
- r->revision, MAX_EDID_MINOR);
-
- return TRUE;
-}
-
-/*
- * Returns true if HDMI, false if definitely not or unknown.
- */
-Bool
-xf86MonitorIsHDMI(xf86MonPtr mon)
-{
- int i = 0, version, offset;
- char *edid = NULL;
-
- if (!mon)
- return FALSE;
-
- if (!(mon->flags & EDID_COMPLETE_RAWDATA))
- return FALSE;
-
- if (!mon->no_sections)
- return FALSE;
-
- edid = (char *)mon->rawData;
- if (!edid)
- return FALSE;
-
- /* find the CEA extension block */
- for (i = 1; i <= mon->no_sections; i++)
- if (edid[i * 128] == 0x02)
- break;
- if (i == mon->no_sections + 1)
- return FALSE;
- edid += (i * 128);
-
- version = edid[1];
- offset = edid[2];
- if (version < 3 || offset < 4)
- return FALSE;
-
- /* walk the cea data blocks */
- for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) {
- char *x = edid + i;
-
- /* find a vendor specific block */
- if ((x[0] & 0xe0) >> 5 == 0x03) {
- int oui = (x[3] << 16) + (x[2] << 8) + x[1];
-
- /* find the HDMI vendor OUI */
- if (oui == 0x000c03)
- return TRUE;
- }
- }
-
- /* guess it's not HDMI after all */
- return FALSE;
-}
+/* + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + * Copyright 2007 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * interpret_edid.c: interpret a primary EDID block + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#define _PARSE_EDID_ +#include "xf86DDC.h" +#include <string.h> + +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 *, + struct edid_version *); +static void get_established_timing_section(Uchar *, + struct established_timings *); +static void get_std_timing_section(Uchar *, struct std_timings *, + struct edid_version *); +static void fetch_detailed_block(Uchar * c, struct edid_version *ver, + struct detailed_monitor_section *det_mon); +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 *, + 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 *); + +static void +find_ranges_section(struct detailed_monitor_section *det, void *ranges) +{ + if (det->type == DS_RANGES && det->section.ranges.max_clock) + *(struct monitor_ranges **) ranges = &det->section.ranges; +} + +static void +find_max_detailed_clock(struct detailed_monitor_section *det, void *ret) +{ + if (det->type == DT) { + *(int *) ret = max(*((int *) ret), det->section.d_timings.clock); + } +} + +static void +handle_edid_quirks(xf86MonPtr m) +{ + struct monitor_ranges *ranges = NULL; + + /* + * max_clock is only encoded in EDID in tens of MHz, so occasionally we + * find a monitor claiming a max of 160 with a mode requiring 162, or + * similar. Strictly we should refuse to round up too far, but let's + * see how well this works. + */ + + /* Try to find Monitor Range and max clock, then re-set range value */ + xf86ForEachDetailedBlock(m, find_ranges_section, &ranges); + if (ranges && ranges->max_clock) { + int clock = 0; + + xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock); + if (clock && (ranges->max_clock * 1e6 < clock)) { + xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max " + "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock); + ranges->max_clock = (clock + 999999) / 1e6; + } + } +} + +struct det_hv_parameter { + int real_hsize; + int real_vsize; + float target_aspect; +}; + +static void +handle_detailed_hvsize(struct detailed_monitor_section *det_mon, void *data) +{ + struct det_hv_parameter *p = (struct det_hv_parameter *) data; + float timing_aspect; + + if (det_mon->type == DT) { + struct detailed_timings *timing; + + timing = &det_mon->section.d_timings; + + if (!timing->v_size) + return; + + timing_aspect = (float) timing->h_size / timing->v_size; + if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) { + p->real_hsize = max(p->real_hsize, timing->h_size); + p->real_vsize = max(p->real_vsize, timing->v_size); + } + } +} + +static void +encode_aspect_ratio(xf86MonPtr m) +{ + /* + * some monitors encode the aspect ratio instead of the physical size. + * try to find the largest detailed timing that matches that aspect + * ratio and use that to fill in the feature section. + */ + if ((m->features.hsize == 16 && m->features.vsize == 9) || + (m->features.hsize == 16 && m->features.vsize == 10) || + (m->features.hsize == 4 && m->features.vsize == 3) || + (m->features.hsize == 5 && m->features.vsize == 4)) { + + struct det_hv_parameter p; + + p.real_hsize = 0; + p.real_vsize = 0; + p.target_aspect = (float) m->features.hsize / m->features.vsize; + + xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p); + + if (!p.real_hsize || !p.real_vsize) { + m->features.hsize = m->features.vsize = 0; + } + else if ((m->features.hsize * 10 == p.real_hsize) && + (m->features.vsize * 10 == p.real_vsize)) { + /* exact match is just unlikely, should do a better check though */ + m->features.hsize = m->features.vsize = 0; + } + else { + /* convert mm to cm */ + m->features.hsize = (p.real_hsize + 5) / 10; + m->features.vsize = (p.real_vsize + 5) / 10; + } + + xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n", + m->features.hsize, m->features.vsize); + } +} + +xf86MonPtr +xf86InterpretEDID(int scrnIndex, Uchar * block) +{ + xf86MonPtr m; + + if (!block) + return NULL; + 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); + 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, + &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); + + handle_edid_quirks(m); + encode_aspect_ratio(m); + + return m; + + error: + free(m); + return NULL; +} + +static int +get_cea_detail_timing(Uchar * blk, xf86MonPtr mon, + struct detailed_monitor_section *det_mon) +{ + int dt_num; + int dt_offset = ((struct cea_ext_body *) blk)->dt_offset; + + dt_num = 0; + + if (dt_offset < CEA_EXT_MIN_DATA_OFFSET) + return dt_num; + + for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) && + dt_num < CEA_EXT_DET_TIMING_NUM; _NEXT_DT_MD_SECTION(dt_offset)) { + + fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num); + dt_num = dt_num + 1; + } + + return dt_num; +} + +static void +handle_cea_detail_block(Uchar * ext, xf86MonPtr mon, + handle_detailed_fn fn, void *data) +{ + int i; + struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM]; + int det_mon_num; + + det_mon_num = get_cea_detail_timing(ext, mon, det_mon); + + for (i = 0; i < det_mon_num; i++) + fn(det_mon + i, data); +} + +void +xf86ForEachDetailedBlock(xf86MonPtr mon, handle_detailed_fn fn, void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < DET_TIMINGS; i++) + fn(mon->det_mon + i, data); + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]) { + case CEA_EXT: + handle_cea_detail_block(ext, mon, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + +static struct cea_data_block * +extract_cea_data_block(Uchar * ext, int data_type) +{ + struct cea_ext_body *cea; + struct cea_data_block *data_collection; + struct cea_data_block *data_end; + + cea = (struct cea_ext_body *) ext; + + if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET) + return NULL; + + data_collection = &cea->data_collection; + data_end = (struct cea_data_block *) (cea->dt_offset + ext); + + for (; data_collection < data_end;) { + + if (data_type == data_collection->tag) { + return data_collection; + } + data_collection = (void *) ((unsigned char *) data_collection + + data_collection->len + 1); + } + + return NULL; +} + +static void +handle_cea_video_block(Uchar * ext, handle_video_fn fn, void *data) +{ + struct cea_video_block *video; + struct cea_video_block *video_end; + struct cea_data_block *data_collection; + + data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK); + if (data_collection == NULL) + return; + + video = &data_collection->u.video; + video_end = (struct cea_video_block *) + ((Uchar *) video + data_collection->len); + + for (; video < video_end; video = video + 1) { + fn(video, data); + } +} + +void +xf86ForEachVideoBlock(xf86MonPtr mon, handle_video_fn fn, void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]) { + case CEA_EXT: + handle_cea_video_block(ext, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + +xf86MonPtr +xf86InterpretEEDID(int scrnIndex, Uchar * block) +{ + xf86MonPtr m; + + m = xf86InterpretEDID(scrnIndex, block); + if (!m) + return NULL; + + /* extension parse */ + + return m; +} + +static void +get_vendor_section(Uchar * c, struct vendor *r) +{ + r->name[0] = L1; + r->name[1] = L2; + r->name[2] = L3; + r->name[3] = '\0'; + + r->prod_id = PROD_ID; + r->serial = SERIAL_NO; + r->week = WEEK; + r->year = YEAR; +} + +static void +get_version_section(Uchar * c, struct edid_version *r) +{ + r->version = VERSION; + r->revision = REVISION; +} + +static void +get_display_section(Uchar * c, struct disp_features *r, struct edid_version *v) +{ + r->input_type = INPUT_TYPE; + if (!DIGITAL(r->input_type)) { + r->input_voltage = INPUT_VOLTAGE; + r->input_setup = SETUP; + r->input_sync = SYNC; + } + else if (v->revision == 2 || v->revision == 3) { + r->input_dfp = DFP; + } + else if (v->revision >= 4) { + r->input_bpc = BPC; + r->input_interface = DIGITAL_INTERFACE; + } + r->hsize = HSIZE_MAX; + r->vsize = VSIZE_MAX; + r->gamma = GAMMA; + r->dpms = DPMS; + r->display_type = DISPLAY_TYPE; + r->msc = MSC; + r->redx = REDX; + r->redy = REDY; + r->greenx = GREENX; + r->greeny = GREENY; + r->bluex = BLUEX; + r->bluey = BLUEY; + r->whitex = WHITEX; + r->whitey = WHITEY; +} + +static void +get_established_timing_section(Uchar * c, struct established_timings *r) +{ + r->t1 = T1; + r->t2 = T2; + 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) +{ + int i; + + for (i = 0; i < STD_TIMINGS; i++) { + 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; + } +} + +static const unsigned char empty_block[18]; + +static void +fetch_detailed_block(Uchar * c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { + switch (MONITOR_DESC_TYPE) { + case SERIAL_NUMBER: + det_mon->type = DS_SERIAL; + copy_string(c, det_mon->section.serial); + break; + case ASCII_STR: + det_mon->type = DS_ASCII_STR; + copy_string(c, det_mon->section.ascii_data); + break; + case MONITOR_RANGES: + det_mon->type = DS_RANGES; + get_monitor_ranges(c, &det_mon->section.ranges); + break; + case MONITOR_NAME: + det_mon->type = DS_NAME; + copy_string(c, det_mon->section.name); + break; + case ADD_COLOR_POINT: + det_mon->type = DS_WHITE_P; + get_whitepoint_section(c, det_mon->section.wp); + break; + case ADD_STD_TIMINGS: + det_mon->type = DS_STD_TIMINGS; + get_dst_timing_section(c, det_mon->section.std_t, ver); + break; + case COLOR_MANAGEMENT_DATA: + det_mon->type = DS_CMD; + break; + case CVT_3BYTE_DATA: + det_mon->type = DS_CVT; + get_cvt_timing_section(c, det_mon->section.cvt); + break; + case ADD_EST_TIMINGS: + det_mon->type = DS_EST_III; + memcpy(det_mon->section.est_iii, c + 6, 6); + break; + case ADD_DUMMY: + det_mon->type = DS_DUMMY; + break; + default: + det_mon->type = DS_UNKOWN; + break; + } + if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { + det_mon->type = DS_VENDOR + c[3]; + } + } + else { + det_mon->type = DT; + get_detailed_timing_section(c, &det_mon->section.d_timings); + } +} + +static void +get_dt_md_section(Uchar * c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + int i; + + for (i = 0; i < DET_TIMINGS; i++) { + fetch_detailed_block(c, ver, det_mon + i); + NEXT_DT_MD_SECTION; + } +} + +static void +copy_string(Uchar * c, Uchar * s) +{ + int i; + + c = c + 5; + for (i = 0; (i < 13 && *c != 0x0A); i++) + *(s++) = *(c++); + *s = 0; + while (i-- && (*--s == 0x20)) + *s = 0; +} + +static void +get_dst_timing_section(Uchar * c, struct std_timings *t, struct edid_version *v) +{ + int j; + + c = c + 5; + for (j = 0; j < 5; j++) { + t[j].hsize = HSIZE1; + VSIZE1(t[j].vsize); + t[j].refresh = REFRESH_R; + t[j].id = STD_TIMING_ID; + NEXT_STD_TIMING; + } +} + +static void +get_monitor_ranges(Uchar * c, struct monitor_ranges *r) +{ + r->min_v = MIN_V; + r->max_v = MAX_V; + r->min_h = MIN_H; + r->max_h = MAX_H; + r->max_clock = 0; + if (MAX_CLOCK != 0xff) /* is specified? */ + r->max_clock = MAX_CLOCK * 10 + 5; + 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; + } + if (HAVE_CVT) { + r->max_clock_khz = MAX_CLOCK_KHZ; + r->max_clock = r->max_clock_khz / 1000; + r->maxwidth = MAXWIDTH; + r->supported_aspect = SUPPORTED_ASPECT; + r->preferred_aspect = PREFERRED_ASPECT; + r->supported_blanking = SUPPORTED_BLANKING; + r->supported_scaling = SUPPORTED_SCALING; + r->preferred_refresh = PREFERRED_REFRESH; + } + else { + r->max_clock_khz = 0; + } +} + +static void +get_whitepoint_section(Uchar * c, struct whitePoints *wp) +{ + wp[0].white_x = WHITEX1; + wp[0].white_y = WHITEY1; + wp[1].white_x = WHITEX2; + wp[1].white_y = WHITEY2; + wp[0].index = WHITE_INDEX1; + wp[1].index = WHITE_INDEX2; + wp[0].white_gamma = WHITE_GAMMA1; + wp[1].white_gamma = WHITE_GAMMA2; +} + +static void +get_detailed_timing_section(Uchar * c, struct detailed_timings *r) +{ + r->clock = PIXEL_CLOCK; + r->h_active = H_ACTIVE; + r->h_blanking = H_BLANK; + r->v_active = V_ACTIVE; + r->v_blanking = V_BLANK; + r->h_sync_off = H_SYNC_OFF; + r->h_sync_width = H_SYNC_WIDTH; + r->v_sync_off = V_SYNC_OFF; + r->v_sync_width = V_SYNC_WIDTH; + r->h_size = H_SIZE; + r->v_size = V_SIZE; + r->h_border = H_BORDER; + r->v_border = V_BORDER; + r->interlaced = INTERLACED; + r->stereo = STEREO; + r->stereo_1 = STEREO1; + r->sync = SYNC_T; + r->misc = MISC; +} + +#define MAX_EDID_MINOR 4 + +static Bool +validate_version(int scrnIndex, struct edid_version *r) +{ + if (r->version != 1) { + xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n", r->version); + return FALSE; + } + + if (r->revision > MAX_EDID_MINOR) + xf86DrvMsg(scrnIndex, X_WARNING, + "Assuming version 1.%d is compatible with 1.%d\n", + r->revision, MAX_EDID_MINOR); + + return TRUE; +} + +/* + * Returns true if HDMI, false if definitely not or unknown. + */ +Bool +xf86MonitorIsHDMI(xf86MonPtr mon) +{ + int i = 0, version, offset; + char *edid = NULL; + + if (!mon) + return FALSE; + + if (!(mon->flags & EDID_COMPLETE_RAWDATA)) + return FALSE; + + if (!mon->no_sections) + return FALSE; + + edid = (char *) mon->rawData; + if (!edid) + return FALSE; + + /* find the CEA extension block */ + for (i = 1; i <= mon->no_sections; i++) + if (edid[i * 128] == 0x02) + break; + if (i == mon->no_sections + 1) + return FALSE; + edid += (i * 128); + + version = edid[1]; + offset = edid[2]; + if (version < 3 || offset < 4) + return FALSE; + + /* walk the cea data blocks */ + for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) { + char *x = edid + i; + + /* find a vendor specific block */ + if ((x[0] & 0xe0) >> 5 == 0x03) { + int oui = (x[3] << 16) + (x[2] << 8) + x[1]; + + /* find the HDMI vendor OUI */ + if (oui == 0x000c03) + return TRUE; + } + } + + /* guess it's not HDMI after all */ + return FALSE; +} diff --git a/xorg-server/hw/xfree86/ddc/print_edid.c b/xorg-server/hw/xfree86/ddc/print_edid.c index 1faae1e33..4f983f934 100644 --- a/xorg-server/hw/xfree86/ddc/print_edid.c +++ b/xorg-server/hw/xfree86/ddc/print_edid.c @@ -36,24 +36,24 @@ #include "xf86_OSproc.h" #include "xf86DDC.h" #include "edid.h" - + #define EDID_WIDTH 16 - + static void print_vendor(int scrnIndex, struct vendor *c) { xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer: %s Model: %x Serial#: %u\n", - (char *)&c->name, c->prod_id, c->serial); + (char *) &c->name, c->prod_id, c->serial); xf86DrvMsg(scrnIndex, X_INFO, "Year: %u Week: %u\n", c->year, c->week); } static void print_version(int scrnIndex, struct edid_version *c) { - xf86DrvMsg(scrnIndex,X_INFO,"EDID Version: %u.%u\n",c->version, - c->revision); + xf86DrvMsg(scrnIndex, X_INFO, "EDID Version: %u.%u\n", c->version, + c->revision); } - + static const char *digital_interfaces[] = { "undefined", "DVI", @@ -64,212 +64,241 @@ static const char *digital_interfaces[] = { "unknown" }; -static void +static void print_input_features(int scrnIndex, struct disp_features *c, - struct edid_version *v) + struct edid_version *v) { if (DIGITAL(c->input_type)) { - xf86DrvMsg(scrnIndex, X_INFO, "Digital Display Input\n"); - if (v->revision == 2 || v->revision == 3) { - if (DFP1(c->input_dfp)) - xf86DrvMsg(scrnIndex, X_INFO, "DFP 1.x compatible TMDS\n"); - } else if (v->revision >= 4) { - int interface = c->input_interface; - int bpc = c->input_bpc; - if (interface > 6) - interface = 6; /* unknown */ - if (bpc == 0 || bpc == 7) - xf86DrvMsg(scrnIndex, X_INFO, "Undefined color depth\n"); - else - xf86DrvMsg(scrnIndex, X_INFO, "%d bits per channel\n", - bpc * 2 + 4); - xf86DrvMsg(scrnIndex, X_INFO, "Digital interface is %s\n", - digital_interfaces[interface]); - } - } else { - xf86DrvMsg(scrnIndex,X_INFO,"Analog Display Input, "); - xf86ErrorF("Input Voltage Level: "); - switch (c->input_voltage){ - case V070: - xf86ErrorF("0.700/0.300 V\n"); - break; - case V071: - xf86ErrorF("0.714/0.286 V\n"); - break; - case V100: - xf86ErrorF("1.000/0.400 V\n"); - break; - case V007: + xf86DrvMsg(scrnIndex, X_INFO, "Digital Display Input\n"); + if (v->revision == 2 || v->revision == 3) { + if (DFP1(c->input_dfp)) + xf86DrvMsg(scrnIndex, X_INFO, "DFP 1.x compatible TMDS\n"); + } + else if (v->revision >= 4) { + int interface = c->input_interface; + int bpc = c->input_bpc; + + if (interface > 6) + interface = 6; /* unknown */ + if (bpc == 0 || bpc == 7) + xf86DrvMsg(scrnIndex, X_INFO, "Undefined color depth\n"); + else + xf86DrvMsg(scrnIndex, X_INFO, "%d bits per channel\n", + bpc * 2 + 4); + xf86DrvMsg(scrnIndex, X_INFO, "Digital interface is %s\n", + digital_interfaces[interface]); + } + } + else { + xf86DrvMsg(scrnIndex, X_INFO, "Analog Display Input, "); + xf86ErrorF("Input Voltage Level: "); + switch (c->input_voltage) { + case V070: + xf86ErrorF("0.700/0.300 V\n"); + break; + case V071: + xf86ErrorF("0.714/0.286 V\n"); + break; + case V100: + xf86ErrorF("1.000/0.400 V\n"); + break; + case V007: xf86ErrorF("0.700/0.700 V\n"); - break; - default: - xf86ErrorF("undefined\n"); - } - if (SIG_SETUP(c->input_setup)) - xf86DrvMsg(scrnIndex,X_INFO,"Signal levels configurable\n"); - xf86DrvMsg(scrnIndex,X_INFO,"Sync:"); - if (SEP_SYNC(c->input_sync)) - xf86ErrorF(" Separate"); - if (COMP_SYNC(c->input_sync)) - xf86ErrorF(" Composite"); - if (SYNC_O_GREEN(c->input_sync)) - xf86ErrorF(" SyncOnGreen"); - if (SYNC_SERR(c->input_sync)) - xf86ErrorF("Serration on. " - "V.Sync Pulse req. if CompSync or SyncOnGreen\n"); - else xf86ErrorF("\n"); + break; + default: + xf86ErrorF("undefined\n"); + } + if (SIG_SETUP(c->input_setup)) + xf86DrvMsg(scrnIndex, X_INFO, "Signal levels configurable\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Sync:"); + if (SEP_SYNC(c->input_sync)) + xf86ErrorF(" Separate"); + if (COMP_SYNC(c->input_sync)) + xf86ErrorF(" Composite"); + if (SYNC_O_GREEN(c->input_sync)) + xf86ErrorF(" SyncOnGreen"); + if (SYNC_SERR(c->input_sync)) + xf86ErrorF("Serration on. " + "V.Sync Pulse req. if CompSync or SyncOnGreen\n"); + else + xf86ErrorF("\n"); } } - -static void + +static void print_dpms_features(int scrnIndex, struct disp_features *c, - struct edid_version *v) + struct edid_version *v) { - if (c->dpms) { - xf86DrvMsg(scrnIndex,X_INFO,"DPMS capabilities:"); - if (DPMS_STANDBY(c->dpms)) xf86ErrorF(" StandBy"); - if (DPMS_SUSPEND(c->dpms)) xf86ErrorF(" Suspend"); - if (DPMS_OFF(c->dpms)) xf86ErrorF(" Off"); - } else - xf86DrvMsg(scrnIndex,X_INFO,"No DPMS capabilities specified"); - if (!c->input_type) { /* analog */ - switch (c->display_type){ - case DISP_MONO: - xf86ErrorF("; Monochorome/GrayScale Display\n"); - break; - case DISP_RGB: - xf86ErrorF("; RGB/Color Display\n"); - break; - case DISP_MULTCOLOR: - xf86ErrorF("; Non RGB Multicolor Display\n"); - break; - default: - xf86ErrorF("\n"); - break; - } - } else { - int enc = c->display_type; - xf86ErrorF("\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Supported color encodings: " - "RGB 4:4:4 %s%s\n", - enc & DISP_YCRCB444 ? "YCrCb 4:4:4 " : "", - enc & DISP_YCRCB422 ? "YCrCb 4:2:2" : ""); + if (c->dpms) { + xf86DrvMsg(scrnIndex, X_INFO, "DPMS capabilities:"); + if (DPMS_STANDBY(c->dpms)) + xf86ErrorF(" StandBy"); + if (DPMS_SUSPEND(c->dpms)) + xf86ErrorF(" Suspend"); + if (DPMS_OFF(c->dpms)) + xf86ErrorF(" Off"); + } + else + xf86DrvMsg(scrnIndex, X_INFO, "No DPMS capabilities specified"); + if (!c->input_type) { /* analog */ + switch (c->display_type) { + case DISP_MONO: + xf86ErrorF("; Monochorome/GrayScale Display\n"); + break; + case DISP_RGB: + xf86ErrorF("; RGB/Color Display\n"); + break; + case DISP_MULTCOLOR: + xf86ErrorF("; Non RGB Multicolor Display\n"); + break; + default: + xf86ErrorF("\n"); + break; + } + } + else { + int enc = c->display_type; + + xf86ErrorF("\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Supported color encodings: " + "RGB 4:4:4 %s%s\n", + enc & DISP_YCRCB444 ? "YCrCb 4:4:4 " : "", + enc & DISP_YCRCB422 ? "YCrCb 4:2:2" : ""); } if (STD_COLOR_SPACE(c->msc)) - xf86DrvMsg(scrnIndex,X_INFO, - "Default color space is primary color space\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "Default color space is primary color space\n"); if (PREFERRED_TIMING_MODE(c->msc) || v->revision >= 4) { - xf86DrvMsg(scrnIndex, X_INFO, - "First detailed timing is preferred mode\n"); - if (v->revision >= 4) - xf86DrvMsg(scrnIndex, X_INFO, - "Preferred mode is native pixel format and refresh rate\n"); - } else if (v->revision == 3) { - xf86DrvMsg(scrnIndex,X_INFO, - "First detailed timing not preferred " - "mode in violation of standard!\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "First detailed timing is preferred mode\n"); + if (v->revision >= 4) + xf86DrvMsg(scrnIndex, X_INFO, + "Preferred mode is native pixel format and refresh rate\n"); + } + else if (v->revision == 3) { + xf86DrvMsg(scrnIndex, X_INFO, + "First detailed timing not preferred " + "mode in violation of standard!\n"); } if (v->revision >= 4) { - if (GFT_SUPPORTED(c->msc)) { - xf86DrvMsg(scrnIndex, X_INFO, "Display is continuous-frequency\n"); - } - } else { - if (GFT_SUPPORTED(c->msc)) - xf86DrvMsg(scrnIndex, X_INFO, "GTF timings supported\n"); + if (GFT_SUPPORTED(c->msc)) { + xf86DrvMsg(scrnIndex, X_INFO, "Display is continuous-frequency\n"); + } + } + else { + if (GFT_SUPPORTED(c->msc)) + xf86DrvMsg(scrnIndex, X_INFO, "GTF timings supported\n"); } } - -static void + +static void print_whitepoint(int scrnIndex, struct disp_features *disp) { - xf86DrvMsg(scrnIndex,X_INFO,"redX: %.3f redY: %.3f ", - disp->redx,disp->redy); - xf86ErrorF("greenX: %.3f greenY: %.3f\n", - disp->greenx,disp->greeny); - xf86DrvMsg(scrnIndex,X_INFO,"blueX: %.3f blueY: %.3f ", - disp->bluex,disp->bluey); - xf86ErrorF("whiteX: %.3f whiteY: %.3f\n", - disp->whitex,disp->whitey); + xf86DrvMsg(scrnIndex, X_INFO, "redX: %.3f redY: %.3f ", + disp->redx, disp->redy); + xf86ErrorF("greenX: %.3f greenY: %.3f\n", disp->greenx, disp->greeny); + xf86DrvMsg(scrnIndex, X_INFO, "blueX: %.3f blueY: %.3f ", + disp->bluex, disp->bluey); + xf86ErrorF("whiteX: %.3f whiteY: %.3f\n", disp->whitex, disp->whitey); } static void -print_display(int scrnIndex, struct disp_features *disp, - struct edid_version *v) +print_display(int scrnIndex, struct disp_features *disp, struct edid_version *v) { print_input_features(scrnIndex, disp, v); if (disp->hsize && disp->vsize) { - xf86DrvMsg(scrnIndex, X_INFO, "Max Image Size [cm]: "); - xf86ErrorF("horiz.: %i ", disp->hsize); - xf86ErrorF("vert.: %i\n", disp->vsize); - } else if (v->revision >= 4 && (disp->hsize || disp->vsize)) { - if (disp->hsize) - xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (landscape)\n", - (disp->hsize + 99) / 100.0); - if (disp->vsize) - xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (portrait)\n", - 100.0 / (float)(disp->vsize + 99)); - - } else { - xf86DrvMsg(scrnIndex, X_INFO, "Indeterminate output size\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Max Image Size [cm]: "); + xf86ErrorF("horiz.: %i ", disp->hsize); + xf86ErrorF("vert.: %i\n", disp->vsize); + } + else if (v->revision >= 4 && (disp->hsize || disp->vsize)) { + if (disp->hsize) + xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (landscape)\n", + (disp->hsize + 99) / 100.0); + if (disp->vsize) + xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (portrait)\n", + 100.0 / (float) (disp->vsize + 99)); + + } + else { + xf86DrvMsg(scrnIndex, X_INFO, "Indeterminate output size\n"); } if (!disp->gamma && v->revision >= 1.4) - xf86DrvMsg(scrnIndex, X_INFO, "Gamma defined in extension block\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Gamma defined in extension block\n"); else - xf86DrvMsg(scrnIndex, X_INFO, "Gamma: %.2f\n", disp->gamma); + xf86DrvMsg(scrnIndex, X_INFO, "Gamma: %.2f\n", disp->gamma); print_dpms_features(scrnIndex, disp, v); print_whitepoint(scrnIndex, disp); } -static void +static void print_established_timings(int scrnIndex, struct established_timings *t) { unsigned char c; if (t->t1 || t->t2 || t->t_manu) - xf86DrvMsg(scrnIndex,X_INFO,"Supported established timings:\n"); - c=t->t1; - if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"720x400@70Hz\n"); - if (c&0x40) xf86DrvMsg(scrnIndex,X_INFO,"720x400@88Hz\n"); - if (c&0x20) xf86DrvMsg(scrnIndex,X_INFO,"640x480@60Hz\n"); - if (c&0x10) xf86DrvMsg(scrnIndex,X_INFO,"640x480@67Hz\n"); - if (c&0x08) xf86DrvMsg(scrnIndex,X_INFO,"640x480@72Hz\n"); - if (c&0x04) xf86DrvMsg(scrnIndex,X_INFO,"640x480@75Hz\n"); - if (c&0x02) xf86DrvMsg(scrnIndex,X_INFO,"800x600@56Hz\n"); - if (c&0x01) xf86DrvMsg(scrnIndex,X_INFO,"800x600@60Hz\n"); - c=t->t2; - if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"800x600@72Hz\n"); - if (c&0x40) xf86DrvMsg(scrnIndex,X_INFO,"800x600@75Hz\n"); - if (c&0x20) xf86DrvMsg(scrnIndex,X_INFO,"832x624@75Hz\n"); - if (c&0x10) xf86DrvMsg(scrnIndex,X_INFO,"1024x768@87Hz (interlaced)\n"); - if (c&0x08) xf86DrvMsg(scrnIndex,X_INFO,"1024x768@60Hz\n"); - if (c&0x04) xf86DrvMsg(scrnIndex,X_INFO,"1024x768@70Hz\n"); - if (c&0x02) xf86DrvMsg(scrnIndex,X_INFO,"1024x768@75Hz\n"); - if (c&0x01) xf86DrvMsg(scrnIndex,X_INFO,"1280x1024@75Hz\n"); - c=t->t_manu; - if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"1152x864@75Hz\n"); - xf86DrvMsg(scrnIndex,X_INFO,"Manufacturer's mask: %X\n",c&0x7F); + xf86DrvMsg(scrnIndex, X_INFO, "Supported established timings:\n"); + c = t->t1; + if (c & 0x80) + xf86DrvMsg(scrnIndex, X_INFO, "720x400@70Hz\n"); + if (c & 0x40) + xf86DrvMsg(scrnIndex, X_INFO, "720x400@88Hz\n"); + if (c & 0x20) + xf86DrvMsg(scrnIndex, X_INFO, "640x480@60Hz\n"); + if (c & 0x10) + xf86DrvMsg(scrnIndex, X_INFO, "640x480@67Hz\n"); + if (c & 0x08) + xf86DrvMsg(scrnIndex, X_INFO, "640x480@72Hz\n"); + if (c & 0x04) + xf86DrvMsg(scrnIndex, X_INFO, "640x480@75Hz\n"); + if (c & 0x02) + xf86DrvMsg(scrnIndex, X_INFO, "800x600@56Hz\n"); + if (c & 0x01) + xf86DrvMsg(scrnIndex, X_INFO, "800x600@60Hz\n"); + c = t->t2; + if (c & 0x80) + xf86DrvMsg(scrnIndex, X_INFO, "800x600@72Hz\n"); + if (c & 0x40) + xf86DrvMsg(scrnIndex, X_INFO, "800x600@75Hz\n"); + if (c & 0x20) + xf86DrvMsg(scrnIndex, X_INFO, "832x624@75Hz\n"); + if (c & 0x10) + xf86DrvMsg(scrnIndex, X_INFO, "1024x768@87Hz (interlaced)\n"); + if (c & 0x08) + xf86DrvMsg(scrnIndex, X_INFO, "1024x768@60Hz\n"); + if (c & 0x04) + xf86DrvMsg(scrnIndex, X_INFO, "1024x768@70Hz\n"); + if (c & 0x02) + xf86DrvMsg(scrnIndex, X_INFO, "1024x768@75Hz\n"); + if (c & 0x01) + xf86DrvMsg(scrnIndex, X_INFO, "1280x1024@75Hz\n"); + c = t->t_manu; + if (c & 0x80) + xf86DrvMsg(scrnIndex, X_INFO, "1152x864@75Hz\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer's mask: %X\n", c & 0x7F); } - + static void print_std_timings(int scrnIndex, struct std_timings *t) { int i; char done = 0; - for (i=0;i<STD_TIMINGS;i++) { - if (t[i].hsize > 256) { /* sanity check */ - if (!done) { - xf86DrvMsg(scrnIndex,X_INFO,"Supported standard timings:\n"); - done = 1; - } - xf86DrvMsg(scrnIndex,X_INFO, - "#%i: hsize: %i vsize %i refresh: %i vid: %i\n", - i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id); - } + + for (i = 0; i < STD_TIMINGS; i++) { + if (t[i].hsize > 256) { /* sanity check */ + if (!done) { + xf86DrvMsg(scrnIndex, X_INFO, "Supported standard timings:\n"); + done = 1; + } + xf86DrvMsg(scrnIndex, X_INFO, + "#%i: hsize: %i vsize %i refresh: %i vid: %i\n", + i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id); + } } } @@ -279,15 +308,17 @@ 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; + 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; } } @@ -296,166 +327,174 @@ print_detailed_timings(int scrnIndex, struct detailed_timings *t) { if (t->clock > 15000000) { /* sanity check */ - xf86DrvMsg(scrnIndex,X_INFO,"Supported detailed timing:\n"); - xf86DrvMsg(scrnIndex,X_INFO,"clock: %.1f MHz ",t->clock/1000000.0); - xf86ErrorF("Image Size: %i x %i mm\n",t->h_size,t->v_size); - xf86DrvMsg(scrnIndex,X_INFO, - "h_active: %i h_sync: %i h_sync_end %i h_blank_end %i ", - t->h_active, t->h_sync_off + t->h_active, - t->h_sync_off + t->h_sync_width + t->h_active, - t->h_active + t->h_blanking); - xf86ErrorF("h_border: %i\n",t->h_border); - xf86DrvMsg(scrnIndex,X_INFO, - "v_active: %i v_sync: %i v_sync_end %i v_blanking: %i ", - t->v_active, t->v_sync_off + t->v_active, - t->v_sync_off + t->v_sync_width + t->v_active, - t->v_active + t->v_blanking); - xf86ErrorF("v_border: %i\n",t->v_border); - if (IS_STEREO(t->stereo)) { - xf86DrvMsg(scrnIndex,X_INFO,"Stereo: "); - 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"); - } - } + xf86DrvMsg(scrnIndex, X_INFO, "Supported detailed timing:\n"); + xf86DrvMsg(scrnIndex, X_INFO, "clock: %.1f MHz ", + t->clock / 1000000.0); + xf86ErrorF("Image Size: %i x %i mm\n", t->h_size, t->v_size); + xf86DrvMsg(scrnIndex, X_INFO, + "h_active: %i h_sync: %i h_sync_end %i h_blank_end %i ", + t->h_active, t->h_sync_off + t->h_active, + t->h_sync_off + t->h_sync_width + t->h_active, + t->h_active + t->h_blanking); + xf86ErrorF("h_border: %i\n", t->h_border); + xf86DrvMsg(scrnIndex, X_INFO, + "v_active: %i v_sync: %i v_sync_end %i v_blanking: %i ", + t->v_active, t->v_sync_off + t->v_active, + t->v_sync_off + t->v_sync_width + t->v_active, + t->v_active + t->v_blanking); + xf86ErrorF("v_border: %i\n", t->v_border); + if (IS_STEREO(t->stereo)) { + xf86DrvMsg(scrnIndex, X_INFO, "Stereo: "); + 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"); + } + } } } /* This function handle all detailed patchs, * including EDID and EDID-extension */ -struct det_print_parameter{ - xf86MonPtr m; - int index; - ddc_quirk_t quirks; +struct det_print_parameter { + xf86MonPtr m; + int index; + ddc_quirk_t quirks; }; static void -handle_detailed_print(struct detailed_monitor_section *det_mon, - void *data) +handle_detailed_print(struct detailed_monitor_section *det_mon, void *data) { int j, scrnIndex; struct det_print_parameter *p; - p = (struct det_print_parameter *)data; + p = (struct det_print_parameter *) data; scrnIndex = p->m->scrnIndex; - xf86DetTimingApplyQuirks(det_mon,p->quirks, - p->m->features.hsize, - p->m->features.vsize); + xf86DetTimingApplyQuirks(det_mon, p->quirks, + p->m->features.hsize, p->m->features.vsize); switch (det_mon->type) { case DT: - print_detailed_timings(scrnIndex,&det_mon->section.d_timings); + print_detailed_timings(scrnIndex, &det_mon->section.d_timings); break; case DS_SERIAL: - xf86DrvMsg(scrnIndex,X_INFO,"Serial No: %s\n",det_mon->section.serial); + xf86DrvMsg(scrnIndex, X_INFO, "Serial No: %s\n", + det_mon->section.serial); break; case DS_ASCII_STR: - xf86DrvMsg(scrnIndex,X_INFO," %s\n",det_mon->section.ascii_data); + xf86DrvMsg(scrnIndex, X_INFO, " %s\n", det_mon->section.ascii_data); break; case DS_NAME: - xf86DrvMsg(scrnIndex,X_INFO,"Monitor name: %s\n",det_mon->section.name); + xf86DrvMsg(scrnIndex, X_INFO, "Monitor name: %s\n", + det_mon->section.name); break; case DS_RANGES: { struct monitor_ranges *r = &det_mon->section.ranges; - xf86DrvMsg(scrnIndex,X_INFO, + + xf86DrvMsg(scrnIndex, X_INFO, "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,", r->min_v, r->max_v, r->min_h, r->max_h); if (r->max_clock_khz != 0) { xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz); - if (r->maxwidth) - xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n", - r->maxwidth); - xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:"); - if (r->supported_aspect & SUPPORTED_ASPECT_4_3) - xf86ErrorF(" 4:3%s", - r->preferred_aspect == PREFERRED_ASPECT_4_3?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_16_9) - xf86ErrorF(" 16:9%s", - r->preferred_aspect == PREFERRED_ASPECT_16_9?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_16_10) - xf86ErrorF(" 16:10%s", - r->preferred_aspect == PREFERRED_ASPECT_16_10?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_5_4) - xf86ErrorF(" 5:4%s", - r->preferred_aspect == PREFERRED_ASPECT_5_4?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_15_9) - xf86ErrorF(" 15:9%s", - r->preferred_aspect == PREFERRED_ASPECT_15_9?"*":""); - xf86ErrorF("\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:"); - if (r->supported_blanking & CVT_STANDARD) - xf86ErrorF(" standard"); - if (r->supported_blanking & CVT_REDUCED) - xf86ErrorF(" reduced"); - xf86ErrorF("\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:"); - if (r->supported_scaling & SCALING_HSHRINK) - xf86ErrorF(" hshrink"); - if (r->supported_scaling & SCALING_HSTRETCH) - xf86ErrorF(" hstretch"); - if (r->supported_scaling & SCALING_VSHRINK) - xf86ErrorF(" vshrink"); - if (r->supported_scaling & SCALING_VSTRETCH) - xf86ErrorF(" vstretch"); - xf86ErrorF("\n"); - if (r->preferred_refresh) - xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n", - r->preferred_refresh); - else - xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred " - "refresh rate given\n"); - } else if (r->max_clock != 0) { - xf86ErrorF(" PixClock max %i MHz\n", r->max_clock); - } else { - xf86ErrorF("\n"); + if (r->maxwidth) + xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n", + r->maxwidth); + xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:"); + if (r->supported_aspect & SUPPORTED_ASPECT_4_3) + xf86ErrorF(" 4:3%s", + r->preferred_aspect == + PREFERRED_ASPECT_4_3 ? "*" : ""); + if (r->supported_aspect & SUPPORTED_ASPECT_16_9) + xf86ErrorF(" 16:9%s", + r->preferred_aspect == + PREFERRED_ASPECT_16_9 ? "*" : ""); + if (r->supported_aspect & SUPPORTED_ASPECT_16_10) + xf86ErrorF(" 16:10%s", + r->preferred_aspect == + PREFERRED_ASPECT_16_10 ? "*" : ""); + if (r->supported_aspect & SUPPORTED_ASPECT_5_4) + xf86ErrorF(" 5:4%s", + r->preferred_aspect == + PREFERRED_ASPECT_5_4 ? "*" : ""); + if (r->supported_aspect & SUPPORTED_ASPECT_15_9) + xf86ErrorF(" 15:9%s", + r->preferred_aspect == + PREFERRED_ASPECT_15_9 ? "*" : ""); + xf86ErrorF("\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:"); + if (r->supported_blanking & CVT_STANDARD) + xf86ErrorF(" standard"); + if (r->supported_blanking & CVT_REDUCED) + xf86ErrorF(" reduced"); + xf86ErrorF("\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:"); + if (r->supported_scaling & SCALING_HSHRINK) + xf86ErrorF(" hshrink"); + if (r->supported_scaling & SCALING_HSTRETCH) + xf86ErrorF(" hstretch"); + if (r->supported_scaling & SCALING_VSHRINK) + xf86ErrorF(" vshrink"); + if (r->supported_scaling & SCALING_VSTRETCH) + xf86ErrorF(" vstretch"); + xf86ErrorF("\n"); + if (r->preferred_refresh) + xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n", + r->preferred_refresh); + else + xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred " + "refresh rate given\n"); + } + else if (r->max_clock != 0) { + xf86ErrorF(" PixClock max %i MHz\n", r->max_clock); + } + else { + xf86ErrorF("\n"); } if (r->gtf_2nd_f > 0) - xf86DrvMsg(scrnIndex,X_INFO," 2nd GTF parameters: f: %i kHz " + xf86DrvMsg(scrnIndex, X_INFO, " 2nd GTF parameters: f: %i kHz " "c: %i m: %i k %i j %i\n", r->gtf_2nd_f, - r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, - r->gtf_2nd_j); + r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, r->gtf_2nd_j); break; } case DS_STD_TIMINGS: - for (j = 0; j<5; j++) - xf86DrvMsg(scrnIndex,X_INFO, - "#%i: hsize: %i vsize %i refresh: %i " - "vid: %i\n",p->index ,det_mon->section.std_t[j].hsize, - det_mon->section.std_t[j].vsize, - det_mon->section.std_t[j].refresh, - det_mon->section.std_t[j].id); + for (j = 0; j < 5; j++) + xf86DrvMsg(scrnIndex, X_INFO, + "#%i: hsize: %i vsize %i refresh: %i " + "vid: %i\n", p->index, det_mon->section.std_t[j].hsize, + det_mon->section.std_t[j].vsize, + det_mon->section.std_t[j].refresh, + det_mon->section.std_t[j].id); break; case DS_WHITE_P: - for (j = 0; j<2; j++) - if (det_mon->section.wp[j].index != 0) - xf86DrvMsg(scrnIndex,X_INFO, - "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", - det_mon->section.wp[j].index,det_mon->section.wp[j].white_x, - det_mon->section.wp[j].white_y, - det_mon->section.wp[j].white_gamma); + for (j = 0; j < 2; j++) + if (det_mon->section.wp[j].index != 0) + xf86DrvMsg(scrnIndex, X_INFO, + "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", + det_mon->section.wp[j].index, + det_mon->section.wp[j].white_x, + det_mon->section.wp[j].white_y, + det_mon->section.wp[j].white_gamma); break; case DS_CMD: - xf86DrvMsg(scrnIndex, X_INFO, - "Color management data: (not decoded)\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Color management data: (not decoded)\n"); break; case DS_CVT: - xf86DrvMsg(scrnIndex, X_INFO, - "CVT 3-byte-code modes:\n"); + xf86DrvMsg(scrnIndex, X_INFO, "CVT 3-byte-code modes:\n"); print_cvt_timings(scrnIndex, det_mon->section.cvt); break; case DS_EST_III: @@ -479,8 +518,8 @@ static void print_number_sections(int scrnIndex, int num) { if (num) - xf86DrvMsg(scrnIndex,X_INFO,"Number of EDID sections to follow: %i\n", - num); + xf86DrvMsg(scrnIndex, X_INFO, "Number of EDID sections to follow: %i\n", + num); } xf86MonPtr @@ -490,7 +529,8 @@ xf86PrintEDID(xf86MonPtr m) char buf[EDID_WIDTH * 2 + 1]; struct det_print_parameter p; - if (!m) return NULL; + if (!m) + return NULL; print_vendor(m->scrnIndex, &m->vendor); print_version(m->scrnIndex, &m->ver); @@ -500,9 +540,7 @@ xf86PrintEDID(xf86MonPtr m) p.m = m; p.index = 0; p.quirks = xf86DDCDetectQuirks(m->scrnIndex, m, FALSE); - xf86ForEachDetailedBlock(m, - handle_detailed_print , - &p); + xf86ForEachDetailedBlock(m, handle_detailed_print, &p); print_number_sections(m->scrnIndex, m->no_sections); /* extension block section stuff */ @@ -511,13 +549,13 @@ xf86PrintEDID(xf86MonPtr m) n = 128; if (m->flags & EDID_COMPLETE_RAWDATA) - n += m->no_sections * 128; + n += m->no_sections * 128; for (i = 0; i < n; i += j) { - for (j = 0; j < EDID_WIDTH; ++j) { - sprintf(&buf[j * 2], "%02x", m->rawData[i + j]); - } - xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf); + for (j = 0; j < EDID_WIDTH; ++j) { + sprintf(&buf[j * 2], "%02x", m->rawData[i + j]); + } + xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf); } return m; diff --git a/xorg-server/hw/xfree86/ddc/xf86DDC.h b/xorg-server/hw/xfree86/ddc/xf86DDC.h index 16a8641c6..2071d530d 100644 --- a/xorg-server/hw/xfree86/ddc/xf86DDC.h +++ b/xorg-server/hw/xfree86/ddc/xf86DDC.h @@ -10,7 +10,7 @@ */ #ifndef XF86_DDC_H -# define XF86_DDC_H +#define XF86_DDC_H #include "edid.h" #include "xf86i2c.h" @@ -18,55 +18,42 @@ /* speed up / slow down */ typedef enum { - DDC_SLOW, - DDC_FAST + DDC_SLOW, + DDC_FAST } xf86ddcSpeed; -typedef void (* DDC1SetSpeedProc)(ScrnInfoPtr, xf86ddcSpeed); +typedef void (*DDC1SetSpeedProc) (ScrnInfoPtr, xf86ddcSpeed); -extern _X_EXPORT xf86MonPtr xf86DoEDID_DDC1( - int scrnIndex, - DDC1SetSpeedProc DDC1SetSpeed, - unsigned int (*DDC1Read)(ScrnInfoPtr) -); +extern _X_EXPORT xf86MonPtr xf86DoEDID_DDC1(int scrnIndex, + DDC1SetSpeedProc DDC1SetSpeed, + unsigned + int (*DDC1Read) (ScrnInfoPtr) + ); -extern _X_EXPORT xf86MonPtr xf86DoEDID_DDC2( - int scrnIndex, - I2CBusPtr pBus -); +extern _X_EXPORT xf86MonPtr xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus); extern _X_EXPORT xf86MonPtr xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool); -extern _X_EXPORT xf86MonPtr xf86PrintEDID( - xf86MonPtr monPtr -); +extern _X_EXPORT xf86MonPtr xf86PrintEDID(xf86MonPtr monPtr); -extern _X_EXPORT xf86MonPtr xf86InterpretEDID( - int screenIndex, Uchar *block -); +extern _X_EXPORT xf86MonPtr xf86InterpretEDID(int screenIndex, Uchar * block); -extern _X_EXPORT xf86MonPtr xf86InterpretEEDID( - int screenIndex, Uchar *block -); +extern _X_EXPORT xf86MonPtr xf86InterpretEEDID(int screenIndex, Uchar * block); extern _X_EXPORT void -xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); + xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); -extern _X_EXPORT Bool xf86SetDDCproperties( - ScrnInfoPtr pScreen, - xf86MonPtr DDC -); +extern _X_EXPORT Bool xf86SetDDCproperties(ScrnInfoPtr pScreen, xf86MonPtr DDC); extern _X_EXPORT DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); extern _X_EXPORT Bool -xf86MonitorIsHDMI(xf86MonPtr mon); + xf86MonitorIsHDMI(xf86MonPtr mon); -extern _X_EXPORT xf86MonPtr -xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus); +extern _X_EXPORT xf86MonPtr xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus); extern _X_EXPORT void -xf86DisplayIDMonitorSet(int scrnIndex, MonPtr mon, xf86MonPtr DDC); + xf86DisplayIDMonitorSet(int scrnIndex, MonPtr mon, xf86MonPtr DDC); extern _X_EXPORT DisplayModePtr FindDMTMode(int hsize, int vsize, int refresh, Bool rb); @@ -100,22 +87,17 @@ typedef enum { DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8, } ddc_quirk_t; -typedef void (* handle_detailed_fn)(struct detailed_monitor_section *,void *); +typedef void (*handle_detailed_fn) (struct detailed_monitor_section *, void *); -void xf86ForEachDetailedBlock(xf86MonPtr mon, - handle_detailed_fn, - void *data); +void xf86ForEachDetailedBlock(xf86MonPtr mon, handle_detailed_fn, void *data); -ddc_quirk_t -xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose); +ddc_quirk_t xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose); void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, ddc_quirk_t quirks, int hsize, int vsize); -typedef void (* handle_video_fn)(struct cea_video_block *, void *); +typedef void (*handle_video_fn) (struct cea_video_block *, void *); -void xf86ForEachVideoBlock(xf86MonPtr, - handle_video_fn, - void *); +void xf86ForEachVideoBlock(xf86MonPtr, handle_video_fn, void *); #endif |