aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/ddc
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/ddc')
-rw-r--r--xorg-server/hw/xfree86/ddc/DDC.HOWTO97
-rw-r--r--xorg-server/hw/xfree86/ddc/Makefile.am12
-rw-r--r--xorg-server/hw/xfree86/ddc/Makefile.in683
-rw-r--r--xorg-server/hw/xfree86/ddc/ddcPriv.h9
-rw-r--r--xorg-server/hw/xfree86/ddc/ddcProperty.c117
-rw-r--r--xorg-server/hw/xfree86/ddc/edid.c140
-rw-r--r--xorg-server/hw/xfree86/ddc/edid.h549
-rw-r--r--xorg-server/hw/xfree86/ddc/interpret_edid.c447
-rw-r--r--xorg-server/hw/xfree86/ddc/print_edid.c489
-rw-r--r--xorg-server/hw/xfree86/ddc/xf86DDC.c292
-rw-r--r--xorg-server/hw/xfree86/ddc/xf86DDC.h58
11 files changed, 2893 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/ddc/DDC.HOWTO b/xorg-server/hw/xfree86/ddc/DDC.HOWTO
new file mode 100644
index 000000000..833a7ab54
--- /dev/null
+++ b/xorg-server/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.2 1998/12/06 13:30:39 dawes Exp $
diff --git a/xorg-server/hw/xfree86/ddc/Makefile.am b/xorg-server/hw/xfree86/ddc/Makefile.am
new file mode 100644
index 000000000..cd146c5a3
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/Makefile.am
@@ -0,0 +1,12 @@
+sdk_HEADERS = edid.h xf86DDC.h
+
+noinst_LIBRARIES = libddc.a
+
+libddc_a_SOURCES = xf86DDC.c edid.c interpret_edid.c print_edid.c \
+ ddcProperty.c
+
+INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c
+
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)
+
+EXTRA_DIST = ddcPriv.h DDC.HOWTO
diff --git a/xorg-server/hw/xfree86/ddc/Makefile.in b/xorg-server/hw/xfree86/ddc/Makefile.in
new file mode 100644
index 000000000..9016bc200
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/Makefile.in
@@ -0,0 +1,683 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = hw/xfree86/ddc
+DIST_COMMON = $(sdk_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
+ $(top_builddir)/include/xorg-server.h \
+ $(top_builddir)/include/dix-config.h \
+ $(top_builddir)/include/xgl-config.h \
+ $(top_builddir)/include/xorg-config.h \
+ $(top_builddir)/include/xkb-config.h \
+ $(top_builddir)/include/xwin-config.h \
+ $(top_builddir)/include/kdrive-config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libddc_a_AR = $(AR) $(ARFLAGS)
+libddc_a_LIBADD =
+am_libddc_a_OBJECTS = xf86DDC.$(OBJEXT) edid.$(OBJEXT) \
+ interpret_edid.$(OBJEXT) print_edid.$(OBJEXT) \
+ ddcProperty.$(OBJEXT)
+libddc_a_OBJECTS = $(am_libddc_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libddc_a_SOURCES)
+DIST_SOURCES = $(libddc_a_SOURCES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(sdkdir)"
+sdkHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(sdk_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+APPDEFAULTDIR = @APPDEFAULTDIR@
+APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASE_FONT_PATH = @BASE_FONT_PATH@
+BUILD_DATE = @BUILD_DATE@
+BUILD_TIME = @BUILD_TIME@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DARWIN_LIBS = @DARWIN_LIBS@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@
+DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@
+DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DGA_CFLAGS = @DGA_CFLAGS@
+DGA_LIBS = @DGA_LIBS@
+DIX_CFLAGS = @DIX_CFLAGS@
+DLLTOOL = @DLLTOOL@
+DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@
+DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@
+DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@
+DMXMODULES_LIBS = @DMXMODULES_LIBS@
+DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@
+DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@
+DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@
+DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@
+DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
+DRI2PROTO_LIBS = @DRI2PROTO_LIBS@
+DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@
+DRIPROTO_LIBS = @DRIPROTO_LIBS@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
+DSYMUTIL = @DSYMUTIL@
+DTRACE = @DTRACE@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
+GLX_DEFINES = @GLX_DEFINES@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KDRIVE_CFLAGS = @KDRIVE_CFLAGS@
+KDRIVE_INCS = @KDRIVE_INCS@
+KDRIVE_LIBS = @KDRIVE_LIBS@
+KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@
+KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@
+KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@
+LAUNCHD = @LAUNCHD@
+LDFLAGS = @LDFLAGS@
+LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
+LIBDRM_LIBS = @LIBDRM_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MESA_SOURCE = @MESA_SOURCE@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+MKFONTDIR = @MKFONTDIR@
+MKFONTSCALE = @MKFONTSCALE@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCCLD = @OBJCCLD@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJCFLAGS = @OBJCFLAGS@
+OBJCLINK = @OBJCLINK@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PROJECTROOT = @PROJECTROOT@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+RAWCPP = @RAWCPP@
+RAWCPPFLAGS = @RAWCPPFLAGS@
+SED = @SED@
+SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@
+SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@
+STRIP = @STRIP@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
+VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@
+VENDOR_NAME = @VENDOR_NAME@
+VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
+VENDOR_RELEASE = @VENDOR_RELEASE@
+VERSION = @VERSION@
+X11APP_ARCHS = @X11APP_ARCHS@
+X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
+X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
+XDMCP_CFLAGS = @XDMCP_CFLAGS@
+XDMCP_LIBS = @XDMCP_LIBS@
+XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@
+XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@
+XDMX_CFLAGS = @XDMX_CFLAGS@
+XDMX_LIBS = @XDMX_LIBS@
+XDMX_SYS_LIBS = @XDMX_SYS_LIBS@
+XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@
+XEGL_LIBS = @XEGL_LIBS@
+XEGL_SYS_LIBS = @XEGL_SYS_LIBS@
+XEPHYR_CFLAGS = @XEPHYR_CFLAGS@
+XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@
+XEPHYR_INCS = @XEPHYR_INCS@
+XEPHYR_LIBS = @XEPHYR_LIBS@
+XF86CONFIGFILE = @XF86CONFIGFILE@
+XF86MISC_CFLAGS = @XF86MISC_CFLAGS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
+XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
+XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@
+XGLMODULES_LIBS = @XGLMODULES_LIBS@
+XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@
+XGLXMODULES_LIBS = @XGLXMODULES_LIBS@
+XGLX_LIBS = @XGLX_LIBS@
+XGLX_SYS_LIBS = @XGLX_SYS_LIBS@
+XGL_LIBS = @XGL_LIBS@
+XGL_MODULE_PATH = @XGL_MODULE_PATH@
+XGL_SYS_LIBS = @XGL_SYS_LIBS@
+XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@
+XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@
+XKB_COMPILED_DIR = @XKB_COMPILED_DIR@
+XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@
+XLIB_CFLAGS = @XLIB_CFLAGS@
+XLIB_LIBS = @XLIB_LIBS@
+XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@
+XNESTMODULES_LIBS = @XNESTMODULES_LIBS@
+XNEST_LIBS = @XNEST_LIBS@
+XNEST_SYS_LIBS = @XNEST_SYS_LIBS@
+XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@
+XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@
+XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@
+XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_INCS = @XORG_INCS@
+XORG_LIBS = @XORG_LIBS@
+XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@
+XORG_MODULES_LIBS = @XORG_MODULES_LIBS@
+XORG_OS = @XORG_OS@
+XORG_OS_SUBDIR = @XORG_OS_SUBDIR@
+XORG_SYS_LIBS = @XORG_SYS_LIBS@
+XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@
+XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@
+XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@
+XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@
+XPRINT_CFLAGS = @XPRINT_CFLAGS@
+XPRINT_LIBS = @XPRINT_LIBS@
+XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@
+XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
+XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@
+XSDL_INCS = @XSDL_INCS@
+XSDL_LIBS = @XSDL_LIBS@
+XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@
+XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@
+XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@
+XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@
+XSERVER_LIBS = @XSERVER_LIBS@
+XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@
+XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@
+XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@
+XVFB_LIBS = @XVFB_LIBS@
+XVFB_SYS_LIBS = @XVFB_SYS_LIBS@
+XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@
+XWINMODULES_LIBS = @XWINMODULES_LIBS@
+XWIN_LIBS = @XWIN_LIBS@
+XWIN_SERVER_NAME = @XWIN_SERVER_NAME@
+XWIN_SYS_LIBS = @XWIN_SYS_LIBS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+__XCONFIGFILE__ = @__XCONFIGFILE__@
+abi_ansic = @abi_ansic@
+abi_extension = @abi_extension@
+abi_font = @abi_font@
+abi_videodrv = @abi_videodrv@
+abi_xinput = @abi_xinput@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+driverdir = @driverdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+extdir = @extdir@
+ft_config = @ft_config@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+launchagentsdir = @launchagentsdir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+logdir = @logdir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sdkdir = @sdkdir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xglmoduledir = @xglmoduledir@
+xpconfigdir = @xpconfigdir@
+sdk_HEADERS = edid.h xf86DDC.h
+noinst_LIBRARIES = libddc.a
+libddc_a_SOURCES = xf86DDC.c edid.c interpret_edid.c print_edid.c \
+ ddcProperty.c
+
+INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)
+EXTRA_DIST = ddcPriv.h DDC.HOWTO
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign hw/xfree86/ddc/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign hw/xfree86/ddc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libddc.a: $(libddc_a_OBJECTS) $(libddc_a_DEPENDENCIES)
+ -rm -f libddc.a
+ $(libddc_a_AR) libddc.a $(libddc_a_OBJECTS) $(libddc_a_LIBADD)
+ $(RANLIB) libddc.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddcProperty.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interpret_edid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_edid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86DDC.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-sdkHEADERS: $(sdk_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sdkdir)" || $(MKDIR_P) "$(DESTDIR)$(sdkdir)"
+ @list='$(sdk_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(sdkHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(sdkdir)/$$f'"; \
+ $(sdkHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(sdkdir)/$$f"; \
+ done
+
+uninstall-sdkHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sdk_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(sdkdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sdkdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(sdkdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-sdkHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-sdkHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-sdkHEADERS install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-sdkHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/xorg-server/hw/xfree86/ddc/ddcPriv.h b/xorg-server/hw/xfree86/ddc/ddcPriv.h
new file mode 100644
index 000000000..b5cb9b836
--- /dev/null
+++ b/xorg-server/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/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c
new file mode 100644
index 000000000..02125dff7
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.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"
+
+static void
+addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC)
+{
+ Atom EDID1Atom=-1, EDID2Atom=-1;
+ CARD8 *EDID1rawdata = NULL;
+ CARD8 *EDID2rawdata = NULL;
+ int i, scrnIndex = pScrn->scrnIndex;
+ Bool makeEDID1prop = FALSE;
+ Bool makeEDID2prop = FALSE;
+
+ 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) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n");
+ xf86DrvMsg(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)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Monitor EDID v1 checksum passed,\n");
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "XFree86_DDC_EDID1_RAWDATA property created\n");
+ makeEDID1prop = TRUE;
+ }
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n",
+ DDC->ver.version, DDC->ver.revision);
+ return;
+ }
+
+ if (makeEDID1prop) {
+ if ((EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL)
+ return;
+
+ EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME) - 1, TRUE);
+ memcpy(EDID1rawdata, DDC->rawData, 128);
+ xf86RegisterRootWindowProperty(scrnIndex, EDID1Atom, XA_INTEGER, 8,
+ 128, (unsigned char *)EDID1rawdata);
+ }
+
+ if (makeEDID2prop) {
+ if ((EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL)
+ return;
+
+ memcpy(EDID2rawdata, DDC->rawData, 256);
+ EDID2Atom = MakeAtom(EDID2_ATOM_NAME, sizeof(EDID2_ATOM_NAME) - 1, TRUE);
+ xf86RegisterRootWindowProperty(scrnIndex, EDID2Atom, XA_INTEGER, 8,
+ 256, (unsigned char *)EDID2rawdata);
+ }
+}
+
+Bool
+xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC)
+{
+ if (!pScrn || !pScrn->monitor || !DDC)
+ return FALSE;
+
+ xf86DDCMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC);
+
+ addRootWindowProperties(pScrn, DDC);
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xfree86/ddc/edid.c b/xorg-server/hw/xfree86/ddc/edid.c
new file mode 100644
index 000000000..3ebafbbba
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/edid.c
@@ -0,0 +1,140 @@
+
+/* 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>
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86DDC.h"
+#include "ddcPriv.h"
+#include <string.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/xorg-server/hw/xfree86/ddc/edid.h b/xorg-server/hw/xfree86/ddc/edid.h
new file mode 100644
index 000000000..a4e79dae0
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/edid.h
@@ -0,0 +1,549 @@
+/*
+ * 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_
+
+/* 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 _DFP(x) (x & 0x01)
+#define DFP _DFP(GET(D_INPUT))
+#define _BPC(x) ((x & 0x70) >> 4)
+#define BPC _BPC(GET(D_INPUT))
+#define _DIGITAL_INTERFACE(x) (x & 0x0F)
+#define DIGITAL_INTERFACE _DIGITAL_INTERFACE(GET(D_INPUT))
+#define _GAMMA(x) (x == 0xff ? 0.0 : ((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 _VALID_TIMING(x) !(((x[0] == 0x01) && (x[1] == 0x01)) \
+ || ((x[0] == 0x00) && (x[1] == 0x00)) \
+ || ((x[0] == 0x20) && (x[1] == 0x20)) )
+#define VALID_TIMING _VALID_TIMING(c)
+#define _HSIZE1(x) ((x[0] + 31) * 8)
+#define HSIZE1 _HSIZE1(c)
+#define RATIO(x) ((x[1] & 0xC0) >> 6)
+#define RATIO1_1 0
+/* EDID Ver. 1.3 redefined this */
+#define RATIO16_10 RATIO1_1
+#define RATIO4_3 1
+#define RATIO5_4 2
+#define RATIO16_9 3
+#define _VSIZE1(x,y,r) switch(RATIO(x)){ \
+ case RATIO1_1: y = ((v->version > 1 || v->revision > 2) \
+ ? (_HSIZE1(x) * 10) / 16 : _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,v)
+#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 */
+/**
+ * Returns true if the pointer is the start of a monitor descriptor block
+ * instead of a detailed timing descriptor.
+ *
+ * Checking the reserved pad fields for zeroes fails on some monitors with
+ * broken empty ASCII strings. Only the first two bytes are reliable.
+ */
+#define _IS_MONITOR_DESC(x) (x[0] == 0 && x[1] == 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) >> 5)
+#define STEREO _STEREO(c)
+#define _STEREO1(x) (x[17] & 0x1)
+#define STEREO1 _STEREO(c)
+#define _SYNC_T(x) ((x[17] & 0x18) >> 3)
+#define SYNC_T _SYNC_T(c)
+#define _MISC(x) ((x[17] & 0x06) >> 1)
+#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_OFFSET(x) ((!!(x[4] & 0x01)) * 255)
+#define _MAX_V_OFFSET(x) ((!!(x[4] & 0x02)) * 255)
+#define _MIN_H_OFFSET(x) ((!!(x[4] & 0x04)) * 255)
+#define _MAX_H_OFFSET(x) ((!!(x[4] & 0x08)) * 255)
+#define _MIN_V(x) x[5]
+#define MIN_V (_MIN_V(c) + _MIN_V_OFFSET(c))
+#define _MAX_V(x) x[6]
+#define MAX_V (_MAX_V(c) + _MAX_V_OFFSET(c))
+#define _MIN_H(x) x[7]
+#define MIN_H (_MIN_H(c) + _MIN_H_OFFSET(c))
+#define _MAX_H(x) x[8]
+#define MAX_H (_MAX_H(c) + _MAX_H_OFFSET(c))
+#define _MAX_CLOCK(x) x[9]
+#define MAX_CLOCK _MAX_CLOCK(c)
+#define _HAVE_2ND_GTF(x) (x[10] == 0x02)
+#define HAVE_2ND_GTF _HAVE_2ND_GTF(c)
+#define _F_2ND_GTF(x) (x[12] * 2)
+#define F_2ND_GTF _F_2ND_GTF(c)
+#define _C_2ND_GTF(x) (x[13] / 2)
+#define C_2ND_GTF _C_2ND_GTF(c)
+#define _M_2ND_GTF(x) (x[14] + (x[15] << 8))
+#define M_2ND_GTF _M_2ND_GTF(c)
+#define _K_2ND_GTF(x) (x[16])
+#define K_2ND_GTF _K_2ND_GTF(c)
+#define _J_2ND_GTF(x) (x[17] / 2)
+#define J_2ND_GTF _J_2ND_GTF(c)
+#define _HAVE_CVT(x) (x[10] == 0x04)
+#define HAVE_CVT _HAVE_CVT(c)
+#define _MAX_CLOCK_KHZ(x) (x[12] >> 2)
+#define MAX_CLOCK_KHZ (MAX_CLOCK * 10000) - (_MAX_CLOCK_KHZ(c) * 250)
+#define _MAXWIDTH(x) ((x[13] == 0 ? 0 : x[13] + ((x[12] & 0x03) << 8)) * 8)
+#define MAXWIDTH _MAXWIDTH(c)
+#define _SUPPORTED_ASPECT(x) x[14]
+#define SUPPORTED_ASPECT _SUPPORTED_ASPECT(c)
+#define SUPPORTED_ASPECT_4_3 0x80
+#define SUPPORTED_ASPECT_16_9 0x40
+#define SUPPORTED_ASPECT_16_10 0x20
+#define SUPPORTED_ASPECT_5_4 0x10
+#define SUPPORTED_ASPECT_15_9 0x08
+#define _PREFERRED_ASPECT(x) ((x[15] & 0xe0) >> 5)
+#define PREFERRED_ASPECT _PREFERRED_ASPECT(c)
+#define PREFERRED_ASPECT_4_3 0
+#define PREFERRED_ASPECT_16_9 1
+#define PREFERRED_ASPECT_16_10 2
+#define PREFERRED_ASPECT_5_4 3
+#define PREFERRED_ASPECT_15_9 4
+#define _SUPPORTED_BLANKING(x) ((x[15] & 0x18) >> 3)
+#define SUPPORTED_BLANKING _SUPPORTED_BLANKING(c)
+#define CVT_STANDARD 0x01
+#define CVT_REDUCED 0x02
+#define _SUPPORTED_SCALING(x) ((x[16] & 0xf0) >> 4)
+#define SUPPORTED_SCALING _SUPPORTED_SCALING(c)
+#define SCALING_HSHRINK 0x08
+#define SCALING_HSTRETCH 0x04
+#define SCALING_VSHRINK 0x02
+#define SCALING_VSTRETCH 0x01
+#define _PREFERRED_REFRESH(x) x[17]
+#define PREFERRED_REFRESH _PREFERRED_REFRESH(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 COLOR_MANAGEMENT_DATA 0xF9
+#define CVT_3BYTE_DATA 0xF8
+#define ADD_EST_TIMINGS 0xF7
+#define ADD_DUMMY 0x10
+
+#define _NEXT_DT_MD_SECTION(x) (x = (x + DET_TIMING_INFO_LEN))
+#define NEXT_DT_MD_SECTION _NEXT_DT_MD_SECTION(c)
+
+#endif /* _PARSE_EDID_ */
+
+/* input type */
+#define DIGITAL(x) x
+
+/* DFP */
+#define DFP1(x) x
+
+/* input voltage level */
+#define V070 0 /* 0.700V/0.300V */
+#define V071 1 /* 0.714V/0.286V */
+#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, analog */
+#define DISP_MONO 0
+#define DISP_RGB 1
+#define DISP_MULTCOLOR 2
+
+/* display color encodings, digital */
+#define DISP_YCRCB444 0x01
+#define DISP_YCRCB422 0x02
+
+/* 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)
+#define GTF_SUPPORTED(x) (x & 0x1)
+#define CVT_SUPPORTED(x) (x & 0x1)
+
+/* detailed timing misc */
+#define IS_INTERLACED(x) (x)
+#define IS_STEREO(x) (x)
+#define IS_RIGHT_STEREO(x) (x & 0x01)
+#define IS_LEFT_STEREO(x) (x & 0x02)
+#define IS_4WAY_STEREO(x) (x & 0x03)
+#define IS_RIGHT_ON_SYNC(x) IS_RIGHT_STEREO(x)
+#define IS_LEFT_ON_SYNC(x) IS_LEFT_STEREO(x)
+
+
+typedef unsigned int Uint;
+typedef unsigned char Uchar;
+
+struct vendor {
+ char name[4];
+ int prod_id;
+ Uint serial;
+ int week;
+ int year;
+};
+
+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;
+ unsigned int input_dfp:1;
+ unsigned int input_bpc:3;
+ unsigned int input_interface:4;
+ /* 15 bit hole */
+ int hsize;
+ int vsize;
+ float gamma;
+ unsigned int dpms:3;
+ unsigned int display_type:2;
+ unsigned int msc:3;
+ float redx;
+ float redy;
+ float greenx;
+ float greeny;
+ float bluex;
+ float bluey;
+ float whitex;
+ float whitey;
+};
+
+struct established_timings {
+ Uchar t1;
+ Uchar t2;
+ Uchar t_manu;
+};
+
+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;
+ unsigned int stereo_1:1;
+};
+
+#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
+#define DS_CMD 0xF9
+#define DS_CVT 0xF8
+#define DS_EST_III 0xF7
+#define DS_DUMMY 0x10
+#define DS_UNKOWN 0x100 /* type is an int */
+#define DS_VENDOR 0x101
+#define DS_VENDOR_MAX 0x110
+
+struct monitor_ranges {
+ int min_v;
+ int max_v;
+ int min_h;
+ int max_h;
+ int max_clock; /* in mhz */
+ int gtf_2nd_f;
+ int gtf_2nd_c;
+ int gtf_2nd_m;
+ int gtf_2nd_k;
+ int gtf_2nd_j;
+ int max_clock_khz;
+ int maxwidth; /* in pixels */
+ char supported_aspect;
+ char preferred_aspect;
+ char supported_blanking;
+ char supported_scaling;
+ int preferred_refresh; /* in hz */
+};
+
+struct whitePoints{
+ int index;
+ float white_x;
+ float white_y;
+ float white_gamma;
+};
+
+struct cvt_timings {
+ int width;
+ int height;
+ int rate;
+ int rates;
+};
+
+/*
+ * Be careful when adding new sections; this structure can't grow, it's
+ * embedded in the middle of xf86Monitor which is ABI. Sizes below are
+ * in bytes, for ILP32 systems. If all else fails just copy the section
+ * literally like serial and friends.
+ */
+struct detailed_monitor_section {
+ int type;
+ union {
+ struct detailed_timings d_timings; /* 56 */
+ Uchar serial[13];
+ Uchar ascii_data[13];
+ Uchar name[13];
+ struct monitor_ranges ranges; /* 56 */
+ struct std_timings std_t[5]; /* 80 */
+ struct whitePoints wp[2]; /* 32 */
+ /* color management data */
+ struct cvt_timings cvt[4]; /* 64 */
+ /* established timings III */
+ } section; /* max: 80 */
+};
+
+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];
+ void *vdif; /* unused */
+ int no_sections;
+ Uchar *rawData;
+} xf86Monitor, *xf86MonPtr;
+
+extern xf86MonPtr ConfiguredMonitor;
+
+#endif /* _EDID_H_ */
diff --git a/xorg-server/hw/xfree86/ddc/interpret_edid.c b/xorg-server/hw/xfree86/ddc/interpret_edid.c
new file mode 100644
index 000000000..879308520
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/interpret_edid.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ * Copyright 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * interpret_edid.c: interpret a primary EDID block
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#define _PARSE_EDID_
+#include "xf86DDC.h"
+#include <string.h>
+
+static void get_vendor_section(Uchar*, struct vendor *);
+static void get_version_section(Uchar*, struct edid_version *);
+static void get_display_section(Uchar*, struct disp_features *,
+ struct edid_version *);
+static void get_established_timing_section(Uchar*, struct established_timings *);
+static void get_std_timing_section(Uchar*, struct std_timings *,
+ struct edid_version *);
+static void get_dt_md_section(Uchar *, struct edid_version *,
+ struct detailed_monitor_section *det_mon);
+static void copy_string(Uchar *, Uchar *);
+static void get_dst_timing_section(Uchar *, struct std_timings *,
+ struct edid_version *);
+static void get_monitor_ranges(Uchar *, struct monitor_ranges *);
+static void get_whitepoint_section(Uchar *, struct whitePoints *);
+static void get_detailed_timing_section(Uchar*, struct detailed_timings *);
+static Bool validate_version(int scrnIndex, struct edid_version *);
+
+static void
+handle_edid_quirks(xf86MonPtr m)
+{
+ int i, j;
+ struct detailed_timings *preferred_timing;
+ struct monitor_ranges *ranges;
+
+ /*
+ * max_clock is only encoded in EDID in tens of MHz, so occasionally we
+ * find a monitor claiming a max of 160 with a mode requiring 162, or
+ * similar. Strictly we should refuse to round up too far, but let's
+ * see how well this works.
+ */
+ for (i = 0; i < 4; i++) {
+ if (m->det_mon[i].type == DS_RANGES) {
+ ranges = &m->det_mon[i].section.ranges;
+ for (j = 0; j < 4; j++) {
+ if (m->det_mon[j].type == DT) {
+ preferred_timing = &m->det_mon[j].section.d_timings;
+ if (!ranges->max_clock) continue; /* zero is legal */
+ if (ranges->max_clock * 1000000 < preferred_timing->clock) {
+ xf86Msg(X_WARNING,
+ "EDID preferred timing clock %.2fMHz exceeds "
+ "claimed max %dMHz, fixing\n",
+ preferred_timing->clock / 1.0e6,
+ ranges->max_clock);
+ ranges->max_clock =
+ (preferred_timing->clock+999999)/1000000;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * some monitors encode the aspect ratio instead of the physical size.
+ * try to find the largest detailed timing that matches that aspect
+ * ratio and use that to fill in the feature section.
+ */
+ if ((m->features.hsize == 16 && m->features.vsize == 9) ||
+ (m->features.hsize == 16 && m->features.vsize == 10) ||
+ (m->features.hsize == 4 && m->features.vsize == 3) ||
+ (m->features.hsize == 5 && m->features.vsize == 4)) {
+ int real_hsize = 0, real_vsize = 0;
+ float target_aspect, timing_aspect;
+
+ target_aspect = (float)m->features.hsize / (float)m->features.vsize;
+ for (i = 0; i < 4; i++) {
+ if (m->det_mon[i].type == DT) {
+ struct detailed_timings *timing;
+ timing = &m->det_mon[i].section.d_timings;
+
+ if (!timing->v_size)
+ continue;
+
+ timing_aspect = (float)timing->h_size / (float)timing->v_size;
+ if (fabs(1 - (timing_aspect / target_aspect)) < 0.05) {
+ real_hsize = max(real_hsize, timing->h_size);
+ real_vsize = max(real_vsize, timing->v_size);
+ }
+ }
+ }
+
+ if (!real_hsize || !real_vsize) {
+ m->features.hsize = m->features.vsize = 0;
+ } else if ((m->features.hsize * 10 == real_hsize) &&
+ (m->features.vsize * 10 == real_vsize)) {
+ /* exact match is just unlikely, should do a better check though */
+ m->features.hsize = m->features.vsize = 0;
+ } else {
+ /* convert mm to cm */
+ m->features.hsize = (real_hsize + 5) / 10;
+ m->features.vsize = (real_vsize + 5) / 10;
+ }
+
+ xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n",
+ m->features.hsize, m->features.vsize);
+ }
+}
+
+xf86MonPtr
+xf86InterpretEDID(int scrnIndex, Uchar *block)
+{
+ xf86MonPtr m;
+
+ if (!block) return NULL;
+ if (! (m = xnfcalloc(sizeof(xf86Monitor),1))) return NULL;
+ m->scrnIndex = scrnIndex;
+ m->rawData = block;
+
+ get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor);
+ get_version_section(SECTION(VERSION_SECTION,block),&m->ver);
+ if (!validate_version(scrnIndex, &m->ver)) goto error;
+ get_display_section(SECTION(DISPLAY_SECTION,block),&m->features,
+ &m->ver);
+ get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block),
+ &m->timings1);
+ get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
+ &m->ver);
+ get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
+ m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
+
+ handle_edid_quirks(m);
+
+ return (m);
+
+ error:
+ xfree(m);
+ return NULL;
+}
+
+static void
+get_vendor_section(Uchar *c, struct vendor *r)
+{
+ r->name[0] = L1;
+ r->name[1] = L2;
+ r->name[2] = L3;
+ r->name[3] = '\0';
+
+ r->prod_id = PROD_ID;
+ r->serial = SERIAL_NO;
+ r->week = WEEK;
+ r->year = YEAR;
+}
+
+static void
+get_version_section(Uchar *c, struct edid_version *r)
+{
+ r->version = VERSION;
+ r->revision = REVISION;
+}
+
+static void
+get_display_section(Uchar *c, struct disp_features *r,
+ struct edid_version *v)
+{
+ r->input_type = INPUT_TYPE;
+ if (!DIGITAL(r->input_type)) {
+ r->input_voltage = INPUT_VOLTAGE;
+ r->input_setup = SETUP;
+ r->input_sync = SYNC;
+ } else if (v->revision == 2 || v->revision == 3) {
+ r->input_dfp = DFP;
+ } else if (v->revision >= 4) {
+ r->input_bpc = BPC;
+ r->input_interface = DIGITAL_INTERFACE;
+ }
+ r->hsize = HSIZE_MAX;
+ r->vsize = VSIZE_MAX;
+ r->gamma = GAMMA;
+ r->dpms = DPMS;
+ r->display_type = DISPLAY_TYPE;
+ r->msc = MSC;
+ r->redx = REDX;
+ r->redy = REDY;
+ r->greenx = GREENX;
+ r->greeny = GREENY;
+ r->bluex = BLUEX;
+ r->bluey = BLUEY;
+ r->whitex = WHITEX;
+ r->whitey = WHITEY;
+}
+
+static void
+get_established_timing_section(Uchar *c, struct established_timings *r)
+{
+ r->t1 = T1;
+ r->t2 = T2;
+ r->t_manu = T_MANU;
+}
+
+static void
+get_cvt_timing_section(Uchar *c, struct cvt_timings *r)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (c[0] && c[1] && c[2]) {
+ r[i].height = (c[0] + ((c[1] & 0xF0) << 8) + 1) * 2;
+ switch (c[1] & 0xc0) {
+ case 0x00: r[i].width = r[i].height * 4 / 3; break;
+ case 0x40: r[i].width = r[i].height * 16 / 9; break;
+ case 0x80: r[i].width = r[i].height * 16 / 10; break;
+ case 0xc0: r[i].width = r[i].height * 15 / 9; break;
+ }
+ switch (c[2] & 0x60) {
+ case 0x00: r[i].rate = 50; break;
+ case 0x20: r[i].rate = 60; break;
+ case 0x40: r[i].rate = 75; break;
+ case 0x60: r[i].rate = 85; break;
+ }
+ r[i].rates = c[2] & 0x1f;
+ } else {
+ return;
+ }
+ c += 3;
+ }
+}
+
+static void
+get_std_timing_section(Uchar *c, struct std_timings *r,
+ struct edid_version *v)
+{
+ int i;
+
+ for (i=0;i<STD_TIMINGS;i++){
+ if (VALID_TIMING) {
+ r[i].hsize = HSIZE1;
+ VSIZE1(r[i].vsize);
+ r[i].refresh = REFRESH_R;
+ r[i].id = STD_TIMING_ID;
+ } else {
+ r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0;
+ }
+ NEXT_STD_TIMING;
+ }
+}
+
+static 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, ver);
+ break;
+ case COLOR_MANAGEMENT_DATA:
+ det_mon[i].type = DS_CMD;
+ break;
+ case CVT_3BYTE_DATA:
+ det_mon[i].type = DS_CVT;
+ get_cvt_timing_section(c, det_mon[i].section.cvt);
+ break;
+ case ADD_EST_TIMINGS:
+ det_mon[i].type = DS_EST_III;
+ break;
+ case ADD_DUMMY:
+ det_mon[i].type = DS_DUMMY;
+ break;
+ default:
+ det_mon[i].type = DS_UNKOWN;
+ break;
+ }
+ if (c[3] <= 0x0F) {
+ det_mon[i].type = DS_VENDOR + c[3];
+ }
+ } 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,
+ struct edid_version *v)
+{
+ int j;
+ c = c + 5;
+ for (j = 0; j < 5; j++) {
+ t[j].hsize = HSIZE1;
+ VSIZE1(t[j].vsize);
+ t[j].refresh = REFRESH_R;
+ t[j].id = STD_TIMING_ID;
+ NEXT_STD_TIMING;
+ }
+}
+
+static void
+get_monitor_ranges(Uchar *c, struct monitor_ranges *r)
+{
+ r->min_v = MIN_V;
+ r->max_v = MAX_V;
+ r->min_h = MIN_H;
+ r->max_h = MAX_H;
+ r->max_clock = 0;
+ if(MAX_CLOCK != 0xff) /* is specified? */
+ r->max_clock = MAX_CLOCK * 10;
+ if (HAVE_2ND_GTF) {
+ r->gtf_2nd_f = F_2ND_GTF;
+ r->gtf_2nd_c = C_2ND_GTF;
+ r->gtf_2nd_m = M_2ND_GTF;
+ r->gtf_2nd_k = K_2ND_GTF;
+ r->gtf_2nd_j = J_2ND_GTF;
+ } else {
+ r->gtf_2nd_f = 0;
+ }
+ if (HAVE_CVT) {
+ r->max_clock_khz = MAX_CLOCK_KHZ;
+ r->max_clock = r->max_clock_khz / 1000;
+ r->maxwidth = MAXWIDTH;
+ r->supported_aspect = SUPPORTED_ASPECT;
+ r->preferred_aspect = PREFERRED_ASPECT;
+ r->supported_blanking = SUPPORTED_BLANKING;
+ r->supported_scaling = SUPPORTED_SCALING;
+ r->preferred_refresh = PREFERRED_REFRESH;
+ } else {
+ r->max_clock_khz = 0;
+ }
+}
+
+static void
+get_whitepoint_section(Uchar *c, struct whitePoints *wp)
+{
+ wp[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->stereo_1 = STEREO1;
+ r->sync = SYNC_T;
+ r->misc = MISC;
+}
+
+#define MAX_EDID_MINOR 4
+
+static Bool
+validate_version(int scrnIndex, struct edid_version *r)
+{
+ if (r->version != 1) {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n",
+ r->version);
+ return FALSE;
+ }
+
+ if (r->revision > MAX_EDID_MINOR)
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Assuming version 1.%d is compatible with 1.%d\n",
+ r->revision, MAX_EDID_MINOR);
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xfree86/ddc/print_edid.c b/xorg-server/hw/xfree86/ddc/print_edid.c
new file mode 100644
index 000000000..df11bfb3d
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/print_edid.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ * Copyright 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * print_edid.c: print out all information retrieved from display device
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+/* XXX kinda gross */
+#define _PARSE_EDID_
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86DDC.h"
+#include "edid.h"
+
+#define EDID_WIDTH 16
+
+static void
+print_vendor(int scrnIndex, struct vendor *c)
+{
+ xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer: %s Model: %x Serial#: %u\n",
+ (char *)&c->name, c->prod_id, c->serial);
+ 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 const char *digital_interfaces[] = {
+ "undefined",
+ "DVI",
+ "HDMI-a",
+ "HDMI-b",
+ "MDDI",
+ "DisplayPort",
+ "unknown"
+};
+
+static void
+print_input_features(int scrnIndex, struct disp_features *c,
+ struct edid_version *v)
+{
+ if (DIGITAL(c->input_type)) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Digital Display Input\n");
+ if (v->revision == 2 || v->revision == 3) {
+ if (DFP1(c->input_dfp))
+ xf86DrvMsg(scrnIndex, X_INFO, "DFP 1.x compatible TMDS\n");
+ } else if (v->revision >= 4) {
+ int interface = c->input_interface;
+ int bpc = c->input_bpc;
+ if (interface > 6)
+ interface = 6; /* unknown */
+ if (bpc == 0 || bpc == 7)
+ xf86DrvMsg(scrnIndex, X_INFO, "Undefined color depth\n");
+ else
+ xf86DrvMsg(scrnIndex, X_INFO, "%d bits per channel\n",
+ bpc * 2 + 4);
+ xf86DrvMsg(scrnIndex, X_INFO, "Digital interface is %s\n",
+ digital_interfaces[interface]);
+ }
+ } else {
+ xf86DrvMsg(scrnIndex,X_INFO,"Analog Display Input, ");
+ xf86ErrorF("Input Voltage Level: ");
+ switch (c->input_voltage){
+ case V070:
+ xf86ErrorF("0.700/0.300 V\n");
+ break;
+ case V071:
+ xf86ErrorF("0.714/0.286 V\n");
+ break;
+ case V100:
+ xf86ErrorF("1.000/0.400 V\n");
+ break;
+ case V007:
+ 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,
+ struct edid_version *v)
+{
+ if (c->dpms) {
+ xf86DrvMsg(scrnIndex,X_INFO,"DPMS capabilities:");
+ if (DPMS_STANDBY(c->dpms)) xf86ErrorF(" StandBy");
+ if (DPMS_SUSPEND(c->dpms)) xf86ErrorF(" Suspend");
+ if (DPMS_OFF(c->dpms)) xf86ErrorF(" Off");
+ } else
+ xf86DrvMsg(scrnIndex,X_INFO,"No DPMS capabilities specified");
+ if (!c->input_type) { /* analog */
+ switch (c->display_type){
+ case DISP_MONO:
+ xf86ErrorF("; Monochorome/GrayScale Display\n");
+ break;
+ case DISP_RGB:
+ xf86ErrorF("; RGB/Color Display\n");
+ break;
+ case DISP_MULTCOLOR:
+ xf86ErrorF("; Non RGB Multicolor Display\n");
+ break;
+ default:
+ xf86ErrorF("\n");
+ break;
+ }
+ } else {
+ int enc = c->display_type;
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Supported color encodings: "
+ "RGB 4:4:4 %s%s\n",
+ enc & DISP_YCRCB444 ? "YCrCb 4:4:4 " : "",
+ enc & DISP_YCRCB422 ? "YCrCb 4:2:2" : "");
+ }
+
+ if (STD_COLOR_SPACE(c->msc))
+ xf86DrvMsg(scrnIndex,X_INFO,
+ "Default color space is primary color space\n");
+
+ if (PREFERRED_TIMING_MODE(c->msc) || v->revision >= 4) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "First detailed timing is preferred mode\n");
+ if (v->revision >= 4)
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Preferred mode is native pixel format and refresh rate\n");
+ } else if (v->revision == 3) {
+ xf86DrvMsg(scrnIndex,X_INFO,
+ "First detailed timing not preferred "
+ "mode in violation of standard!");
+ }
+
+ if (v->revision >= 4) {
+ if (GFT_SUPPORTED(c->msc)) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Display is continuous-frequency\n");
+ }
+ } else {
+ if (GFT_SUPPORTED(c->msc))
+ xf86DrvMsg(scrnIndex, X_INFO, "GTF timings supported\n");
+ }
+}
+
+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_display(int scrnIndex, struct disp_features *disp,
+ struct edid_version *v)
+{
+ print_input_features(scrnIndex, disp, v);
+ if (disp->hsize && disp->vsize) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Max Image Size [cm]: ");
+ xf86ErrorF("horiz.: %i ", disp->hsize);
+ xf86ErrorF("vert.: %i\n", disp->vsize);
+ } else if (v->revision >= 4 && (disp->hsize || disp->vsize)) {
+ if (disp->hsize)
+ xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (landscape)\n",
+ (disp->hsize + 99) / 100.0);
+ if (disp->vsize)
+ xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (portrait)\n",
+ 100.0 / (float)(disp->vsize + 99));
+
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO, "Indeterminate output size\n");
+ }
+
+ if (!disp->gamma && v->revision >= 1.4)
+ xf86DrvMsg(scrnIndex, X_INFO, "Gamma defined in extension block\n");
+ else
+ xf86DrvMsg(scrnIndex, X_INFO, "Gamma: %.2f\n", disp->gamma);
+
+ print_dpms_features(scrnIndex, disp, v);
+ print_whitepoint(scrnIndex, disp);
+}
+
+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_cvt_timings(int si, struct cvt_timings *t)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (t[i].height) {
+ xf86DrvMsg(si, X_INFO, "%dx%d @ %s%s%s%s%s Hz\n",
+ t[i].width, t[i].height,
+ t[i].rates & 0x10 ? "50," : "",
+ t[i].rates & 0x08 ? "60," : "",
+ t[i].rates & 0x04 ? "75," : "",
+ t[i].rates & 0x02 ? "85," : "",
+ t[i].rates & 0x01 ? "60RB" : "");
+ } else break;
+ }
+}
+
+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_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("right channel on sync\n");
+ else
+ xf86ErrorF("left channel on sync\n");
+ } else if (IS_LEFT_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("right channel on even line\n");
+ else
+ xf86ErrorF("left channel on evel line\n");
+ }
+ if (IS_4WAY_STEREO(t->stereo)) {
+ if (!t->stereo_1)
+ xf86ErrorF("4-way interleaved\n");
+ else
+ xf86ErrorF("side-by-side interleaved");
+ }
+ }
+ }
+}
+
+static void
+print_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:
+ {
+ struct monitor_ranges *r = &m[i].section.ranges;
+ xf86DrvMsg(scrnIndex,X_INFO,
+ "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,",
+ r->min_v, r->max_v, r->min_h, r->max_h);
+ if (r->max_clock_khz != 0) {
+ xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz);
+ if (r->maxwidth)
+ xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n",
+ r->maxwidth);
+ xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:");
+ if (r->supported_aspect & SUPPORTED_ASPECT_4_3)
+ xf86ErrorF(" 4:3%s",
+ r->preferred_aspect == PREFERRED_ASPECT_4_3?"*":"");
+ if (r->supported_aspect & SUPPORTED_ASPECT_16_9)
+ xf86ErrorF(" 16:9%s",
+ r->preferred_aspect == PREFERRED_ASPECT_16_9?"*":"");
+ if (r->supported_aspect & SUPPORTED_ASPECT_16_10)
+ xf86ErrorF(" 16:10%s",
+ r->preferred_aspect == PREFERRED_ASPECT_16_10?"*":"");
+ if (r->supported_aspect & SUPPORTED_ASPECT_5_4)
+ xf86ErrorF(" 5:4%s",
+ r->preferred_aspect == PREFERRED_ASPECT_5_4?"*":"");
+ if (r->supported_aspect & SUPPORTED_ASPECT_15_9)
+ xf86ErrorF(" 15:9%s",
+ r->preferred_aspect == PREFERRED_ASPECT_15_9?"*":"");
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:");
+ if (r->supported_blanking & CVT_STANDARD)
+ xf86ErrorF(" standard");
+ if (r->supported_blanking & CVT_REDUCED)
+ xf86ErrorF(" reduced");
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:");
+ if (r->supported_scaling & SCALING_HSHRINK)
+ xf86ErrorF(" hshrink");
+ if (r->supported_scaling & SCALING_HSTRETCH)
+ xf86ErrorF(" hstretch");
+ if (r->supported_scaling & SCALING_VSHRINK)
+ xf86ErrorF(" vshrink");
+ if (r->supported_scaling & SCALING_VSTRETCH)
+ xf86ErrorF(" vstretch");
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n",
+ r->preferred_refresh);
+ } else if (r->max_clock != 0) {
+ xf86ErrorF(" PixClock max %i MHz\n", r->max_clock);
+ } else {
+ xf86ErrorF("\n");
+ }
+ if (r->gtf_2nd_f > 0)
+ xf86DrvMsg(scrnIndex,X_INFO," 2nd GTF parameters: f: %i kHz "
+ "c: %i m: %i k %i j %i\n", r->gtf_2nd_f,
+ r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k,
+ r->gtf_2nd_j);
+ 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;
+ case DS_CMD:
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Color management data: (not decoded)\n");
+ break;
+ case DS_CVT:
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "CVT 3-byte-code modes:\n");
+ print_cvt_timings(scrnIndex, m[i].section.cvt);
+ break;
+ case DS_EST_III:
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Established timings III: (not decoded)\n");
+ break;
+ case DS_DUMMY:
+ default:
+ break;
+ }
+ if (m[i].type >= DS_VENDOR && m[i].type <= DS_VENDOR_MAX) {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Unknown vendor-specific block %hx\n",
+ m[i].type - DS_VENDOR);
+ }
+ }
+}
+
+static void
+print_number_sections(int scrnIndex, int num)
+{
+ if (num)
+ xf86DrvMsg(scrnIndex,X_INFO,"Number of EDID sections to follow: %i\n",
+ num);
+}
+
+xf86MonPtr
+xf86PrintEDID(xf86MonPtr m)
+{
+ CARD16 i, j;
+ char buf[EDID_WIDTH * 2 + 1];
+
+ if (!(m)) return NULL;
+
+ print_vendor(m->scrnIndex,&m->vendor);
+ print_version(m->scrnIndex,&m->ver);
+ print_display(m->scrnIndex,&m->features, &m->ver);
+ print_established_timings(m->scrnIndex,&m->timings1);
+ print_std_timings(m->scrnIndex,m->timings2);
+ print_detailed_monitor_section(m->scrnIndex,m->det_mon);
+ print_number_sections(m->scrnIndex,m->no_sections);
+
+ xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n");
+
+ for (i = 0; i < 128; i += j) {
+ for (j = 0; j < EDID_WIDTH; ++j) {
+ sprintf(&buf[j * 2], "%02x", m->rawData[i + j]);
+ }
+ xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf);
+ }
+
+ return m;
+}
diff --git a/xorg-server/hw/xfree86/ddc/xf86DDC.c b/xorg-server/hw/xfree86/ddc/xf86DDC.c
new file mode 100644
index 000000000..28e2ead28
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/xf86DDC.c
@@ -0,0 +1,292 @@
+/* xf86DDC.c
+ *
+ * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86DDC.h"
+#include "ddcPriv.h"
+#include <string.h>
+
+#define RETRIES 4
+
+static unsigned char *EDIDRead_DDC1(
+ ScrnInfoPtr pScrn,
+ DDC1SetSpeedProc,
+ 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 * 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 },
+};
+
+/**
+ * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are
+ * unset. EDID information blocks are interpreted and the results returned in
+ * an xf86MonPtr.
+ *
+ * This function does not affect the list of modes used by drivers -- it is up
+ * to the driver to decide policy on what to do with EDID information.
+ *
+ * @return pointer to a new xf86MonPtr containing the EDID information.
+ * @return NULL if no monitor attached or failure to interpret the EDID.
+ */
+xf86MonPtr
+xf86DoEDID_DDC1(
+ int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed,
+ 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;
+}
+
+/**
+ * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
+ * unset. EDID information blocks are interpreted and the results returned in
+ * an xf86MonPtr.
+ *
+ * This function does not affect the list of modes used by drivers -- it is up
+ * to the driver to decide policy on what to do with EDID information.
+ *
+ * @return pointer to a new xf86MonPtr containing the EDID information.
+ * @return NULL if no monitor attached or failure to interpret the EDID.
+ */
+xf86MonPtr
+xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ unsigned char *EDID_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");
+ else
+ ErrorF("Sections to follow: %i\n",tmp->no_sections);
+#endif
+
+ 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, DDC1SetSpeedProc DDCSpeed,
+ unsigned int (*read_DDC)(ScrnInfoPtr))
+{
+ unsigned char *EDID_block = NULL;
+ int count = RETRIES;
+
+ if (!read_DDC) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "chipset doesn't support DDC1\n");
+ return NULL;
+ };
+
+ if (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 *
+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;
+
+ /*
+ * Slow down the bus so that older monitors don't
+ * miss things.
+ */
+ pBus->RiseFallTime = 20;
+
+ 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->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;
+}
diff --git a/xorg-server/hw/xfree86/ddc/xf86DDC.h b/xorg-server/hw/xfree86/ddc/xf86DDC.h
new file mode 100644
index 000000000..3b072dda7
--- /dev/null
+++ b/xorg-server/hw/xfree86/ddc/xf86DDC.h
@@ -0,0 +1,58 @@
+
+/* 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;
+
+typedef void (* DDC1SetSpeedProc)(ScrnInfoPtr, xf86ddcSpeed);
+
+extern xf86MonPtr xf86DoEDID_DDC1(
+ int scrnIndex,
+ DDC1SetSpeedProc DDC1SetSpeed,
+ 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 void
+xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC);
+
+extern Bool xf86SetDDCproperties(
+ ScrnInfoPtr pScreen,
+ xf86MonPtr DDC
+);
+
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+
+#endif
+
+