diff options
Diffstat (limited to 'xorg-server/hw/xfree86/ddc')
-rw-r--r-- | xorg-server/hw/xfree86/ddc/DDC.HOWTO | 16 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/Makefile.in | 76 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/ddcProperty.c | 11 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/edid.h | 7 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/interpret_edid.c | 90 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/print_edid.c | 36 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/xf86DDC.c | 241 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/ddc/xf86DDC.h | 11 |
8 files changed, 296 insertions, 192 deletions
diff --git a/xorg-server/hw/xfree86/ddc/DDC.HOWTO b/xorg-server/hw/xfree86/ddc/DDC.HOWTO index 833a7ab54..1d06ca124 100644 --- a/xorg-server/hw/xfree86/ddc/DDC.HOWTO +++ b/xorg-server/hw/xfree86/ddc/DDC.HOWTO @@ -6,24 +6,24 @@ When implementing DDC in the driver one has the choice between DDC1 and DDC2. - DDC1 data is contiuously transmitted by a DDC1 capable display + DDC1 data is continuously 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. + soon as it detects DDC1 activity 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 + activity 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. + DDC2 it is preferable. All relevant prototypes and defines are in xf86DDC.h. DDC2 additionally requires I2C support. The I2C prototypes @@ -37,7 +37,7 @@ unsigned int XXX_ddc1Read(ScrnInfoPtr pScrn) - Additionally a function is required to inclrease the Vsync + Additionally a function is required to increase the Vsync frequency to max. 25 kHz. void XXX_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) @@ -58,7 +58,7 @@ 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. + which contains all information retrieved by DDC. NULL will be returned on failure. DDC2 Support @@ -73,7 +73,7 @@ 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. + which contains all information retrieved by DDC. NULL will be returned on failure. Printing monitor parameters @@ -86,7 +86,7 @@ is provided. Further processing of the xf86Monitor structure is not yet - implemented. Howerver it is planned to use the information + implemented. However, 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. diff --git a/xorg-server/hw/xfree86/ddc/Makefile.in b/xorg-server/hw/xfree86/ddc/Makefile.in index 9016bc200..3e7813965 100644 --- a/xorg-server/hw/xfree86/ddc/Makefile.in +++ b/xorg-server/hw/xfree86/ddc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. +# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -45,7 +45,6 @@ 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 \ @@ -64,9 +63,6 @@ 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) \ @@ -90,8 +86,9 @@ ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ -APPDEFAULTDIR = @APPDEFAULTDIR@ APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@ +APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ APP_MAN_DIR = @APP_MAN_DIR@ APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ AR = @AR@ @@ -112,10 +109,6 @@ 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@ @@ -137,6 +130,7 @@ DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DOLT_BASH = @DOLT_BASH@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ @@ -146,18 +140,15 @@ DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ DSYMUTIL = @DSYMUTIL@ DTRACE = @DTRACE@ -ECHO = @ECHO@ +DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ +FGREP = @FGREP@ 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@ @@ -176,7 +167,7 @@ KDRIVE_LIBS = @KDRIVE_LIBS@ KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ -LAUNCHD = @LAUNCHD@ +LD = @LD@ LDFLAGS = @LDFLAGS@ LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ LEX = @LEX@ @@ -190,7 +181,10 @@ LIBTOOL = @LIBTOOL@ LIB_MAN_DIR = @LIB_MAN_DIR@ LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ LINUXDOC = @LINUXDOC@ +LIPO = @LIPO@ LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ @@ -202,8 +196,7 @@ MESA_SOURCE = @MESA_SOURCE@ MISC_MAN_DIR = @MISC_MAN_DIR@ MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ MKDIR_P = @MKDIR_P@ -MKFONTDIR = @MKFONTDIR@ -MKFONTSCALE = @MKFONTSCALE@ +NM = @NM@ NMEDIT = @NMEDIT@ OBJC = @OBJC@ OBJCCLD = @OBJCCLD@ @@ -212,8 +205,8 @@ OBJCFLAGS = @OBJCFLAGS@ OBJCLINK = @OBJCLINK@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -246,7 +239,6 @@ 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@ @@ -256,27 +248,12 @@ 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@ @@ -287,10 +264,6 @@ 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@ @@ -299,13 +272,8 @@ 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@ +XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@ +XPBPROXY_LIBS = @XPBPROXY_LIBS@ XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ XSDL_INCS = @XSDL_INCS@ @@ -338,8 +306,7 @@ 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@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -359,7 +326,6 @@ driverdir = @driverdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ extdir = @extdir@ -ft_config = @ft_config@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -369,12 +335,12 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -launchagentsdir = @launchagentsdir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ +lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ moduledir = @moduledir@ @@ -392,8 +358,6 @@ 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 \ @@ -410,8 +374,8 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ @@ -504,7 +468,7 @@ ID: $(HEADERS) $(SOURCES) $(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; } \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS diff --git a/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c index 02125dff7..a4384f1d3 100644 --- a/xorg-server/hw/xfree86/ddc/ddcProperty.c +++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c @@ -83,13 +83,18 @@ addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) } if (makeEDID1prop) { - if ((EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL) + int size = 128; + + if (DDC->flags & EDID_COMPLETE_RAWDATA) + size += DDC->no_sections * 128; + + if ((EDID1rawdata = xalloc(size*sizeof(CARD8)))==NULL) return; EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME) - 1, TRUE); - memcpy(EDID1rawdata, DDC->rawData, 128); + memcpy(EDID1rawdata, DDC->rawData, size); xf86RegisterRootWindowProperty(scrnIndex, EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata); + size, (unsigned char *)EDID1rawdata); } if (makeEDID2prop) { diff --git a/xorg-server/hw/xfree86/ddc/edid.h b/xorg-server/hw/xfree86/ddc/edid.h index a4e79dae0..3ca402f57 100644 --- a/xorg-server/hw/xfree86/ddc/edid.h +++ b/xorg-server/hw/xfree86/ddc/edid.h @@ -527,10 +527,13 @@ struct detailed_monitor_section { struct whitePoints wp[2]; /* 32 */ /* color management data */ struct cvt_timings cvt[4]; /* 64 */ - /* established timings III */ + Uchar est_iii[6]; /* 6 */ } section; /* max: 80 */ }; +/* flags */ +#define EDID_COMPLETE_RAWDATA 0x1 + typedef struct { int scrnIndex; struct vendor vendor; @@ -539,7 +542,7 @@ typedef struct { struct established_timings timings1; struct std_timings timings2[8]; struct detailed_monitor_section det_mon[4]; - void *vdif; /* unused */ + unsigned long flags; int no_sections; Uchar *rawData; } xf86Monitor, *xf86MonPtr; diff --git a/xorg-server/hw/xfree86/ddc/interpret_edid.c b/xorg-server/hw/xfree86/ddc/interpret_edid.c index 879308520..310606c7c 100644 --- a/xorg-server/hw/xfree86/ddc/interpret_edid.c +++ b/xorg-server/hw/xfree86/ddc/interpret_edid.c @@ -163,6 +163,20 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) return NULL; } +xf86MonPtr +xf86InterpretEEDID(int scrnIndex, Uchar *block) +{ + xf86MonPtr m; + + m = xf86InterpretEDID(scrnIndex, block); + if (!m) + return NULL; + + /* extension parse */ + + return m; +} + static void get_vendor_section(Uchar *c, struct vendor *r) { @@ -270,6 +284,8 @@ get_std_timing_section(Uchar *c, struct std_timings *r, } } +static const unsigned char empty_block[18]; + static void get_dt_md_section(Uchar *c, struct edid_version *ver, struct detailed_monitor_section *det_mon) @@ -313,6 +329,7 @@ get_dt_md_section(Uchar *c, struct edid_version *ver, break; case ADD_EST_TIMINGS: det_mon[i].type = DS_EST_III; + memcpy(det_mon[i].section.est_iii, c + 6, 6); break; case ADD_DUMMY: det_mon[i].type = DS_DUMMY; @@ -321,10 +338,10 @@ get_dt_md_section(Uchar *c, struct edid_version *ver, det_mon[i].type = DS_UNKOWN; break; } - if (c[3] <= 0x0F) { + if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { det_mon[i].type = DS_VENDOR + c[3]; } - } else { + } else { det_mon[i].type = DT; get_detailed_timing_section(c,&det_mon[i].section.d_timings); } @@ -394,14 +411,14 @@ get_monitor_ranges(Uchar *c, struct monitor_ranges *r) 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; + wp[0].white_x = WHITEX1; + wp[0].white_y = WHITEY1; + wp[1].white_x = WHITEX2; + wp[1].white_y = WHITEY2; + wp[0].index = WHITE_INDEX1; + wp[1].index = WHITE_INDEX2; + wp[0].white_gamma = WHITE_GAMMA1; + wp[1].white_gamma = WHITE_GAMMA2; } static void @@ -445,3 +462,56 @@ validate_version(int scrnIndex, struct edid_version *r) return TRUE; } + +/* + * Returns true if HDMI, false if definitely not or unknown. + */ +_X_EXPORT Bool +xf86MonitorIsHDMI(xf86MonPtr mon) +{ + int i = 0, version, offset; + char *edid = NULL; + + if (!mon) + return FALSE; + + if (!(mon->flags & EDID_COMPLETE_RAWDATA)) + return FALSE; + + if (!mon->no_sections) + return FALSE; + + edid = (char *)mon->rawData; + if (!edid) + return FALSE; + + /* find the CEA extension block */ + for (i = 1; i <= mon->no_sections; i++) + if (edid[i * 128] == 0x02) + break; + if (i == mon->no_sections + 1) + return FALSE; + edid += (i * 128); + + version = edid[1]; + offset = edid[2]; + if (version < 3 || offset < 4) + return FALSE; + + /* walk the cea data blocks */ + for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) { + char *x = edid + i; + + /* find a vendor specific block */ + if ((x[0] & 0xe0) >> 5 == 0x03) { + int oui = (x[3] << 16) + (x[2] << 8) + x[1]; + + /* find the HDMI vendor OUI */ + if (oui == 0x000c03) + return TRUE; + } + } + + /* guess it's not HDMI after all */ + return FALSE; +} diff --git a/xorg-server/hw/xfree86/ddc/print_edid.c b/xorg-server/hw/xfree86/ddc/print_edid.c index df11bfb3d..e9c8cbdf7 100644 --- a/xorg-server/hw/xfree86/ddc/print_edid.c +++ b/xorg-server/hw/xfree86/ddc/print_edid.c @@ -168,7 +168,7 @@ print_dpms_features(int scrnIndex, struct disp_features *c, } else if (v->revision == 3) { xf86DrvMsg(scrnIndex,X_INFO, "First detailed timing not preferred " - "mode in violation of standard!"); + "mode in violation of standard!\n"); } if (v->revision >= 4) { @@ -230,7 +230,7 @@ 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"); + xf86DrvMsg(scrnIndex,X_INFO,"Supported established timings:\n"); c=t->t1; if (c&0x80) xf86DrvMsg(scrnIndex,X_INFO,"720x400@70Hz\n"); if (c&0x40) xf86DrvMsg(scrnIndex,X_INFO,"720x400@88Hz\n"); @@ -262,7 +262,7 @@ print_std_timings(int scrnIndex, struct std_timings *t) 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"); + xf86DrvMsg(scrnIndex,X_INFO,"Supported standard timings:\n"); done = 1; } xf86DrvMsg(scrnIndex,X_INFO, @@ -295,7 +295,7 @@ 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,"Supported detailed timing:\n"); xf86DrvMsg(scrnIndex,X_INFO,"clock: %.1f MHz ",t->clock/1000000.0); xf86ErrorF("Image Size: %i x %i mm\n",t->h_size,t->v_size); xf86DrvMsg(scrnIndex,X_INFO, @@ -463,22 +463,28 @@ print_number_sections(int scrnIndex, int num) xf86MonPtr xf86PrintEDID(xf86MonPtr m) { - CARD16 i, j; + CARD16 i, j, n; char buf[EDID_WIDTH * 2 + 1]; - if (!(m)) return NULL; + 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); + 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); + + /* extension block section stuff */ xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n"); - - for (i = 0; i < 128; i += j) { + + n = 128; + if (m->flags & EDID_COMPLETE_RAWDATA) + n += m->no_sections * 128; + + for (i = 0; i < n; i += j) { for (j = 0; j < EDID_WIDTH; ++j) { sprintf(&buf[j * 2], "%02x", m->rawData[i + j]); } diff --git a/xorg-server/hw/xfree86/ddc/xf86DDC.c b/xorg-server/hw/xfree86/ddc/xf86DDC.c index 28e2ead28..0d8677637 100644 --- a/xorg-server/hw/xfree86/ddc/xf86DDC.c +++ b/xorg-server/hw/xfree86/ddc/xf86DDC.c @@ -2,6 +2,14 @@ * * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> */ + +/* + * Note that DDC1 does not define any method for returning blocks beyond + * the first. DDC2 does, but the original implementation would only ever + * read the first block. If you want to read and parse all blocks, use + * xf86DoEEDID(). + */ + #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif @@ -31,18 +39,6 @@ static unsigned int *FetchEDID_DDC1( 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, @@ -107,10 +103,102 @@ xf86DoEDID_DDC1( return tmp; } +static I2CDevPtr +DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) +{ + I2CDevPtr dev = NULL; + + if (!(dev = xf86I2CFindDev(pBus, address))) { + dev = xf86CreateI2CDevRec(); + dev->DevName = name; + dev->SlaveAddr = address; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->AcknTimeout = 40; + + dev->pI2CBus = pBus; + if (!xf86I2CDevInit(dev)) { + xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); + return NULL; + } + } + + return dev; +} + +static I2CDevPtr +DDC2Init(int scrnIndex, I2CBusPtr pBus) +{ + I2CDevPtr dev = NULL; + + /* + * Slow down the bus so that older monitors don't + * miss things. + */ + pBus->RiseFallTime = 20; + + DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); + dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); + + return dev; +} + +/* Mmmm, smell the hacks */ +static void +EEDIDStop(I2CDevPtr d) +{ +} + +/* block is the EDID block number. a segment is two blocks. */ +static Bool +DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) +{ + unsigned char W_Buffer[1]; + int i, segment; + I2CDevPtr seg; + void (*stop)(I2CDevPtr); + + for (i = 0; i < RETRIES; i++) { + /* Stop bits reset the segment pointer to 0, so be careful here. */ + segment = block >> 1; + if (segment) { + Bool b; + + if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) + return FALSE; + + W_Buffer[0] = segment; + + stop = dev->pI2CBus->I2CStop; + dev->pI2CBus->I2CStop = EEDIDStop; + + b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); + + dev->pI2CBus->I2CStop = stop; + if (!b) { + dev->pI2CBus->I2CStop(dev); + continue; + } + } + + W_Buffer[0] = (block & 0x01) * EDID1_LEN; + + if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { + if (!DDC_checksum(R_Buffer, EDID1_LEN)) + return TRUE; + } + } + + return FALSE; +} + /** * 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. + * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return + * the complete EDID data, including all extension blocks, if the 'complete' + * parameter is TRUE; * * 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. @@ -119,46 +207,72 @@ xf86DoEDID_DDC1( * @return NULL if no monitor attached or failure to interpret the EDID. */ xf86MonPtr -xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) +xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; unsigned char *EDID_block = NULL; xf86MonPtr tmp = NULL; + I2CDevPtr dev = NULL; /* Default DDC and DDC2 to enabled. */ Bool noddc = FALSE, noddc2 = FALSE; OptionInfoPtr options; - options = xnfalloc(sizeof(DDCOptions)); - (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + options = xalloc(sizeof(DDCOptions)); + if (!options) + return NULL; + 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 (!(dev = DDC2Init(scrnIndex, pBus))) + return NULL; - if (EDID_block){ - tmp = xf86InterpretEDID(scrnIndex,EDID_block); - } else { -#ifdef DEBUG - ErrorF("No EDID block returned\n"); -#endif + EDID_block = xcalloc(1, EDID1_LEN); + if (!EDID_block) return NULL; + + if (DDC2Read(dev, 0, EDID_block)) { + int i, n = EDID_block[0x7e]; + + if (complete && n) { + EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n)); + + for (i = 0; i < n; i++) + DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); + } + + tmp = xf86InterpretEEDID(scrnIndex, EDID_block); } -#ifdef DEBUG - if (!tmp) - ErrorF("Cannot interpret EDID block\n"); - else - ErrorF("Sections to follow: %i\n",tmp->no_sections); -#endif - + + if (tmp && complete) + tmp->flags |= EDID_COMPLETE_RAWDATA; + 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) +{ + return xf86DoEEDID(scrnIndex, pBus, FALSE); +} + /* * read EDID record , pass it to callback function to interpret. * callback function will store it for further use by calling @@ -225,68 +339,3 @@ FetchEDID_DDC1(register ScrnInfoPtr pScrn, } 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 index 3b072dda7..3172b555d 100644 --- a/xorg-server/hw/xfree86/ddc/xf86DDC.h +++ b/xorg-server/hw/xfree86/ddc/xf86DDC.h @@ -35,6 +35,8 @@ extern xf86MonPtr xf86DoEDID_DDC2( I2CBusPtr pBus ); +extern xf86MonPtr xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool); + extern xf86MonPtr xf86PrintEDID( xf86MonPtr monPtr ); @@ -43,6 +45,10 @@ extern xf86MonPtr xf86InterpretEDID( int screenIndex, Uchar *block ); +extern xf86MonPtr xf86InterpretEEDID( + int screenIndex, Uchar *block +); + extern void xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); @@ -53,6 +59,7 @@ extern Bool xf86SetDDCproperties( DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); -#endif - +extern Bool +xf86MonitorIsHDMI(xf86MonPtr mon); +#endif |