Blob Blame Raw
commit 03b34c5fb12c4df180d4df113d2b654f6afd7230
Author: Dave Airlie <airlied@redhat.com>
Date:   Mon Apr 19 17:58:07 2010 +1000

    radeon: add FireMV 2400 pci id.
    
    From RH#581927 - thanks to Carsten Clasohm
    
    Signed-off-by: Dave Airlie <airlied@redhat.com>

commit 6c07816025f70e522986614c29c300ea13e5d932
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 18:50:17 2010 -0400

    r5xx texvid: deal with large numbers of verts
    
    should fix fdo bug 25884

commit 5ee320a6b1b4c65fe592c8ac4d1981799242d59e
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 18:42:56 2010 -0400

    r3xx texvid: deal with large numbers of verts
    
    should fix fdo bug 25884

commit 47af3f4f266232517486238917d82fc5ca9c82e6
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 20:50:18 2010 -0400

    r2xx texvid: deal with large numbers of verts
    
    should fix fdo bug 25884

commit 57577d5cd0641b7cad02242478699bcfece59227
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 20:40:56 2010 -0400

    r1xx texvid: deal with large numbers of verts
    
    should fix fdo bug 25884

commit 31a888e78fa403f2bddacee098a29f36eaa969cb
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 15:52:59 2010 -0400

    r5xx textured video: split into prepare and draw functions

commit f7ebe4a127965bb9e46d20c60331bcc4dab76fc5
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 15:46:24 2010 -0400

    r3xx textured video: split into prepare and draw functions

commit 10799b4ce0c18c5a7d92d688549e8e777344f111
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 15:38:49 2010 -0400

    r2xx textured video: split into prepare and draw functions

commit bd1cf42201a1f918080bf34786a6de327cb31b5f
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 15:31:40 2010 -0400

    r1xx textured video: split into prepare and draw functions

commit c1136f94b80346065893f8a43c0fbf60c8c9b057
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 15:23:14 2010 -0400

    Xv: track vtx_count, is_planar in port priv

commit 2f680b631357661511456f07b7b4ba1aa2cbf30c
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 13:43:41 2010 -0400

    radeon/kms: fix possible crtc mask for evergreen

commit 4656f5dff1ed72fa2c7a1484305f2aef7b65ff2b
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 16 13:36:25 2010 -0400

    radeon/kms: fix crash when using more than two heads
    
    fixes fdo bug 27692

commit a69e749d0562887af6bd236c38802472e54640c4
Author: Dave Airlie <airlied@redhat.com>
Date:   Fri Apr 16 13:58:54 2010 +1000

    kms: add uevent support.
    
    When we get a hotplug event from the kernel we should notify the client side to reconfigure displays.
    
    based on work by ajax in intel driver.
    
    Signed-off-by: Dave Airlie <airlied@redhat.com>

commit 22a46dddd375b2b9399e12fdf168fa5292ff17a4
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Tue Apr 13 11:08:59 2010 -0400

    radeon: add support for pll algo selection
    
    tv-out on atom systems is very particular about it's
    dividers.  force it to use the old algo.
    
    Should fix fdo bug 27593.

commit c1b817c45477c21234abaaebe78feb7ea4fd92b1
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Mon Apr 12 16:32:04 2010 -0400

    atom: disable TV encoder when VGA is in use
    
    Switching between TV and VGA caused problems on some
    systems since the TV encoder was left enabled.
    
    Should fix fdo bug 25520.

commit 878814aeab7031ff6169fcaf2be869b7595c8699
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Mon Apr 12 11:16:14 2010 -0400

    Xv overlay: set scalerwidth to 1920 on r3xx/r4xx chips
    
    reported on phoronix forums.

commit 276fe739f1caa95778213054375a65288b80f320
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Fri Apr 9 20:03:09 2010 -0400

    radeon: add some new pci ids

commit eb5665688ef9b52f03f61546351d0848cab54740
Author: Alex Deucher <alexdeucher@gmail.com>
Date:   Thu Apr 8 00:31:52 2010 -0400

    radeon: don't setup Xv on rn50
    
    It has no overlay or 3D engine.
    
    fixes fdo bug 27528
diff --git a/configure.ac b/configure.ac
index b9274d6..cf0a855 100644
--- a/configure.ac
+++ b/configure.ac
@@ -152,6 +152,10 @@ if test "$DRI" = yes; then
                         else
                                 DRM_MODE=no
 			fi
+			PKG_CHECK_MODULES(LIBUDEV, [libudev], [LIBUDEV=yes], [LIBUDEV=no])
+			if test "x$LIBUDEV" = xyes; then
+			       AC_DEFINE(HAVE_LIBUDEV, 1,[libudev support])
+			fi
         	fi
 	fi
 	CFLAGS="$save_CFLAGS"
@@ -159,6 +163,7 @@ else
 	DRM_MODE=no
 fi
 AM_CONDITIONAL(DRM_MODE, test x$DRM_MODE = xyes)
+AM_CONDITIONAL(LIBUDEV, test x$LIBUDEV = xyes)
 
 save_CFLAGS="$CFLAGS"
 CFLAGS="$XORG_CFLAGS"
@@ -358,6 +363,8 @@ AC_SUBST([XORG_CFLAGS])
 AC_SUBST([DRI_CFLAGS])
 AC_SUBST([LIBDRM_RADEON_CFLAGS])
 AC_SUBST([LIBDRM_RADEON_LIBS])
+AC_SUBST([LIBUDEV_CFLAGS])
+AC_SUBST([LIBUDEV_LIBS])
 AC_SUBST([moduledir])
 
 DRIVER_NAME=ati
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f89480..0ce46b0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,6 +78,7 @@ AM_CFLAGS = \
             @XORG_CFLAGS@ \
             @DRI_CFLAGS@ \
             @XMODES_CFLAGS@ \
+            @LIBUDEV_CFLAGS@ \
             -DDISABLE_EASF \
             -DENABLE_ALL_SERVICE_FUNCTIONS \
             -DATOM_BIOS \
@@ -91,6 +92,10 @@ ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD += $(PCIACCESS_LIBS)
 endif
 
+if LIBUDEV
+radeon_drv_la_LIBADD += $(LIBUDEV_LIBS)
+endif
+
 ati_drv_la_LTLIBRARIES = ati_drv.la
 ati_drv_la_LDFLAGS = -module -avoid-version
 ati_drv_ladir = @moduledir@/drivers
diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
index f88b069..b4479ac 100644
--- a/src/ati_pciids_gen.h
+++ b/src/ati_pciids_gen.h
@@ -2,6 +2,7 @@
 #define PCI_CHIP_RV380_3151 0x3151
 #define PCI_CHIP_RV380_3152 0x3152
 #define PCI_CHIP_RV380_3154 0x3154
+#define PCI_CHIP_RV380_3155 0x3155
 #define PCI_CHIP_RV380_3E50 0x3E50
 #define PCI_CHIP_RV380_3E54 0x3E54
 #define PCI_CHIP_RS100_4136 0x4136
@@ -348,6 +349,7 @@
 #define PCI_CHIP_RV770_9456 0x9456
 #define PCI_CHIP_RV770_945A 0x945A
 #define PCI_CHIP_RV770_945B 0x945B
+#define PCI_CHIP_RV770_945E 0x945E
 #define PCI_CHIP_RV790_9460 0x9460
 #define PCI_CHIP_RV790_9462 0x9462
 #define PCI_CHIP_RV770_946A 0x946A
@@ -358,6 +360,7 @@
 #define PCI_CHIP_RV730_9487 0x9487
 #define PCI_CHIP_RV730_9488 0x9488
 #define PCI_CHIP_RV730_9489 0x9489
+#define PCI_CHIP_RV730_948A 0x948A
 #define PCI_CHIP_RV730_948F 0x948F
 #define PCI_CHIP_RV730_9490 0x9490
 #define PCI_CHIP_RV730_9491 0x9491
@@ -401,12 +404,14 @@
 #define PCI_CHIP_RV670_9519 0x9519
 #define PCI_CHIP_RV710_9540 0x9540
 #define PCI_CHIP_RV710_9541 0x9541
+#define PCI_CHIP_RV710_9542 0x9542
 #define PCI_CHIP_RV710_954E 0x954E
 #define PCI_CHIP_RV710_954F 0x954F
 #define PCI_CHIP_RV710_9552 0x9552
 #define PCI_CHIP_RV710_9553 0x9553
 #define PCI_CHIP_RV710_9555 0x9555
 #define PCI_CHIP_RV710_9557 0x9557
+#define PCI_CHIP_RV710_955F 0x955F
 #define PCI_CHIP_RV630_9580 0x9580
 #define PCI_CHIP_RV630_9581 0x9581
 #define PCI_CHIP_RV630_9583 0x9583
@@ -420,7 +425,6 @@
 #define PCI_CHIP_RV630_958D 0x958D
 #define PCI_CHIP_RV630_958E 0x958E
 #define PCI_CHIP_RV630_958F 0x958F
-#define PCI_CHIP_RV710_9542 0x9542
 #define PCI_CHIP_RV620_95C0 0x95C0
 #define PCI_CHIP_RV620_95C2 0x95C2
 #define PCI_CHIP_RV620_95C4 0x95C4
@@ -473,6 +477,7 @@
 #define PCI_CHIP_JUNIPER_68BE 0x68BE
 #define PCI_CHIP_REDWOOD_68C0 0x68C0
 #define PCI_CHIP_REDWOOD_68C1 0x68C1
+#define PCI_CHIP_REDWOOD_68C7 0x68C7
 #define PCI_CHIP_REDWOOD_68C8 0x68C8
 #define PCI_CHIP_REDWOOD_68C9 0x68C9
 #define PCI_CHIP_REDWOOD_68D8 0x68D8
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 1d86643..6f083b4 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -458,6 +458,19 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     unsigned char *space;
 
     memset(&spc_param, 0, sizeof(spc_param));
+
+    if (IS_AVIVO_VARIANT) {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
+	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
+	else
+	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+    } else {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
+	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
+	else
+	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+    }
+
     if (IS_AVIVO_VARIANT) {
 	if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
 	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
@@ -471,6 +484,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	for (i = 0; i < xf86_config->num_output; i++) {
 	    xf86OutputPtr output = xf86_config->output[i];
 	    if (output->crtc == crtc) {
+		radeon_output = output->driver_private;
 		radeon_encoder = radeon_get_encoder(output);
 		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 		/* AdjustDisplayPll handles this on DCE3.x */
@@ -478,6 +492,11 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) &&
 		    !IS_DCE3_VARIANT)
 		    sclock *= 2;
+		if (radeon_output->active_device &
+		    (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) {
+		    pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
+		    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+		}
 	    }
 	}
 
@@ -614,7 +633,8 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	}
     }
 
-    RADEONComputePLL(pScrn, &info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
+    RADEONComputePLL(crtc, &info->pll, sclock, &temp,
+		     &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
     sclock = temp; /* 10 khz */
 
     xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 0a54657..3e2d301 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -1801,8 +1801,12 @@ atombios_output_mode_set(xf86OutputPtr output,
     case ENCODER_OBJECT_ID_INTERNAL_DAC2:
     case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 	atombios_output_dac_setup(output, ATOM_ENABLE);
-	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-	    atombios_output_tv_setup(output, ATOM_ENABLE);
+	if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+			atombios_output_tv_setup(output, ATOM_ENABLE);
+		else
+			atombios_output_tv_setup(output, ATOM_DISABLE);
+	}
 	break;
     }
     atombios_apply_output_quirks(output, adjusted_mode);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 399a6a7..ea361d6 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -933,7 +933,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
 	output->driver_private = drmmode_output;
 	
-	output->possible_crtcs = 0xf;
+	output->possible_crtcs = 0x7f;
 	for (i = 0; i < koutput->count_encoders; i++) {
 		output->possible_crtcs &= kencoders[i]->possible_crtcs;
 	}
@@ -1159,6 +1159,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
 	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
+	drmmode->scrn = pScrn;
 	drmmode->cpp = cpp;
 	drmmode->mode_res = drmModeGetResources(drmmode->fd);
 	if (!drmmode->mode_res)
@@ -1347,4 +1348,67 @@ Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
          return FALSE;
     return TRUE;
 }
+
+#ifdef HAVE_LIBUDEV
+static void
+drmmode_handle_uevents(int fd, void *closure)
+{
+	drmmode_ptr drmmode = closure;
+	ScrnInfoPtr scrn = drmmode->scrn;
+	struct udev_device *dev;
+	dev = udev_monitor_receive_device(drmmode->uevent_monitor);
+	if (!dev)
+		return;
+
+	RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
+	udev_device_unref(dev);
+}
+#endif
+
+void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+#ifdef HAVE_LIBUDEV
+	struct udev *u;
+	struct udev_monitor *mon;
+
+	u = udev_new();
+	if (!u)
+		return;
+	mon = udev_monitor_new_from_netlink(u, "udev");
+	if (!mon) {
+		udev_unref(u);
+		return;
+	}
+
+	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
+							    "drm",
+							    "drm_minor") < 0 ||
+	    udev_monitor_enable_receiving(mon) < 0) {
+		udev_monitor_unref(mon);
+		udev_unref(u);
+		return;
+	}
+
+	drmmode->uevent_handler =
+		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
+				      drmmode_handle_uevents,
+				      drmmode);
+
+	drmmode->uevent_monitor = mon;
+#endif
+}
+
+void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+#ifdef HAVE_LIBUDEV
+	if (drmmode->uevent_handler) {
+		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
+		xf86RemoveGeneralHandler(drmmode->uevent_handler);
+
+		udev_monitor_unref(drmmode->uevent_monitor);
+		udev_unref(u);
+	}
+#endif
+}
+
 #endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 2e76259..86caabb 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -30,6 +30,9 @@
 #ifdef XF86DRM_MODE
 
 #include "xf86drmMode.h"
+#ifdef HAVE_LIBUDEV
+#include "libudev.h"
+#endif
 
 #include "radeon_probe.h"
 
@@ -40,10 +43,14 @@ typedef struct {
   drmModeFBPtr mode_fb;
   int cpp;
   struct radeon_bo_manager *bufmgr;
+  ScrnInfoPtr scrn;
+#ifdef HAVE_LIBUDEV
+  struct udev_monitor *uevent_monitor;
+  InputHandlerProc uevent_handler;
+#endif
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
-
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
     struct radeon_bo *cursor_bo;
@@ -81,6 +88,10 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y,
 extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+
+extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
+extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
+
 #endif
 
 #endif
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index e4c1f04..0beb54d 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -1184,10 +1184,12 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 
 /* Define PLL registers for requested video mode */
 static void
-RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+RADEONInitPLLRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 		       RADEONPLLPtr pll, DisplayModePtr mode,
 		       int flags)
 {
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    ScrnInfoPtr pScrn = crtc->scrn;
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     uint32_t feedback_div = 0;
     uint32_t frac_fb_div = 0;
@@ -1223,7 +1225,13 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
        return;
     }
 
-    RADEONComputePLL(pScrn, pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
+    if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
+	radeon_crtc->pll_algo = RADEON_PLL_NEW;
+    else
+	radeon_crtc->pll_algo = RADEON_PLL_OLD;
+
+    RADEONComputePLL(crtc, pll, mode->Clock, &freq,
+		     &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
 
     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 	if (post_div->divider == post_divider)
@@ -1266,10 +1274,12 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
 
 /* Define PLL2 registers for requested video mode */
 static void
-RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
+RADEONInitPLL2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 			RADEONPLLPtr pll, DisplayModePtr mode,
 			int flags)
 {
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    ScrnInfoPtr pScrn = crtc->scrn;
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     uint32_t feedback_div = 0;
     uint32_t frac_fb_div = 0;
@@ -1303,7 +1313,13 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
        return;
     }
 
-    RADEONComputePLL(pScrn, pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
+    if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
+	radeon_crtc->pll_algo = RADEON_PLL_NEW;
+    else
+	radeon_crtc->pll_algo = RADEON_PLL_OLD;
+
+    RADEONComputePLL(crtc, pll, mode->Clock, &freq,
+		     &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
 
     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 	if (post_div->divider == post_divider)
@@ -1795,7 +1811,7 @@ legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	dot_clock = adjusted_mode->Clock / 1000.0;
 	if (dot_clock) {
 	    ErrorF("init pll1\n");
-	    RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
+	    RADEONInitPLLRegisters(crtc, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
 	} else {
 	    info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
 	    info->ModeReg->ppll_div_3   = info->SavedReg->ppll_div_3;
@@ -1809,7 +1825,7 @@ legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	dot_clock = adjusted_mode->Clock / 1000.0;
 	if (dot_clock) {
 	    ErrorF("init pll2\n");
-	    RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
+	    RADEONInitPLL2Registers(crtc, info->ModeReg, &info->pll, adjusted_mode, pll_flags);
 	}
 	break;
     }
diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index b26cf25..6f101b2 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -3,6 +3,7 @@
 "0x3151","RV380_3151","RV380",,,,,,"ATI FireMV 2400 (PCI)"
 "0x3152","RV380_3152","RV380",1,,,,,"ATI Radeon Mobility X300 (M24) 3152 (PCIE)"
 "0x3154","RV380_3154","RV380",1,,,,,"ATI FireGL M24 GL 3154 (PCIE)"
+"0x3155","RV380_3155","RV380",1,,,,,"ATI FireMV 2400 3155 (PCI)"
 "0x3E50","RV380_3E50","RV380",,,,,,"ATI Radeon X600 (RV380) 3E50 (PCIE)"
 "0x3E54","RV380_3E54","RV380",,,,,,"ATI FireGL V3200 (RV380) 3E54 (PCIE)"
 "0x4136","RS100_4136","RS100",,1,,,1,"ATI Radeon IGP320 (A3) 4136"
@@ -349,6 +350,7 @@
 "0x9456","RV770_9456","RV770",,,,,,"ATI FirePro V8700 (FireGL)"
 "0x945A","RV770_945A","RV770",1,,,,,"ATI Mobility RADEON HD 4870"
 "0x945B","RV770_945B","RV770",1,,,,,"ATI Mobility RADEON M98"
+"0x945E","RV770_945E","RV770",1,,,,,"ATI Mobility RADEON HD 4870"
 "0x9460","RV790_9460","RV770",,,,,,"ATI Radeon 4800 Series"
 "0x9462","RV790_9462","RV770",,,,,,"ATI Radeon 4800 Series"
 "0x946A","RV770_946A","RV770",1,,,,,"ATI FirePro M7750"
@@ -359,6 +361,7 @@
 "0x9487","RV730_9487","RV730",,,,,,"ATI Radeon RV730 (AGP)"
 "0x9488","RV730_9488","RV730",1,,,,,"ATI Mobility Radeon HD 4670"
 "0x9489","RV730_9489","RV730",1,,,,,"ATI FirePro M5750"
+"0x948A","RV730_948A","RV730",1,,,,,"ATI Mobility Radeon HD 4670"
 "0x948F","RV730_948F","RV730",,,,,,"ATI Radeon RV730 (AGP)"
 "0x9490","RV730_9490","RV730",,,,,,"ATI RV730XT [Radeon HD 4670]"
 "0x9491","RV730_9491","RV730",,,,,,"ATI RADEON E4600"
@@ -402,12 +405,14 @@
 "0x9519","RV670_9519","RV670",,,,,,"AMD Firestream 9170"
 "0x9540","RV710_9540","RV710",,,,,,"ATI Radeon HD 4550"
 "0x9541","RV710_9541","RV710",,,,,,"ATI Radeon RV710"
+"0x9542","RV710_9542","RV710",,,,,,"ATI Radeon RV710"
 "0x954E","RV710_954E","RV710",,,,,,"ATI Radeon RV710"
 "0x954F","RV710_954F","RV710",,,,,,"ATI Radeon HD 4350"
 "0x9552","RV710_9552","RV710",1,,,,,"ATI Mobility Radeon 4300 Series"
 "0x9553","RV710_9553","RV710",1,,,,,"ATI Mobility Radeon 4500 Series"
 "0x9555","RV710_9555","RV710",1,,,,,"ATI Mobility Radeon 4500 Series"
 "0x9557","RV710_9557","RV710",1,,,,,"ATI FirePro RG220"
+"0x955F","RV710_955F","RV710",1,,,,,"ATI Mobility Radeon 4330"
 "0x9580","RV630_9580","RV630",,,,,,"ATI RV630"
 "0x9581","RV630_9581","RV630",1,,,,,"ATI Mobility Radeon HD 2600"
 "0x9583","RV630_9583","RV630",1,,,,,"ATI Mobility Radeon HD 2600 XT"
@@ -421,7 +426,6 @@
 "0x958D","RV630_958D","RV630",,,,,,"ATI FireGL V3600"
 "0x958E","RV630_958E","RV630",,,,,,"ATI Radeon HD 2600 LE"
 "0x958F","RV630_958F","RV630",1,,,,,"ATI Mobility FireGL Graphics Processor"
-"0x9542","RV710_9542","RV710",,,,,,"ATI Radeon RV710"
 "0x95C0","RV620_95C0","RV620",,,,,,"ATI Radeon HD 3470"
 "0x95C2","RV620_95C2","RV620",1,,,,,"ATI Mobility Radeon HD 3430"
 "0x95C4","RV620_95C4","RV620",1,,,,,"ATI Mobility Radeon HD 3400 Series"
@@ -474,6 +478,7 @@
 "0x68BE","JUNIPER_68BE","JUNIPER",,,,,,"ATI Radeon HD 5700 Series"
 "0x68C0","REDWOOD_68C0","REDWOOD",1,,,,,"ATI Mobility Radeon HD 5000 Series"
 "0x68C1","REDWOOD_68C1","REDWOOD",1,,,,,"ATI Mobility Radeon HD 5000 Series"
+"0x68C7","REDWOOD_68C7","REDWOOD",1,,,,,"ATI Mobility Radeon HD 5570"
 "0x68C8","REDWOOD_68C8","REDWOOD",,,,,,"ATI FirePro (FireGL) Graphics Adapter"
 "0x68C9","REDWOOD_68C9","REDWOOD",,,,,,"ATI FirePro (FireGL) Graphics Adapter"
 "0x68D8","REDWOOD_68D8","REDWOOD",,,,,,"ATI Radeon HD 5670"
diff --git a/src/radeon.h b/src/radeon.h
index 88f1516..859224c 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1042,7 +1042,7 @@ typedef struct {
     struct radeon_cs_manager *csm;
     struct radeon_cs *cs;
 
-    struct radeon_bo *cursor_bo[2];
+    struct radeon_bo *cursor_bo[6];
     uint64_t vram_size;
     uint64_t gart_size;
     drmmode_rec drmmode;
@@ -1138,6 +1138,7 @@ extern Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen);
 #  endif
 uint32_t radeonGetPixmapOffset(PixmapPtr pPix);
 #endif
+extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn);
 
 #ifdef USE_XAA
 /* radeon_accelfuncs.c */
@@ -1176,7 +1177,7 @@ extern void radeon_crtc_load_lut(xf86CrtcPtr crtc);
 extern void radeon_crtc_modeset_ioctl(xf86CrtcPtr crtc, Bool post);
 extern Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask);
 extern void RADEONBlank(ScrnInfoPtr pScrn);
-extern void RADEONComputePLL(ScrnInfoPtr pScrn,
+extern void RADEONComputePLL(xf86CrtcPtr crtc,
 			     RADEONPLLPtr pll, unsigned long freq,
 			     uint32_t *chosen_dot_clock_freq,
 			     uint32_t *chosen_feedback_div,
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 0250d91..823f91d 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -573,6 +573,18 @@ uint32_t radeonGetPixmapOffset(PixmapPtr pPix)
     return offset;
 }
 
+int radeon_cs_space_remaining(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef XF86DRM_MODE
+    if (info->cs)
+	return (info->cs->ndw - info->cs->cdw);
+    else
+#endif
+        return (info->cp->indirectBuffer->total - info->cp->indirectBuffer->used) / (int)sizeof(uint32_t);
+}
+
 #define ACCEL_MMIO
 #define ACCEL_PREAMBLE()        unsigned char *RADEONMMIO = info->MMIO
 #define BEGIN_ACCEL(n)          RADEONWaitForFifo(pScrn, (n))
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index 0f53790..3fc2a53 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -4,6 +4,7 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x3151, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
  { 0x3152, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
  { 0x3154, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
+ { 0x3155, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
  { 0x3E50, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
  { 0x3E54, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
  { 0x4136, CHIP_FAMILY_RS100, 0, 1, 0, 0, 1 },
@@ -268,6 +269,7 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x9456, CHIP_FAMILY_RV770, 0, 0, 0, 0, 0 },
  { 0x945A, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
  { 0x945B, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
+ { 0x945E, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
  { 0x9460, CHIP_FAMILY_RV770, 0, 0, 0, 0, 0 },
  { 0x9462, CHIP_FAMILY_RV770, 0, 0, 0, 0, 0 },
  { 0x946A, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
@@ -278,6 +280,7 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x9487, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9488, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
  { 0x9489, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
+ { 0x948A, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
  { 0x948F, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9490, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9491, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
@@ -321,12 +324,14 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x9519, CHIP_FAMILY_RV670, 0, 0, 0, 0, 0 },
  { 0x9540, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
  { 0x9541, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
+ { 0x9542, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
  { 0x954E, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
  { 0x954F, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
  { 0x9552, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9553, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9555, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9557, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
+ { 0x955F, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9580, CHIP_FAMILY_RV630, 0, 0, 0, 0, 0 },
  { 0x9581, CHIP_FAMILY_RV630, 1, 0, 0, 0, 0 },
  { 0x9583, CHIP_FAMILY_RV630, 1, 0, 0, 0, 0 },
@@ -340,7 +345,6 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x958D, CHIP_FAMILY_RV630, 0, 0, 0, 0, 0 },
  { 0x958E, CHIP_FAMILY_RV630, 0, 0, 0, 0, 0 },
  { 0x958F, CHIP_FAMILY_RV630, 1, 0, 0, 0, 0 },
- { 0x9542, CHIP_FAMILY_RV710, 0, 0, 0, 0, 0 },
  { 0x95C0, CHIP_FAMILY_RV620, 0, 0, 0, 0, 0 },
  { 0x95C2, CHIP_FAMILY_RV620, 1, 0, 0, 0, 0 },
  { 0x95C4, CHIP_FAMILY_RV620, 1, 0, 0, 0, 0 },
@@ -393,6 +397,7 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x68BE, CHIP_FAMILY_JUNIPER, 0, 0, 0, 0, 0 },
  { 0x68C0, CHIP_FAMILY_REDWOOD, 1, 0, 0, 0, 0 },
  { 0x68C1, CHIP_FAMILY_REDWOOD, 1, 0, 0, 0, 0 },
+ { 0x68C7, CHIP_FAMILY_REDWOOD, 1, 0, 0, 0, 0 },
  { 0x68C8, CHIP_FAMILY_REDWOOD, 0, 0, 0, 0, 0 },
  { 0x68C9, CHIP_FAMILY_REDWOOD, 0, 0, 0, 0, 0 },
  { 0x68D8, CHIP_FAMILY_REDWOOD, 0, 0, 0, 0, 0 },
diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
index 7b74d7e..e38579b 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -4,6 +4,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV380_3151, "ATI FireMV 2400 (PCI)" },
   { PCI_CHIP_RV380_3152, "ATI Radeon Mobility X300 (M24) 3152 (PCIE)" },
   { PCI_CHIP_RV380_3154, "ATI FireGL M24 GL 3154 (PCIE)" },
+  { PCI_CHIP_RV380_3155, "ATI FireMV 2400 3155 (PCI)" },
   { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" },
   { PCI_CHIP_RV380_3E54, "ATI FireGL V3200 (RV380) 3E54 (PCIE)" },
   { PCI_CHIP_RS100_4136, "ATI Radeon IGP320 (A3) 4136" },
@@ -268,6 +269,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV770_9456, "ATI FirePro V8700 (FireGL)" },
   { PCI_CHIP_RV770_945A, "ATI Mobility RADEON HD 4870" },
   { PCI_CHIP_RV770_945B, "ATI Mobility RADEON M98" },
+  { PCI_CHIP_RV770_945E, "ATI Mobility RADEON HD 4870" },
   { PCI_CHIP_RV790_9460, "ATI Radeon 4800 Series" },
   { PCI_CHIP_RV790_9462, "ATI Radeon 4800 Series" },
   { PCI_CHIP_RV770_946A, "ATI FirePro M7750" },
@@ -278,6 +280,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV730_9487, "ATI Radeon RV730 (AGP)" },
   { PCI_CHIP_RV730_9488, "ATI Mobility Radeon HD 4670" },
   { PCI_CHIP_RV730_9489, "ATI FirePro M5750" },
+  { PCI_CHIP_RV730_948A, "ATI Mobility Radeon HD 4670" },
   { PCI_CHIP_RV730_948F, "ATI Radeon RV730 (AGP)" },
   { PCI_CHIP_RV730_9490, "ATI RV730XT [Radeon HD 4670]" },
   { PCI_CHIP_RV730_9491, "ATI RADEON E4600" },
@@ -321,12 +324,14 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV670_9519, "AMD Firestream 9170" },
   { PCI_CHIP_RV710_9540, "ATI Radeon HD 4550" },
   { PCI_CHIP_RV710_9541, "ATI Radeon RV710" },
+  { PCI_CHIP_RV710_9542, "ATI Radeon RV710" },
   { PCI_CHIP_RV710_954E, "ATI Radeon RV710" },
   { PCI_CHIP_RV710_954F, "ATI Radeon HD 4350" },
   { PCI_CHIP_RV710_9552, "ATI Mobility Radeon 4300 Series" },
   { PCI_CHIP_RV710_9553, "ATI Mobility Radeon 4500 Series" },
   { PCI_CHIP_RV710_9555, "ATI Mobility Radeon 4500 Series" },
   { PCI_CHIP_RV710_9557, "ATI FirePro RG220" },
+  { PCI_CHIP_RV710_955F, "ATI Mobility Radeon 4330" },
   { PCI_CHIP_RV630_9580, "ATI RV630" },
   { PCI_CHIP_RV630_9581, "ATI Mobility Radeon HD 2600" },
   { PCI_CHIP_RV630_9583, "ATI Mobility Radeon HD 2600 XT" },
@@ -340,7 +345,6 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV630_958D, "ATI FireGL V3600" },
   { PCI_CHIP_RV630_958E, "ATI Radeon HD 2600 LE" },
   { PCI_CHIP_RV630_958F, "ATI Mobility FireGL Graphics Processor" },
-  { PCI_CHIP_RV710_9542, "ATI Radeon RV710" },
   { PCI_CHIP_RV620_95C0, "ATI Radeon HD 3470" },
   { PCI_CHIP_RV620_95C2, "ATI Mobility Radeon HD 3430" },
   { PCI_CHIP_RV620_95C4, "ATI Mobility Radeon HD 3400 Series" },
@@ -393,6 +397,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_JUNIPER_68BE, "ATI Radeon HD 5700 Series" },
   { PCI_CHIP_REDWOOD_68C0, "ATI Mobility Radeon HD 5000 Series" },
   { PCI_CHIP_REDWOOD_68C1, "ATI Mobility Radeon HD 5000 Series" },
+  { PCI_CHIP_REDWOOD_68C7, "ATI Mobility Radeon HD 5570" },
   { PCI_CHIP_REDWOOD_68C8, "ATI FirePro (FireGL) Graphics Adapter" },
   { PCI_CHIP_REDWOOD_68C9, "ATI FirePro (FireGL) Graphics Adapter" },
   { PCI_CHIP_REDWOOD_68D8, "ATI Radeon HD 5670" },
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 0b071b8..a4a3302 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -447,7 +447,7 @@ done:
 }
 
 void
-RADEONComputePLL(ScrnInfoPtr pScrn,
+RADEONComputePLL(xf86CrtcPtr crtc,
 		 RADEONPLLPtr pll,
 		 unsigned long freq,
 		 uint32_t *chosen_dot_clock_freq,
@@ -457,28 +457,21 @@ RADEONComputePLL(ScrnInfoPtr pScrn,
 		 uint32_t *chosen_post_div,
 		 int flags)
 {
-    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
 
-    if (IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) {
-	    /* disable frac fb dividers */
-	    flags &= ~RADEON_PLL_USE_FRAC_FB_DIV;
-	    RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
-				 chosen_feedback_div, chosen_frac_feedback_div,
-				 chosen_reference_div, chosen_post_div, flags);
-	} else
-	    RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
-				 chosen_feedback_div, chosen_frac_feedback_div,
-				 chosen_reference_div, chosen_post_div, flags);
-    } else {
-	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
-	    RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
-				 chosen_feedback_div, chosen_frac_feedback_div,
-				 chosen_reference_div, chosen_post_div, flags);
-	else
-	    RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
-				 chosen_feedback_div, chosen_frac_feedback_div,
-				 chosen_reference_div, chosen_post_div, flags);
+    switch (radeon_crtc->pll_algo) {
+    case RADEON_PLL_OLD:
+	RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
+			     chosen_feedback_div, chosen_frac_feedback_div,
+			     chosen_reference_div, chosen_post_div, flags);
+	break;
+    case RADEON_PLL_NEW:
+	/* disable frac fb dividers */
+	flags &= ~RADEON_PLL_USE_FRAC_FB_DIV;
+	RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
+			     chosen_feedback_div, chosen_frac_feedback_div,
+			     chosen_reference_div, chosen_post_div, flags);
+	break;
     }
 }
 
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index b627637..0aaf82b 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2701,7 +2701,11 @@ static Bool RADEONPreInitXv(ScrnInfoPtr pScrn)
 	switch(info->ChipFamily){
 	case CHIP_FAMILY_R200:
 	case CHIP_FAMILY_R300:
+	case CHIP_FAMILY_R350:
 	case CHIP_FAMILY_RV350:
+	case CHIP_FAMILY_RV380:
+	case CHIP_FAMILY_R420:
+	case CHIP_FAMILY_RV410:
 		info->overlay_scaler_buffer_width = 1920;
 		break;
 	default:
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 15e5e3f..e33c9ef 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -601,6 +601,7 @@ static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONCloseScreen\n");
 
+    drmmode_uevent_fini(pScrn, &info->drmmode);
     if (info->cs)
       radeon_cs_flush_indirect(pScrn);
 
@@ -866,6 +867,7 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     info->accel_state->XInited3D = FALSE;
     info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
 
+    drmmode_uevent_init(pScrn, &info->drmmode);
     return TRUE;
 }
 
diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
index 8afa10d..c1ead9c 100644
--- a/src/radeon_pci_chipset_gen.h
+++ b/src/radeon_pci_chipset_gen.h
@@ -4,6 +4,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV380_3151, PCI_CHIP_RV380_3151, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3152, PCI_CHIP_RV380_3152, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3154, PCI_CHIP_RV380_3154, RES_SHARED_VGA },
+ { PCI_CHIP_RV380_3155, PCI_CHIP_RV380_3155, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3E50, PCI_CHIP_RV380_3E50, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3E54, PCI_CHIP_RV380_3E54, RES_SHARED_VGA },
  { PCI_CHIP_RS100_4136, PCI_CHIP_RS100_4136, RES_SHARED_VGA },
@@ -268,6 +269,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV770_9456, PCI_CHIP_RV770_9456, RES_SHARED_VGA },
  { PCI_CHIP_RV770_945A, PCI_CHIP_RV770_945A, RES_SHARED_VGA },
  { PCI_CHIP_RV770_945B, PCI_CHIP_RV770_945B, RES_SHARED_VGA },
+ { PCI_CHIP_RV770_945E, PCI_CHIP_RV770_945E, RES_SHARED_VGA },
  { PCI_CHIP_RV790_9460, PCI_CHIP_RV790_9460, RES_SHARED_VGA },
  { PCI_CHIP_RV790_9462, PCI_CHIP_RV790_9462, RES_SHARED_VGA },
  { PCI_CHIP_RV770_946A, PCI_CHIP_RV770_946A, RES_SHARED_VGA },
@@ -278,6 +280,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV730_9487, PCI_CHIP_RV730_9487, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9488, PCI_CHIP_RV730_9488, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9489, PCI_CHIP_RV730_9489, RES_SHARED_VGA },
+ { PCI_CHIP_RV730_948A, PCI_CHIP_RV730_948A, RES_SHARED_VGA },
  { PCI_CHIP_RV730_948F, PCI_CHIP_RV730_948F, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9490, PCI_CHIP_RV730_9490, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9491, PCI_CHIP_RV730_9491, RES_SHARED_VGA },
@@ -321,12 +324,14 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV670_9519, PCI_CHIP_RV670_9519, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9540, PCI_CHIP_RV710_9540, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9541, PCI_CHIP_RV710_9541, RES_SHARED_VGA },
+ { PCI_CHIP_RV710_9542, PCI_CHIP_RV710_9542, RES_SHARED_VGA },
  { PCI_CHIP_RV710_954E, PCI_CHIP_RV710_954E, RES_SHARED_VGA },
  { PCI_CHIP_RV710_954F, PCI_CHIP_RV710_954F, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9552, PCI_CHIP_RV710_9552, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9553, PCI_CHIP_RV710_9553, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9555, PCI_CHIP_RV710_9555, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9557, PCI_CHIP_RV710_9557, RES_SHARED_VGA },
+ { PCI_CHIP_RV710_955F, PCI_CHIP_RV710_955F, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9580, PCI_CHIP_RV630_9580, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9581, PCI_CHIP_RV630_9581, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9583, PCI_CHIP_RV630_9583, RES_SHARED_VGA },
@@ -340,7 +345,6 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV630_958D, PCI_CHIP_RV630_958D, RES_SHARED_VGA },
  { PCI_CHIP_RV630_958E, PCI_CHIP_RV630_958E, RES_SHARED_VGA },
  { PCI_CHIP_RV630_958F, PCI_CHIP_RV630_958F, RES_SHARED_VGA },
- { PCI_CHIP_RV710_9542, PCI_CHIP_RV710_9542, RES_SHARED_VGA },
  { PCI_CHIP_RV620_95C0, PCI_CHIP_RV620_95C0, RES_SHARED_VGA },
  { PCI_CHIP_RV620_95C2, PCI_CHIP_RV620_95C2, RES_SHARED_VGA },
  { PCI_CHIP_RV620_95C4, PCI_CHIP_RV620_95C4, RES_SHARED_VGA },
@@ -393,6 +397,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_JUNIPER_68BE, PCI_CHIP_JUNIPER_68BE, RES_SHARED_VGA },
  { PCI_CHIP_REDWOOD_68C0, PCI_CHIP_REDWOOD_68C0, RES_SHARED_VGA },
  { PCI_CHIP_REDWOOD_68C1, PCI_CHIP_REDWOOD_68C1, RES_SHARED_VGA },
+ { PCI_CHIP_REDWOOD_68C7, PCI_CHIP_REDWOOD_68C7, RES_SHARED_VGA },
  { PCI_CHIP_REDWOOD_68C8, PCI_CHIP_REDWOOD_68C8, RES_SHARED_VGA },
  { PCI_CHIP_REDWOOD_68C9, PCI_CHIP_REDWOOD_68C9, RES_SHARED_VGA },
  { PCI_CHIP_REDWOOD_68D8, PCI_CHIP_REDWOOD_68D8, RES_SHARED_VGA },
diff --git a/src/radeon_pci_device_match_gen.h b/src/radeon_pci_device_match_gen.h
index a09c969..709d8cc 100644
--- a/src/radeon_pci_device_match_gen.h
+++ b/src/radeon_pci_device_match_gen.h
@@ -4,6 +4,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3151, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3152, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3154, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV380_3155, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3E50, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3E54, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RS100_4136, 0 ),
@@ -268,6 +269,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_9456, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_945A, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_945B, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV770_945E, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV790_9460, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV790_9462, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_946A, 0 ),
@@ -278,6 +280,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9487, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9488, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9489, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV730_948A, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_948F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9490, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9491, 0 ),
@@ -321,12 +324,14 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV670_9519, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9540, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9541, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV710_9542, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_954E, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_954F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9552, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9553, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9555, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9557, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV710_955F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9580, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9581, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9583, 0 ),
@@ -340,7 +345,6 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_958D, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_958E, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_958F, 0 ),
- ATI_DEVICE_MATCH( PCI_CHIP_RV710_9542, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV620_95C0, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV620_95C2, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV620_95C4, 0 ),
@@ -393,6 +397,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_JUNIPER_68BE, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68C0, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68C1, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68C7, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68C8, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68C9, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_REDWOOD_68D8, 0 ),
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index dc02bdf..cab077f 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -147,6 +147,11 @@ typedef struct
     Bool hw_capable;
 } RADEONI2CBusRec, *RADEONI2CBusPtr;
 
+enum radeon_pll_algo {
+    RADEON_PLL_OLD,
+    RADEON_PLL_NEW
+};
+
 typedef struct _RADEONCrtcPrivateRec {
     void *crtc_rotate_mem;
     void *cursor_mem;
@@ -164,6 +169,7 @@ typedef struct _RADEONCrtcPrivateRec {
     float vsc;
     float hsc;
     int pll_id;
+    enum radeon_pll_algo     pll_algo;
 } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr;
 
 typedef struct _radeon_encoder {
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index f967331..138dfa3 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -87,8 +87,8 @@ do {								\
 
 #endif /* !ACCEL_CP */
 
-static void
-FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+static Bool
+FUNC_NAME(RADEONPrepareTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
@@ -97,10 +97,9 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     uint32_t txformat, txsize, txpitch, txoffset;
     uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
-    Bool isplanar = FALSE;
-    int dstxoff, dstyoff, pixel_shift, vtx_count;
-    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
-    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int pixel_shift;
+    int scissor_w = MIN(pPixmap->drawable.width, 2047);
+    int scissor_h = MIN(pPixmap->drawable.height, 2047);
     ACCEL_PREAMBLE();
 
 #ifdef XF86DRM_MODE
@@ -119,14 +118,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	ret = radeon_cs_space_check(info->cs);
 	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
-	    return;
+	    return FALSE;
 	}
     }
 #endif
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
-    
+
 #ifdef USE_EXA
     if (info->useEXA) {
 	dst_pitch = exaGetPixmapPitch(pPixmap);
@@ -136,14 +135,6 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
         dst_pitch = pPixmap->devKind;
     }
 
-#ifdef COMPOSITE
-    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
-    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
-#else
-    dstxoff = 0;
-    dstyoff = 0;
-#endif
-
 #ifdef USE_EXA
     if (info->useEXA) {
 	RADEON_SWITCH_TO_3D();
@@ -176,13 +167,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	dst_format = RADEON_COLOR_FORMAT_ARGB8888;
 	break;
     default:
-	return;
+	return FALSE;
     }
 
     if (pPriv->id == FOURCC_I420 || pPriv->id == FOURCC_YV12) {
-	isplanar = TRUE;
+	pPriv->is_planar = TRUE;
 	txformat = RADEON_TXFORMAT_Y8;
     } else {
+	pPriv->is_planar = FALSE;
 	if (pPriv->id == FOURCC_UYVY)
 	    txformat = RADEON_TXFORMAT_YVYU422;
 	else
@@ -208,11 +200,11 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
     FINISH_ACCEL();
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	/* need 2 texcoord sets (even though they are identical) due
 	   to denormalization! hw apparently can't premultiply
 	   same coord set by different texture size */
-	vtx_count = 6;
+	pPriv->vtx_count = 6;
 
 	txsize = (((((pPriv->w + 1 ) >> 1) - 1) & 0x7ff) |
 		  (((((pPriv->h + 1 ) >> 1) - 1) & 0x7ff) << RADEON_TEX_VSIZE_SHIFT));
@@ -307,7 +299,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_2, txpitch);
 	FINISH_ACCEL();
     } else {
-	vtx_count = 4;
+	pPriv->vtx_count = 4;
 	BEGIN_ACCEL_RELOC(9, 1);
 
 	OUT_ACCEL_REG(RADEON_SE_VTX_FMT, (RADEON_SE_VTX_FMT_XY |
@@ -344,17 +336,12 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	FINISH_ACCEL();
     }
 
-    {
-      int scissor_w, scissor_h;
-      scissor_w = MIN(pPixmap->drawable.width, 2047);
-      scissor_h = MIN(pPixmap->drawable.height, 2047);
-
-      BEGIN_ACCEL(2);
-      OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
-      OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) |
-					     (scissor_h << RADEON_RE_HEIGHT_SHIFT)));
-      FINISH_ACCEL();
-    }
+    BEGIN_ACCEL(2);
+    OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
+    OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) |
+					   (scissor_h << RADEON_RE_HEIGHT_SHIFT)));
+    FINISH_ACCEL();
+
     if (pPriv->vsync) {
 	xf86CrtcPtr crtc;
 	if (pPriv->desired_crtc)
@@ -371,6 +358,31 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
     }
+
+    return TRUE;
+}
+
+static void
+FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    PixmapPtr pPixmap = pPriv->pPixmap;
+    int dstxoff, dstyoff;
+    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
+    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    ACCEL_PREAMBLE();
+
+#ifdef COMPOSITE
+    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    dstxoff = 0;
+    dstyoff = 0;
+#endif
+
+    if (!FUNC_NAME(RADEONPrepareTexturedVideo)(pScrn, pPriv))
+	return;
+
     /*
      * Rendering of the actual polygon is done in two different
      * ways depending on chip generation:
@@ -390,12 +402,26 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
      *     the single triangle up to 2560/4021 pixels; above that we
      *     render as a quad.
      */
-
 #ifdef ACCEL_CP
-	BEGIN_RING(nBox * 3 * vtx_count + 5);
+    while (nBox) {
+	int draw_size = 3 * pPriv->vtx_count + 5;
+	int loop_boxes;
+
+	if (draw_size > radeon_cs_space_remaining(pScrn)) {
+	    if (info->cs)
+		radeon_cs_flush_indirect(pScrn);
+	    else
+		RADEONCPFlushIndirect(pScrn, 1);
+	    if (!FUNC_NAME(RADEONPrepareTexturedVideo)(pScrn, pPriv))
+		return;
+	}
+	loop_boxes = MIN(radeon_cs_space_remaining(pScrn) / draw_size, nBox);
+	nBox -= loop_boxes;
+
+	BEGIN_RING(loop_boxes * 3 * pPriv->vtx_count + 5);
 	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
-			    nBox * 3 * vtx_count + 1));
-	if (isplanar)
+			    loop_boxes * 3 * pPriv->vtx_count + 1));
+	if (pPriv->is_planar)
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0 |
 		     RADEON_CP_VC_FRMT_ST1);
@@ -406,15 +432,64 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 		 RADEON_CP_VC_CNTL_MAOS_ENABLE |
 		 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
-		 ((nBox * 3) << RADEON_CP_VC_CNTL_NUM_SHIFT));
-#else /* ACCEL_CP */
-	BEGIN_ACCEL(nBox * vtx_count * 3 + 2);
-	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
-					  RADEON_VF_PRIM_WALK_DATA |
-					  RADEON_VF_RADEON_MODE |
-					  ((nBox * 3) << RADEON_VF_NUM_VERTICES_SHIFT)));
-#endif
+		 ((loop_boxes * 3) << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+	while (loop_boxes--) {
+	    int srcX, srcY, srcw, srch;
+	    int dstX, dstY, dstw, dsth;
+	    dstX = pBox->x1 + dstxoff;
+	    dstY = pBox->y1 + dstyoff;
+	    dstw = pBox->x2 - pBox->x1;
+	    dsth = pBox->y2 - pBox->y1;
+
+	    srcX = pPriv->src_x;
+	    srcX += ((pBox->x1 - pPriv->drw_x) *
+		     pPriv->src_w) / pPriv->dst_w;
+	    srcY = pPriv->src_y;
+	    srcY += ((pBox->y1 - pPriv->drw_y) *
+		     pPriv->src_h) / pPriv->dst_h;
+
+	    srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
+	    srch = (pPriv->src_h * dsth) / pPriv->dst_h;
 
+
+	    if (pPriv->is_planar) {
+		/*
+		 * Just render a rect (using three coords).
+		 */
+		VTX_OUT_6((float)dstX,                     (float)(dstY + dsth),
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h,
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_6((float)(dstX + dstw),            (float)(dstY + dsth),
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h,
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_6((float)(dstX + dstw),            (float)dstY,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h);
+	    } else {
+		/*
+		 * Just render a rect (using three coords).
+		 */
+		VTX_OUT_4((float)dstX,                     (float)(dstY + dsth),
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_4((float)(dstX + dstw),            (float)(dstY + dsth),
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_4((float)(dstX + dstw),            (float)dstY,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h);
+	    }
+
+	    pBox++;
+	}
+
+	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+	ADVANCE_RING();
+    }
+#else /* ACCEL_CP */
+    BEGIN_ACCEL(nBox * pPriv->vtx_count * 3 + 2);
+    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
+				      RADEON_VF_PRIM_WALK_DATA |
+				      RADEON_VF_RADEON_MODE |
+				      ((nBox * 3) << RADEON_VF_NUM_VERTICES_SHIFT)));
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
@@ -434,7 +509,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
 
 
-	if (isplanar) {
+	if (pPriv->is_planar) {
 	    /*
 	     * Just render a rect (using three coords).
 	     */
@@ -463,17 +538,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     }
 
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
-#ifdef ACCEL_CP
-	ADVANCE_RING();
-#else
-	FINISH_ACCEL();
+    FINISH_ACCEL();
 #endif /* !ACCEL_CP */
 
     DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
 }
 
-static void
-FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+static Bool
+FUNC_NAME(R200PrepareTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
@@ -483,11 +555,9 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     uint32_t txfilter, txsize, txpitch, txoffset;
     uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
-    Bool isplanar = FALSE;
-    int dstxoff, dstyoff, pixel_shift, vtx_count;
-    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
-    int nBox = REGION_NUM_RECTS(&pPriv->clip);
-
+    int pixel_shift;
+    int scissor_w = MIN(pPixmap->drawable.width, 2047);
+    int scissor_h = MIN(pPixmap->drawable.height, 2047);
     /* note: in contrast to r300, use input biasing on uv components */
     const float Loff = -0.0627;
     float uvcosf, uvsinf;
@@ -515,7 +585,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	ret = radeon_cs_space_check(info->cs);
 	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
-	    return;
+	    return FALSE;
 	}
     }
 #endif
@@ -531,14 +601,6 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_pitch = pPixmap->devKind;
     }
 
-#ifdef COMPOSITE
-    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
-    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
-#else
-    dstxoff = 0;
-    dstyoff = 0;
-#endif
-
 #ifdef USE_EXA
     if (info->useEXA) {
 	RADEON_SWITCH_TO_3D();
@@ -571,13 +633,14 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_format = RADEON_COLOR_FORMAT_ARGB8888;
 	break;
     default:
-	return;
+	return FALSE;
     }
 
     if (pPriv->id == FOURCC_I420 || pPriv->id == FOURCC_YV12) {
-	isplanar = TRUE;
+	pPriv->is_planar = TRUE;
 	txformat = RADEON_TXFORMAT_I8;
     } else {
+	pPriv->is_planar = FALSE;
 	if (pPriv->id == FOURCC_UYVY)
 	    txformat = RADEON_TXFORMAT_YVYU422;
 	else
@@ -640,11 +703,11 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     txoffset = info->cs ? 0 : pPriv->src_offset;
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	/* need 2 texcoord sets (even though they are identical) due
 	   to denormalization! hw apparently can't premultiply
 	   same coord set by different texture size */
-	vtx_count = 6;
+	pPriv->vtx_count = 6;
 
 	txsize = (((((pPriv->w + 1 ) >> 1) - 1) & 0x7ff) |
 		  (((((pPriv->h + 1 ) >> 1) - 1) & 0x7ff) << RADEON_TEX_VSIZE_SHIFT));
@@ -807,7 +870,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
 	FINISH_ACCEL();
     } else {
-	vtx_count = 4;
+	pPriv->vtx_count = 4;
 
 	BEGIN_ACCEL_RELOC(24, 1);
 
@@ -912,15 +975,10 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
     }
 
-    {
-      int scissor_w, scissor_h;
-      scissor_w = MIN(pPixmap->drawable.width, 2047);
-      scissor_h = MIN(pPixmap->drawable.height, 2047);
-      BEGIN_ACCEL(2);
-      OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
-      OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) |
-					     (scissor_h << RADEON_RE_HEIGHT_SHIFT)));
-    }
+    BEGIN_ACCEL(2);
+    OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
+    OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) |
+					   (scissor_h << RADEON_RE_HEIGHT_SHIFT)));
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
@@ -939,6 +997,31 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
     }
+
+    return TRUE;
+}
+
+static void
+FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    PixmapPtr pPixmap = pPriv->pPixmap;
+    int dstxoff, dstyoff;
+    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
+    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    ACCEL_PREAMBLE();
+
+#ifdef COMPOSITE
+    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    dstxoff = 0;
+    dstyoff = 0;
+#endif
+
+    if (!FUNC_NAME(R200PrepareTexturedVideo)(pScrn, pPriv))
+	return;
+
     /*
      * Rendering of the actual polygon is done in two different
      * ways depending on chip generation:
@@ -960,20 +1043,82 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
      */
 
 #ifdef ACCEL_CP
-	BEGIN_RING(nBox * 3 * vtx_count + 4);
+    while (nBox) {
+	int draw_size = 3 * pPriv->vtx_count + 4;
+	int loop_boxes;
+
+	if (draw_size > radeon_cs_space_remaining(pScrn)) {
+	    if (info->cs)
+		radeon_cs_flush_indirect(pScrn);
+	    else
+		RADEONCPFlushIndirect(pScrn, 1);
+	    if (!FUNC_NAME(R200PrepareTexturedVideo)(pScrn, pPriv))
+		return;
+	}
+	loop_boxes = MIN(radeon_cs_space_remaining(pScrn) / draw_size, nBox);
+	nBox -= loop_boxes;
+
+	BEGIN_RING(loop_boxes * 3 * pPriv->vtx_count + 4);
 	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-			    nBox * 3 * vtx_count));
+			    loop_boxes * 3 * pPriv->vtx_count));
 	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
 		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-		 ((nBox * 3) << RADEON_CP_VC_CNTL_NUM_SHIFT));
-#else /* ACCEL_CP */
-	BEGIN_ACCEL(nBox * 3 * vtx_count + 2);
-	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
-					  RADEON_VF_PRIM_WALK_DATA |
-					  ((nBox * 3) << RADEON_VF_NUM_VERTICES_SHIFT)));
+		 ((loop_boxes * 3) << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+	while (loop_boxes--) {
+	    int srcX, srcY, srcw, srch;
+	    int dstX, dstY, dstw, dsth;
+	    dstX = pBox->x1 + dstxoff;
+	    dstY = pBox->y1 + dstyoff;
+	    dstw = pBox->x2 - pBox->x1;
+	    dsth = pBox->y2 - pBox->y1;
+
+	    srcX = pPriv->src_x;
+	    srcX += ((pBox->x1 - pPriv->drw_x) *
+		     pPriv->src_w) / pPriv->dst_w;
+	    srcY = pPriv->src_y;
+	    srcY += ((pBox->y1 - pPriv->drw_y) *
+		     pPriv->src_h) / pPriv->dst_h;
+
+	    srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
+	    srch = (pPriv->src_h * dsth) / pPriv->dst_h;
+
+	    if (pPriv->is_planar) {
+		/*
+		 * Just render a rect (using three coords).
+		 */
+		VTX_OUT_6((float)dstX,                     (float)(dstY + dsth),
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h,
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_6((float)(dstX + dstw),            (float)(dstY + dsth),
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h,
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_6((float)(dstX + dstw),            (float)dstY,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h);
+	    } else {
+		/*
+		 * Just render a rect (using three coords).
+		 */
+		VTX_OUT_4((float)dstX,                     (float)(dstY + dsth),
+			  (float)srcX / pPriv->w,          (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_4((float)(dstX + dstw),            (float)(dstY + dsth),
+			  (float)(srcX + srcw) / pPriv->w, (float)(srcY + srch) / pPriv->h);
+		VTX_OUT_4((float)(dstX + dstw),            (float)dstY,
+			  (float)(srcX + srcw) / pPriv->w, (float)srcY / pPriv->h);
+	    }
 
-#endif
+	    pBox++;
+	}
 
+	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+	ADVANCE_RING();
+    }
+#else /* ACCEL_CP */
+    BEGIN_ACCEL(nBox * 3 * pPriv->vtx_count + 2);
+    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
+				      RADEON_VF_PRIM_WALK_DATA |
+				      ((nBox * 3) << RADEON_VF_NUM_VERTICES_SHIFT)));
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
@@ -992,7 +1137,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
 	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
 
-	if (isplanar) {
+	if (pPriv->is_planar) {
 	    /*
 	     * Just render a rect (using three coords).
 	     */
@@ -1021,18 +1166,14 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     }
 
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
-
-#ifdef ACCEL_CP
-	ADVANCE_RING();
-#else
-	FINISH_ACCEL();
+    FINISH_ACCEL();
 #endif /* !ACCEL_CP */
 
     DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
 }
 
-static void
-FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+static Bool
+FUNC_NAME(R300PrepareTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
@@ -1042,10 +1183,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     uint32_t dst_pitch, dst_format;
     uint32_t txenable, colorpitch, bicubic_offset;
     uint32_t output_fmt;
-    Bool isplanar = FALSE;
-    int dstxoff, dstyoff, pixel_shift, vtx_count;
-    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
-    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int pixel_shift;
     ACCEL_PREAMBLE();
 
 #ifdef XF86DRM_MODE
@@ -1064,7 +1202,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	ret = radeon_cs_space_check(info->cs);
 	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
-	    return;
+	    return FALSE;
 	}
     }
 #endif
@@ -1080,14 +1218,6 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_pitch = pPixmap->devKind;
     }
 
-#ifdef COMPOSITE
-    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
-    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
-#else
-    dstxoff = 0;
-    dstyoff = 0;
-#endif
-
 #ifdef USE_EXA
     if (info->useEXA) {
 	RADEON_SWITCH_TO_3D();
@@ -1109,9 +1239,9 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     }
 
     if (pPriv->bicubic_enabled)
-	vtx_count = 6;
+	pPriv->vtx_count = 6;
     else
-	vtx_count = 4;
+	pPriv->vtx_count = 4;
 
     switch (pPixmap->drawable.bitsPerPixel) {
     case 16:
@@ -1124,7 +1254,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_format = R300_COLORFORMAT_ARGB8888;
 	break;
     default:
-	return;
+	return FALSE;
     }
 
     output_fmt = (R300_OUT_FMT_C4_8 |
@@ -1142,9 +1272,11 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     if (((pPriv->bicubic_state == BICUBIC_OFF)) &&
 	(pPriv->id == FOURCC_I420 || pPriv->id == FOURCC_YV12))
-	isplanar = TRUE;
+	pPriv->is_planar = TRUE;
+    else
+	pPriv->is_planar = FALSE;
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	txformat1 = R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_HALF_REGION_0;
 	txpitch = pPriv->src_pitch;
     } else {
@@ -1177,7 +1309,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     OUT_ACCEL_REG(R300_TX_FILTER0_0, txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0, 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0);
-    if (isplanar)
+    if (pPriv->is_planar)
 	OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1 | R300_TX_FORMAT_CACHE_HALF_REGION_0);
     else
 	OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
@@ -1187,7 +1319,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     txenable = R300_TEX_0_ENABLE;
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	txformat0 = ((((((pPriv->w + 1 ) >> 1) - 1) & 0x7ff) << R300_TXWIDTH_SHIFT) |
 		     (((((pPriv->h + 1 ) >> 1 ) - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT) |
 		     R300_TXPITCH_EN);
@@ -1824,7 +1956,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	       if that's of any use. */
 	}
 
-	if (isplanar) {
+	if (pPriv->is_planar) {
 	    BEGIN_ACCEL(needgamma ? 28 + 33 : 33);
 	    /* 2 components: same 2 for tex0/1/2 */
 	    OUT_ACCEL_REG(R300_RS_COUNT,
@@ -2296,7 +2428,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     /* no need to enable blending */
     OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
 
-    OUT_ACCEL_REG(R300_VAP_VTX_SIZE, vtx_count);
+    OUT_ACCEL_REG(R300_VAP_VTX_SIZE, pPriv->vtx_count);
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
@@ -2315,6 +2447,31 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
     }
+
+    return TRUE;
+}
+
+static void
+FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    PixmapPtr pPixmap = pPriv->pPixmap;
+    int dstxoff, dstyoff;
+    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
+    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    ACCEL_PREAMBLE();
+
+#ifdef COMPOSITE
+    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    dstxoff = 0;
+    dstyoff = 0;
+#endif
+
+    if (!FUNC_NAME(R300PrepareTexturedVideo)(pScrn, pPriv))
+	return;
+
     /*
      * Rendering of the actual polygon is done in two different
      * ways depending on chip generation:
@@ -2339,6 +2496,19 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
 	Bool use_quad = FALSE;
+#ifdef ACCEL_CP
+	int draw_size = 4 * pPriv->vtx_count + 4 + 2 + 3;
+
+	if (draw_size > radeon_cs_space_remaining(pScrn)) {
+	    if (info->cs)
+		radeon_cs_flush_indirect(pScrn);
+	    else
+		RADEONCPFlushIndirect(pScrn, 1);
+	    if (!FUNC_NAME(R300PrepareTexturedVideo)(pScrn, pPriv))
+		return;
+	}
+#endif
+
 	dstX = pBox->x1 + dstxoff;
 	dstY = pBox->y1 + dstyoff;
 	dstw = pBox->x2 - pBox->x1;
@@ -2354,11 +2524,6 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
 	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
 
-#if 0
-	ErrorF("dst: %d, %d, %d, %d\n", dstX, dstY, dstw, dsth);
-	ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch);
-#endif
-
 	if (IS_R400_3D) {
 	    if ((dstw+dsth) > 4021)
 		use_quad = TRUE;
@@ -2379,25 +2544,25 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
 #ifdef ACCEL_CP
 	if (use_quad) {
-	    BEGIN_RING(4 * vtx_count + 4);
+	    BEGIN_RING(4 * pPriv->vtx_count + 4);
 	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-				4 * vtx_count));
+				4 * pPriv->vtx_count));
 	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
 		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	} else {
-	    BEGIN_RING(3 * vtx_count + 4);
+	    BEGIN_RING(3 * pPriv->vtx_count + 4);
 	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-				3 * vtx_count));
+				3 * pPriv->vtx_count));
 	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST |
 		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	}
 #else /* ACCEL_CP */
 	if (use_quad)
-	    BEGIN_ACCEL(2 + vtx_count * 4);
+	    BEGIN_ACCEL(2 + pPriv->vtx_count * 4);
 	else
-	    BEGIN_ACCEL(2 + vtx_count * 3);
+	    BEGIN_ACCEL(2 + pPriv->vtx_count * 3);
 
 	if (use_quad)
 	    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
@@ -2489,8 +2654,8 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
 }
 
-static void
-FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+static Bool
+FUNC_NAME(R500PrepareTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
@@ -2500,10 +2665,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     uint32_t dst_pitch, dst_format;
     uint32_t txenable, colorpitch, bicubic_offset;
     uint32_t output_fmt;
-    Bool isplanar = FALSE;
-    int dstxoff, dstyoff, pixel_shift, vtx_count;
-    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
-    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int pixel_shift;
     ACCEL_PREAMBLE();
 
 #ifdef XF86DRM_MODE
@@ -2522,7 +2684,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	ret = radeon_cs_space_check(info->cs);
 	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
-	    return;
+	    return FALSE;
 	}
     }
 #endif
@@ -2538,14 +2700,6 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_pitch = pPixmap->devKind;
     }
 
-#ifdef COMPOSITE
-    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
-    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
-#else
-    dstxoff = 0;
-    dstyoff = 0;
-#endif
-
 #ifdef USE_EXA
     if (info->useEXA) {
 	RADEON_SWITCH_TO_3D();
@@ -2567,9 +2721,9 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     }
 
     if (pPriv->bicubic_enabled)
-	vtx_count = 6;
+	pPriv->vtx_count = 6;
     else
-	vtx_count = 4;
+	pPriv->vtx_count = 4;
 
     switch (pPixmap->drawable.bitsPerPixel) {
     case 16:
@@ -2582,7 +2736,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	dst_format = R300_COLORFORMAT_ARGB8888;
 	break;
     default:
-	return;
+	return FALSE;
     }
 
     output_fmt = (R300_OUT_FMT_C4_8 |
@@ -2599,9 +2753,11 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     if (((pPriv->bicubic_state == BICUBIC_OFF)) &&
         (pPriv->id == FOURCC_I420 || pPriv->id == FOURCC_YV12))
-	isplanar = TRUE;
+	pPriv->is_planar = TRUE;
+    else
+	pPriv->is_planar = FALSE;
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	txformat1 = R300_TX_FORMAT_X8;
 	txpitch = pPriv->src_pitch;
     } else {
@@ -2648,7 +2804,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     txenable = R300_TEX_0_ENABLE;
 
-    if (isplanar) {
+    if (pPriv->is_planar) {
 	txformat0 = ((((((pPriv->w + 1 ) >> 1) - 1) & 0x7ff) << R300_TXWIDTH_SHIFT) |
 		     (((((pPriv->h + 1 ) >> 1 ) - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT) |
 		     R300_TXPITCH_EN);
@@ -3439,7 +3595,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	       if that's of any use. */
 	}
 
-	if (isplanar) {
+	if (pPriv->is_planar) {
 	    BEGIN_ACCEL(56);
 	    /* 2 components: 2 for tex0 */
 	    OUT_ACCEL_REG(R300_RS_COUNT,
@@ -3880,7 +4036,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     /* no need to enable blending */
     OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
 
-    OUT_ACCEL_REG(R300_VAP_VTX_SIZE, vtx_count);
+    OUT_ACCEL_REG(R300_VAP_VTX_SIZE, pPriv->vtx_count);
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
@@ -3899,6 +4055,31 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
     }
+
+    return TRUE;
+}
+
+static void
+FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    PixmapPtr pPixmap = pPriv->pPixmap;
+    int dstxoff, dstyoff;
+    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
+    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    ACCEL_PREAMBLE();
+
+#ifdef COMPOSITE
+    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    dstxoff = 0;
+    dstyoff = 0;
+#endif
+
+    if (!FUNC_NAME(R500PrepareTexturedVideo)(pScrn, pPriv))
+	return;
+
     /*
      * Rendering of the actual polygon is done in two different
      * ways depending on chip generation:
@@ -3922,6 +4103,19 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
+#ifdef ACCEL_CP
+	int draw_size = 3 * pPriv->vtx_count + 4 + 2 + 3;
+
+	if (draw_size > radeon_cs_space_remaining(pScrn)) {
+	    if (info->cs)
+		radeon_cs_flush_indirect(pScrn);
+	    else
+		RADEONCPFlushIndirect(pScrn, 1);
+	    if (!FUNC_NAME(R500PrepareTexturedVideo)(pScrn, pPriv))
+		return;
+	}
+#endif
+
 	dstX = pBox->x1 + dstxoff;
 	dstY = pBox->y1 + dstyoff;
 	dstw = pBox->x2 - pBox->x1;
@@ -3945,14 +4139,14 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
 
 #ifdef ACCEL_CP
-	BEGIN_RING(3 * vtx_count + 4);
+	BEGIN_RING(3 * pPriv->vtx_count + 4);
 	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-			    3 * vtx_count));
+			    3 * pPriv->vtx_count));
 	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST |
 		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 		 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 #else /* ACCEL_CP */
-	BEGIN_ACCEL(2 + vtx_count * 3);
+	BEGIN_ACCEL(2 + pPriv->vtx_count * 3);
 	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_LIST |
 					  RADEON_VF_PRIM_WALK_DATA |
 					  (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 8f0917f..5e2a723 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -271,10 +271,14 @@ void RADEONInitVideo(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr    info = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
     XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
     int num_adaptors;
 
+    /* no overlay or 3D on RN50 */
+    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
+	    return;
 
     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
     newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
diff --git a/src/radeon_video.h b/src/radeon_video.h
index be3df69..ab0c433 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -118,6 +118,8 @@ typedef struct {
     int drw_x, drw_y;
     int src_x, src_y;
     int vsync;
+    Bool is_planar;
+    int vtx_count;
 
     struct radeon_bo *src_bo[2];
 } RADEONPortPrivRec, *RADEONPortPrivPtr;