diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
commit | 9508a382f8a9f241dab097d921b6d290c1c3a776 (patch) | |
tree | fa456480bae7040c3f971a70b390f2d091c680b5 /hw/xfree86/ddc | |
parent | ded6147bfb5d75ff1e67c858040a628b61bc17d1 (diff) |
Initial revision
Diffstat (limited to 'hw/xfree86/ddc')
-rw-r--r-- | hw/xfree86/ddc/DDC.HOWTO | 97 | ||||
-rw-r--r-- | hw/xfree86/ddc/ddcPriv.h | 9 | ||||
-rw-r--r-- | hw/xfree86/ddc/ddcProperty.c | 160 | ||||
-rw-r--r-- | hw/xfree86/ddc/edid.c | 137 | ||||
-rw-r--r-- | hw/xfree86/ddc/edid.h | 424 | ||||
-rw-r--r-- | hw/xfree86/ddc/interpret_edid.c | 226 | ||||
-rw-r--r-- | hw/xfree86/ddc/interpret_vdif.c | 129 | ||||
-rw-r--r-- | hw/xfree86/ddc/print_edid.c | 286 | ||||
-rw-r--r-- | hw/xfree86/ddc/print_vdif.c | 222 | ||||
-rw-r--r-- | hw/xfree86/ddc/vdif.h | 174 | ||||
-rw-r--r-- | hw/xfree86/ddc/xf86DDC.c | 379 | ||||
-rw-r--r-- | hw/xfree86/ddc/xf86DDC.h | 61 |
12 files changed, 2304 insertions, 0 deletions
diff --git a/hw/xfree86/ddc/DDC.HOWTO b/hw/xfree86/ddc/DDC.HOWTO new file mode 100644 index 000000000..2f2c95b7f --- /dev/null +++ b/hw/xfree86/ddc/DDC.HOWTO @@ -0,0 +1,97 @@ + DDC.HOWTO + + This file describes how to add DDC support to a chipset driver. + +1) DDC INITIALIZATION + + When implementing DDC in the driver one has the choice between + DDC1 and DDC2. + DDC1 data is contiuously transmitted by a DDC1 capable display + device. The data is send serially over a data line; the Vsync + signal serves as clock. Only one EDID 1.x data block can be + transmitted using DDC1. Since transmission of an EDID1 block + using a regular Vsync frequency would take up several seconds + the driver can increase the Vsync frequency to up to 25 kHz as + soon as it detects DDC1 activety on the data line. + DDC2 data is transmitted using the I2C protocol. This requires + an additional clock line. DDC2 is capable of transmitting EDID1 + and EDID2 block as well as a VDIF block on display devices that + support these. + Display devices switch into the DDC2 mode as soon as they detect + activety on the DDC clock line. Once the are in DDC2 mode they + stop transmitting DDC1 signals until the next power cycle. + + Some graphics chipset configurations which are not capable of + DDC2 might still be able to read DDC1 data. Where available + DDC2 it is preferrable. + + All relevant prototypes and defines are in xf86DDC.h. + DDC2 additionally requires I2C support. The I2C prototypes + are in xf86i2c.h. + + DDC1 Support: + + The driver has to provide a read function which waits for the + end of the next Vsync signal and reads in and returns the status + of the DDC line: + + unsigned int XXX_ddc1Read(ScrnInfoPtr pScrn) + + Additionally a function is required to inclrease the Vsync + frequency to max. 25 kHz. + + void XXX_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) + + If the speed argument is DDC_FAST the function should increase + the Vsync frequency on DDC_SLOW it should restore the original + value. For convenience a generic ddc1SetSpeed() function is provided + in the vga module for VGA-like chipsets. + + void vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, sf86ddcSpeed speed). + + To read out the DDC1 data the driver should call + + xf86MonPtr xf86DoEDID_DDC1(int scrnIndex, + void (*DDC1SetSpeed)(ScrnInfoPtr, xf86ddcSpeed), + unsigned int (*DDC1Read)(ScrnInfoPtr)) + + in PreInit(). DDC1SetSpeed is a pointer to the SetSpeed() + function, DDC1Read has to point to the DDC1 read function. + The function will return a pointer to the xf86Monitor structure + which contains all information retreived by DDC. + NULL will be returned on failure. + + DDC2 Support + + To read out DDC2 information I2C has to be initialized first. + (See documentation for the i2c module). + The function + + xf86MonPtr xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) + + is provided to read out and process DDC2 data. A pointer + to the I2CBusRec of the appropriate I2C Bus has to be passed + as the second argument. + The function will return a pointer to the xf86Monitor structure + which contains all information retreived by DDC. + NULL will be returned on failure. + + Printing monitor parameters + + To print out the information contained in the xf86Monitor + structure the function + + xf86MonPtr xf86PrintEDID(xf86MonPtr monitor) + + is provided. + + Further processing of the xf86Monitor structure is not yet + implemented. Howerver it is planned to use the information + about video modes, gamma values etc. + Therefore it is strongly recommended to read out DDC data + before any video mode processing is done. + + + + +$XFree86: xc/programs/Xserver/hw/xfree86/ddc/DDC.HOWTO,v 1.3 1999/09/25 14:37:16 dawes Exp $ diff --git a/hw/xfree86/ddc/ddcPriv.h b/hw/xfree86/ddc/ddcPriv.h new file mode 100644 index 000000000..b5cb9b836 --- /dev/null +++ b/hw/xfree86/ddc/ddcPriv.h @@ -0,0 +1,9 @@ +extern unsigned char *GetEDID_DDC1( + unsigned int * +); + +extern int DDC_checksum( + unsigned char *, + int +); + diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c new file mode 100644 index 000000000..d779834c2 --- /dev/null +++ b/hw/xfree86/ddc/ddcProperty.c @@ -0,0 +1,160 @@ +/* ddcProperty.c: Make the DDC monitor information available to clients + * as properties on the root window + * + * Copyright 1999 by Andrew C Aitchison <A.C.Aitchison@dpmms.cam.ac.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/ddcProperty.c,v 1.9 2001/10/28 03:33:21 tsi Exp $ */ + +#include "misc.h" +#include "xf86.h" +/* #include "xf86_ansic.h" */ +/* #include "xf86_OSproc.h" */ +#include "Xatom.h" +#include "property.h" +#include "propertyst.h" +#include "xf86DDC.h" + +#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" +#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" +#define VDIF_ATOM_NAME "XFree86_DDC_VDIF_RAWDATA" + +Bool +xf86SetDDCproperties(ScrnInfoPtr pScrnInfo, xf86MonPtr DDC) +{ + Atom EDID1Atom=-1, EDID2Atom=-1, VDIFAtom=-1; + CARD8 *EDID1rawdata = NULL; + CARD8 *EDID2rawdata = NULL; + int i, ret; + Bool makeEDID1prop = FALSE; + Bool makeEDID2prop = FALSE; + +#ifdef DEBUG + ErrorF("xf86SetDDCproperties(%p, %p)\n", pScrnInfo, DDC); +#endif + + if (pScrnInfo==NULL || pScrnInfo->monitor==NULL || DDC==NULL) { + return FALSE; + } + +#ifdef DEBUG + ErrorF("pScrnInfo->scrnIndex %d\n", pScrnInfo->scrnIndex); + + ErrorF("pScrnInfo->monitor was %p\n", pScrnInfo->monitor); +#endif + + pScrnInfo->monitor->DDC = DDC; + + if (DDC->ver.version == 1) { + makeEDID1prop = TRUE; + } else if (DDC->ver.version == 2) { + int checksum1; + int checksum2; + makeEDID2prop = TRUE; + + /* Some monitors (eg Panasonic PanaSync4) + * report version==2 because they used EDID v2 spec document, + * although they use EDID v1 data structure :-( + * + * Try using checksum to determine when we have such a monitor. + */ + checksum2 = 0; + for (i=0; i<256; i++) { checksum2 += DDC->rawData[i]; } + if ( (checksum2 % 256) != 0 ) { + xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v2 checksum failed\n"); + xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); + checksum1 = 0; + for (i=0; i<128; i++) { checksum1 += DDC->rawData[i]; } + if ( (checksum1 % 256) == 0 ) { + xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v1 checksum passed,\n"); + xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID1_RAWDATA property created\n"); + makeEDID1prop = TRUE; + } + } + } else { + xf86DrvMsg(pScrnInfo->scrnIndex, X_PROBED, + "unexpected EDID version %d revision %d\n", + DDC->ver.version, DDC->ver.revision ); + } + + if (makeEDID1prop) { + if ( (EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL ) { + return FALSE; + } + + EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME), TRUE); + + + for (i=0; i<128; i++) { + EDID1rawdata[i] = DDC->rawData[i]; + } + +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", + xf86RegisterRootWindowProperty, + pScrnInfo->scrnIndex, + EDID1Atom, XA_INTEGER, 8, + 128, (unsigned char *)EDID1rawdata ); +#endif + + ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, + EDID1Atom, XA_INTEGER, 8, + 128, (unsigned char *)EDID1rawdata + ); +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); +#endif + + } + + if (makeEDID2prop) { + if ( (EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL ) { + return FALSE; + } + for (i=0; i<256; i++) { + EDID2rawdata[i] = DDC->rawData[i]; + } + + EDID2Atom = MakeAtom(EDID2_ATOM_NAME, sizeof(EDID2_ATOM_NAME), TRUE); + +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", + xf86RegisterRootWindowProperty, + pScrnInfo->scrnIndex, + EDID2Atom, XA_INTEGER, 8, + 256, (unsigned char *)EDID2rawdata ); +#endif + ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, + EDID2Atom, XA_INTEGER, 8, + 256, (unsigned char *)EDID2rawdata + ); +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); +#endif + } + + if (DDC->vdif) { +#define VDIF_DUMMY_STRING "setting dummy VDIF property - please insert correct values\n" +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", + xf86RegisterRootWindowProperty, + pScrnInfo->scrnIndex, + VDIFAtom, XA_STRING, 8, + strlen(VDIF_DUMMY_STRING), VDIF_DUMMY_STRING + ); +#endif + + + VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE); + + ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, + VDIFAtom, XA_STRING, 8, + strlen(VDIF_DUMMY_STRING), + VDIF_DUMMY_STRING + ); +#ifdef DEBUG + ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); +#endif + } + + return TRUE; +} diff --git a/hw/xfree86/ddc/edid.c b/hw/xfree86/ddc/edid.c new file mode 100644 index 000000000..a61940cfa --- /dev/null +++ b/hw/xfree86/ddc/edid.c @@ -0,0 +1,137 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/edid.c,v 1.4 2003/02/17 16:08:27 dawes Exp $ */ + +/* edid.c: retrieve EDID record from raw DDC1 data stream: data + * is contained in an array of unsigned int each unsigned int + * contains one bit if bit is 0 unsigned int has to be zero else + * unsigned int > 0 + * + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ +#include "misc.h" +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" +#include "ddcPriv.h" + +static int find_start(unsigned int *); +static unsigned char * find_header(unsigned char *); +static unsigned char * resort(unsigned char *); + +unsigned char * +GetEDID_DDC1(unsigned int *s_ptr) +{ + unsigned char *d_block, *d_pos; + unsigned int *s_pos, *s_end; + int s_start; + int i,j; + s_start = find_start(s_ptr); + if (s_start==-1) return NULL; + s_end = s_ptr + NUM; + s_pos = s_ptr + s_start; + d_block=xalloc(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++; + } + xfree(s_ptr); + if (d_block && DDC_checksum(d_block,EDID1_LEN)) return NULL; + return (resort(d_block)); +} + +int +DDC_checksum(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]; + } + +#ifdef DEBUG + 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; + + return (result&0xFF); +} + +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; + } + 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); + return (-1); +} + +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}; + + 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++; + } + if (ptr == end) return (NULL); + return (ptr); +} + +static unsigned char * +resort(unsigned char *s_block) +{ + unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; + unsigned char tmp; + + s_end = s_block + EDID1_LEN; + d_new = xalloc(EDID1_LEN); + 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; + } + xfree(s_block); + return (d_new); +} + + diff --git a/hw/xfree86/ddc/edid.h b/hw/xfree86/ddc/edid.h new file mode 100644 index 000000000..7a2f30cb4 --- /dev/null +++ b/hw/xfree86/ddc/edid.h @@ -0,0 +1,424 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/edid.h,v 1.7 2000/04/20 21:28:26 tsi Exp $ */ + +/* edid.h: defines to parse an EDID block + * + * This file contains all information to interpret a standard EDIC block + * transmitted by a display device via DDC (Display Data Channel). So far + * there is no information to deal with optional EDID blocks. + * DDC is a Trademark of VESA (Video Electronics Standard Association). + * + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ + +#ifndef _EDID_H_ +#define _EDID_H_ 1 + +#include "vdif.h" + +/* read complete EDID record */ +#define EDID1_LEN 128 +#define BITS_PER_BYTE 9 +#define NUM BITS_PER_BYTE*EDID1_LEN +#define HEADER 6 + +#define STD_TIMINGS 8 +#define DET_TIMINGS 4 + +#ifdef _PARSE_EDID_ + +/* header: 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 */ +#define HEADER_SECTION 0 +#define HEADER_LENGTH 8 + +/* vendor section */ +#define VENDOR_SECTION (HEADER_SECTION + HEADER_LENGTH) +#define V_MANUFACTURER 0 +#define V_PROD_ID (V_MANUFACTURER + 2) +#define V_SERIAL (V_PROD_ID + 2) +#define V_WEEK (V_SERIAL + 4) +#define V_YEAR (V_WEEK + 1) +#define VENDOR_LENGTH (V_YEAR + 1) + +/* EDID version */ +#define VERSION_SECTION (VENDOR_SECTION + VENDOR_LENGTH) +#define V_VERSION 0 +#define V_REVISION (V_VERSION + 1) +#define VERSION_LENGTH (V_REVISION + 1) + +/* display information */ +#define DISPLAY_SECTION (VERSION_SECTION + VERSION_LENGTH) +#define D_INPUT 0 +#define D_HSIZE (D_INPUT + 1) +#define D_VSIZE (D_HSIZE + 1) +#define D_GAMMA (D_VSIZE + 1) +#define FEAT_S (D_GAMMA + 1) +#define D_RG_LOW (FEAT_S + 1) +#define D_BW_LOW (D_RG_LOW + 1) +#define D_REDX (D_BW_LOW + 1) +#define D_REDY (D_REDX + 1) +#define D_GREENX (D_REDY + 1) +#define D_GREENY (D_GREENX + 1) +#define D_BLUEX (D_GREENY + 1) +#define D_BLUEY (D_BLUEX + 1) +#define D_WHITEX (D_BLUEY + 1) +#define D_WHITEY (D_WHITEX + 1) +#define DISPLAY_LENGTH (D_WHITEY + 1) + +/* supported VESA and other standard timings */ +#define ESTABLISHED_TIMING_SECTION (DISPLAY_SECTION + DISPLAY_LENGTH) +#define E_T1 0 +#define E_T2 (E_T1 + 1) +#define E_TMANU (E_T2 + 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) +#define STD_TIMING_INFO_LEN 2 +#define STD_TIMING_INFO_NUM STD_TIMINGS +#define STD_TIMING_LENGTH (STD_TIMING_INFO_LEN * STD_TIMING_INFO_NUM) + +/* detailed timing info of non standard timings */ +#define DET_TIMING_SECTION (STD_TIMING_SECTION + STD_TIMING_LENGTH) +#define DET_TIMING_INFO_LEN 18 +#define MONITOR_DESC_LEN DET_TIMING_INFO_LEN +#define DET_TIMING_INFO_NUM DET_TIMINGS +#define DET_TIMING_LENGTH (DET_TIMING_INFO_LEN * DET_TIMING_INFO_NUM) + +/* number of EDID sections to follow */ +#define NO_EDID (DET_TIMING_SECTION + DET_TIMING_LENGTH) +/* one byte checksum */ +#define CHECKSUM (NO_EDID + 1) + +#if (CHECKSUM != (EDID1_LEN - 1)) +# 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) + +/* extract information from vendor section */ +#define _PROD_ID(x) x[0] + (x[1] << 8); +#define PROD_ID _PROD_ID(GET_ARRAY(V_PROD_ID)) +#define _SERIAL_NO(x) x[0] + (x[1] << 8) + (x[2] << 16) + (x[3] << 24) +#define SERIAL_NO _SERIAL_NO(GET_ARRAY(V_SERIAL)) +#define _YEAR(x) (x & 0xFF) + 1990 +#define YEAR _YEAR(GET(V_YEAR)) +#define WEEK GET(V_WEEK) & 0xFF +#define _L1(x) ((x[0] & 0x7C) >> 2) + '@' +#define _L2(x) ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@' +#define _L3(x) (x[1] & 0x1F) + '@'; +#define L1 _L1(GET_ARRAY(V_MANUFACTURER)) +#define L2 _L2(GET_ARRAY(V_MANUFACTURER)) +#define L3 _L3(GET_ARRAY(V_MANUFACTURER)) + +/* extract information from version section */ +#define VERSION GET(V_VERSION) +#define REVISION GET(V_REVISION) + +/* extract information from display section */ +#define _INPUT_TYPE(x) ((x & 0x80) >> 7) +#define INPUT_TYPE _INPUT_TYPE(GET(D_INPUT)) +#define _INPUT_VOLTAGE(x) ((x & 0x60) >> 5) +#define INPUT_VOLTAGE _INPUT_VOLTAGE(GET(D_INPUT)) +#define _SETUP(x) ((x & 0x10) >> 4) +#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 GAMMA _GAMMA(GET(D_GAMMA)) +#define HSIZE_MAX GET(D_HSIZE) +#define VSIZE_MAX GET(D_VSIZE) +#define _DPMS(x) ((x & 0xE0) >> 5) +#define DPMS _DPMS(GET(FEAT_S)) +#define _DISPLAY_TYPE(x) ((x & 0x18) >> 3) +#define DISPLAY_TYPE _DISPLAY_TYPE(GET(FEAT_S)) +#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) +#define I_CC(x,y,z) CC_H(y) | CC_L(x,z) +#define F_CC(x) ((x)/1024.0) +#define REDX F_CC(I_CC((GET(D_RG_LOW)),(GET(D_REDX)),6)) +#define REDY F_CC(I_CC((GET(D_RG_LOW)),(GET(D_REDY)),4)) +#define GREENX F_CC(I_CC((GET(D_RG_LOW)),(GET(D_GREENX)),2)) +#define GREENY F_CC(I_CC((GET(D_RG_LOW)),(GET(D_GREENY)),0)) +#define BLUEX F_CC(I_CC((GET(D_BW_LOW)),(GET(D_BLUEX)),6)) +#define BLUEY F_CC(I_CC((GET(D_BW_LOW)),(GET(D_BLUEY)),4)) +#define WHITEX F_CC(I_CC((GET(D_BW_LOW)),(GET(D_WHITEX)),2)) +#define WHITEY F_CC(I_CC((GET(D_BW_LOW)),(GET(D_WHITEY)),0)) + +/* extract information from standard timing section */ +#define T1 GET(E_T1) +#define T2 GET(E_T2) +#define T_MANU GET(E_TMANU) + +/* extract information from estabished timing section */ +#define _HSIZE1(x) ((x[0] + 31) * 8) +#define HSIZE1 _HSIZE1(c) +#define RATIO(x) ((x[1] & 0xC0) >> 6) +#define RATIO1_1 0 +#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; \ + 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 _REFRESH_R(x) (x[1] & 0x3F) + 60 +#define REFRESH_R _REFRESH_R(c) +#define _ID_LOW(x) x[0] +#define ID_LOW _ID_LOW(c) +#define _ID_HIGH(x) (x[1] << 8) +#define ID_HIGH _ID_HIGH(c) +#define STD_TIMING_ID (ID_LOW | ID_HIGH) +#define _NEXT_STD_TIMING(x) (x = (x + STD_TIMING_INFO_LEN)) +#define NEXT_STD_TIMING _NEXT_STD_TIMING(c) + + +/* 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 +#define PIXEL_CLOCK _PIXEL_CLOCK(c) +#define _H_ACTIVE(x) (x[2] + ((x[4] & 0xF0) << 4)) +#define H_ACTIVE _H_ACTIVE(c) +#define _H_BLANK(x) (x[3] + ((x[4] & 0x0F) << 8)) +#define H_BLANK _H_BLANK(c) +#define _V_ACTIVE(x) (x[5] + ((x[7] & 0xF0) << 4)) +#define V_ACTIVE _V_ACTIVE(c) +#define _V_BLANK(x) (x[6] + ((x[7] & 0x0F) << 8)) +#define V_BLANK _V_BLANK(c) +#define _H_SYNC_OFF(x) (x[8] + ((x[11] & 0xC0) << 2)) +#define H_SYNC_OFF _H_SYNC_OFF(c) +#define _H_SYNC_WIDTH(x) (x[9] + ((x[11] & 0x30) << 4)) +#define H_SYNC_WIDTH _H_SYNC_WIDTH(c) +#define _V_SYNC_OFF(x) ((x[10] >> 4) + ((x[11] & 0x0C) << 2)) +#define V_SYNC_OFF _V_SYNC_OFF(c) +#define _V_SYNC_WIDTH(x) ((x[10] & 0x0F) + ((x[11] & 0x03) << 4)) +#define V_SYNC_WIDTH _V_SYNC_WIDTH(c) +#define _H_SIZE(x) (x[12] + ((x[14] & 0xF0) << 4)) +#define H_SIZE _H_SIZE(c) +#define _V_SIZE(x) (x[13] + ((x[14] & 0x0F) << 8)) +#define V_SIZE _V_SIZE(c) +#define _H_BORDER(x) (x[15]) +#define H_BORDER _H_BORDER(c) +#define _V_BORDER(x) (x[16]) +#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 _STEREO(c) +#define _SYNC_T(x) ((x[17] & 0x18) >> 4) +#define SYNC_T _SYNC_T(c) +#define _MISC(x) ((x[17] & 0x06) >> 2) +#define MISC _MISC(c) + +#define _MONITOR_DESC_TYPE(x) x[3] +#define MONITOR_DESC_TYPE _MONITOR_DESC_TYPE(c) +#define SERIAL_NUMBER 0xFF +#define ASCII_STR 0xFE +#define MONITOR_RANGES 0xFD +#define _MIN_V(x) x[5] +#define MIN_V _MIN_V(c) +#define _MAX_V(x) x[6] +#define MAX_V _MAX_V(c) +#define _MIN_H(x) x[7] +#define MIN_H _MIN_H(c) +#define _MAX_H(x) x[8] +#define MAX_H _MAX_H(c) +#define _MAX_CLOCK(x) x[9] +#define MAX_CLOCK _MAX_CLOCK(c) +#define MONITOR_NAME 0xFC +#define ADD_COLOR_POINT 0xFB +#define WHITEX F_CC(I_CC((GET(D_BW_LOW)),(GET(D_WHITEX)),2)) +#define WHITEY F_CC(I_CC((GET(D_BW_LOW)),(GET(D_WHITEY)),0)) +#define _WHITEX_ADD(x,y) F_CC(I_CC(((*(x + y))),(*(x + y + 1)),2)) +#define _WHITEY_ADD(x,y) F_CC(I_CC(((*(x + y))),(*(x + y + 2)),0)) +#define _WHITE_INDEX1(x) x[5] +#define WHITE_INDEX1 _WHITE_INDEX1(c) +#define _WHITE_INDEX2(x) x[10] +#define WHITE_INDEX2 _WHITE_INDEX2(c) +#define WHITEX1 _WHITEX_ADD(c,6) +#define WHITEY1 _WHITEY_ADD(c,6) +#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_GAMMA2(x) _GAMMA(x[14]) +#define WHITE_GAMMA2 _WHITE_GAMMA2(c) +#define ADD_STD_TIMINGS 0xFA + +#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_ */ + +/* input type */ +#define DIGITAL(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 */ + +/* Signal level setup */ +#define SIG_SETUP(x) (x) + +/* sync characteristics */ +#define SEP_SYNC(x) (x & 0x08) +#define COMP_SYNC(x) (x & 0x04) +#define SYNC_O_GREEN(x) (x & 0x02) +#define SYNC_SERR(x) (x & 0x01) + +/* DPMS features */ +#define DPMS_STANDBY(x) (x & 0x04) +#define DPMS_SUSPEND(x) (x & 0x02) +#define DPMS_OFF(x) (x & 0x01) + +/* display type */ +#define DISP_MONO 0 +#define DISP_RGB 1 +#define DISP_MULTCOLOR 2 + +/* Msc stuff EDID Ver > 1.1 */ +#define STD_COLOR_SPACE(x) (x & 0x4) +#define PREFERRED_TIMING_MODE(x) (x & 0x2) +#define GFT_SUPPORTED(x) (x & 0x1) + +/* 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) + +typedef unsigned int Uint; +typedef unsigned char Uchar; + +struct vendor { + char name[4]; + int prod_id; + Uint serial; + int week; + int year; +}; + +struct edid_version { + 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; + 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; +}; + +struct std_timings { + 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; +}; + +#define DT 0 +#define DS_SERIAL 0xFF +#define DS_ASCII_STR 0xFE +#define DS_NAME 0xFC +#define DS_RANGES 0xFD +#define DS_WHITE_P 0xFB +#define DS_STD_TIMINGS 0xFA + +struct monitor_ranges { + int min_v; + int max_v; + int min_h; + int max_h; + int max_clock; +}; + +struct whitePoints{ + int index; + float white_x; + float white_y; + float white_gamma; +}; + +struct detailed_monitor_section { + int type; + union { + struct detailed_timings d_timings; + Uchar serial[13]; + Uchar ascii_data[13]; + Uchar name[13]; + struct monitor_ranges ranges; + struct std_timings std_t[5]; + struct whitePoints wp[2]; + } section; +}; + +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]; + xf86vdifPtr vdif; + int no_sections; + Uchar *rawData; +} xf86Monitor, *xf86MonPtr; + +extern xf86MonPtr ConfiguredMonitor; + +#endif /* _EDID_H_ */ diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c new file mode 100644 index 000000000..c0092aed9 --- /dev/null +++ b/hw/xfree86/ddc/interpret_edid.c @@ -0,0 +1,226 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/interpret_edid.c,v 1.8 2000/07/13 21:31:37 tsi Exp $ */ + +/* interpret_edid.c: interpret a primary EDID block + * + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ +#include "misc.h" +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#define _PARSE_EDID_ +#include "xf86DDC.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 *); +static void get_established_timing_section(Uchar*, struct established_timings *); +static void get_std_timing_section(Uchar*, struct std_timings *); +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_monitor_ranges(Uchar *, struct monitor_ranges *); +static void get_whitepoint_section(Uchar *, struct whitePoints *); +static void get_detailed_timing_section(Uchar*, struct detailed_timings *); + +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); + get_display_section(SECTION(DISPLAY_SECTION,block),&m->features); + get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block), + &m->timings1); + get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2); + 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); +} + +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) +{ + r->input_type = INPUT_TYPE; + r->input_voltage = INPUT_VOLTAGE; + r->input_setup = SETUP; + r->input_sync = SYNC; + 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_std_timing_section(Uchar *c, struct std_timings *r) +{ + 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; + NEXT_STD_TIMING; + } +} + +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++) { + if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { + + switch (MONITOR_DESC_TYPE) { + case SERIAL_NUMBER: + det_mon[i].type = DS_SERIAL; + copy_string(c,det_mon[i].section.serial); + break; + case ASCII_STR: + det_mon[i].type = DS_ASCII_STR; + copy_string(c,det_mon[i].section.ascii_data); + break; + case MONITOR_RANGES: + det_mon[i].type = DS_RANGES; + get_monitor_ranges(c,&det_mon[i].section.ranges); + break; + case MONITOR_NAME: + det_mon[i].type = DS_NAME; + copy_string(c,det_mon[i].section.name); + break; + case ADD_COLOR_POINT: + det_mon[i].type = DS_WHITE_P; + get_whitepoint_section(c,det_mon[i].section.wp); + break; + case ADD_STD_TIMINGS: + det_mon[i].type = DS_STD_TIMINGS; + get_dst_timing_section(c,det_mon[i].section.std_t); + break; + } + } else { + det_mon[i].type = DT; + get_detailed_timing_section(c,&det_mon[i].section.d_timings); + } + 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) +{ + 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 = MAX_CLOCK * 10; +} + +static void +get_whitepoint_section(Uchar *c, struct whitePoints *wp) +{ + wp[1].white_x = WHITEX1; + wp[1].white_y = WHITEY1; + wp[2].white_x = WHITEX2; + wp[2].white_y = WHITEY2; + wp[1].index = WHITE_INDEX1; + wp[2].index = WHITE_INDEX2; + wp[1].white_gamma = WHITE_GAMMA1; + wp[2].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->sync = SYNC_T; + r->misc = MISC; +} + + diff --git a/hw/xfree86/ddc/interpret_vdif.c b/hw/xfree86/ddc/interpret_vdif.c new file mode 100644 index 000000000..acd931e70 --- /dev/null +++ b/hw/xfree86/ddc/interpret_vdif.c @@ -0,0 +1,129 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/interpret_vdif.c,v 1.6 2000/01/21 02:30:00 dawes Exp $ */ + +#include "Xarch.h" +#include "xf86DDC.h" +#include "vdif.h" + +static xf86VdifLimitsPtr* get_limits(CARD8 *c); +static xf86VdifGammaPtr* get_gamma(CARD8 *c); +static xf86VdifTimingPtr* get_timings(CARD8 *c); +#if X_BYTE_ORDER == X_BIG_ENDIAN +static CARD32 swap_byte_order(CARD32 c); +#endif + +xf86vdifPtr +xf86InterpretVdif(CARD8 *c) +{ + xf86VdifPtr p = (xf86VdifPtr)c; + xf86vdifPtr vdif; + int i; +#if X_BYTE_ORDER == X_BIG_ENDIAN + int length; +#endif + unsigned long l = 0; + + if (c == NULL) return NULL; +#if X_BYTE_ORDER == X_BIG_ENDIAN + length = swap_byte_order(p->FileLength); + for (i = 0; i < (length >>2); i++) + ((CARD32*)c)[i] = swap_byte_order(((CARD32*)c)[i]) ; +#endif + if (p->VDIFId[0] != 'V' || p->VDIFId[1] != 'D' || p->VDIFId[2] != 'I' + || p->VDIFId[3] != 'F') return NULL; + for ( i = 12; i < p->FileLength; i++) + l += c[i]; + if ( l != p->Checksum) return NULL; + vdif = xalloc(sizeof(xf86vdif)); + vdif->vdif = p; + vdif->limits = get_limits(c); + vdif->timings = get_timings(c); + vdif->gamma = get_gamma(c); + vdif->strings = VDIF_STRING(((xf86VdifPtr)c),0); + xfree(c); + return vdif; +} + +static xf86VdifLimitsPtr* +get_limits(CARD8 *c) +{ + int num, i, j; + xf86VdifLimitsPtr *pp; + xf86VdifLimitsPtr p; + + num = ((xf86VdifPtr)c)->NumberOperationalLimits; + pp = xalloc(sizeof(xf86VdifLimitsPtr) * (num+1)); + p = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c)); + j = 0; + for ( i = 0; i<num; i++) { + if (p->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG) + pp[j++] = p; + VDIF_NEXT_OPERATIONAL_LIMITS(p); + } + pp[j] = NULL; + return pp; +} + +static xf86VdifGammaPtr* +get_gamma(CARD8 *c) +{ + int num, i, j; + xf86VdifGammaPtr *pp; + xf86VdifGammaPtr p; + + num = ((xf86VdifPtr)c)->NumberOptions; + pp = xalloc(sizeof(xf86VdifGammaPtr) * (num+1)); + p = (xf86VdifGammaPtr)VDIF_OPTIONS(((xf86VdifPtr)c)); + j = 0; + for ( i = 0; i<num; i++) + { + if (p->Header.ScnTag == VDIF_GAMMA_TABLE_TAG) + pp[j++] = p; + VDIF_NEXT_OPTIONS(p); + } + pp[j] = NULL; + return pp; +} + +static xf86VdifTimingPtr* +get_timings(CARD8 *c) +{ + int num, num_limits; + int i,j,k; + xf86VdifLimitsPtr lp; + xf86VdifTimingPtr *pp; + xf86VdifTimingPtr p; + + num = ((xf86VdifPtr)c)->NumberOperationalLimits; + lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c)); + num_limits = 0; + for (i = 0; i < num; i++) { + if (lp->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG) + num_limits += lp->NumberPreadjustedTimings; + VDIF_NEXT_OPERATIONAL_LIMITS(lp); + } + pp = xalloc(sizeof(xf86VdifTimingPtr) + * (num_limits+1)); + j = 0; + lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr) c)); + for (i = 0; i < num; i++) { + p = VDIF_PREADJUSTED_TIMING(lp); + for (k = 0; k < lp->NumberPreadjustedTimings; k++) { + if (p->Header.ScnTag == VDIF_PREADJUSTED_TIMING_TAG) + pp[j++] = p; + VDIF_NEXT_PREADJUSTED_TIMING(p); + } + VDIF_NEXT_OPERATIONAL_LIMITS(lp); + } + pp[j] = NULL; + return pp; +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN +static CARD32 +swap_byte_order(CARD32 c) +{ + return ((c & 0xFF000000) >> 24) | ((c & 0xFF0000) >> 8) + | ((c & 0xFF00) << 8) | ((c & 0xFF) << 24); +} + +#endif diff --git a/hw/xfree86/ddc/print_edid.c b/hw/xfree86/ddc/print_edid.c new file mode 100644 index 000000000..3451e52f6 --- /dev/null +++ b/hw/xfree86/ddc/print_edid.c @@ -0,0 +1,286 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/print_edid.c,v 1.15 2001/05/22 17:01:23 tsi Exp $ */ + +/* print_edid.c: print out all information retrieved from display device + * + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ +#include "misc.h" +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" + +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_established_timings(int scrnIndex, + struct established_timings *); +static void print_std_timings(int scrnIndex, struct std_timings *); +static void print_detailed_monitor_section(int scrnIndex, + struct detailed_monitor_section *); +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_whitepoint(int scrnIndex, struct disp_features *); + +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_established_timings(m->scrnIndex,&m->timings1); + print_std_timings(m->scrnIndex,m->timings2); + print_detailed_monitor_section(m->scrnIndex,m->det_mon); + return m; +} + +static void +print_vendor(int scrnIndex, struct vendor *c) +{ + xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer: %s Model: %x Serial#: %u\n", + &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); +} + +static void +print_display(int scrnIndex, struct disp_features *disp) +{ + print_input_features(scrnIndex,disp); + xf86DrvMsg(scrnIndex,X_INFO,"Max H-Image Size [cm]: "); + if (disp->hsize) + xf86ErrorF("horiz.: %i ",disp->hsize); + else + xf86ErrorF("H-Size may change, "); + if (disp->vsize) + xf86ErrorF("vert.: %i\n",disp->vsize); + else + xf86ErrorF("V-Size may change\n"); + xf86DrvMsg(scrnIndex,X_INFO,"Gamma: %.2f\n", disp->gamma); + print_dpms_features(scrnIndex,disp); + print_whitepoint(scrnIndex,disp); +} + +static void +print_input_features(int scrnIndex, struct disp_features *c) +{ + if (DIGITAL(c->input_type)) + xf86DrvMsg(scrnIndex,X_INFO,"Digital Display Input\n"); + 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"); + } +} + +static void +print_dpms_features(int scrnIndex, struct disp_features *c) +{ + 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"); + 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; + } + if (STD_COLOR_SPACE(c->msc)) + xf86DrvMsg(scrnIndex,X_INFO, + "Default color space is primary color space\n"); + if (PREFERRED_TIMING_MODE(c->msc)) + xf86DrvMsg(scrnIndex,X_INFO, + "First detailed timing is preferred mode\n"); + if (GFT_SUPPORTED(c->msc)) + xf86DrvMsg(scrnIndex,X_INFO, + "GTF timings supported\n"); +} + +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); +} + +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 VESA Video Modes:\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,"1152x870@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 Future Video Modes:\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); + } + } +} + +static void +print_detailed_monitor_section(int scrnIndex, + struct detailed_monitor_section *m) +{ + int i,j; + + for (i=0;i<DET_TIMINGS;i++) { + switch (m[i].type) { + case DT: + print_detailed_timings(scrnIndex,&m[i].section.d_timings); + break; + case DS_SERIAL: + xf86DrvMsg(scrnIndex,X_INFO,"Serial No: %s\n",m[i].section.serial); + break; + case DS_ASCII_STR: + xf86DrvMsg(scrnIndex,X_INFO," %s\n",m[i].section.ascii_data); + break; + case DS_NAME: + xf86DrvMsg(scrnIndex,X_INFO,"Monitor name: %s\n",m[i].section.name); + break; + case DS_RANGES: + xf86DrvMsg(scrnIndex,X_INFO, + "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,", + m[i].section.ranges.min_v, m[i].section.ranges.max_v, + m[i].section.ranges.min_h, m[i].section.ranges.max_h); + 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"); + 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",i,m[i].section.std_t[i].hsize, + m[i].section.std_t[j].vsize,m[i].section.std_t[j].refresh, + m[i].section.std_t[j].id); + break; + case DS_WHITE_P: + for (j = 0; j<2; j++) + if (m[i].section.wp[j].index != 0) + xf86DrvMsg(scrnIndex,X_INFO, + "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", + m[i].section.wp[j].index,m[i].section.wp[j].white_x, + m[i].section.wp[j].white_y, + m[i].section.wp[j].white_gamma); + break; + } + } +} + +static void +print_detailed_timings(int scrnIndex, struct detailed_timings *t) +{ + + if (t->clock > 15000000) { /* sanity check */ + xf86DrvMsg(scrnIndex,X_INFO,"Supported additional Video Mode:\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_ON_SYNC(t->stereo)) + xf86ErrorF("right channel on sync\n"); + else xf86ErrorF("right channel on sync\n"); + } + } +} diff --git a/hw/xfree86/ddc/print_vdif.c b/hw/xfree86/ddc/print_vdif.c new file mode 100644 index 000000000..c65d1a0c9 --- /dev/null +++ b/hw/xfree86/ddc/print_vdif.c @@ -0,0 +1,222 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/print_vdif.c,v 1.3 2003/02/17 16:08:27 dawes Exp $ */ + +#include "vdif.h" +#include "misc.h" +#include "xf86DDC.h" + +static void print_vdif(xf86VdifPtr l, char *s); +static void print_timings(xf86VdifTimingPtr *pt); +static void print_limits(xf86VdifLimitsPtr *pl); +static void print_gamma(xf86VdifGammaPtr *pg); +static void print_type(CARD8 c); +static void print_polarity(CARD8 c); + +void +xf86print_vdif(xf86vdifPtr v) +{ + print_vdif(v->vdif,v->strings); + print_limits(v->limits); + print_timings(v->timings); + print_gamma(v->gamma); +} + +static void +print_vdif(xf86VdifPtr l, char *s) +{ + ErrorF("Version %i.%i",l->VDIFVersion,l->VDIFRevision); + ErrorF(" Date: %i/%i/%i, Manufactured: %i/%i/%i\n",l->Date[0], + l->Date[1],l->Date[2],l->DateManufactured[0], + l->DateManufactured[1],l->DateManufactured[2]); + ErrorF("File Revision: %i",l->FileRevision); + ErrorF("Manufacturer: %s\n",s + l->Manufacturer); + ErrorF("ModelNumber: %s\n",s + l->ModelNumber); + ErrorF("VDIFIndex: %s\n",s +l->MinVDIFIndex); + ErrorF("Version: %s\n",s + l->Version); + ErrorF("SerialNumber %s\n",s + l->SerialNumber); + ErrorF("MonitorType: "); + switch (l->MonitorType) { + case VDIF_MONITOR_MONOCHROME: + ErrorF("Mono\n"); + break; + case VDIF_MONITOR_COLOR: + ErrorF("Color\n"); + break; + } + ErrorF("CRT Size: %i inches\n",l->CRTSize); + switch (l->MonitorType) { + case VDIF_MONITOR_MONOCHROME: + ErrorF("Border: %i percent\n", + l->BorderRed); + ErrorF("Phosphor Decay: 1: %i,",l->RedPhosphorDecay); + if (l->GreenPhosphorDecay !=0) + ErrorF(" 2: %i,",l->GreenPhosphorDecay); + if (l->BluePhosphorDecay !=0) + ErrorF(" 3: %i",l->BluePhosphorDecay); + ErrorF(" ms\n"); + if (l->RedChromaticity_x) + ErrorF("Chromaticity: 1: x:%f, y:%f; ", + l->RedChromaticity_x/1000.0,l->RedChromaticity_y/1000.0); + if (l->GreenChromaticity_x) + ErrorF("Chromaticity: 2: x:%f, y:%f; ", + l->GreenChromaticity_x/1000.0,l->GreenChromaticity_y/1000.0); + if (l->BlueChromaticity_x) + ErrorF("Chromaticity: 3: x:%f, y:%f ", + l->BlueChromaticity_x/1000.0,l->BlueChromaticity_y/1000.0); + ErrorF("\n"); + ErrorF("Gamma: %f\n",l->RedGamma/1000.0); + break; + case VDIF_MONITOR_COLOR: + ErrorF("Border: Red: %i Green: %i Blue: %i percent\n", + l->BorderRed,l->BorderGreen,l->BorderBlue); + ErrorF("Phosphor Decay: Red: %i, Green: %i, Blue: %i ms\n", + l->RedPhosphorDecay,l->GreenPhosphorDecay,l->BluePhosphorDecay); + ErrorF("Chromaticity: Red: x:%f, y:%f; Green: x:%f, y:%f; " + "Blue: x:%f, y:%f\n", + l->RedChromaticity_x/1000.0,l->RedChromaticity_y/1000.0, + l->GreenChromaticity_x/1000.0,l->GreenChromaticity_y/1000.0, + l->BlueChromaticity_x/1000.0,l->BlueChromaticity_y/1000.0); + ErrorF("Gamma: Red:%f, Green:%f, Blue:%f\n",l->RedGamma/1000.0, + l->GreenGamma/1000.0,l->BlueGamma/1000.0); + break; + } + ErrorF("White Point: x: %f y: %f Y: %f\n",l->WhitePoint_x/1000.0, + l->WhitePoint_y/1000.0,l->WhitePoint_Y/1000.0); +} + +static void +print_limits(xf86VdifLimitsPtr *pl) +{ + int i = 0; + xf86VdifLimitsPtr l; + + while((l = pl[i]) != NULL) { + ErrorF("Max display resolution: %i x %i pixel\n",l->MaxHorPixel, + l->MaxVerPixel); + ErrorF("Size of active area: %i x %i millimeters\n",l->MaxHorActiveLength, + l->MaxVerActiveHeight); + ErrorF("Video Type: "); + print_type(l->VideoType); + ErrorF("Sync Type: "); + print_type(l->SyncType); + ErrorF("Sync Configuration "); + switch (l->SyncConfiguration) { + case VDIF_SYNC_SEPARATE: + ErrorF("separate\n"); + break; + case VDIF_SYNC_C: + ErrorF("composite C\n"); + break; + case VDIF_SYNC_CP: + ErrorF("composite CP\n"); + break; + case VDIF_SYNC_G: + ErrorF("composite G\n"); + break; + case VDIF_SYNC_GP: + ErrorF("composite GP\n"); + break; + case VDIF_SYNC_OTHER: + ErrorF("other\n"); + break; + } + ErrorF("Termination Resistance: %i\n",l->TerminationResistance); + ErrorF("Levels: white: %i, black: %i, blank: %i, sync: %i mV\n", + l->WhiteLevel,l->BlackLevel,l->BlankLevel,l->SyncLevel); + ErrorF("Max. Pixel Clock: %f MHz\n",l->MaxPixelClock/1000.0); + ErrorF("Freq. Range: Hor.: %f - %f kHz, Ver.: %f - %f Hz\n", + l->MaxHorFrequency/1000.0,l->MinHorFrequency/1000.0, + l->MaxVerFrequency/1000.0,l->MinVerFrequency/1000.0); + ErrorF("Retrace time: Hor: %f us, Ver: %f ms\n",l->MinHorRetrace/1000.0, + l->MinVerRetrace/1000.0); + } +} + +static void +print_timings(xf86VdifTimingPtr *pt) +{ + int i = 0; + xf86VdifTimingPtr t; + + while((t = pt[i]) != NULL) { + ErrorF("SVGA / SVPMI mode number: %i\n",t->PreadjustedTimingName); + ErrorF("Mode %i x %i\n",t->HorPixel,t->VerPixel); + ErrorF("Size: %i x %i mm\n",t->HorAddrLength,t->VerAddrHeight); + ErrorF("Ratios: %i/%i\n",t->PixelWidthRatio,t->PixelHeightRatio); + ErrorF("Character width: %i",t->CharacterWidth); + ErrorF("Clock: %f MHz HFreq.: %f kHz, VFreq: %f Hz\n",t->PixelClock/1000.0, + t->HorFrequency/1000.0,t->VerFrequency/1000.0); + ErrorF("Htotal: %f us, Vtotal %f ms\n", t->HorTotalTime/1000.0, + t->VerTotalTime/1000.0); + ErrorF("HDisp: %f, HBlankStart: %f, HBlankLength: %f, " + "HSyncStart: %f HSyncEnd: %f us\n",t->HorAddrTime/1000.0, + t->HorBlankStart/1000.0,t->HorBlankTime/1000.0, + t->HorSyncStart/1000.0,t->HorSyncTime/1000.0); + ErrorF("VDisp: %f, VBlankStart: %f, VBlankLength: %f, " + "VSyncStart: %f VSyncEnd: %f us\n",t->VerAddrTime/1000.0, + t->VerBlankStart/1000.0,t->VerBlankTime/1000.0, + t->VerSyncStart/1000.0,t->VerSyncTime/1000.0); + ErrorF("Scan Type: "); + switch (t->ScanType) { + case VDIF_SCAN_INTERLACED: + ErrorF("interlaced "); + break; + case VDIF_SCAN_NONINTERLACED: + ErrorF("non interlaced "); + break; + case VDIF_SCAN_OTHER: + ErrorF("other "); + break; + } + ErrorF("Polarity: H: "); + print_polarity(t->HorSyncPolarity); + ErrorF("V: "); + print_polarity(t->VerSyncPolarity); + ErrorF("\n"); + } +} + +static void +print_gamma(xf86VdifGammaPtr *pg) +{ + int i = 0; + xf86VdifGammaPtr g; + + while((g = pg[i]) != NULL) { + ErrorF("Gamma Table Entries: %i\n",g->GammaTableEntries); + } +} + +static void +print_type(CARD8 c) +{ + switch (c) { + case VDIF_VIDEO_TTL : + ErrorF("TTL\n"); + break; + case VDIF_VIDEO_ANALOG : + ErrorF("Analog\n"); + break; + case VDIF_VIDEO_ECL: + ErrorF("ECL\n"); + break; + case VDIF_VIDEO_DECL: + ErrorF("DECL\n"); + break; + case VDIF_VIDEO_OTHER: + ErrorF("other\n"); + break; + } +} + +static void +print_polarity(CARD8 c) +{ + switch (c) { + case VDIF_POLARITY_NEGATIVE: + ErrorF(" Neg."); + break; + case VDIF_POLARITY_POSITIVE: + ErrorF(" Pos."); + break; + } +} diff --git a/hw/xfree86/ddc/vdif.h b/hw/xfree86/ddc/vdif.h new file mode 100644 index 000000000..38026e56a --- /dev/null +++ b/hw/xfree86/ddc/vdif.h @@ -0,0 +1,174 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/vdif.h,v 1.3 2000/04/14 12:16:04 tsi Exp $ */ + +#ifndef _VDIF_H +#define _VDIF_H + +#define VDIF_MONITOR_MONOCHROME 0 +#define VDIF_MONITOR_COLOR 1 +#define VDIF_VIDEO_TTL 0 +#define VDIF_VIDEO_ANALOG 1 +#define VDIF_VIDEO_ECL 2 +#define VDIF_VIDEO_DECL 3 +#define VDIF_VIDEO_OTHER 4 +#define VDIF_SYNC_SEPARATE 0 +#define VDIF_SYNC_C 1 +#define VDIF_SYNC_CP 2 +#define VDIF_SYNC_G 3 +#define VDIF_SYNC_GP 4 +#define VDIF_SYNC_OTHER 5 +#define VDIF_SCAN_NONINTERLACED 0 +#define VDIF_SCAN_INTERLACED 1 +#define VDIF_SCAN_OTHER 2 +#define VDIF_POLARITY_NEGATIVE 0 +#define VDIF_POLARITY_POSITIVE 1 + +#include "Xmd.h" + +#pragma pack(1) + +typedef struct _VDIF { /* Monitor Description: */ + CARD8 VDIFId[4]; /* alway "VDIF" */ + CARD32 FileLength; /* lenght of the whole file */ + CARD32 Checksum; /* sum of all bytes in the file after*/ + /* this field */ + CARD16 VDIFVersion; /* structure version number */ + CARD16 VDIFRevision; /* structure revision number */ + CARD16 Date[3]; /* file date Year/Month/Day */ + CARD16 DateManufactured[3]; /* date Year/Month/Day */ + CARD32 FileRevision; /* file revision string */ + CARD32 Manufacturer; /* ASCII ID of the manufacturer */ + CARD32 ModelNumber; /* ASCII ID of the model */ + CARD32 MinVDIFIndex; /* ASCII ID of Minimum VDIF index */ + CARD32 Version; /* ASCII ID of the model version */ + CARD32 SerialNumber; /* ASCII ID of the serial number */ + CARD8 MonitorType; /* Monochrome or Color */ + CARD8 CRTSize; /* inches */ + CARD8 BorderRed; /* percent */ + CARD8 BorderGreen; /* percent */ + CARD8 BorderBlue; /* percent */ + CARD8 Reserved1; /* padding */ + CARD16 Reserved2; /* padding */ + CARD32 RedPhosphorDecay; /* microseconds */ + CARD32 GreenPhosphorDecay; /* microseconds */ + CARD32 BluePhosphorDecay; /* microseconds */ + CARD16 WhitePoint_x; /* WhitePoint in CIExyY (scale 1000) */ + CARD16 WhitePoint_y; + CARD16 WhitePoint_Y; + CARD16 RedChromaticity_x; /* Red chromaticity in x,y */ + CARD16 RedChromaticity_y; + CARD16 GreenChromaticity_x; /* Green chromaticity in x,y */ + CARD16 GreenChromaticity_y; + CARD16 BlueChromaticity_x; /* Blue chromaticity in x,y */ + CARD16 BlueChromaticity_y; + CARD16 RedGamma; /* Gamme curve exponent (scale 1000) */ + CARD16 GreenGamma; + CARD16 BlueGamma; + CARD32 NumberOperationalLimits; + CARD32 OffsetOperationalLimits; + CARD32 NumberOptions; /* optinal sections (gamma table) */ + CARD32 OffsetOptions; + CARD32 OffsetStringTable; +} xf86VdifRec, *xf86VdifPtr; + +typedef enum { /* Tags for section identification */ + VDIF_OPERATIONAL_LIMITS_TAG = 1, + VDIF_PREADJUSTED_TIMING_TAG, + VDIF_GAMMA_TABLE_TAG +} VDIFScnTag; + +typedef struct _VDIFScnHdr { /* Generic Section Header: */ + CARD32 ScnLength; /* lenght of section */ + CARD32 ScnTag; /* tag for section identification */ +} VDIFScnHdrRec, *VDIFScnHdrPtr; + +typedef struct _VDIFLimits { /* Operational Limits: */ + VDIFScnHdrRec Header; /* common section info */ + CARD16 MaxHorPixel; /* pixels */ + CARD16 MaxVerPixel; /* lines */ + CARD16 MaxHorActiveLength; /* millimeters */ + CARD16 MaxVerActiveHeight; /* millimeters */ + CARD8 VideoType; /* TTL / Analog / ECL / DECL */ + CARD8 SyncType; /* TTL / Analog / ECL / DECL */ + CARD8 SyncConfiguration; /* separate / composite / other */ + CARD8 Reserved1; /* padding */ + CARD16 Reserved2; /* padding */ + CARD16 TerminationResistance; /* */ + CARD16 WhiteLevel; /* millivolts */ + CARD16 BlackLevel; /* millivolts */ + CARD16 BlankLevel; /* millivolts */ + CARD16 SyncLevel; /* millivolts */ + CARD32 MaxPixelClock; /* kiloHertz */ + CARD32 MinHorFrequency; /* Hertz */ + CARD32 MaxHorFrequency; /* Hertz */ + CARD32 MinVerFrequency; /* milliHertz */ + CARD32 MaxVerFrequency; /* milliHertz */ + CARD16 MinHorRetrace; /* nanoseconds */ + CARD16 MinVerRetrace; /* microseconds */ + CARD32 NumberPreadjustedTimings; + CARD32 OffsetNextLimits; +} xf86VdifLimitsRec, *xf86VdifLimitsPtr; + +typedef struct _VDIFTiming { /* Preadjusted Timing: */ + VDIFScnHdrRec Header; /* common section info */ + CARD32 PreadjustedTimingName; /* SVGA/SVPMI mode number */ + CARD16 HorPixel; /* pixels */ + CARD16 VerPixel; /* lines */ + CARD16 HorAddrLength; /* millimeters */ + CARD16 VerAddrHeight; /* millimeters */ + CARD8 PixelWidthRatio; /* gives H:V */ + CARD8 PixelHeightRatio; + CARD8 Reserved1; /* padding */ + CARD8 ScanType; /* noninterlaced / interlaced / other*/ + CARD8 HorSyncPolarity; /* negative / positive */ + CARD8 VerSyncPolarity; /* negative / positive */ + CARD16 CharacterWidth; /* pixels */ + CARD32 PixelClock; /* kiloHertz */ + CARD32 HorFrequency; /* Hertz */ + CARD32 VerFrequency; /* milliHertz */ + CARD32 HorTotalTime; /* nanoseconds */ + CARD32 VerTotalTime; /* microseconds */ + CARD16 HorAddrTime; /* nanoseconds */ + CARD16 HorBlankStart; /* nanoseconds */ + CARD16 HorBlankTime; /* nanoseconds */ + CARD16 HorSyncStart; /* nanoseconds */ + CARD16 HorSyncTime; /* nanoseconds */ + CARD16 VerAddrTime; /* microseconds */ + CARD16 VerBlankStart; /* microseconds */ + CARD16 VerBlankTime; /* microseconds */ + CARD16 VerSyncStart; /* microseconds */ + CARD16 VerSyncTime; /* microseconds */ +} xf86VdifTimingRec, *xf86VdifTimingPtr; + +typedef struct _VDIFGamma { /* Gamma Table: */ + VDIFScnHdrRec Header; /* common section info */ + CARD16 GammaTableEntries; /* count of grays or RGB 3-tuples */ + CARD16 Unused1; +} xf86VdifGammaRec, *xf86VdifGammaPtr; + +/* access macros */ +#define VDIF_OPERATIONAL_LIMITS(vdif) \ +((xf86VdifLimitsPtr)((char*)(vdif) + (vdif)->OffsetOperationalLimits)) +#define VDIF_NEXT_OPERATIONAL_LIMITS(limits) limits = \ + ((xf86VdifLimitsPtr)((char*)(limits) + (limits)->OffsetNextLimits)) +#define VDIF_PREADJUSTED_TIMING(limits) \ +((xf86VdifTimingPtr)((char*)(limits) + (limits)->Header.ScnLength)) +#define VDIF_NEXT_PREADJUSTED_TIMING(timing) timing = \ + ((xf86VdifTimingPtr)((char*)(timing) + (timing)->Header.ScnLength)) +#define VDIF_OPTIONS(vdif) \ + ((VDIFScnHdrPtr)((char*)(vdif) + (vdif)->OffsetOptions)) +#define VDIF_NEXT_OPTIONS(options) options = \ + ((xf86VdifGammaPtr)((char*)(options) + (options)->Header.ScnLength)) +#define VDIF_STRING(vdif, string) \ + ((char*)((char*)vdif + vdif->OffsetStringTable + (string))) + +typedef struct _vdif { + xf86VdifPtr vdif; + xf86VdifLimitsPtr *limits; + xf86VdifTimingPtr *timings; + xf86VdifGammaPtr *gamma; + char * strings; +} xf86vdif, *xf86vdifPtr; + +#pragma pack() + +#endif diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c new file mode 100644 index 000000000..736fb741b --- /dev/null +++ b/hw/xfree86/ddc/xf86DDC.c @@ -0,0 +1,379 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/xf86DDC.c,v 1.23 2003/02/17 16:08:27 dawes Exp $ */ + +/* xf86DDC.c + * + * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ +#include "misc.h" +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" +#include "ddcPriv.h" + +#ifdef XFree86LOADER +static const OptionInfoRec *DDCAvailableOptions(void *unused); +#endif + +const char *i2cSymbols[] = { + "xf86CreateI2CDevRec", + "xf86I2CDevInit", + "xf86I2CWriteRead", + "xf86DestroyI2CDevRec", + NULL +}; + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(ddcSetup); + +static XF86ModuleVersionInfo ddcVersRec = +{ + "ddc", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +XF86ModuleData ddcModuleData = { &ddcVersRec, ddcSetup, NULL }; + +ModuleInfoRec DDC = { + 1, + "DDC", + NULL, + 0, + DDCAvailableOptions, +}; + +static pointer +ddcSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; +#ifndef REMOVE_LOADER_CHECK_MODULE_INFO + if (xf86LoaderCheckSymbol("xf86AddModuleInfo")) +#endif + xf86AddModuleInfo(&DDC, module); + /* + * Tell the loader about symbols from other modules that this module + * might refer to. + */ + LoaderRefSymLists(i2cSymbols, NULL); + + } + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer)1; +} + +#endif + +#define RETRIES 4 + +static unsigned char *EDIDRead_DDC1( + ScrnInfoPtr pScrn, + void (*)(ScrnInfoPtr,xf86ddcSpeed), + unsigned int (*)(ScrnInfoPtr) +); + +static Bool TestDDC1( + ScrnInfoPtr pScrn, + unsigned int (*)(ScrnInfoPtr) +); + +static unsigned int *FetchEDID_DDC1( + ScrnInfoPtr, + register unsigned int (*)(ScrnInfoPtr) +); + +static unsigned char* EDID1Read_DDC2( + int scrnIndex, + I2CBusPtr pBus +); + +static unsigned char * VDIFRead( + int scrnIndex, + I2CBusPtr pBus, + int start +); + +static unsigned char * DDCRead_DDC2( + int scrnIndex, + I2CBusPtr pBus, + int start, + int len +); + +typedef enum { + DDCOPT_NODDC1, + DDCOPT_NODDC2, + DDCOPT_NODDC +} 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 }, +}; + +#ifdef XFree86LOADER +/*ARGSUSED*/ +static const OptionInfoRec * +DDCAvailableOptions(void *unused) +{ + return (DDCOptions); +} +#endif + +xf86MonPtr +xf86DoEDID_DDC1( + int scrnIndex, void (*DDC1SetSpeed)(ScrnInfoPtr, xf86ddcSpeed), + unsigned int (*DDC1Read)(ScrnInfoPtr) +) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + xf86MonPtr tmp = NULL; + int sigio; + /* Default DDC and DDC1 to enabled. */ + Bool noddc = FALSE, noddc1 = FALSE; + OptionInfoPtr options; + + options = xnfalloc(sizeof(DDCOptions)); + (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); + xfree(options); + + if (noddc || noddc1) + return NULL; + + sigio = xf86BlockSIGIO(); + EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); + xf86UnblockSIGIO(sigio); + + if (EDID_block){ + tmp = xf86InterpretEDID(scrnIndex,EDID_block); + } +#ifdef DEBUG + else ErrorF("No EDID block returned\n"); + if (!tmp) + ErrorF("Cannot interpret EDID block\n"); +#endif + return tmp; +} + +xf86MonPtr +xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + unsigned char *VDIF_Block = NULL; + xf86MonPtr tmp = NULL; + /* Default DDC and DDC2 to enabled. */ + Bool noddc = FALSE, noddc2 = FALSE; + OptionInfoPtr options; + + options = xnfalloc(sizeof(DDCOptions)); + (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); + xfree(options); + + if (noddc || noddc2) + return NULL; + + EDID_block = EDID1Read_DDC2(scrnIndex,pBus); + + if (EDID_block){ + tmp = xf86InterpretEDID(scrnIndex,EDID_block); + } else { +#ifdef DEBUG + ErrorF("No EDID block returned\n"); +#endif + return NULL; + } +#ifdef DEBUG + if (!tmp) + ErrorF("Cannot interpret EDID block\n"); + ErrorF("Sections to follow: %i\n",tmp->no_sections); +#endif + VDIF_Block = + VDIFRead(scrnIndex, pBus, EDID1_LEN * (tmp->no_sections + 1)); + tmp->vdif = xf86InterpretVdif(VDIF_Block); + + return tmp; +} + +/* + * read EDID record , pass it to callback function to interpret. + * callback function will store it for further use by calling + * function; it will also decide if we need to reread it + */ +static unsigned char * +EDIDRead_DDC1(ScrnInfoPtr pScrn, void (*DDCSpeed)(ScrnInfoPtr,xf86ddcSpeed), + 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 (TestDDC1(pScrn,read_DDC)==-1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); + return NULL; + }; + + if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); + do { + EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); + count --; + } while (!EDID_block && count); + if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); + + return EDID_block; +} + +/* test if DDC1 return 0 if not */ +static Bool +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--); + return (count); +} + +/* fetch entire EDID record; DDC bit needs to be masked */ +static unsigned int * +FetchEDID_DDC1(register ScrnInfoPtr pScrn, + register unsigned int (*read_DDC)(ScrnInfoPtr)) +{ + int count = NUM; + unsigned int *ptr, *xp; + + ptr=xp=xalloc(sizeof(int)*NUM); + + if (!ptr) return NULL; + do { + /* wait for next retrace */ + *xp = read_DDC(pScrn); + xp++; + } while(--count); + return (ptr); +} + +static unsigned char* +EDID1Read_DDC2(int scrnIndex, I2CBusPtr pBus) +{ + return DDCRead_DDC2(scrnIndex, pBus, 0, EDID1_LEN); +} + +static unsigned char* +VDIFRead(int scrnIndex, I2CBusPtr pBus, int start) +{ + unsigned char * Buffer, *v_buffer = NULL, *v_bufferp = NULL; + int i, num = 0; + + /* read VDIF length in 64 byte blocks */ + Buffer = DDCRead_DDC2(scrnIndex, pBus,start,64); + if (Buffer == NULL) + return NULL; +#ifdef DEBUG + ErrorF("number of 64 bit blocks: %i\n",Buffer[0]); +#endif + if ((num = Buffer[0]) > 0) + v_buffer = v_bufferp = xalloc(sizeof(unsigned char) * 64 * num); + + for (i = 0; i < num; i++) { + Buffer = DDCRead_DDC2(scrnIndex, pBus,start,64); + if (Buffer == NULL) { + xfree (v_buffer); + return NULL; + } + memcpy(v_bufferp,Buffer,63); /* 64th byte is checksum */ + xfree(Buffer); + v_bufferp += 63; + } + return v_buffer; +} + +static unsigned char * +DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len) +{ + I2CDevPtr dev; + unsigned char W_Buffer[2]; + int w_bytes; + unsigned char *R_Buffer; + int i; + + xf86LoaderReqSymLists(i2cSymbols, NULL); + dev = xf86CreateI2CDevRec(); + dev->DevName = "ddc2"; + dev->SlaveAddr = 0xA0; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->ByteTimeout = 40; + dev->AcknTimeout = 40; + + dev->pI2CBus = pBus; + if (! xf86I2CDevInit(dev)) { + xf86DrvMsg(X_PROBED,scrnIndex,"No DDC2 device\n"); + return NULL; + } + if (start < 0x100) { + w_bytes = 1; + W_Buffer[0] = start; + } else { + w_bytes = 2; + W_Buffer[0] = start & 0xFF; + W_Buffer[1] = (start & 0xFF00) >> 8; + } + R_Buffer = xcalloc(1,sizeof(unsigned char) + * (len)); + for (i=0; i<RETRIES; i++) { + if (xf86I2CWriteRead(dev, W_Buffer,w_bytes, R_Buffer,len)) { + if (!DDC_checksum(R_Buffer,len)) { + xf86DestroyI2CDevRec(dev,TRUE); + return R_Buffer; + } +#ifdef DEBUG + else ErrorF("Checksum error in EDID block\n"); +#endif + } +#ifdef DEBUG + else ErrorF("Error reading EDID block\n"); +#endif + } + + xf86DestroyI2CDevRec(dev,TRUE); + xfree(R_Buffer); + return NULL; +} + + diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h new file mode 100644 index 000000000..b4252ef6b --- /dev/null +++ b/hw/xfree86/ddc/xf86DDC.h @@ -0,0 +1,61 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/xf86DDC.h,v 1.11 2003/02/17 16:08:27 dawes Exp $ */ + +/* xf86DDC.h + * + * This file contains all information to interpret a standard EDIC block + * transmitted by a display device via DDC (Display Data Channel). So far + * there is no information to deal with optional EDID blocks. + * DDC is a Trademark of VESA (Video Electronics Standard Association). + * + * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ + + +#ifndef XF86_DDC_H +# define XF86_DDC_H + +#include "edid.h" +#include "xf86i2c.h" +#include "xf86str.h" + +/* speed up / slow down */ +typedef enum { + DDC_SLOW, + DDC_FAST +} xf86ddcSpeed; + +extern xf86MonPtr xf86DoEDID_DDC1( + int scrnIndex, + void (*DDC1SetSpeed)(ScrnInfoPtr, xf86ddcSpeed), + unsigned int (*DDC1Read)(ScrnInfoPtr) +); + +extern xf86MonPtr xf86DoEDID_DDC2( + int scrnIndex, + I2CBusPtr pBus +); + +extern xf86MonPtr xf86PrintEDID( + xf86MonPtr monPtr +); + +extern xf86MonPtr xf86InterpretEDID( + int screenIndex, Uchar *block +); + +extern xf86vdifPtr xf86InterpretVdif( + CARD8 *c +); + +extern Bool xf86SetDDCproperties( + ScrnInfoPtr pScreen, + xf86MonPtr DDC +); + +extern void xf86print_vdif( + xf86vdifPtr v +); + +#endif + + |