summaryrefslogtreecommitdiff
path: root/hw/xfree86/ddc
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:57 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:57 +0000
commit9508a382f8a9f241dab097d921b6d290c1c3a776 (patch)
treefa456480bae7040c3f971a70b390f2d091c680b5 /hw/xfree86/ddc
parentded6147bfb5d75ff1e67c858040a628b61bc17d1 (diff)
Initial revision
Diffstat (limited to 'hw/xfree86/ddc')
-rw-r--r--hw/xfree86/ddc/DDC.HOWTO97
-rw-r--r--hw/xfree86/ddc/ddcPriv.h9
-rw-r--r--hw/xfree86/ddc/ddcProperty.c160
-rw-r--r--hw/xfree86/ddc/edid.c137
-rw-r--r--hw/xfree86/ddc/edid.h424
-rw-r--r--hw/xfree86/ddc/interpret_edid.c226
-rw-r--r--hw/xfree86/ddc/interpret_vdif.c129
-rw-r--r--hw/xfree86/ddc/print_edid.c286
-rw-r--r--hw/xfree86/ddc/print_vdif.c222
-rw-r--r--hw/xfree86/ddc/vdif.h174
-rw-r--r--hw/xfree86/ddc/xf86DDC.c379
-rw-r--r--hw/xfree86/ddc/xf86DDC.h61
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
+
+