xserver/hw/xorg/ddc Makefile.am, NONE, 1.1 ddcPriv.h, NONE, 1.1 ddcProperty.c, NONE, 1.1 edid.c, NONE, 1.1 edid.h, NONE, 1.1 interpret_edid.c, NONE, 1.1 interpret_vdif.c, NONE, 1.1 print_edid.c, NONE, 1.1 print_vdif.c, NONE, 1.1 vdif.h, NONE, 1.1 xf86DDC.c, NONE, 1.1 xf86DDC.h, NONE, 1.1

Daniel Stone xserver-commit at pdx.freedesktop.org
Sun Apr 25 23:52:16 EST 2004


Committed by: daniel

Update of /cvs/xserver/xserver/hw/xorg/ddc
In directory pdx:/tmp/cvs-serv17025/hw/xorg/ddc

Added Files:
	Makefile.am ddcPriv.h ddcProperty.c edid.c edid.h 
	interpret_edid.c interpret_vdif.c print_edid.c print_vdif.c 
	vdif.h xf86DDC.c xf86DDC.h 
Log Message:
Xizzle is dead, long live Xorg.

Re-import the DDX from X11R6.7, complete with automakey goodness, and do the
requisite configure.ac, et al, updates; also import the XKB extension from the
6.7 DIX.

Currently it'll link and then hang solid in RADEONInitAccel(), or the next
function if you enable NoAccel.


--- NEW FILE: Makefile.am ---
sdk_INCLUDEDIR = $(includedir)/xorg
sdk_INCLUDES = edid.h vdif.h xf86DDC.h

lib_LIBRARIES = libxorgddc.a
libxorgddc_a_SOURCES = xf86DDC.c edid.c interpret_edid.c print_edid.c \
                       interpret_vdif.c print_vdif.c ddcProperty.c

INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c
AM_CFLAGS = $(XORG_CFLAGS)

--- NEW FILE: ddcPriv.h ---
extern unsigned char *GetEDID_DDC1(
    unsigned int *
);

extern int DDC_checksum(
    unsigned char *,
    int
);


--- NEW FILE: ddcProperty.c ---
/* 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 at dpmms.cam.ac.uk>
 */
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/ddcProperty.c,v 1.9tsi Exp $ */

#include "misc.h"
#include "xf86.h"
/* #include "xf86_ansic.h" */
/* #include "xf86_OSproc.h" */
#include <X11/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
					   );
      if (ret != Success)
      ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret );
    } 

    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
					   );
      if (ret != Success)
      ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret );
    }

    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 
					   );
      if (ret != Success)
      ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret );
    }

    return TRUE;
}

--- NEW FILE: edid.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/edid.c,v 1.3 2000/11/03 18:46:08 eich 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 at 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);
}



--- NEW FILE: edid.h ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/edid.h,v 1.6 2000/04/17 16:29:55 eich 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 at 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_ */

--- NEW FILE: interpret_edid.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/interpret_edid.c,v 1.7 2000/04/17 16:29:55 eich Exp $ */

/* interpret_edid.c: interpret a primary EDID block
 * 
 * Copyright 1998 by Egbert Eich <Egbert.Eich at 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;
}



--- NEW FILE: interpret_vdif.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/interpret_vdif.c,v 1.5 1999/12/03 19:17:26 eich Exp $ */

#include <X11/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

--- NEW FILE: print_edid.c ---
/* $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 at 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",
	(char *)&c->name, c->prod_id, c->serial);
    xf86DrvMsg(scrnIndex, X_INFO, "Year: %u  Week: %u\n", c->year, c->week);
}
  
static void
print_version(int scrnIndex, struct edid_version *c)
{
    xf86DrvMsg(scrnIndex,X_INFO,"EDID Version: %u.%u\n",c->version,
	       c->revision);  
}
  
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 at 70Hz\n");
    if (c&0x40) xf86DrvMsg(scrnIndex,X_INFO,"720x400 at 88Hz\n");
    if (c&0x20) xf86DrvMsg(scrnIndex,X_INFO,"640x480 at 60Hz\n");
    if (c&0x10) xf86DrvMsg(scrnIndex,X_INFO,"640x480 at 67Hz\n");
    if (c&0x08) xf86DrvMsg(scrnIndex,X_INFO,"640x480 at 72Hz\n");
    if (c&0x04) xf86DrvMsg(scrnIndex,X_INFO,"640x480 at 75Hz\n");
    if (c&0x02) xf86DrvMsg(scrnIndex,X_INFO,"800x600 at 56Hz\n");
    if (c&0x01) xf86DrvMsg(scrnIndex,X_INFO,"800x600 at 60Hz\n");
    c=t->t2;
    if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"800x600 at 72Hz\n");
    if (c&0x40) xf86DrvMsg(scrnIndex,X_INFO,"800x600 at 75Hz\n");
    if (c&0x20) xf86DrvMsg(scrnIndex,X_INFO,"832x624 at 75Hz\n");
    if (c&0x10) xf86DrvMsg(scrnIndex,X_INFO,"1024x768 at 87Hz (interlaced)\n");
    if (c&0x08) xf86DrvMsg(scrnIndex,X_INFO,"1024x768 at 60Hz\n");
    if (c&0x04) xf86DrvMsg(scrnIndex,X_INFO,"1024x768 at 70Hz\n");
    if (c&0x02) xf86DrvMsg(scrnIndex,X_INFO,"1024x768 at 75Hz\n");
    if (c&0x01) xf86DrvMsg(scrnIndex,X_INFO,"1280x1024 at 75Hz\n");
    c=t->t_manu;
    if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"1152x870 at 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");
	}
    }
}

--- NEW FILE: print_vdif.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/print_vdif.c,v 1.4tsi 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;
    }
}

--- NEW FILE: vdif.h ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/vdif.h,v 1.4tsi 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 <X11/Xmd.h>

#undef  CARD32
#define CARD32 unsigned int	/* ... on all supported platforms */

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;

#undef CARD32

#endif

--- NEW FILE: xf86DDC.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/xf86DDC.c,v 1.26 2003/08/22 17:56:24 dawes Exp $ */

/* xf86DDC.c 
 * 
 * Copyright 1998,1999 by Egbert Eich <Egbert.Eich at 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",
    "xf86I2CFindDev",
    "xf86DestroyI2CDevRec",
    NULL
};

#ifdef XFree86LOADER

static MODULESETUPPROTO(ddcSetup);

static XF86ModuleVersionInfo ddcVersRec =
{
    "ddc",
    MODULEVENDORSTRING,
    MODINFOSTRING1,
    MODINFOSTRING2,
    XORG_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);

    if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
	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(scrnIndex, X_PROBED, "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))
		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;
}

--- NEW FILE: xf86DDC.h ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/ddc/xf86DDC.h,v 1.10 2000/06/07 22:03:09 tsi 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 at 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






More information about the xserver-commit mailing list