[Xquartz-changes] xserver: Branch 'master' - 24 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Tue Nov 3 16:07:48 PST 2009


 Xext/shm.c                        |   17 -
 configure.ac                      |   99 ++++++--
 exa/exa_mixed.c                   |    4 
 glx/Makefile.am                   |    4 
 glx/glapi.c                       |    7 
 glx/unpack.h                      |    2 
 hw/kdrive/linux/evdev.c           |   15 +
 hw/xfree86/common/xf86Configure.c |   56 ++--
 hw/xfree86/common/xf86Init.c      |   32 +-
 hw/xfree86/common/xf86Mode.c      |   29 +-
 hw/xfree86/common/xf86Xinput.c    |    4 
 hw/xfree86/common/xf86str.h       |    1 
 hw/xfree86/ddc/edid.h             |   97 ++++++++
 hw/xfree86/ddc/interpret_edid.c   |  375 +++++++++++++++++++++++---------
 hw/xfree86/ddc/print_edid.c       |  264 ++++++++++++----------
 hw/xfree86/ddc/xf86DDC.h          |   50 ++++
 hw/xfree86/i2c/fi1236.c           |   10 
 hw/xfree86/loader/Makefile.am     |    1 
 hw/xfree86/loader/sdksyms.sh      |    1 
 hw/xfree86/modes/xf86Crtc.c       |  164 +++++++-------
 hw/xfree86/modes/xf86EdidModes.c  |  444 +++++++++++++++++++++++++-------------
 hw/xfree86/modes/xf86Modes.c      |   42 +++
 hw/xfree86/modes/xf86Modes.h      |    3 
 hw/xfree86/parser/Flags.c         |    2 
 hw/xfree86/x86emu/Makefile.am     |    2 
 hw/xfree86/x86emu/sys.c           |  181 ---------------
 include/Makefile.am               |    3 
 include/dix-config.h.in           |   11 
 include/xsha1.h                   |   19 +
 os/Makefile.am                    |    4 
 os/xsha1.c                        |  140 +++++++++++
 render/glyph.c                    |   36 ---
 32 files changed, 1365 insertions(+), 754 deletions(-)

New commits:
commit 412c56ef3332d09efbd861e41c3e985f44729729
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sun Nov 1 22:08:40 2009 +0100

    exa: remove some outdated comment
    
    - This comment is still in exa_driver.c and there it makes sense.
    
    Signed-off-by: Maarten Maathuis <madman2003 at gmail.com>
    Acked-by: Michel Dänzer <michel at daenzer.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index bc393c7..b29ee35 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -154,10 +154,6 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
     if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
 	ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
 						bitsPerPixel, devKind, pPixData);
-	/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
-	 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap.
-	 * We need to store the pointer, because PrepareAccess won't be called.
-	 */
 	if (ret == TRUE)
 	    goto out;
     }
commit 48b8c076a7b7dbbddfc472e8c6e5251a0b174cbc
Author: Matthieu Herrb <matthieu at laas.fr>
Date:   Mon Nov 2 11:11:24 2009 +0100

    add libc as a choice for SHA1 implementation
    
    On Sun, Nov 01, 2009 at 02:54:13PM -0800, Keith Packard wrote:
    > Excerpts from Matthieu Herrb's message of Sun Nov 01 09:34:35 -0800 2009:
    >
    > > +AC_CHECK_FUNCS([SHA1Init], [HAVE_LIBC_SHA1=yes])
    >
    > I'd suggest AC_CHECK_FUNC instead; as far as I can tell, AC_CHECK_FUNCS
    > will also define HAVE_SHA1INIT. Also, can you  use HAVE_LIBC_SHA1
    > consistently rather than having two separate names (HAVE_LIBC_SHA1 and
    > HAVE_SHA1_IN_LIBC)? Yes, I know one is a preprocessor symbol and the
    > other is a cpp shell variable, but I think that will work anyway.
    >
    New version taking you comments into account.
    
    From: Matthieu Herrb <matthieu.herrb at laas.fr>
    Date: Sun, 1 Nov 2009 18:19:27 +0100
    Subject: [PATCH] Add a probe for SHA1 functions in libc in *BSD.
    
    The interface is the same as the one in libmd.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index bdbbc7a..8e1edba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1287,8 +1287,20 @@ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 
 # SHA1 hashing
 AC_ARG_WITH([sha1],
-            [AS_HELP_STRING([--with-sha1=libmd|libgcrypt|libcrypto|libsha1],
+            [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1],
                             [choose SHA1 implementation])])
+AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes])
+if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then
+	with_sha1=libc
+fi
+if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then
+	AC_MSG_ERROR([libc requested but not found])
+fi
+if test "x$with_sha1" = xlibc; then
+	AC_DEFINE([HAVE_SHA1_IN_LIBC], [1],
+		[Use libc SHA1 functions])
+	SHA1_LIBS=""
+fi
 AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes])
 if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then
 	with_sha1=libmd
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index ebf3733..274ce89 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -160,6 +160,9 @@
 /* Define to 1 if you have the <rpcsvc/dbm.h> header file. */
 #undef HAVE_RPCSVC_DBM_H
 
+/* Define to use libc SHA1 functions */
+#undef HAVE_SHA1_IN_LIBC
+
 /* Define to use libmd SHA1 functions */
 #undef HAVE_SHA1_IN_LIBMD
 
diff --git a/os/xsha1.c b/os/xsha1.c
index 94092ca..229ce89 100644
--- a/os/xsha1.c
+++ b/os/xsha1.c
@@ -5,7 +5,8 @@
 #include "os.h"
 #include "xsha1.h"
 
-#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
+#if defined(HAVE_SHA1_IN_LIBMD)  /* Use libmd for SHA1 */ \
+	|| defined(HAVE_SHA1_IN_LIBC) /* Use libc for SHA1 */
 
 # include <sha1.h>
 
commit da923d0bc15e99a8ed1986bd6f5df37f7af7284b
Author: Matt Turner <mattst88 at gmail.com>
Date:   Sun Nov 1 14:30:48 2009 -0500

    Make sys.c use unaligned access functions provided in compiler.
    
    Favorite deleted line was definitely
    	/* to cope with broken egcs-1.1.2 :-(((( */
    
    Signed-off-by: Matt Turner <mattst88 at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/x86emu/Makefile.am b/hw/xfree86/x86emu/Makefile.am
index 987ea8b..bcacb33 100644
--- a/hw/xfree86/x86emu/Makefile.am
+++ b/hw/xfree86/x86emu/Makefile.am
@@ -9,7 +9,7 @@ libx86emu_la_SOURCES = debug.c \
                       sys.c \
                       x86emu.h
 
-INCLUDES = 
+INCLUDES = $(XORG_INCS)
 
 AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)
 
diff --git a/hw/xfree86/x86emu/sys.c b/hw/xfree86/x86emu/sys.c
index e15fb09..2ebf6f1 100644
--- a/hw/xfree86/x86emu/sys.c
+++ b/hw/xfree86/x86emu/sys.c
@@ -48,168 +48,13 @@
 #ifndef NO_SYS_HEADERS
 #include <string.h>
 #endif                                                                                           
+#include "compiler.h" /* for unaligned access functions */
 /*------------------------- Global Variables ------------------------------*/
 
 X86EMU_sysEnv		_X86EMU_env;		/* Global emulator machine state */
 X86EMU_intrFuncs	_X86EMU_intrTab[256];
 
 /*----------------------------- Implementation ----------------------------*/
-#if defined(__alpha__) || defined(__alpha)
-/* to cope with broken egcs-1.1.2 :-(((( */
-
-#define ALPHA_UALOADS
-/*
- * inline functions to do unaligned accesses
- * from linux/include/asm-alpha/unaligned.h
- */
-
-/*
- * EGCS 1.1 knows about arbitrary unaligned loads.  Define some
- * packed structures to talk about such things with.
- */
-
-#if defined(__GNUC__)
-struct __una_u64 { unsigned long  x __attribute__((packed)); };
-struct __una_u32 { unsigned int   x __attribute__((packed)); };
-struct __una_u16 { unsigned short x __attribute__((packed)); };
-#endif
-
-static __inline__ unsigned long ldq_u(unsigned long * r11)
-{
-#if defined(__GNUC__)
-	const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
-	return ptr->x;
-#else
-	unsigned long r1,r2;
-	__asm__("ldq_u %0,%3\n\t"
-		"ldq_u %1,%4\n\t"
-		"extql %0,%2,%0\n\t"
-		"extqh %1,%2,%1"
-		:"=&r" (r1), "=&r" (r2)
-		:"r" (r11),
-		 "m" (*r11),
-		 "m" (*(const unsigned long *)(7+(char *) r11)));
-	return r1 | r2;
-#endif
-}
-
-static __inline__ unsigned long ldl_u(unsigned int * r11)
-{
-#if defined(__GNUC__)
-	const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
-	return ptr->x;
-#else
-	unsigned long r1,r2;
-	__asm__("ldq_u %0,%3\n\t"
-		"ldq_u %1,%4\n\t"
-		"extll %0,%2,%0\n\t"
-		"extlh %1,%2,%1"
-		:"=&r" (r1), "=&r" (r2)
-		:"r" (r11),
-		 "m" (*r11),
-		 "m" (*(const unsigned long *)(3+(char *) r11)));
-	return r1 | r2;
-#endif
-}
-
-static __inline__ unsigned long ldw_u(unsigned short * r11)
-{
-#if defined(__GNUC__)
-	const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
-	return ptr->x;
-#else
-	unsigned long r1,r2;
-	__asm__("ldq_u %0,%3\n\t"
-		"ldq_u %1,%4\n\t"
-		"extwl %0,%2,%0\n\t"
-		"extwh %1,%2,%1"
-		:"=&r" (r1), "=&r" (r2)
-		:"r" (r11),
-		 "m" (*r11),
-		 "m" (*(const unsigned long *)(1+(char *) r11)));
-	return r1 | r2;
-#endif
-}
-
-/*
- * Elemental unaligned stores 
- */
-
-static __inline__ void stq_u(unsigned long r5, unsigned long * r11)
-{
-#if defined(__GNUC__)
-	struct __una_u64 *ptr = (struct __una_u64 *) r11;
-	ptr->x = r5;
-#else
-	unsigned long r1,r2,r3,r4;
-
-	__asm__("ldq_u %3,%1\n\t"
-		"ldq_u %2,%0\n\t"
-		"insqh %6,%7,%5\n\t"
-		"insql %6,%7,%4\n\t"
-		"mskqh %3,%7,%3\n\t"
-		"mskql %2,%7,%2\n\t"
-		"bis %3,%5,%3\n\t"
-		"bis %2,%4,%2\n\t"
-		"stq_u %3,%1\n\t"
-		"stq_u %2,%0"
-		:"=m" (*r11),
-		 "=m" (*(unsigned long *)(7+(char *) r11)),
-		 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
-		:"r" (r5), "r" (r11));
-#endif
-}
-
-static __inline__ void stl_u(unsigned long r5, unsigned int * r11)
-{
-#if defined(__GNUC__)
-	struct __una_u32 *ptr = (struct __una_u32 *) r11;
-	ptr->x = r5;
-#else
-	unsigned long r1,r2,r3,r4;
-
-	__asm__("ldq_u %3,%1\n\t"
-		"ldq_u %2,%0\n\t"
-		"inslh %6,%7,%5\n\t"
-		"insll %6,%7,%4\n\t"
-		"msklh %3,%7,%3\n\t"
-		"mskll %2,%7,%2\n\t"
-		"bis %3,%5,%3\n\t"
-		"bis %2,%4,%2\n\t"
-		"stq_u %3,%1\n\t"
-		"stq_u %2,%0"
-		:"=m" (*r11),
-		 "=m" (*(unsigned long *)(3+(char *) r11)),
-		 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
-		:"r" (r5), "r" (r11));
-#endif
-}
-
-static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
-{
-#if defined(__GNUC__)
-	struct __una_u16 *ptr = (struct __una_u16 *) r11;
-	ptr->x = r5;
-#else
-	unsigned long r1,r2,r3,r4;
-
-	__asm__("ldq_u %3,%1\n\t"
-		"ldq_u %2,%0\n\t"
-		"inswh %6,%7,%5\n\t"
-		"inswl %6,%7,%4\n\t"
-		"mskwh %3,%7,%3\n\t"
-		"mskwl %2,%7,%2\n\t"
-		"bis %3,%5,%3\n\t"
-		"bis %2,%4,%2\n\t"
-		"stq_u %3,%1\n\t"
-		"stq_u %2,%0"
-		:"=m" (*r11),
-		 "=m" (*(unsigned long *)(1+(char *) r11)),
-		 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
-		:"r" (r5), "r" (r11));
-#endif
-}
-#endif
 
 /****************************************************************************
 PARAMETERS:
@@ -262,13 +107,7 @@ u16 X86API rdw(
 		}
 	else
 #endif
-#if defined(ALPHA_UALOADS)
 		val = ldw_u((u16*)(M.mem_base + addr));
-#elif  defined(IA64_UALOADS)
-      val = uldw((u16*)(M.mem_base + addr));
-#else
-		val = *(u16*)(M.mem_base + addr);
-#endif
 		DB(	if (DEBUG_MEM_TRACE())
 		printk("%#08x 2 -> %#x\n", addr, val);)
     return val;
@@ -301,13 +140,7 @@ u32 X86API rdl(
 		}
 	else
 #endif
-#if defined(ALPHA_UALOADS)
 		val = ldl_u((u32*)(M.mem_base + addr));
-#elif  defined(IA64_UALOADS)
-        val = uldl((u32*)(M.mem_base + addr));
-#else
-		val = *(u32*)(M.mem_base + addr);
-#endif
 DB(	if (DEBUG_MEM_TRACE())
 		printk("%#08x 4 -> %#x\n", addr, val);)
 	return val;
@@ -359,13 +192,7 @@ DB(	if (DEBUG_MEM_TRACE())
 		}
 	else
 #endif
-#if defined(ALPHA_UALOADS)
 	 stw_u(val,(u16*)(M.mem_base + addr));
-#elif defined(IA64_UALOADS)
-     ustw(val,(u16*)(M.mem_base + addr));
-#else
-	 *(u16*)(M.mem_base + addr) = val;
-#endif
 }
 
 /****************************************************************************
@@ -395,13 +222,7 @@ DB(	if (DEBUG_MEM_TRACE())
 		}
 	else
 #endif
-#if defined(ALPHA_UALOADS)
 	 stl_u(val,(u32*)(M.mem_base + addr));
-#elif defined(IA64_UALOADS)
-     ustl(val,(u32*)(M.mem_base + addr));
-#else
-	 *(u32*)(M.mem_base + addr) = val;
-#endif
 }
 
 /****************************************************************************
commit d30637339963950910e5f5fb755b8465ac7dddb4
Author: Mikhail Gusarov <dottedmag at dottedmag.net>
Date:   Thu Oct 29 11:46:22 2009 -0700

    Supply all code using dl*() with DLOPEN_LIBS
    
    Previously DLOPEN_LIBS was managed in top-level configure.ac.
    Instead bundle it with the code using dl*() functions to
    avoid breakages in uncommon configurations.
    
    Signed-off-by: Mikhail Gusarov <dottedmag at dottedmag.net>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 02e9146..bdbbc7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -195,6 +195,7 @@ dnl Check to see if dlopen is in default libraries (like Solaris, which
 dnl has it in libc), or if libdl is needed to get it.
 AC_CHECK_FUNC([dlopen], [],
 	AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl"))
+AC_SUBST(DLOPEN_LIBS)
 
 dnl Checks for library functions.
 AC_FUNC_VPRINTF
@@ -922,7 +923,7 @@ if test "x$GLX" = xyes; then
 	AC_SUBST(XLIB_CFLAGS)
 	AC_DEFINE(GLXEXT, 1, [Build GLX extension])
 	GLX_LIBS='$(top_builddir)/glx/libglx.la'
-	GLX_SYS_LIBS="$GLX_SYS_LIBS $DLOPEN_LIBS"
+	GLX_SYS_LIBS="$GLX_SYS_LIBS"
 else
         GLX=no
 fi
@@ -1513,7 +1514,7 @@ if test "x$XORG" = xyes; then
 	AC_CHECK_FUNCS([pci_device_vgaarb_init])
 	LIBS=$SAVE_LIBS
 	CFLAGS=$SAVE_CFLAGS
-	XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $DLOPEN_LIBS $GLX_SYS_LIBS $SELINUX_LIB"
+	XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS $SELINUX_LIB"
 	XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS"
 
 	case $host_os in
diff --git a/glx/Makefile.am b/glx/Makefile.am
index a23ae0a..9d9fa3c 100644
--- a/glx/Makefile.am
+++ b/glx/Makefile.am
@@ -58,6 +58,8 @@ if DRI2_AIGLX
 libglxdri_la_SOURCES += glxdri2.c
 endif
 
+libglxdri_la_LIBADD = $(DLOPEN_LIBS)
+
 libglx_la_SOURCES = \
 	$(indirect_sources) \
 	$(glapi_sources) \
@@ -95,3 +97,5 @@ libglx_la_SOURCES = \
         swap_interval.c \
         unpack.h \
         xfont.c
+
+libglx_la_LIBADD = $(DLOPEN_LIBS)
diff --git a/hw/xfree86/loader/Makefile.am b/hw/xfree86/loader/Makefile.am
index 0bfa7a2..d3c17d1 100644
--- a/hw/xfree86/loader/Makefile.am
+++ b/hw/xfree86/loader/Makefile.am
@@ -21,6 +21,7 @@ libloader_la_SOURCES = \
         dlloader.c \
 	os.c \
 	sdksyms.c
+libloader_la_LIBADD = $(DLOPEN_LIBS)
 
 CLEANFILES = sdksyms.c sdksyms.dep
 
diff --git a/os/Makefile.am b/os/Makefile.am
index 9902f04..66a4a0f 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -26,7 +26,7 @@ libos_la_SOURCES = 	\
 	xstrans.c	\
 	xprintf.c	\
 	$(XORG_SRCS)
-libos_la_LIBADD = @SHA1_LIBS@
+libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS)
 
 if SECURE_RPC
 libos_la_SOURCES += $(SECURERPC_SRCS)
commit ec98d7fc78efefcf9fc61492529157c0d289c3f2
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Sep 21 10:23:16 2009 -0400

    EDID: Extend the HDTV hack to handle "1368x769"
    
    Hate televisions so much.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 15021a8..449078e 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -473,8 +473,10 @@ DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
 	vsize = timing[i].vsize;
 	refresh = timing[i].refresh;
 
-	/* HDTV hack.  Hooray. */
-	if (hsize == 1360 && vsize == 765 && refresh == 60) {
+	/* HDTV hack, because you can't say 1366 */
+	if (refresh == 60 &&
+	    ((hsize == 1360 && vsize == 765) ||
+	     (hsize == 1368 && vsize == 769))) {
 	    Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE);
 	    Mode->HDisplay = 1366;
 	    Mode->VSyncStart--;
commit 7c0803f555782dbf451b7c79112d7deae02e5c9f
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Oct 28 15:44:37 2009 -0400

    modes: Fix duplicate detection, and do it more consistently
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 138adc0..fad50a2 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1377,34 +1377,6 @@ xf86InitialPanning (ScrnInfoPtr scrn)
     }
 }
 
-/*
- * XXX walk the monitor mode list and prune out duplicates that
- * are inserted by xf86DDCMonitorSet. In an ideal world, that
- * function would do this work by itself.
- */
-
-static void
-xf86PruneDuplicateMonitorModes (MonPtr Monitor)
-{
-    DisplayModePtr  master, clone, next;
-
-    for (master = Monitor->Modes; 
-	 master && master != Monitor->Last; 
-	 master = master->next)
-    {
-	for (clone = master->next; clone && clone != Monitor->Modes; clone = next)
-	{
-	    next = clone->next;
-	    if (xf86ModesEqual (master, clone))
-	    {
-		if (Monitor->Last == clone)
-		    Monitor->Last = clone->prev;
-		xf86DeleteMode (&Monitor->Modes, clone);
-	    }
-	}
-    }
-}
-
 /** Return - 0 + if a should be earlier, same or later than b in list
  */
 static int
@@ -1575,9 +1547,6 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 	maxY = config->maxHeight;
     }
 
-    /* Elide duplicate modes before defaulting code uses them */
-    xf86PruneDuplicateMonitorModes (scrn->monitor);
-    
     /* Probe the list of modes for each output. */
     for (o = 0; o < config->num_output; o++) 
     {
diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 23d6416..15021a8 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -1082,6 +1082,8 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
     if (quirks & DDC_QUIRK_PREFER_LARGE_75)
 	xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
 
+    Modes = xf86PruneDuplicateModes(Modes);
+
     return Modes;
 }
 
diff --git a/hw/xfree86/modes/xf86Modes.c b/hw/xfree86/modes/xf86Modes.c
index ae6d956..75aedaa 100644
--- a/hw/xfree86/modes/xf86Modes.c
+++ b/hw/xfree86/modes/xf86Modes.c
@@ -691,3 +691,37 @@ xf86GetDefaultModes (void)
     }
     return head;
 }
+
+/*
+ * Walk a mode list and prune out duplicates.  Will preserve the preferred
+ * mode of an otherwise-duplicate pair.
+ *
+ * Probably best to call this on lists that are all of a single class
+ * (driver, default, user, etc.), otherwise, which mode gets deleted is
+ * not especially well defined.
+ *
+ * Returns the new list.
+ */
+
+DisplayModePtr
+xf86PruneDuplicateModes(DisplayModePtr modes)
+{
+    DisplayModePtr m, n, o;
+
+top:
+    for (m = modes; m; m = m->next) {
+	for (n = m->next; n; n = o) {
+	    o = n->next;
+	    if (xf86ModesEqual(m, n)) {
+		if (n->type & M_T_PREFERRED) {
+		    xf86DeleteMode(&modes, m);
+		    goto top;
+		}
+		else
+		    xf86DeleteMode(&modes, n);
+	    }
+	}
+    }
+
+    return modes;
+}
diff --git a/hw/xfree86/modes/xf86Modes.h b/hw/xfree86/modes/xf86Modes.h
index 908f59b..38927b1 100644
--- a/hw/xfree86/modes/xf86Modes.h
+++ b/hw/xfree86/modes/xf86Modes.h
@@ -95,6 +95,9 @@ extern _X_EXPORT void
 xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
 		      Bool verbose);
 
+extern _X_EXPORT DisplayModePtr
+xf86PruneDuplicateModes(DisplayModePtr modes);
+
 extern _X_EXPORT void
 xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 		       int flags);
commit ba2d39dd5428cb5922b797a1d4ea45b859412b40
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Oct 26 15:10:30 2009 -0400

    modes: De-duplicate a clock range check.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index 0e43946..4a948d7 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -249,6 +249,15 @@ xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges)
     }
 }
 
+static Bool
+modeInClockRange(ClockRangePtr cp, DisplayModePtr p)
+{
+    return ((p->Clock >= cp->minClock) &&
+	    (p->Clock <= cp->maxClock) &&
+	    (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) &&
+	    (cp->doubleScanAllowed ||
+	     ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN))));
+}
 
 /*
  * xf86FindClockRangeForMode()    [... like the name says ...]
@@ -259,12 +268,7 @@ xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p)
     ClockRangePtr cp;
 
     for (cp = clockRanges; ; cp = cp->next)
-	if (!cp ||
-	    ((p->Clock >= cp->minClock) &&
-	     (p->Clock <= cp->maxClock) &&
-	     (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) &&
-	     (cp->doubleScanAllowed ||
-	      ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))))
+	if (!cp || modeInClockRange(cp, p))
 	    return cp;
 }
 
@@ -979,11 +983,7 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags)
     if (scrp->progClock) {
 	/* Check clock is in range */
 	for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
-	    if ((cp->minClock <= mode->Clock) &&
-		(cp->maxClock >= mode->Clock) &&
-		(cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) &&
-		(cp->doubleScanAllowed ||
-		 ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1))))
+	    if (modeInClockRange(cp, mode))
 	        break;
 	}
 	if (cp == NULL) {
@@ -999,12 +999,7 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags)
 	 status = MODE_CLOCK_RANGE;
 	/* Check clock is in range */
 	for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
-	    if ((cp->minClock <= mode->Clock) &&
-		(cp->maxClock >= mode->Clock) &&
-		(cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) &&
-		(cp->doubleScanAllowed ||
-		 ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1)))) {
-
+	    if (modeInClockRange(cp, mode)) {
 		/*
 	 	 * Clock is in range, so if it is not a programmable clock,
 		 * find a matching clock.
commit 25236d19e6ef07fcb2c71569f1b7b0c12810834a
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Oct 26 14:49:57 2009 -0400

    EDID: Fix interlaced detailed timings to be frame size, not field size
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 6fef1e0..23d6416 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -502,6 +502,45 @@ DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
     return Modes;
 }
 
+static void
+DDCModeDoInterlaceQuirks(DisplayModePtr mode)
+{
+    /*
+     * EDID is delightfully ambiguous about how interlaced modes are to be
+     * encoded.  X's internal representation is of frame height, but some
+     * HDTV detailed timings are encoded as field height.
+     *
+     * The format list here is from CEA, in frame size.  Technically we
+     * should be checking refresh rate too.  Whatever.
+     */
+    static const struct {
+	int w, h;
+    } cea_interlaced[] = {
+	{ 1920, 1080 },
+	{  720,  480 },
+	{ 1440,  480 },
+	{ 2880,  480 },
+	{  720,  576 },
+	{ 1440,  576 },
+	{ 2880,  576 },
+    };
+    static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
+    int i;
+
+    for (i = 0; i < n_modes; i++) {
+	if ((mode->HDisplay == cea_interlaced[i].w) &&
+	    (mode->VDisplay == cea_interlaced[i].h / 2)) {
+	    mode->VDisplay *= 2;
+	    mode->VSyncStart *= 2;
+	    mode->VSyncEnd *= 2;
+	    mode->VTotal *= 2;
+	    mode->VTotal |= 1;
+	}
+    }
+
+    mode->Flags |= V_INTERLACE;
+}
+
 /*
  *
  */
@@ -569,7 +608,7 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
     /* We ignore h/v_size and h/v_border for now. */
 
     if (timing->interlaced)
-        Mode->Flags |= V_INTERLACE;
+	DDCModeDoInterlaceQuirks(Mode);
 
     if (quirks & DDC_QUIRK_DETAILED_SYNC_PP)
 	Mode->Flags |= V_PVSYNC | V_PHSYNC;
commit fb86433d897c116315cc7994390d11ac2f577511
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Oct 26 14:04:23 2009 -0400

    modes: Decorate interlaced mode names with a trailing 'i'
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 8885a7c..6fef1e0 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -566,8 +566,6 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
 	return NULL;
     }
 
-    xf86SetModeDefaultName(Mode);
-
     /* We ignore h/v_size and h/v_border for now. */
 
     if (timing->interlaced)
@@ -587,6 +585,8 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
 	    Mode->Flags |= V_NHSYNC;
     }
 
+    xf86SetModeDefaultName(Mode);
+
     return Mode;
 }
 
diff --git a/hw/xfree86/modes/xf86Modes.c b/hw/xfree86/modes/xf86Modes.c
index d105b48..ae6d956 100644
--- a/hw/xfree86/modes/xf86Modes.c
+++ b/hw/xfree86/modes/xf86Modes.c
@@ -136,10 +136,12 @@ xf86ModeBandwidth(DisplayModePtr mode, int depth)
 void
 xf86SetModeDefaultName(DisplayModePtr mode)
 {
-    if (mode->name != NULL)
-	xfree(mode->name);
+    Bool interlaced = !!(mode->Flags & V_INTERLACE);
 
-    mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
+    xfree(mode->name);
+
+    mode->name = XNFprintf("%dx%d%s", mode->HDisplay, mode->VDisplay,
+			   interlaced ? "i" : "");
 }
 
 /*
commit fc2ec95664d55f45f77f1ebb039a7c17a1fcdaa3
Author: Ma Ling <ling.ma at intel.com>
Date:   Wed Feb 18 17:41:26 2009 +0800

    EDID: CEA extension support
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index 3b7828a..2df6b4e 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -544,6 +544,36 @@ configureMonitorSection (int screennum)
     return ptr;
 }
 
+/* Initialize Configure Monitor from Detailed Timing Block */
+static void handle_detailed_input(struct detailed_monitor_section *det_mon,
+                                  void *data)
+{
+    XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
+
+    switch (det_mon->type) {
+    case DS_NAME:
+        ptr->mon_modelname = realloc(ptr->mon_modelname,
+                                     strlen((char*)(det_mon->section.name)) +
+                                     1);
+        strcpy(ptr->mon_modelname,
+	      (char*)(det_mon->section.name));
+        break;
+    case DS_RANGES:
+        ptr->mon_hsync[ptr->mon_n_hsync].lo =
+            det_mon->section.ranges.min_h;
+        ptr->mon_hsync[ptr->mon_n_hsync].hi =
+            det_mon->section.ranges.max_h;
+        ptr->mon_n_vrefresh = 1;
+        ptr->mon_vrefresh[ptr->mon_n_hsync].lo =
+            det_mon->section.ranges.min_v;
+        ptr->mon_vrefresh[ptr->mon_n_hsync].hi =
+            det_mon->section.ranges.max_v;
+        ptr->mon_n_hsync++;
+    default:
+        break;
+    }
+}
+
 static XF86ConfMonitorPtr
 configureDDCMonitorSection (int screennum)
 {
@@ -590,30 +620,8 @@ configureDDCMonitorSection (int screennum)
     }
 #endif /* def CONFIGURE_DISPLAYSIZE */
 
-    for (i=0;i<4;i++) {
-	switch (ConfiguredMonitor->det_mon[i].type) {
-	    case DS_NAME:
-		ptr->mon_modelname  = realloc(ptr->mon_modelname, 
-		  strlen((char*)(ConfiguredMonitor->det_mon[i].section.name))
-		    + 1);
-		strcpy(ptr->mon_modelname,
-		       (char*)(ConfiguredMonitor->det_mon[i].section.name));
-		break;
-	    case DS_RANGES:
-		ptr->mon_hsync[ptr->mon_n_hsync].lo =
-		    ConfiguredMonitor->det_mon[i].section.ranges.min_h;
-		ptr->mon_hsync[ptr->mon_n_hsync].hi =
-		    ConfiguredMonitor->det_mon[i].section.ranges.max_h;
-		ptr->mon_n_vrefresh = 1;
-		ptr->mon_vrefresh[ptr->mon_n_hsync].lo =
-		    ConfiguredMonitor->det_mon[i].section.ranges.min_v;
-		ptr->mon_vrefresh[ptr->mon_n_hsync].hi =
-		    ConfiguredMonitor->det_mon[i].section.ranges.max_v;
-		ptr->mon_n_hsync++;
-	    default:
-		break;
-	}
-    }
+    xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input,
+                             ptr);
 
     if (ConfiguredMonitor->features.dpms) {
       ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, xstrdup("DPMS"), NULL);
diff --git a/hw/xfree86/ddc/edid.h b/hw/xfree86/ddc/edid.h
index 3feb979..cc4bd02 100644
--- a/hw/xfree86/ddc/edid.h
+++ b/hw/xfree86/ddc/edid.h
@@ -562,4 +562,101 @@ typedef struct {
 
 extern _X_EXPORT xf86MonPtr ConfiguredMonitor;
 
+#define EXT_TAG 0
+#define EXT_REV 1
+#define CEA_EXT   0x02
+#define VTB_EXT   0x10
+#define DI_EXT    0x40
+#define LS_EXT    0x50
+#define MI_EXT    0x60
+
+#define CEA_EXT_MIN_DATA_OFFSET 4
+#define CEA_EXT_MAX_DATA_OFFSET 127
+#define CEA_EXT_DET_TIMING_NUM 6
+
+#define IEEE_ID_HDMI    0x000C03
+#define CEA_AUDIO_BLK   1
+#define CEA_VIDEO_BLK   2
+#define CEA_VENDOR_BLK  3
+#define CEA_SPEAKER_ALLOC_BLK 4
+#define CEA_VESA_DTC_BLK 5
+#define VENDOR_SUPPORT_AI(x) ((x) >> 7)
+#define VENDOR_SUPPORT_DC_48bit(x)  ( ( (x) >> 6) & 0x01)
+#define VENDOR_SUPPORT_DC_36bit(x)  ( ( (x) >> 5) & 0x01)
+#define VENDOR_SUPPORT_DC_30bit(x)  ( ( (x) >> 4) & 0x01)
+#define VENDOR_SUPPORT_DC_Y444(x)   ( ( (x) >> 3) & 0x01)
+#define VENDOR_LATENCY_PRESENT(x)     ( (x) >> 7)
+#define VENDOR_LATENCY_PRESENT_I(x) ( ( (x) >> 6) & 0x01)
+#define HDMI_MAX_TMDS_UNIT   (5000)
+
+struct cea_video_block {
+  Uchar video_code;
+};
+
+struct cea_audio_block_descriptor {
+  Uchar audio_code[3];
+};
+
+struct cea_audio_block {
+  struct cea_audio_block_descriptor descriptor[10];
+};
+
+struct cea_vendor_block_hdmi {
+  Uchar  portB:4;
+  Uchar  portA:4;
+  Uchar  portD:4;
+  Uchar  portC:4;
+  Uchar  support_flags;
+  Uchar  max_tmds_clock;
+  Uchar  latency_present;
+  Uchar  video_latency;
+  Uchar  audio_latency;
+  Uchar  interlaced_video_latency;
+  Uchar  interlaced_audio_latency;
+};
+
+struct cea_vendor_block {
+  unsigned char ieee_id[3];
+  union {
+      struct cea_vendor_block_hdmi hdmi;
+      /* any other vendor blocks we know about */
+  };
+};
+
+struct cea_speaker_block
+{
+  Uchar FLR:1;
+  Uchar LFE:1;
+  Uchar FC:1;
+  Uchar RLR:1;
+  Uchar RC:1;
+  Uchar FLRC:1;
+  Uchar RLRC:1;
+  Uchar FLRW:1;
+  Uchar FLRH:1;
+  Uchar TC:1;
+  Uchar FCH:1;
+  Uchar Resv:5;
+  Uchar ResvByte;
+};
+
+struct cea_data_block {
+  Uchar len:5;
+  Uchar tag:3;
+  union{
+    struct cea_video_block video;
+    struct cea_audio_block audio;
+    struct cea_vendor_block vendor;
+    struct cea_speaker_block speaker;
+  }u;
+};
+
+struct cea_ext_body {
+  Uchar tag;
+  Uchar rev;
+  Uchar dt_offset;
+  Uchar flags;
+  struct cea_data_block data_collection;
+};
+
 #endif /* _EDID_H_ */
diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index 12a5254..f3e593a 100644
--- a/hw/xfree86/ddc/interpret_edid.c
+++ b/hw/xfree86/ddc/interpret_edid.c
@@ -42,6 +42,8 @@ static void get_display_section(Uchar*, struct disp_features *,
 static void get_established_timing_section(Uchar*, struct established_timings *);
 static void get_std_timing_section(Uchar*, struct std_timings *,
 				   struct edid_version *);
+static void fetch_detailed_block(Uchar *c, struct edid_version *ver,
+                                 struct detailed_monitor_section *det_mon);
 static void get_dt_md_section(Uchar *, struct edid_version *,
 			      struct detailed_monitor_section *det_mon);
 static void copy_string(Uchar *, Uchar *);
@@ -53,11 +55,25 @@ static void get_detailed_timing_section(Uchar*, struct 	detailed_timings *);
 static Bool validate_version(int scrnIndex, struct edid_version *);
 
 static void
+find_ranges_section(struct detailed_monitor_section *det, void *ranges)
+{
+   if (det->type == DS_RANGES && det->section.ranges.max_clock)
+       *(struct monitor_ranges **)ranges = &det->section.ranges;
+}
+
+static void
+find_max_detailed_clock(struct detailed_monitor_section *det, void *ret)
+{
+    if (det->type == DT) {
+        *(int *)ret = max(*((int *)ret),
+                          det->section.d_timings.clock);
+    }
+}
+
+static void
 handle_edid_quirks(xf86MonPtr m)
 {
-    int i, j;
-    struct detailed_timings *preferred_timing;
-    struct monitor_ranges *ranges;
+    struct monitor_ranges *ranges = NULL;
 
     /*
      * max_clock is only encoded in EDID in tens of MHz, so occasionally we
@@ -65,28 +81,49 @@ handle_edid_quirks(xf86MonPtr m)
      * 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;
-		    }
-		}
-	    }
-	}
+
+    /* Try to find Monitor Range and max clock, then re-set range value*/
+    xf86ForEachDetailedBlock(m, find_ranges_section, &ranges);
+    if (ranges && ranges->max_clock) {
+        int clock = 0;
+        xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock);
+        if (clock && (ranges->max_clock * 1e6 < clock)) {
+            xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max "
+                    "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock);
+            ranges->max_clock = (clock+999999)/1e6;
+        }
+    }
+}
+
+struct det_hv_parameter {
+    int real_hsize;
+    int real_vsize;
+    float target_aspect;
+};
+
+static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    struct det_hv_parameter *p = (struct det_hv_parameter *)data;
+    float timing_aspect;
+
+    if (det_mon->type == DT) {
+        struct detailed_timings *timing;
+        timing = &det_mon->section.d_timings;
+
+        if (!timing->v_size)
+            return;
+
+        timing_aspect = (float)timing->h_size / timing->v_size;
+        if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) {
+            p->real_hsize = max(p->real_hsize, timing->h_size);
+            p->real_vsize = max(p->real_vsize, timing->v_size);
+        }
     }
+}
 
+static void encode_aspect_ratio(xf86MonPtr m)
+{
     /*
      * some monitors encode the aspect ratio instead of the physical size.
      * try to find the largest detailed timing that matches that aspect
@@ -96,38 +133,26 @@ handle_edid_quirks(xf86MonPtr m)
 	(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) {
+        struct det_hv_parameter p;
+        p.real_hsize = 0;
+        p.real_vsize = 0;
+        p.target_aspect = (float)m->features.hsize /m->features.vsize;
+
+        xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p);
+
+	if (!p.real_hsize || !p.real_vsize) {
 	    m->features.hsize = m->features.vsize = 0;
-	} else if ((m->features.hsize * 10 == real_hsize) &&
-		   (m->features.vsize * 10 == real_vsize)) {
+	} else if ((m->features.hsize * 10 == p.real_hsize) &&
+		   (m->features.vsize * 10 == p.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;
+	    m->features.hsize = (p.real_hsize + 5) / 10;
+	    m->features.vsize = (p.real_vsize + 5) / 10;
 	}
-	
+
 	xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n",
 		m->features.hsize, m->features.vsize);
     }
@@ -156,6 +181,7 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
     m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
 
     handle_edid_quirks(m);
+    encode_aspect_ratio(m);
 
     return (m);
 
@@ -164,6 +190,141 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
     return NULL;
 }
 
+static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon,
+                                 struct detailed_monitor_section *det_mon)
+{
+    int dt_num;
+    int dt_offset = ((struct cea_ext_body *)blk)->dt_offset;
+
+    dt_num = 0;
+
+    if (dt_offset < CEA_EXT_MIN_DATA_OFFSET)
+        return dt_num;
+
+    for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) &&
+           dt_num < CEA_EXT_DET_TIMING_NUM;
+	   _NEXT_DT_MD_SECTION(dt_offset)) {
+
+        fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num);
+        dt_num = dt_num + 1 ;
+    }
+
+    return dt_num;
+}
+
+static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon,
+                                    handle_detailed_fn fn,
+                                    void *data)
+{
+    int i;
+    struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM];
+    int det_mon_num;
+
+    det_mon_num = get_cea_detail_timing(ext, mon, det_mon);
+
+    for (i = 0; i < det_mon_num; i++)
+        fn(det_mon + i, data);
+}
+
+void xf86ForEachDetailedBlock(xf86MonPtr mon,
+                              handle_detailed_fn fn,
+                              void *data)
+{
+    int i;
+    Uchar *ext;
+
+    if (mon == NULL)
+        return;
+
+    for (i = 0; i < DET_TIMINGS; i++)
+        fn(mon->det_mon + i, data);
+
+    for (i = 0; i < mon->no_sections; i++) {
+        ext = mon->rawData + EDID1_LEN * (i + 1);
+        switch (ext[EXT_TAG]){
+        case CEA_EXT:
+            handle_cea_detail_block(ext, mon, fn, data);
+            break;
+        case VTB_EXT:
+        case DI_EXT:
+        case LS_EXT:
+        case MI_EXT:
+	    break;
+        }
+    }
+}
+
+static struct cea_data_block *
+extract_cea_data_block(Uchar *ext, int data_type)
+{
+    struct cea_ext_body *cea;
+    struct cea_data_block *data_collection;
+    struct cea_data_block *data_end;
+
+    cea = (struct cea_ext_body *)ext;
+
+    if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET)
+        return NULL;
+
+    data_collection = &cea->data_collection;
+    data_end = (struct cea_data_block *)(cea->dt_offset + ext);
+
+    for ( ;data_collection < data_end;) {
+
+	if (data_type == data_collection->tag) {
+	    return data_collection;
+	}
+	data_collection = (void *)((unsigned char *)data_collection +
+	    data_collection->len + 1);
+    }
+
+    return NULL;
+}
+
+static void handle_cea_video_block(Uchar *ext, handle_video_fn fn, void *data)
+{
+    struct cea_video_block *video;
+    struct cea_video_block *video_end;
+    struct cea_data_block *data_collection;
+
+    data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK);
+    if (data_collection == NULL)
+        return;
+
+    video = &data_collection->u.video;
+    video_end = (struct cea_video_block *)
+	((Uchar *)video + data_collection->len);
+
+    for (; video < video_end; video = video + 1) {
+	fn(video, data);
+    }
+}
+
+void xf86ForEachVideoBlock(xf86MonPtr mon,
+	                   handle_video_fn fn,
+                           void *data)
+{
+    int i;
+    Uchar *ext;
+
+    if (mon == NULL)
+	return;
+
+    for (i = 0; i < mon->no_sections; i++) {
+	ext = mon->rawData + EDID1_LEN * (i + 1);
+	switch (ext[EXT_TAG]) {
+	case CEA_EXT:
+	    handle_cea_video_block(ext, fn, data);
+	    break;
+	case VTB_EXT:
+	case DI_EXT:
+	case LS_EXT:
+	case MI_EXT:
+	    break;
+	}
+    }
+}
+
 xf86MonPtr
 xf86InterpretEEDID(int scrnIndex, Uchar *block)
 {
@@ -288,66 +449,72 @@ 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)
+fetch_detailed_block(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;
-	memcpy(det_mon[i].section.est_iii, c + 6, 6);
-	break;
-      case ADD_DUMMY:
-	det_mon[i].type = DS_DUMMY;
-        break;
-      default:
-        det_mon[i].type = DS_UNKOWN;
-        break;
-      }
-      if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) {
-	det_mon[i].type = DS_VENDOR + c[3];
-      }
+        switch (MONITOR_DESC_TYPE) {
+        case SERIAL_NUMBER:
+            det_mon->type = DS_SERIAL;
+            copy_string(c,det_mon->section.serial);
+            break;
+        case ASCII_STR:
+            det_mon->type = DS_ASCII_STR;
+            copy_string(c,det_mon->section.ascii_data);
+            break;
+        case MONITOR_RANGES:
+            det_mon->type = DS_RANGES;
+            get_monitor_ranges(c,&det_mon->section.ranges);
+            break;
+        case MONITOR_NAME:
+            det_mon->type = DS_NAME;
+            copy_string(c,det_mon->section.name);
+            break;
+        case ADD_COLOR_POINT:
+            det_mon->type = DS_WHITE_P;
+            get_whitepoint_section(c,det_mon->section.wp);
+            break;
+        case ADD_STD_TIMINGS:
+            det_mon->type = DS_STD_TIMINGS;
+            get_dst_timing_section(c,det_mon->section.std_t, ver);
+            break;
+        case COLOR_MANAGEMENT_DATA:
+            det_mon->type = DS_CMD;
+            break;
+        case CVT_3BYTE_DATA:
+            det_mon->type = DS_CVT;
+            get_cvt_timing_section(c, det_mon->section.cvt);
+            break;
+        case ADD_EST_TIMINGS:
+            det_mon->type = DS_EST_III;
+	    memcpy(det_mon->section.est_iii, c + 6, 6);
+            break;
+        case ADD_DUMMY:
+            det_mon->type = DS_DUMMY;
+            break;
+        default:
+            det_mon->type = DS_UNKOWN;
+            break;
+        }
+	if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) {
+            det_mon->type = DS_VENDOR + c[3];
+        }
     } else {
-      det_mon[i].type = DT;
-      get_detailed_timing_section(c,&det_mon[i].section.d_timings);
+        det_mon->type = DT;
+        get_detailed_timing_section(c, &det_mon->section.d_timings);
+    }
+}
+
+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++) {
+        fetch_detailed_block(c, ver, det_mon + i);
+        NEXT_DT_MD_SECTION;
     }
-    NEXT_DT_MD_SECTION;
-  }
 }
 
 static void
diff --git a/hw/xfree86/ddc/print_edid.c b/hw/xfree86/ddc/print_edid.c
index ff0b39c..1faae1e 100644
--- a/hw/xfree86/ddc/print_edid.c
+++ b/hw/xfree86/ddc/print_edid.c
@@ -334,129 +334,147 @@ print_detailed_timings(int scrnIndex, struct detailed_timings *t)
     }
 }
 
+/* This function handle all detailed patchs,
+ * including EDID and EDID-extension
+ */
+struct det_print_parameter{
+  xf86MonPtr m;
+  int index;
+  ddc_quirk_t quirks;
+};
+
 static void
-print_detailed_monitor_section(int scrnIndex,
-			       struct detailed_monitor_section *m)
+handle_detailed_print(struct detailed_monitor_section *det_mon,
+                      void *data)
 {
-    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;
+    int j, scrnIndex;
+    struct det_print_parameter *p;
+
+    p = (struct det_print_parameter *)data;
+    scrnIndex = p->m->scrnIndex;
+    xf86DetTimingApplyQuirks(det_mon,p->quirks,
+                             p->m->features.hsize,
+                             p->m->features.vsize);
+
+    switch (det_mon->type) {
+    case DT:
+        print_detailed_timings(scrnIndex,&det_mon->section.d_timings);
+        break;
+    case DS_SERIAL:
+        xf86DrvMsg(scrnIndex,X_INFO,"Serial No: %s\n",det_mon->section.serial);
+        break;
+    case DS_ASCII_STR:
+        xf86DrvMsg(scrnIndex,X_INFO," %s\n",det_mon->section.ascii_data);
+        break;
+    case DS_NAME:
+        xf86DrvMsg(scrnIndex,X_INFO,"Monitor name: %s\n",det_mon->section.name);
+        break;
+    case DS_RANGES:
+    {
+        struct monitor_ranges *r = &det_mon->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");
+	if (r->preferred_refresh)
+	    xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n",
+		    r->preferred_refresh);
+	else
+	    xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred "
+		       "refresh rate given\n");
+        } 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,
-		       "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");
-		if (r->preferred_refresh)
-		    xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n",
-			       r->preferred_refresh);
-		else
-		    xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred "
-			       "refresh rate given\n");
-	    } 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_INFO,
-		       "Unknown vendor-specific block %hx\n",
-		       m[i].type - DS_VENDOR);
-	}
+		    "#%i: hsize: %i  vsize %i  refresh: %i  "
+		    "vid: %i\n",p->index ,det_mon->section.std_t[j].hsize,
+		    det_mon->section.std_t[j].vsize,
+		    det_mon->section.std_t[j].refresh,
+		    det_mon->section.std_t[j].id);
+        break;
+    case DS_WHITE_P:
+        for (j = 0; j<2; j++)
+        if (det_mon->section.wp[j].index != 0)
+            xf86DrvMsg(scrnIndex,X_INFO,
+                       "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n",
+                       det_mon->section.wp[j].index,det_mon->section.wp[j].white_x,
+                       det_mon->section.wp[j].white_y,
+                       det_mon->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, det_mon->section.cvt);
+        break;
+    case DS_EST_III:
+        xf86DrvMsg(scrnIndex, X_INFO,
+                   "Established timings III: (not decoded)\n");
+        break;
+    case DS_DUMMY:
+    default:
+        break;
+    }
+    if (det_mon->type >= DS_VENDOR && det_mon->type <= DS_VENDOR_MAX) {
+        xf86DrvMsg(scrnIndex, X_INFO,
+                   "Unknown vendor-specific block %hx\n",
+                   det_mon->type - DS_VENDOR);
     }
+
+    p->index = p->index + 1;
 }
-  
+
 static void
 print_number_sections(int scrnIndex, int num)
 {
@@ -470,6 +488,7 @@ xf86PrintEDID(xf86MonPtr m)
 {
     CARD16 i, j, n;
     char buf[EDID_WIDTH * 2 + 1];
+    struct det_print_parameter p;
 
     if (!m) return NULL;
 
@@ -478,7 +497,12 @@ xf86PrintEDID(xf86MonPtr m)
     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);
+    p.m = m;
+    p.index = 0;
+    p.quirks = xf86DDCDetectQuirks(m->scrnIndex, m, FALSE);
+    xf86ForEachDetailedBlock(m,
+                             handle_detailed_print ,
+                             &p);
     print_number_sections(m->scrnIndex, m->no_sections);
 
     /* extension block section stuff */
@@ -495,6 +519,6 @@ xf86PrintEDID(xf86MonPtr m)
 	}
 	xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf);
     }
-    
+
     return m;
 }
diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h
index 64869da..af3ba06 100644
--- a/hw/xfree86/ddc/xf86DDC.h
+++ b/hw/xfree86/ddc/xf86DDC.h
@@ -73,4 +73,54 @@ FindDMTMode(int hsize, int vsize, int refresh, Bool rb);
 
 extern _X_EXPORT const DisplayModeRec DMTModes[];
 
+/*
+ * Quirks to work around broken EDID data from various monitors.
+ */
+typedef enum {
+    DDC_QUIRK_NONE = 0,
+    /* First detailed mode is bogus, prefer largest mode at 60hz */
+    DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
+    /* 135MHz clock is too high, drop a bit */
+    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
+    /* Prefer the largest mode at 75 Hz */
+    DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
+    /* Convert detailed timing's horizontal from units of cm to mm */
+    DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
+    /* Convert detailed timing's vertical from units of cm to mm */
+    DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
+    /* Detailed timing descriptors have bogus size values, so just take the
+     * maximum size and use that.
+     */
+    DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
+    /* Monitor forgot to set the first detailed is preferred bit. */
+    DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
+    /* use +hsync +vsync for detailed mode */
+    DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
+    /* Force single-link DVI bandwidth limit */
+    DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
+} ddc_quirk_t;
+
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+
+extern Bool
+xf86MonitorIsHDMI(xf86MonPtr mon);
+
+typedef void (* handle_detailed_fn)(struct detailed_monitor_section *,void *);
+
+void xf86ForEachDetailedBlock(xf86MonPtr mon,
+                              handle_detailed_fn,
+                              void *data);
+
+ddc_quirk_t
+xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose);
+
+void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
+                              ddc_quirk_t quirks, int hsize, int vsize);
+
+typedef void (* handle_video_fn)(struct cea_video_block *, void *);
+
+void xf86ForEachVideoBlock(xf86MonPtr,
+                           handle_video_fn,
+                           void *);
+
 #endif
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 506fbb9..138adc0 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1523,6 +1523,42 @@ GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
        mon->vrefresh[0].lo = 58.0;
 }
 
+struct det_monrec_parameter {
+    MonRec *mon_rec;
+    int *max_clock;
+    Bool set_hsync;
+    Bool set_vrefresh;
+    enum { sync_config, sync_edid, sync_default } *sync_source;
+};
+
+static void handle_detailed_monrec(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    enum { sync_config, sync_edid, sync_default };
+    struct det_monrec_parameter *p;
+    p = (struct det_monrec_parameter *)data;
+
+    if (det_mon->type == DS_RANGES) {
+        struct monitor_ranges *ranges = &det_mon->section.ranges;
+        if (p->set_hsync && ranges->max_h) {
+            p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h;
+            p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h;
+            p->mon_rec->nHsync++;
+            if (*p->sync_source == sync_default)
+                *p->sync_source = sync_edid;
+        }
+        if (p->set_vrefresh && ranges->max_v) {
+            p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v;
+            p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v;
+            p->mon_rec->nVrefresh++;
+            if (*p->sync_source == sync_default)
+                *p->sync_source = sync_edid;
+        }
+        if (ranges->max_clock * 1000 > *p->max_clock)
+            *p->max_clock = ranges->max_clock * 1000;
+    }
+}
+
 void
 xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 {
@@ -1601,42 +1637,24 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 	
 	edid_monitor = output->MonInfo;
 	
-	if (edid_monitor)
-	{
-	    int			    i;
-	    Bool		    set_hsync = mon_rec.nHsync == 0;
-	    Bool		    set_vrefresh = mon_rec.nVrefresh == 0;
-	    struct disp_features    *features = &edid_monitor->features;
+        if (edid_monitor)
+        {
+            struct det_monrec_parameter p;
+            struct disp_features    *features = &edid_monitor->features;
 
 	    /* if display is not continuous-frequency, don't add default modes */
 	    if (!GTF_SUPPORTED(features->msc))
 		add_default_modes = FALSE;
 
-	    for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++)
-	    {
-		if (edid_monitor->det_mon[i].type == DS_RANGES)
-		{
-		    struct monitor_ranges   *ranges = &edid_monitor->det_mon[i].section.ranges;
-		    if (set_hsync && ranges->max_h)
-		    {
-			mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h;
-			mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h;
-			mon_rec.nHsync++;
-			if (sync_source == sync_default)
-			    sync_source = sync_edid;
-		    }
-		    if (set_vrefresh && ranges->max_v)
-		    {
-			mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v;
-			mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v;
-			mon_rec.nVrefresh++;
-			if (sync_source == sync_default)
-			    sync_source = sync_edid;
-		    }
-		    if (ranges->max_clock * 1000 > max_clock)
-			max_clock = ranges->max_clock * 1000;
-		}
-	    }
+	    p.mon_rec = &mon_rec;
+	    p.max_clock = &max_clock;
+	    p.set_hsync = mon_rec.nHsync == 0;
+	    p.set_vrefresh = mon_rec.nVrefresh == 0;
+	    p.sync_source = &sync_source;
+
+	    xf86ForEachDetailedBlock(edid_monitor,
+			             handle_detailed_monrec,
+			             &p);
 	}
 
 	if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
@@ -2900,6 +2918,35 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
 
 #endif
 
+/* Pull out a phyiscal size from a detailed timing if available. */
+struct det_phySize_parameter {
+    xf86OutputPtr output;
+    ddc_quirk_t quirks;
+    Bool ret;
+};
+
+static void  handle_detailed_physical_size(struct detailed_monitor_section
+		                          *det_mon, void *data)
+{
+    struct det_phySize_parameter *p;
+    p = (struct det_phySize_parameter *)data;
+
+    if (p->ret == TRUE )
+        return ;
+
+    xf86DetTimingApplyQuirks(det_mon, p->quirks,
+                             p->output->MonInfo->features.hsize,
+                             p->output->MonInfo->features.vsize);
+    if (det_mon->type == DT &&
+        det_mon->section.d_timings.h_size != 0 &&
+        det_mon->section.d_timings.v_size != 0) {
+
+        p->output->mm_width = det_mon->section.d_timings.h_size;
+        p->output->mm_height = det_mon->section.d_timings.v_size;
+        p->ret = TRUE;
+    }
+}
+
 /**
  * Set the EDID information for the specified output
  */
@@ -2908,7 +2955,6 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
 {
     ScrnInfoPtr		scrn = output->scrn;
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
-    int			i;
 #ifdef RANDR_12_INTERFACE
     int			size;
 #endif
@@ -2943,20 +2989,15 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
     xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
 #endif
 
-    if (edid_mon)
-    {
-	/* Pull out a phyiscal size from a detailed timing if available. */
-	for (i = 0; i < 4; i++) {
-	    if (edid_mon->det_mon[i].type == DT &&
-		edid_mon->det_mon[i].section.d_timings.h_size != 0 &&
-		edid_mon->det_mon[i].section.d_timings.v_size != 0)
-	    {
-		output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size;
-		output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size;
-		break;
-	    }
-	}
-    
+    if (edid_mon) {
+
+        struct det_phySize_parameter p;
+        p.output = output;
+        p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE);
+        p.ret = FALSE;
+        xf86ForEachDetailedBlock(edid_mon,
+                                 handle_detailed_physical_size, &p);
+
 	/* if no mm size is available from a detailed timing, check the max size field */
 	if ((!output->mm_width || !output->mm_height) &&
 	    (edid_mon->features.hsize && edid_mon->features.vsize))
diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 058e75d..8885a7c 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -45,20 +45,23 @@
 #include <string.h>
 #include <math.h>
 
+static void handle_detailed_rblank(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    if (det_mon->type == DS_RANGES)
+        if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
+            *(Bool*)data = TRUE;
+}
+
 static Bool
 xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
 {
     /* EDID 1.4 explicitly defines RB support */
     if (DDC->ver.revision >= 4) {
-	int i;
-	for (i = 0; i < DET_TIMINGS; i++) {
-	    struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-	    if (det_mon->type == DS_RANGES)
-		if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
-		    return TRUE;
-	}
-	
-	return FALSE;
+        Bool ret = FALSE;
+
+        xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret);
+        return ret;
     }
 
     /* For anything older, assume digital means RB support. Boo. */
@@ -68,34 +71,6 @@ xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
     return FALSE;
 }
 
-/*
- * Quirks to work around broken EDID data from various monitors.
- */
-
-typedef enum {
-    DDC_QUIRK_NONE = 0,
-    /* First detailed mode is bogus, prefer largest mode at 60hz */
-    DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
-    /* 135MHz clock is too high, drop a bit */
-    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
-    /* Prefer the largest mode at 75 Hz */
-    DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
-    /* Convert detailed timing's horizontal from units of cm to mm */
-    DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
-    /* Convert detailed timing's vertical from units of cm to mm */
-    DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
-    /* Detailed timing descriptors have bogus size values, so just take the
-     * maximum size and use that.
-     */
-    DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
-    /* Monitor forgot to set the first detailed is preferred bit. */
-    DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
-    /* use +hsync +vsync for detailed mode */
-    DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
-    /* Force single-link DVI bandwidth limit */
-    DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
-} ddc_quirk_t;
-
 static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
 {
     /* Belinea 10 15 55 */
@@ -774,7 +749,7 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
     }
 }
 
-static ddc_quirk_t
+ddc_quirk_t
 xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
 {
     ddc_quirk_t	quirks;
@@ -794,6 +769,25 @@ xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
     return quirks;
 }
 
+void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
+                              ddc_quirk_t quirks,
+                              int hsize, int vsize)
+{
+    if (det_mon->type != DT)
+        return;
+
+    if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
+        det_mon->section.d_timings.h_size *= 10;
+
+    if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
+        det_mon->section.d_timings.v_size *= 10;
+
+    if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
+        det_mon->section.d_timings.h_size = 10 * hsize;
+        det_mon->section.d_timings.v_size = 10 * vsize;
+    }
+}
+
 /**
  * Applies monitor-specific quirks to the decoded EDID information.
  *
@@ -807,21 +801,9 @@ xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC)
     int i;
 
     for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-	if (det_mon->type != DT)
-	    continue;
-
-	if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
-	    det_mon->section.d_timings.h_size *= 10;
-
-	if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
-	    det_mon->section.d_timings.v_size *= 10;
-
-	if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
-	    det_mon->section.d_timings.h_size = 10 * DDC->features.hsize;
-	    det_mon->section.d_timings.v_size = 10 * DDC->features.vsize;
-	}
+        xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks,
+                                 DDC->features.hsize,
+                                 DDC->features.vsize);
     }
 }
 
@@ -866,14 +848,156 @@ xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes,
 	    best->type |= M_T_PREFERRED;
 }
 
+#define CEA_VIDEO_MODES_NUM  64
+static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = {
+    { MODEPREFIX,    25175,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480 at 60Hz */
+    { MODEPREFIX,    27000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480 at 60Hz */
+    { MODEPREFIX,    27000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480 at 60Hz */
+    { MODEPREFIX,    74250, 1280, 1390, 1430, 1650, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720 at 60Hz */
+    { MODEPREFIX,    74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i at 60Hz */
+    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i at 60Hz */
+    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i at 60Hz */
+    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240 at 60Hz */
+    { MODEPREFIX,    27000, 1440, 1478, 1602, 1716, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240 at 60Hz */
+    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i at 60Hz */
+    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i at 60Hz */
+    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240 at 60Hz */
+    { MODEPREFIX,    54000, 2880, 2956, 3204, 3432, 0,  240,  244,  247,  262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240 at 60Hz */
+    { MODEPREFIX,    54000, 1440, 1472, 1596, 1716, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480 at 60Hz */
+    { MODEPREFIX,    54000, 1440, 1472, 1596, 1716, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480 at 60Hz */
+    { MODEPREFIX,   148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080 at 60Hz */
+    { MODEPREFIX,    27000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576 at 50Hz */
+    { MODEPREFIX,    27000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576 at 50Hz */
+    { MODEPREFIX,    74250, 1280, 1720, 1760, 1980, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720 at 50Hz */
+    { MODEPREFIX,    74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i at 50Hz */
+    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i at 50Hz */
+    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i at 50Hz */
+    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288 at 50Hz */
+    { MODEPREFIX,    27000, 1440, 1464, 1590, 1728, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288 at 50Hz */
+    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i at 50Hz */
+    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i at 50Hz */
+    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288 at 50Hz */
+    { MODEPREFIX,    54000, 2880, 2928, 3180, 3456, 0,  288,  290,  293,  312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288 at 50Hz */
+    { MODEPREFIX,    54000, 1440, 1464, 1592, 1728, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576 at 50Hz */
+    { MODEPREFIX,    54000, 1440, 1464, 1592, 1728, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576 at 50Hz */
+    { MODEPREFIX,   148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080 at 50Hz */
+    { MODEPREFIX,    74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080 at 24Hz */
+    { MODEPREFIX,    74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080 at 25Hz */
+    { MODEPREFIX,    74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080 at 30Hz */
+    { MODEPREFIX,   108000, 2880, 2944, 3192, 3432, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480 at 60Hz */
+    { MODEPREFIX,   108000, 2880, 2944, 3192, 3432, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480 at 60Hz */
+    { MODEPREFIX,   108000, 2880, 2928, 3184, 3456, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576 at 50Hz */
+    { MODEPREFIX,   108000, 2880, 2928, 3184, 3456, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576 at 50Hz */
+    { MODEPREFIX,    72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i at 50Hz */
+    { MODEPREFIX,   148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i at 100Hz */
+    { MODEPREFIX,   148500, 1280, 1720, 1760, 1980, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720 at 100Hz */
+    { MODEPREFIX,    54000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576 at 100Hz */
+    { MODEPREFIX,    54000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576 at 100Hz */
+    { MODEPREFIX,    54000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i at 100Hz */
+    { MODEPREFIX,    54000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i at 100Hz */
+    { MODEPREFIX,   148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i at 120Hz */
+    { MODEPREFIX,   148500, 1280, 1390, 1430, 1650, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720 at 120Hz */
+    { MODEPREFIX,    54000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480 at 120Hz */
+    { MODEPREFIX,    54000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480 at 120Hz */
+    { MODEPREFIX,    54000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i at 120Hz */
+    { MODEPREFIX,    54000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i at 120Hz */
+    { MODEPREFIX,   108000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576 at 200Hz */
+    { MODEPREFIX,   108000,  720,  732,  796,  864, 0,  576,  581,  586,  625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576 at 200Hz */
+    { MODEPREFIX,   108000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i at 200Hz */
+    { MODEPREFIX,   108000, 1440, 1464, 1590, 1728, 0,  576,  580,  586,  625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i at 200Hz */
+    { MODEPREFIX,   108000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480 at 240Hz */
+    { MODEPREFIX,   108000,  720,  736,  798,  858, 0,  480,  489,  495,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480 at 240Hz */
+    { MODEPREFIX,   108000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i at 240 */
+    { MODEPREFIX,   108000, 1440, 1478, 1602, 1716, 0,  480,  488,  494,  525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i at 240 */
+    { MODEPREFIX,    59400, 1280, 3040, 3080, 3300, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720 at 24Hz */
+    { MODEPREFIX,    74250, 3700, 3740, 1430, 3960, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720 at 25Hz */
+    { MODEPREFIX,    74250, 1280, 3040, 3080, 3300, 0,  720,  725,  730,  750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720 at 30Hz */
+    { MODEPREFIX,   297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080 at 120Hz */
+    { MODEPREFIX,   297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080 at 100Hz */
+};
+
+/* chose mode line by cea short video descriptor*/
+static void handle_cea_svd(struct cea_video_block *video, void *data)
+{
+    DisplayModePtr Mode;
+    DisplayModePtr *Modes = (DisplayModePtr *) data;
+    int vid;
+
+    vid = video ->video_code & 0x7f;
+    if (vid < CEA_VIDEO_MODES_NUM) {
+	Mode = xf86DuplicateMode(CEAVideoModes + vid);
+	*Modes = xf86ModesAdd(*Modes, Mode);
+    }
+}
+
+static DisplayModePtr
+DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr)
+{
+    DisplayModePtr Modes = NULL;
+
+    xf86ForEachVideoBlock(MonPtr,
+                          handle_cea_svd,
+                          &Modes);
+
+    return Modes;
+}
+
+struct det_modes_parameter {
+    xf86MonPtr DDC;
+    ddc_quirk_t quirks;
+    DisplayModePtr  Modes;
+    Bool rb;
+    Bool preferred;
+    int timing_level;
+};
+
+static void handle_detailed_modes(struct detailed_monitor_section *det_mon,
+	                          void *data)
+{
+    DisplayModePtr  Mode;
+    struct det_modes_parameter *p = (struct det_modes_parameter *)data;
+
+    xf86DetTimingApplyQuirks(det_mon,p->quirks,
+                             p->DDC->features.hsize,
+                             p->DDC->features.vsize);
+
+    switch (det_mon->type) {
+    case DT:
+        Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex,
+                                         &det_mon->section.d_timings,
+                                         p->preferred,
+                                         p->quirks);
+        p->preferred = FALSE;
+        p->Modes = xf86ModesAdd(p->Modes, Mode);
+        break;
+    case DS_STD_TIMINGS:
+        Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
+                                          p->quirks, p->timing_level,p->rb);
+        p->Modes = xf86ModesAdd(p->Modes, Mode);
+        break;
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
+    case DS_CVT:
+        Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt);
+        p->Modes = xf86ModesAdd(p->Modes, Mode);
+        break;
+#endif
+    case DS_EST_III:
+	Mode = DDCModesFromEstIII(det_mon->section.est_iii);
+	p->Modes = xf86ModesAdd(p->Modes, Mode);
+	break;
+    default:
+        break;
+    }
+}
+
 DisplayModePtr
 xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 {
-    int		    i;
     DisplayModePtr  Modes = NULL, Mode;
     ddc_quirk_t	    quirks;
     Bool	    preferred, rb;
     int		    timing_level;
+    struct det_modes_parameter p;
 
     xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
 		DDC->vendor.name, DDC->vendor.prod_id);
@@ -892,35 +1016,14 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
 
     timing_level = MonitorStandardTimingLevel(DDC);
 
-    for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
-
-	Mode = NULL;
-        switch (det_mon->type) {
-        case DT:
-            Mode = DDCModeFromDetailedTiming(scrnIndex,
-                                             &det_mon->section.d_timings,
-					     preferred,
-					     quirks);
-	    preferred = FALSE;
-            break;
-        case DS_STD_TIMINGS:
-            Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
-					      quirks, timing_level, rb);
-            break;
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
-	case DS_CVT:
-	    Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt);
-	    break;
-#endif
-	case DS_EST_III:
-	    Mode = DDCModesFromEstIII(det_mon->section.est_iii);
-	    break;
-        default:
-            break;
-        }
-	Modes = xf86ModesAdd(Modes, Mode);
-    }
+    p.quirks = quirks;
+    p.DDC = DDC;
+    p.Modes = Modes;
+    p.rb = rb;
+    p.preferred = preferred;
+    p.timing_level = timing_level;
+    xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p);
+    Modes = p.Modes;
 
     /* Add established timings */
     Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
@@ -930,6 +1033,10 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
     Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
     Modes = xf86ModesAdd(Modes, Mode);
 
+    /* Add cea-extension mode timings */
+    Mode = DDCModesFromCEAExtension(scrnIndex,DDC);
+    Modes = xf86ModesAdd(Modes, Mode);
+
     if (quirks & DDC_QUIRK_PREFER_LARGE_60)
 	xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
 
@@ -939,6 +1046,63 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
     return Modes;
 }
 
+struct det_mon_parameter {
+    MonPtr Monitor;
+    ddc_quirk_t quirks;
+    Bool have_hsync;
+    Bool have_vrefresh;
+    Bool have_maxpixclock;
+};
+
+static void handle_detailed_monset(struct detailed_monitor_section *det_mon,
+                                   void *data)
+{
+    int clock;
+    struct det_mon_parameter *p = (struct det_mon_parameter *)data;
+    int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex;
+
+    switch (det_mon->type) {
+    case DS_RANGES:
+        if (!p->have_hsync) {
+            if (!p->Monitor->nHsync)
+                xf86DrvMsg(scrnIndex, X_INFO,
+                    "Using EDID range info for horizontal sync\n");
+                p->Monitor->hsync[p->Monitor->nHsync].lo =
+                    det_mon->section.ranges.min_h;
+                p->Monitor->hsync[p->Monitor->nHsync].hi =
+                    det_mon->section.ranges.max_h;
+                p->Monitor->nHsync++;
+        } else {
+            xf86DrvMsg(scrnIndex, X_INFO,
+                "Using hsync ranges from config file\n");
+        }
+
+        if (!p->have_vrefresh) {
+            if (!p->Monitor->nVrefresh)
+                xf86DrvMsg(scrnIndex, X_INFO,
+                    "Using EDID range info for vertical refresh\n");
+            p->Monitor->vrefresh[p->Monitor->nVrefresh].lo =
+                det_mon->section.ranges.min_v;
+            p->Monitor->vrefresh[p->Monitor->nVrefresh].hi =
+                det_mon->section.ranges.max_v;
+            p->Monitor->nVrefresh++;
+        } else {
+            xf86DrvMsg(scrnIndex, X_INFO,
+                "Using vrefresh ranges from config file\n");
+        }
+
+        clock = det_mon->section.ranges.max_clock * 1000;
+        if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK)
+            clock = min(clock, 165000);
+        if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock)
+            p->Monitor->maxPixClock = clock;
+
+        break;
+    default:
+        break;
+    }
+}
+
 /*
  * Fill out MonPtr with xf86MonPtr information.
  */
@@ -946,17 +1110,13 @@ void
 xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 {
     DisplayModePtr Modes = NULL, Mode;
-    int i, clock;
-    Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE;
-    ddc_quirk_t quirks;
+    struct det_mon_parameter p;
 
     if (!Monitor || !DDC)
         return;
 
     Monitor->DDC = DDC;
 
-    quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE);
-
     if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) {
 	Monitor->widthmm = 10 * DDC->features.hsize;
 	Monitor->heightmm = 10 * DDC->features.vsize;
@@ -966,54 +1126,13 @@ xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 
     Modes = xf86DDCGetModes(scrnIndex, DDC);
 
-    /* Skip EDID ranges if they were specified in the config file */
-    have_hsync = (Monitor->nHsync != 0);
-    have_vrefresh = (Monitor->nVrefresh != 0);
-    have_maxpixclock = (Monitor->maxPixClock != 0);
-
     /* Go through the detailed monitor sections */
-    for (i = 0; i < DET_TIMINGS; i++) {
-        switch (DDC->det_mon[i].type) {
-        case DS_RANGES:
-	    if (!have_hsync) {
-		if (!Monitor->nHsync)
-		    xf86DrvMsg(scrnIndex, X_INFO,
-			    "Using EDID range info for horizontal sync\n");
-		Monitor->hsync[Monitor->nHsync].lo =
-		    DDC->det_mon[i].section.ranges.min_h;
-		Monitor->hsync[Monitor->nHsync].hi =
-		    DDC->det_mon[i].section.ranges.max_h;
-		Monitor->nHsync++;
-	    } else {
-		xf86DrvMsg(scrnIndex, X_INFO,
-			"Using hsync ranges from config file\n");
-	    }
-
-	    if (!have_vrefresh) {
-		if (!Monitor->nVrefresh)
-		    xf86DrvMsg(scrnIndex, X_INFO,
-			    "Using EDID range info for vertical refresh\n");
-		Monitor->vrefresh[Monitor->nVrefresh].lo =
-		    DDC->det_mon[i].section.ranges.min_v;
-		Monitor->vrefresh[Monitor->nVrefresh].hi =
-		    DDC->det_mon[i].section.ranges.max_v;
-		Monitor->nVrefresh++;
-	    } else {
-		xf86DrvMsg(scrnIndex, X_INFO,
-			"Using vrefresh ranges from config file\n");
-	    }
-
-	    clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
-	    if (quirks & DDC_QUIRK_DVI_SINGLE_LINK)
-		clock = min(clock, 165000);
-	    if (!have_maxpixclock && clock > Monitor->maxPixClock)
-		Monitor->maxPixClock = clock;
-
-            break;
-        default:
-            break;
-        }
-    }
+    p.Monitor = Monitor;
+    p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE);
+    p.have_hsync = (Monitor->nHsync != 0);
+    p.have_vrefresh = (Monitor->nVrefresh != 0);
+    p.have_maxpixclock = (Monitor->maxPixClock != 0);
+    xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p);
 
     if (Modes) {
         /* Print Modes */
commit fab74d1081270fb8f1d231e6e10d10aa33e164da
Author: Jamey Sharp <jamey at minilop.net>
Date:   Wed Oct 28 17:48:19 2009 -0700

    Suppress certain GCC warnings in auto-generated code.
    
    - Don't warn for references to deprecated functions in xorg_symbols.
    - Ignore functions generated by gl_apitemp.py that are never used.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glx/glapi.c b/glx/glapi.c
index fa3808e..d6a568e 100644
--- a/glx/glapi.c
+++ b/glx/glapi.c
@@ -114,10 +114,15 @@ warn(void)
    }
 }
 
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define possibly_unused __attribute((unused))
+#else
+#define possibly_unused
+#endif
 
 #define KEYWORD1 static
 #define KEYWORD1_ALT static
-#define KEYWORD2 GLAPIENTRY
+#define KEYWORD2 GLAPIENTRY possibly_unused
 #define NAME(func)  NoOp##func
 
 #define F NULL
diff --git a/hw/xfree86/loader/sdksyms.sh b/hw/xfree86/loader/sdksyms.sh
index 1186547..eea0240 100755
--- a/hw/xfree86/loader/sdksyms.sh
+++ b/hw/xfree86/loader/sdksyms.sh
@@ -2,6 +2,7 @@
 
 cat > sdksyms.c << EOF
 /* This file is automatically generated by sdksyms.sh. */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
commit 239435875d6a92ed31731b500a992a3af0943594
Author: Jamey Sharp <jamey at minilop.net>
Date:   Wed Oct 28 17:48:18 2009 -0700

    Don't cast double to int: use default conversions or explicitly round.
    
    GCC warns about casting a double return value to int.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/i2c/fi1236.c b/hw/xfree86/i2c/fi1236.c
index 110563e..7c39edb 100644
--- a/hw/xfree86/i2c/fi1236.c
+++ b/hw/xfree86/i2c/fi1236.c
@@ -225,7 +225,7 @@ m->f_ifbw=f_ifbw;
 m->f_step=f_step;
 
 m->f_lo1=f_rf+f_if1;
-m->LO1I=(int)floor((m->f_lo1/f_ref)+0.5);
+m->LO1I=lrint(m->f_lo1/f_ref);
 m->f_lo1=f_ref*m->LO1I;
 
 m->f_lo2=m->f_lo1-f_rf-f_if2;
@@ -258,10 +258,10 @@ if(m->f_lo1<1890.0)m->SEL=1;
 	m->SEL=0;
 
 /* calculate the rest of the registers */
-m->LO2I=(int)floor(m->f_lo2/f_ref);
-m->STEP=(int)floor(3780.0*f_step/f_ref);
-m->NUM=(int)floor(3780.0*(m->f_lo2/f_ref-m->LO2I));
-m->NUM=m->STEP*(int)floor((1.0*m->NUM)/(1.0*m->STEP)+0.5);
+m->LO2I=floor(m->f_lo2/f_ref);
+m->STEP=floor(3780.0*f_step/f_ref);
+m->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I));
+m->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP));
 }
 
 static int MT2032_wait_for_lock(FI1236Ptr f)
diff --git a/hw/xfree86/parser/Flags.c b/hw/xfree86/parser/Flags.c
index 6865d35..699f15c 100644
--- a/hw/xfree86/parser/Flags.c
+++ b/hw/xfree86/parser/Flags.c
@@ -434,7 +434,7 @@ xf86uLongToString(unsigned long i)
 	char *s;
 	int l;
 
-	l = (int)(ceil(log10((double)i) + 2.5));
+	l = ceil(log10((double)i) + 2.5);
 	s = malloc(l);
 	if (!s)
 		return NULL;
commit e8c48fd8f7aab54327b0091cd17c60235ae27168
Author: Jamey Sharp <jamey at minilop.net>
Date:   Wed Oct 28 17:48:17 2009 -0700

    Suppress GCC warnings like "the address of `u1' will always evaluate as `true'".
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glx/unpack.h b/glx/unpack.h
index a1dd17d..90cb71b 100644
--- a/glx/unpack.h
+++ b/glx/unpack.h
@@ -47,7 +47,7 @@
 ** Fetch a double from potentially unaligned memory.
 */
 #ifdef __GLX_ALIGN64
-#define __GLX_MEM_COPY(dst,src,n)	if (src && dst) memcpy(dst,src,n)
+#define __GLX_MEM_COPY(dst,src,n)	if (src != NULL && dst != NULL) memcpy(dst,src,n)
 #define __GLX_GET_DOUBLE(dst,src)	__GLX_MEM_COPY(&dst,src,8)
 #else
 #define __GLX_GET_DOUBLE(dst,src)	(dst) = *((GLdouble*)(src))
commit 662594aeff9d1767316f08600949c73ac5060d18
Author: Mikhail Gusarov <dottedmag at dottedmag.net>
Date:   Thu Oct 29 00:40:48 2009 +0600

    kdrive: Grab evdev mouse/keyboard devices when X server is active
    
    Input events are directed to both vt and input devices by default.
    Unless input devices are grabbed, keyboard events fill it vt buffers
    and cause spontaneous wakeups in kernel tty layer when buffers are full.
    
    Signed-off-by: Mikhail Gusarov <dottedmag at dottedmag.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/linux/evdev.c b/hw/kdrive/linux/evdev.c
index f6017ba..096a2dd 100644
--- a/hw/kdrive/linux/evdev.c
+++ b/hw/kdrive/linux/evdev.c
@@ -243,7 +243,9 @@ EvdevPtrEnable (KdPointerInfo *pi)
     if (fd < 0)
         return BadMatch;
 
-        
+    if (ioctl (fd, EVIOCGRAB, 1) < 0)
+        perror ("Grabbing evdev mouse device failed");
+
     if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
     {
         perror ("EVIOCGBIT 0");
@@ -335,6 +337,10 @@ EvdevPtrDisable (KdPointerInfo *pi)
         return;
 
     KdUnregisterFd (pi, ke->fd, TRUE);
+
+    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
+        perror ("Ungrabbing evdev mouse device failed");
+
     xfree (ke);
     pi->driverPrivate = 0;
 }
@@ -425,6 +431,9 @@ EvdevKbdEnable (KdKeyboardInfo *ki)
     if (fd < 0)
         return BadMatch;
 
+    if (ioctl (fd, EVIOCGRAB, 1) < 0)
+        perror ("Grabbing evdev keyboard device failed");
+
     if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) {
         perror ("EVIOCGBIT 0");
         close (fd);
@@ -496,6 +505,10 @@ EvdevKbdDisable (KdKeyboardInfo *ki)
         return;
 
     KdUnregisterFd (ki, ke->fd, TRUE);
+
+    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
+        perror ("Ungrabbing evdev keyboard device failed");
+
     xfree (ke);
     ki->driverPrivate = 0;
 }
commit 83d520d86c888f2c8a4abb18b7a8858d568aa18f
Author: Jamey Sharp <jamey at minilop.net>
Date:   Wed Oct 28 16:45:44 2009 -0700

    Add video driver flag to indicate that console access is not needed.
    
    Existing video drivers will get the console enabled by default.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index c9baff3..2d682aa 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -97,6 +97,7 @@ static Bool add_matching_devices_to_configure_list(DriverPtr drvp);
 #ifdef XF86PM
 void (*xf86OSPMClose)(void) = NULL;
 #endif
+static Bool xorgHWOpenConsole = FALSE;
 
 /* Common pixmap formats */
 
@@ -601,8 +602,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     if (xf86DoShowOptions)
         DoShowOptions();
 
-    xf86OpenConsole();
-
     /* Do a general bus probe.  This will be a PCI probe for x86 platforms */
     xf86BusProbe();
 
@@ -676,20 +675,29 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
      */
 
     for (i = 0; i < xf86NumDrivers; i++) {
-	xorgHWFlags flags;
-
 	if (xf86DriverList[i]->Identify != NULL)
 	    xf86DriverList[i]->Identify(0);
 
-	if (!xorgHWAccess
-	    && (!xf86DriverList[i]->driverFunc
+	if (!xorgHWAccess || !xorgHWOpenConsole) {
+	    xorgHWFlags flags;
+	    if(!xf86DriverList[i]->driverFunc
 		|| !xf86DriverList[i]->driverFunc(NULL,
 						  GET_REQUIRED_HW_INTERFACES,
-						  &flags)
-		|| NEED_IO_ENABLED(flags)))
-	    xorgHWAccess = TRUE;
+						  &flags))
+		flags = HW_IO;
+
+	    if(NEED_IO_ENABLED(flags))
+		xorgHWAccess = TRUE;
+	    if(!(flags & HW_SKIP_CONSOLE))
+		xorgHWOpenConsole = TRUE;
+	}
     }
 
+    if (xorgHWOpenConsole)
+	xf86OpenConsole();
+    else
+	xf86Info.dontVTSwitch = TRUE;
+
     /* Enable full I/O access */
     if (xorgHWAccess)
 	xorgHWAccess = xf86EnableIO();
@@ -966,7 +974,8 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     /*
      * serverGeneration != 1; some OSs have to do things here, too.
      */
-    xf86OpenConsole();
+    if (xorgHWOpenConsole)
+	xf86OpenConsole();
 
 #ifdef XF86PM
     /*
@@ -1203,7 +1212,8 @@ ddxGiveUp(void)
     DGAShutdown();
 #endif
 
-    xf86CloseConsole();
+    if (xorgHWOpenConsole)
+	xf86CloseConsole();
 
     xf86CloseLog();
 
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index b9a2e06..7b0b758 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/hw/xfree86/common/xf86str.h
@@ -299,6 +299,7 @@ typedef struct {
 /* GET_REQUIRED_HW_INTERFACES */
 #define HW_IO 1
 #define HW_MMIO 2
+#define HW_SKIP_CONSOLE 4
 #define NEED_IO_ENABLED(x) (x & HW_IO)
 
 typedef CARD32 xorgHWFlags;
commit 25979c46b467847ccb54f5c86a1be6b9c303c99a
Author: Jamey Sharp <jamey at minilop.net>
Date:   Wed Oct 28 16:35:28 2009 -0700

    Alloc/free drawables array for each ProcPanoramiXShmGetImage call.
    
    Updates my previous patch, b422b532f3dcab54c53f61a66f2ad76059d1874a.
    keithp recommended against allocating the drawables array globally, but my
    updated patch with that fixed isn't the patch that landed.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/shm.c b/Xext/shm.c
index 8106c40..9e462f2 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -141,7 +141,6 @@ int BadShmSegCode;
 RESTYPE ShmSegType;
 static ShmDescPtr Shmsegs;
 static Bool sharedPixmaps;
-static DrawablePtr *drawables;
 static int shmScrPrivateKeyIndex;
 static DevPrivateKey shmScrPrivateKey = &shmScrPrivateKeyIndex;
 static int shmPixmapPrivateIndex;
@@ -259,13 +258,6 @@ ShmExtensionInit(INITARGS)
     }
 #endif
 
-    drawables = xcalloc(screenInfo.numScreens, sizeof(DrawablePtr));
-    if (!drawables)
-    {
-	ErrorF("MIT-SHM extension disabled: no memory for per-screen drawables\n");
-	return;
-    }
-
     sharedPixmaps = xFalse;
     {
       sharedPixmaps = xTrue;
@@ -618,6 +610,7 @@ static int
 ProcPanoramiXShmGetImage(ClientPtr client)
 {
     PanoramiXRes	*draw;
+    DrawablePtr 	*drawables;
     DrawablePtr 	pDraw;
     xShmGetImageReply	xgi;
     ShmDescPtr		shmdesc;
@@ -678,12 +671,19 @@ ProcPanoramiXShmGetImage(ClientPtr client)
 	    return(BadMatch);
     }
 
+    drawables = xcalloc(PanoramiXNumScreens, sizeof(DrawablePtr));
+    if(!drawables)
+	return(BadAlloc);
+
     drawables[0] = pDraw;
     for(i = 1; i < PanoramiXNumScreens; i++) {
 	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, 
 			       DixReadAccess);
 	if (rc != Success)
+	{
+	    xfree(drawables);
 	    return rc;
+	}
     }
 
     xgi.visual = wVisual(((WindowPtr)pDraw));
@@ -722,6 +722,7 @@ ProcPanoramiXShmGetImage(ClientPtr client)
 	    }
 	}
     }
+    xfree(drawables);
     
     if (client->swapped) {
 	int n;
commit 757c11630d5999ad13dcac79191429badc92a3a6
Author: Tormod Volden <lists.tormod at gmail.com>
Date:   Wed Oct 28 23:10:43 2009 +0100

    xfree86: Fix description of DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE
    
    The message ending up in the log is misleading as to what the quirk
    actually does: It ignores the sizes in the detailed timings and
    replaces them with the display "Max Image Size".
    
    Signed-off-by: Tormod Volden <debian.tormod at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 2f80070..058e75d 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -266,7 +266,7 @@ static const ddc_quirk_map_t ddc_quirks[] = {
     },
     {
 	quirk_detailed_use_maximum_size,   DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
-	"Detailed timings give sizes in cm."
+	"Use maximum size instead of detailed timing sizes."
     },
     {
 	quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED,
commit ccf4a69db747b000aee09072aac0a2891bde139a
Author: Mikhail Gusarov <dottedmag at dottedmag.net>
Date:   Thu Oct 29 01:54:00 2009 +0600

    os: Add libsha1 as a choice of SHA1 implementation
    
    There are small systems which don't need OpenSSL or gcrypt.
    Add libsha1 (http://github.com/dottedmag/libsha1) as an alternative
    small SHA1 implementation.
    
    Signed-off-by: Mikhail Gusarov <dottedmag at dottedmag.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index e7c0504..02e9146 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1286,7 +1286,7 @@ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 
 # SHA1 hashing
 AC_ARG_WITH([sha1],
-            [AS_HELP_STRING([--with-sha1=libmd|libgcrypt|libcrypto],
+            [AS_HELP_STRING([--with-sha1=libmd|libgcrypt|libcrypto|libsha1],
                             [choose SHA1 implementation])])
 AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes])
 if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then
@@ -1309,6 +1309,15 @@ if test "x$with_sha1" = xlibgcrypt; then
 	          [Use libgcrypt SHA1 functions])
 	SHA1_LIBS=-lgcrypt
 fi
+AC_CHECK_LIB([sha1], [sha1_begin], [HAVE_LIBSHA1=yes])
+if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then
+   with_sha1=libsha1
+fi
+if test "x$with_sha1" = xlibsha1; then
+	AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1],
+	          [Use libsha1 for SHA1])
+	SHA1_LIBS=-lsha1
+fi
 # We don't need all of the OpenSSL libraries, just libcrypto
 AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes])
 PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes],
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 7f1fb18..ebf3733 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -166,6 +166,9 @@
 /* Define to use libgcrypt SHA1 functions */
 #undef HAVE_SHA1_IN_LIBGCRYPT
 
+/* Define to use libsha1 for SHA1 */
+#undef HAVE_SHA1_IN_LIBSHA1
+
 /* Define to 1 if you have the `shmctl64' function. */
 #undef HAVE_SHMCTL64
 
diff --git a/os/xsha1.c b/os/xsha1.c
index 723521e..94092ca 100644
--- a/os/xsha1.c
+++ b/os/xsha1.c
@@ -72,6 +72,32 @@ int x_sha1_final(void *ctx, unsigned char result[20])
     return 1;
 }
 
+#elif defined(HAVE_SHA1_IN_LIBSHA1) /* Use libsha1 */
+
+# include <libsha1.h>
+
+void *x_sha1_init(void)
+{
+    sha1_ctx *ctx = xalloc(sizeof(*ctx));
+    if(!ctx)
+        return NULL;
+    sha1_begin(ctx);
+    return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+    sha1_hash(data, size, ctx);
+    return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+    sha1_end(result, ctx);
+    xfree(ctx);
+    return 1;
+}
+
 #else /* Use OpenSSL's libcrypto */
 
 # include <stddef.h>  /* buggy openssl/sha.h wants size_t */
commit 8613e4b0eb04150b1e377871f02b164be5d001e9
Author: Mikhail Gusarov <dottedmag at dottedmag.net>
Date:   Wed Oct 28 11:44:27 2009 -0700

    Add missing DLOPEN_LIBS to kdrive compilation flags
    
    Xfbdev failed to build due to dladdr being used by xorg_backtrace.
    Explicitly add DLOPEN_LIBS to KDRIVE_LIBS as there does not
    seem to be a better place for it.
    
    Signed-off-by: Mikhail Gusarov <dottedmag at dottedmag.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index e7d8a4b..e7c0504 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1979,7 +1979,7 @@ if test "$KDRIVE" = yes; then
     KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB $CONFIG_LIB"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB $OS_LIB"
-    KDRIVE_LIBS="$TSLIB_LIBS $KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS"
+    KDRIVE_LIBS="$TSLIB_LIBS $KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS"
 
     AC_SUBST([XEPHYR_LIBS])
     AC_SUBST([XEPHYR_INCS])
commit deb72fc61464250af8185dab2da8ee09f13c55d8
Merge: 55f4c80... a60e676...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Oct 28 10:54:13 2009 -0700

    Merge remote branch 'jcristau/sha1'

commit 55f4c80a4c891b355a99e6a05978ca945397c5cc
Author: Hans Nieser <hnsr at xs4all.nl>
Date:   Wed Oct 28 06:59:40 2009 +0100

    Xinput: allow non-integer values again for Constant- and AdaptiveDeceleration
    
    This was initially fixed by commit 3932a848572f4eaf8b7f1d91d9b74aeafab069a2
    but then (presumably not intentionally) undone by commit
    1d54479cb3c8b4f75b7564f8b5e1c5da940b20f4 .
    
    Signed-off-by: Hans Nieser <hnsr at xs4all.nl>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6887f55..f637cfe 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -113,7 +113,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list,
         return;
 
     /* common settings (available via device properties) */
-    tempf = xf86SetIntOption(list, "ConstantDeceleration", 1);
+    tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0);
     if(tempf > 1.0){
         xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n",
                 devname, tempf);
@@ -122,7 +122,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list,
                                PropModeReplace, 1, &tempf, FALSE);
     }
 
-    tempf = xf86SetIntOption(list, "AdaptiveDeceleration", 1);
+    tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0);
     if(tempf > 1.0){
         xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n",
                 devname, tempf);
commit a60e676f1fd243c78859440b87652f523d3f2ec1
Author: Julien Cristau <jcristau at debian.org>
Date:   Wed Oct 14 23:51:22 2009 +0200

    Add libgcrypt as an option for SHA1
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Rémi Cardona <remi at gentoo.org>

diff --git a/configure.ac b/configure.ac
index 082f67d..9888528 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1282,7 +1282,7 @@ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 
 # SHA1 hashing
 AC_ARG_WITH([sha1],
-            [AS_HELP_STRING([--with-sha1=libmd|libcrypto],
+            [AS_HELP_STRING([--with-sha1=libmd|libgcrypt|libcrypto],
                             [choose SHA1 implementation])])
 AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes])
 if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then
@@ -1296,6 +1296,15 @@ if test "x$with_sha1" = xlibmd; then
 	          [Use libmd SHA1 functions])
 	SHA1_LIBS=-lmd
 fi
+AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes])
+if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then
+	with_sha1=libgcrypt
+fi
+if test "x$with_sha1" = xlibgcrypt; then
+	AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1],
+	          [Use libgcrypt SHA1 functions])
+	SHA1_LIBS=-lgcrypt
+fi
 # We don't need all of the OpenSSL libraries, just libcrypto
 AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes])
 PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes],
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index a19c3c7..7f1fb18 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -163,6 +163,9 @@
 /* Define to use libmd SHA1 functions */
 #undef HAVE_SHA1_IN_LIBMD
 
+/* Define to use libgcrypt SHA1 functions */
+#undef HAVE_SHA1_IN_LIBGCRYPT
+
 /* Define to 1 if you have the `shmctl64' function. */
 #undef HAVE_SHMCTL64
 
diff --git a/os/xsha1.c b/os/xsha1.c
index 2016980..723521e 100644
--- a/os/xsha1.c
+++ b/os/xsha1.c
@@ -33,6 +33,45 @@ int x_sha1_final(void *ctx, unsigned char result[20])
     return 1;
 }
 
+#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */
+
+# include <gcrypt.h>
+
+void *x_sha1_init(void)
+{
+    static int init;
+    gcry_md_hd_t h;
+    gcry_error_t err;
+
+    if (!init) {
+        if (!gcry_check_version(NULL))
+            return NULL;
+        gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+        gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+        init = 1;
+    }
+
+    err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
+    if (err)
+        return NULL;
+    return h;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+    gcry_md_hd_t h = ctx;
+    gcry_md_write(h, data, size);
+    return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+    gcry_md_hd_t h = ctx;
+    memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20);
+    gcry_md_close(h);
+    return 1;
+}
+
 #else /* Use OpenSSL's libcrypto */
 
 # include <stddef.h>  /* buggy openssl/sha.h wants size_t */
commit d2a6a395435919aff8943285f9cbfe6569a9728f
Author: Julien Cristau <jcristau at debian.org>
Date:   Wed Oct 14 23:30:55 2009 +0200

    configure: add --with-sha1={libmd,libcrypto} option
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Rémi Cardona <remi at gentoo.org>

diff --git a/configure.ac b/configure.ac
index 1a8f97e..082f67d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1280,25 +1280,45 @@ MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow'
 MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la'
 CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 
-# OpenSSL used for SHA1 hashing in render/glyph.c, but we don't need all of
-# the OpenSSL libraries, just libcrypto
-# Some systems have matching functionality in the smaller/simpler libmd
-# Builders who want to force a choice can set SHA1_LIBS and SHA1_CFLAGS
-if test "x$SHA1_LIB" = "x" ; then
-  AC_CHECK_LIB([md], [SHA1Init], [SHA1_LIBS="-lmd"
-            AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1],
-            [Use libmd SHA1 functions instead of OpenSSL libcrypto])])
-fi
-
-if test "x$SHA1_LIB" = "x" ; then
-  PKG_CHECK_EXISTS([openssl], [HAVE_OPENSSL_PKC=yes],
-                    [HAVE_OPENSSL_PKC=no])
-  if test "x$HAVE_OPENSSL_PKC" = xyes; then
-    PKG_CHECK_MODULES([SHA1], [openssl])
-  else
-    AC_CHECK_LIB([crypto], [SHA1_Init], [SHA1_LIBS="-lcrypto"],
-                 [AC_MSG_ERROR([OpenSSL must be installed in order to build the X server.])])
-  fi
+# SHA1 hashing
+AC_ARG_WITH([sha1],
+            [AS_HELP_STRING([--with-sha1=libmd|libcrypto],
+                            [choose SHA1 implementation])])
+AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes])
+if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then
+	with_sha1=libmd
+fi
+if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then
+	AC_MSG_ERROR([libmd requested but not found])
+fi
+if test "x$with_sha1" = xlibmd; then
+	AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1],
+	          [Use libmd SHA1 functions])
+	SHA1_LIBS=-lmd
+fi
+# We don't need all of the OpenSSL libraries, just libcrypto
+AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes])
+PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes],
+                  [HAVE_OPENSSL_PKC=no])
+if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then
+	if test "x$with_sha1" = x; then
+		with_sha1=libcrypto
+	fi
+else
+	if test "x$with_sha1" = xlibcrypto; then
+		AC_MSG_ERROR([OpenSSL libcrypto requested but not found])
+	fi
+fi
+if test "x$with_sha1" = xlibcrypto; then
+	if test "x$HAVE_LIBCRYPTO" = xyes; then
+		SHA1_LIBS=-lcrypto
+	else
+		SHA1_LIBS="$OPENSSL_LIBS"
+		SHA1_CFLAGS="$OPENSSL_CFLAGS"
+	fi
+fi
+if test "x$with_sha1" = x; then
+	AC_MSG_ERROR([No suitable SHA1 implementation found])
 fi
 AC_SUBST(SHA1_LIBS)
 AC_SUBST(SHA1_CFLAGS)
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 798d9e7..a19c3c7 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -160,7 +160,7 @@
 /* Define to 1 if you have the <rpcsvc/dbm.h> header file. */
 #undef HAVE_RPCSVC_DBM_H
 
-/* Define to use libmd SHA1 functions instead of OpenSSL libcrypto */
+/* Define to use libmd SHA1 functions */
 #undef HAVE_SHA1_IN_LIBMD
 
 /* Define to 1 if you have the `shmctl64' function. */
commit 55516094947dd78ad2734bb784a2fb109b64c990
Author: Julien Cristau <jcristau at debian.org>
Date:   Wed Oct 14 23:20:44 2009 +0200

    Move SHA1 computation from render/glyph.c to os/
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Rémi Cardona <remi at gentoo.org>

diff --git a/configure.ac b/configure.ac
index fa454fa..1a8f97e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1283,23 +1283,25 @@ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 # OpenSSL used for SHA1 hashing in render/glyph.c, but we don't need all of
 # the OpenSSL libraries, just libcrypto
 # Some systems have matching functionality in the smaller/simpler libmd
-# Builders who want to force a choice can set SHA1_LIB and SHA1_CFLAGS
+# Builders who want to force a choice can set SHA1_LIBS and SHA1_CFLAGS
 if test "x$SHA1_LIB" = "x" ; then
-  AC_CHECK_LIB([md], [SHA1Init], [SHA1_LIB="-lmd"
+  AC_CHECK_LIB([md], [SHA1Init], [SHA1_LIBS="-lmd"
             AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1],
             [Use libmd SHA1 functions instead of OpenSSL libcrypto])])
 fi
 
 if test "x$SHA1_LIB" = "x" ; then
-  PKG_CHECK_EXISTS([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes],
+  PKG_CHECK_EXISTS([openssl], [HAVE_OPENSSL_PKC=yes],
                     [HAVE_OPENSSL_PKC=no])
   if test "x$HAVE_OPENSSL_PKC" = xyes; then
-    REQUIRED_LIBS="$REQUIRED_LIBS openssl"
+    PKG_CHECK_MODULES([SHA1], [openssl])
   else
-    AC_CHECK_LIB([crypto], [SHA1_Init], [SHA1_LIB="-lcrypto"],
+    AC_CHECK_LIB([crypto], [SHA1_Init], [SHA1_LIBS="-lcrypto"],
                  [AC_MSG_ERROR([OpenSSL must be installed in order to build the X server.])])
   fi
 fi
+AC_SUBST(SHA1_LIBS)
+AC_SUBST(SHA1_CFLAGS)
 
 PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS])
 PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS])
@@ -1319,9 +1321,9 @@ PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS])
 # XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers
 # require.
 #
-XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS} ${SHA1_CFLAGS}"
+XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}"
 XSERVER_LIBS="$DIX_LIB $CONFIG_LIB $MI_LIB $OS_LIB"
-XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS} ${SHA1_LIB}"
+XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}"
 AC_SUBST([XSERVER_LIBS])
 AC_SUBST([XSERVER_SYS_LIBS])
 
diff --git a/include/Makefile.am b/include/Makefile.am
index aa5db7d..d684f9c 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -66,4 +66,5 @@ AM_CFLAGS = $(DIX_CFLAGS)
 EXTRA_DIST = 	\
 	dix-config-apple-verbatim.h \
 	eventconvert.h eventstr.h \
-	protocol-versions.h
+	protocol-versions.h \
+	xsha1.h
diff --git a/include/xsha1.h b/include/xsha1.h
new file mode 100644
index 0000000..aab7106
--- /dev/null
+++ b/include/xsha1.h
@@ -0,0 +1,19 @@
+#ifndef XSHA1_H
+#define XSHA1_H
+
+/* Initialize SHA1 computation.  Returns NULL on error. */
+void *x_sha1_init(void);
+
+/*
+ * Add some data to be hashed.  ctx is the value returned by x_sha1_init()
+ * Returns 0 on error, 1 on success.
+ */
+int x_sha1_update(void *ctx, void *data, int size);
+
+/*
+ * Place the hash in result, and free ctx.
+ * Returns 0 on error, 1 on success. 
+ */
+int x_sha1_final(void *ctx, unsigned char result[20]);
+
+#endif
diff --git a/os/Makefile.am b/os/Makefile.am
index a7f34a5..9902f04 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -1,6 +1,6 @@
 noinst_LTLIBRARIES = libos.la
 
-AM_CFLAGS = $(DIX_CFLAGS)
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
 
 SECURERPC_SRCS = rpcauth.c
 XDMCP_SRCS = xdmcp.c
@@ -22,9 +22,11 @@ libos_la_SOURCES = 	\
 	strcasecmp.c	\
 	strcasestr.c	\
 	xdmauth.c	\
+	xsha1.c		\
 	xstrans.c	\
 	xprintf.c	\
 	$(XORG_SRCS)
+libos_la_LIBADD = @SHA1_LIBS@
 
 if SECURE_RPC
 libos_la_SOURCES += $(SECURERPC_SRCS)
diff --git a/os/xsha1.c b/os/xsha1.c
new file mode 100644
index 0000000..2016980
--- /dev/null
+++ b/os/xsha1.c
@@ -0,0 +1,74 @@
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "os.h"
+#include "xsha1.h"
+
+#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
+
+# include <sha1.h>
+
+void *x_sha1_init(void)
+{
+    SHA1_CTX *ctx = xalloc(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+    SHA1Init(ctx);
+    return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+    SHA1_CTX *sha1_ctx = ctx;
+    SHA1Update(sha1_ctx, data, size);
+    return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+    SHA1_CTX *sha1_ctx = ctx;
+    SHA1Final(result, sha1_ctx);
+    xfree(sha1_ctx);
+    return 1;
+}
+
+#else /* Use OpenSSL's libcrypto */
+
+# include <stddef.h>  /* buggy openssl/sha.h wants size_t */
+# include <openssl/sha.h>
+
+void *x_sha1_init(void)
+{
+    int ret;
+    SHA_CTX *ctx = xalloc(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+    ret = SHA1_Init(ctx);
+    if (!ret) {
+        xfree(ctx);
+        return NULL;
+    }
+    return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+    int ret;
+    SHA_CTX *sha_ctx = ctx;
+    ret = SHA1_Update(sha_ctx, data, size);
+    if (!ret)
+        xfree(sha_ctx);
+    return ret;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+    int ret;
+    SHA_CTX *sha_ctx = ctx;
+    ret = SHA1_Final(result, sha_ctx);
+    xfree(sha_ctx);
+    return ret;
+}
+
+#endif
diff --git a/render/glyph.c b/render/glyph.c
index 7fcdfd9..0b864ad 100644
--- a/render/glyph.c
+++ b/render/glyph.c
@@ -26,12 +26,7 @@
 #include <dix-config.h>
 #endif
 
-#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
-# include <sha1.h>
-#else /* Use OpenSSL's libcrypto */
-# include <stddef.h>  /* buggy openssl/sha.h wants size_t */
-# include <openssl/sha.h>
-#endif
+#include "xsha1.h"
 
 #include "misc.h"
 #include "scrnintstr.h"
@@ -198,34 +193,21 @@ HashGlyph (xGlyphInfo    *gi,
 	   unsigned long size,
 	   unsigned char sha1[20])
 {
-#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
-    SHA1_CTX ctx;
-
-    SHA1Init (&ctx);
-    SHA1Update (&ctx, gi, sizeof (xGlyphInfo));
-    SHA1Update (&ctx, bits, size);
-    SHA1Final (sha1, &ctx);
-#else /* Use OpenSSL's libcrypto */
-    SHA_CTX ctx;
+    void *ctx = x_sha1_init();
     int success;
 
-    success = SHA1_Init (&ctx);
-    if (! success)
+    if (!ctx)
 	return BadAlloc;
 
-    success = SHA1_Update (&ctx, gi, sizeof (xGlyphInfo));
-    if (! success)
+    success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo));
+    if (!success)
 	return BadAlloc;
-
-    success = SHA1_Update (&ctx, bits, size);
-    if (! success)
+    success = x_sha1_update(ctx, bits, size);
+    if (!success)
 	return BadAlloc;
-
-    success = SHA1_Final (sha1, &ctx);
-    if (! success)
+    success = x_sha1_final(ctx, sha1);
+    if (!success)
 	return BadAlloc;
-#endif
-
     return Success;
 }
 


More information about the Xquartz-changes mailing list