diff --git a/src/Makefile.am b/src/Makefile.am
index a7f219c..2aec5a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,6 +69,7 @@ intel_drv_la_SOURCES = \
 	 i965_reg.h \
 	 i965_video.c \
 	 i965_render.c \
+	 intel_sprite.c \
 	 $(NULL)
 
 if DRI
diff --git a/src/intel.h b/src/intel.h
index 2b114c3..11d911a 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -334,6 +334,7 @@ typedef struct intel_screen_private {
 
 	int colorKey;
 	XF86VideoAdaptorPtr adaptor;
+	XF86VideoAdaptorPtr sprite_adaptor;
 	ScreenBlockHandlerProcPtr BlockHandler;
 	Bool overlayOn;
 
@@ -461,6 +462,7 @@ extern void intel_mode_fini(intel_screen_private *intel);
 
 extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
 extern int intel_crtc_id(xf86CrtcPtr crtc);
+extern int intel_crtc_to_sprite(xf86CrtcPtr crtc);
 extern int intel_output_dpms_status(xf86OutputPtr output);
 
 enum DRI2FrameEventType {
@@ -518,6 +520,7 @@ extern void I915EmitInvarientState(ScrnInfoPtr scrn);
 extern void I830EmitFlush(ScrnInfoPtr scrn);
 
 extern void I830InitVideo(ScreenPtr pScreen);
+extern XF86VideoAdaptorPtr intel_setup_sprite(ScreenPtr screen);
 extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
 				      xf86CrtcPtr desired, BoxPtr crtc_box_ret);
 
diff --git a/src/intel_display.c b/src/intel_display.c
index b55b110..4b032af 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -75,6 +75,7 @@ struct intel_crtc {
 	dri_bo *rotate_bo;
 	uint32_t rotate_pitch;
 	uint32_t rotate_fb_id;
+	uint32_t sprite_id;
 	xf86CrtcPtr crtc;
 	struct list link;
 };
@@ -1564,9 +1565,50 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 		drmHandleEvent(mode->fd, &mode->event_context);
 }
 
+static void intel_crtc_find_plane(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
+{
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+	struct intel_crtc *intel_crtc = crtc->driver_private;
+	drmModePlaneRes *plane_resources;
+	drmModePlane *ovr;
+	uint32_t id = 0;
+	int i;
+
+	plane_resources = drmModeGetPlaneResources(intel->drmSubFD);
+	if (!plane_resources) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "failed to get plane resources: %s\n",
+			   strerror(errno));
+		goto out;
+	}
+
+	for (i = 0; i < plane_resources->count_planes; i++) {
+		ovr = drmModeGetPlane(intel->drmSubFD,
+				      plane_resources->planes[i]);
+		if (!ovr) {
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				   "failed to get plane info: %s\n",
+				   strerror(errno));
+			continue;
+		}
+
+		if (ovr->possible_crtcs & (1 << intel_crtc_to_pipe(crtc))) {
+			id = ovr->plane_id;
+			drmModeFreePlane(ovr);
+			break;
+		}
+		drmModeFreePlane(ovr);
+	}
+
+	free(plane_resources);
+out:
+	intel_crtc->sprite_id = id;
+}
+
 Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
+	struct intel_crtc *intel_crtc;
 	struct drm_i915_getparam gp;
 	struct intel_mode *mode;
 	unsigned int i;
@@ -1597,6 +1639,9 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 	for (i = 0; i < mode->mode_res->count_crtcs; i++)
 		intel_crtc_init(scrn, mode, i);
 
+	list_for_each_entry(intel_crtc, &mode->crtcs, link)
+		intel_crtc_find_plane(scrn, intel_crtc->crtc);
+
 	for (i = 0; i < mode->mode_res->count_connectors; i++)
 		intel_output_init(scrn, mode, i);
 
@@ -1618,6 +1663,8 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 	}
 
 	intel->modes = mode;
+
+
 	return TRUE;
 }
 
@@ -1687,3 +1734,9 @@ int intel_crtc_to_pipe(xf86CrtcPtr crtc)
 	struct intel_crtc *intel_crtc = crtc->driver_private;
 	return intel_crtc->pipe;
 }
+
+int intel_crtc_to_sprite(xf86CrtcPtr crtc)
+{
+	struct intel_crtc *intel_crtc = crtc->driver_private;
+	return intel_crtc->sprite_id;
+}
diff --git a/src/intel_sprite.c b/src/intel_sprite.c
new file mode 100644
index 0000000..618a526
--- /dev/null
+++ b/src/intel_sprite.c
@@ -0,0 +1,291 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <xf86drmMode.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+#include "randrstr.h"
+#include "windowstr.h"
+#include "damage.h"
+#include "intel.h"
+#include "intel_video.h"
+#include "i830_reg.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#define IMAGE_MAX_WIDTH		2048
+#define IMAGE_MAX_HEIGHT	2048
+
+static XF86VideoFormatRec xv_formats[] = {
+	{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86ImageRec xv_images[] = {
+	XVIMAGE_YUY2,
+	XVIMAGE_UYVY,
+};
+
+static const XF86VideoEncodingRec xv_dummy_encoding[] = {
+	{
+	 0,
+	 "XV_IMAGE",
+	 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+	 {1, 1}
+	 }
+};
+
+static void intel_sprite_stop(ScrnInfoPtr scrn, pointer data, Bool shutdown)
+{
+}
+
+static int intel_sprite_set_attr(ScrnInfoPtr scrn, Atom attribute, INT32 value,
+				 pointer data)
+{
+	return Success;
+}
+
+static int intel_sprite_get_attr(ScrnInfoPtr scrn, Atom attribute, INT32 *value,
+				 pointer data)
+{
+	return Success;
+}
+
+static void intel_sprite_best_size(ScrnInfoPtr scrn, Bool motion, short vid_w,
+				   short vid_h, short drw_w, short drw_h,
+				   unsigned int *p_w, unsigned int *p_h,
+				   pointer data)
+{
+	*p_w = vid_w;
+	*p_h = vid_h;
+}
+
+static int intel_sprite_put(ScrnInfoPtr scrn, short src_x, short src_y,
+			    short drw_x, short drw_y, short src_w, short src_h,
+			    short drw_w, short drw_h, int id,
+			    unsigned char *buf, short width, short height,
+			    Bool sync, RegionPtr clipBoxes, pointer data,
+			    DrawablePtr drawable)
+{
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+	intel_adaptor_private *adaptor_priv = intel_get_sprite_adaptor_private(intel);
+	dri_bo *new_frame;
+	unsigned char *src, *dst, *dst_base;
+	int pitch, i;
+	xf86CrtcPtr crtc;
+	BoxRec dst_box;
+	int ret, top, left, lines, pixel_width;
+	int plane_id;
+	uint32_t fb_id;
+	unsigned long alloc_pitch;
+
+	ret = intel_clip_video_helper(scrn, adaptor_priv, &crtc, &dst_box,
+				      src_x, src_y, drw_x, drw_y,
+				      src_w, src_h, drw_w, drw_h,
+				      id, &top, &left, &pixel_width, &lines,
+				      clipBoxes, width, height);
+	if (!ret)
+		return Success;
+
+	plane_id = intel_crtc_to_sprite(crtc);
+	if (!plane_id) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "no planes available for crtc\n");
+		return Success;
+	}
+
+	new_frame = adaptor_priv->buf;
+	pitch = ALIGN(pixel_width, 64);
+
+	if (!new_frame) {
+		uint32_t tiling_mode = I915_TILING_X;
+
+		new_frame = drm_intel_bo_alloc_tiled(intel->bufmgr,
+						     "sprite buffer",
+						     pixel_width, lines,
+						     drawable->bitsPerPixel / 8,
+						     &tiling_mode, &alloc_pitch,
+						     BO_ALLOC_FOR_RENDER);
+		if (!new_frame) {
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				   "failed to create bo for video data: %s\n",
+				   strerror(errno));
+			return BadAlloc;
+		}
+		adaptor_priv->reusable = TRUE;
+		adaptor_priv->buf = new_frame;
+	}
+
+	if (drm_intel_gem_bo_map_gtt(new_frame))
+		return BadAlloc;
+
+	dst_base = new_frame->virtual;
+	dst = dst_base + adaptor_priv->YBufOffset;
+
+	src = buf + (top * (width * 2)) + (left << 1);
+
+	for (i = 0; i < height; i++) {
+		memcpy(dst, src, width * 2);
+		src += width * 2;
+		dst += pitch;
+	}
+
+	drm_intel_gem_bo_unmap_gtt(new_frame);
+
+	ret = drmModeAddFB2(intel->drmSubFD, pixel_width, lines,
+			    V4L2_PIX_FMT_RGB32, drawable->depth,
+			    drawable->bitsPerPixel, alloc_pitch,
+			    new_frame->handle, &fb_id);
+	if (ret) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "failed to add fb for video data: %s\n",
+			   strerror(errno));
+		return BadAlloc;
+	}
+
+	ret = drmModeSetPlane(intel->drmSubFD, plane_id, intel_crtc_id(crtc),
+			      fb_id, left, top, 0, 0);
+	if (ret) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "failed to enable plane for video data: %s\n",
+			   strerror(errno));
+		return BadAlloc;
+	}
+
+	return Success;
+}
+
+static int intel_sprite_query_attrs(ScrnInfoPtr scrn, int id, unsigned short *w,
+				    unsigned short *h, int *pitches,
+				    int *offsets)
+{
+	int size;
+
+	if (*w > IMAGE_MAX_WIDTH)
+		*w = IMAGE_MAX_WIDTH;
+	if (*h > IMAGE_MAX_HEIGHT)
+		*h = IMAGE_MAX_HEIGHT;
+
+	*w = (*w + 1) & ~1;
+	if (offsets)
+		offsets[0] = 0;
+
+	switch (id) {
+	case FOURCC_YUY2:
+	default:
+		size = *w << 1;
+		if (pitches)
+			pitches[0] = size;
+		size *= *h;
+		break;
+	}
+
+	return size;
+}
+
+XF86VideoAdaptorPtr intel_setup_sprite(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+	XF86VideoAdaptorPtr adapt;
+	intel_adaptor_private *adaptor_priv;
+	drmModePlaneRes *plane_resources;
+	drmModePlane *planes;
+
+	adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
+		       sizeof(intel_adaptor_private) + sizeof(DevUnion));
+	if (!adapt)
+		goto err;
+
+	plane_resources = drmModeGetPlaneResources(intel->drmSubFD);
+	if (!plane_resources) {
+		xf86DrvMsg(scrn->scrnIndex, X_INFO, "No sprite support\n");
+		goto err_free_adaptor;
+	}
+
+	planes = calloc(plane_resources->count_planes, sizeof(*planes));
+	if (!planes) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Out of memory in %s\n",
+			   __func__);
+		goto err_free_res;
+	}
+
+	adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+	adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ;
+	adapt->name = "Intel(R) Video Sprite";
+	adapt->nEncodings = ARRAY_SIZE(xv_dummy_encoding);
+	adapt->pEncodings = xnfalloc(sizeof(xv_dummy_encoding));
+	memcpy(adapt->pEncodings, xv_dummy_encoding, sizeof(xv_dummy_encoding));
+	adapt->nFormats = ARRAY_SIZE(xv_formats);
+	adapt->pFormats = xv_formats;
+	adapt->nPorts = 1;
+	adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+
+	adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1];
+	adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv);
+
+	adapt->nAttributes = 0;
+	adapt->pAttributes = NULL;
+
+	adapt->nImages = ARRAY_SIZE(xv_images);
+	adapt->pImages = xv_images;
+
+	adapt->PutVideo = NULL;
+	adapt->PutStill = NULL;
+	adapt->GetVideo = NULL;
+	adapt->GetStill = NULL;
+	adapt->StopVideo = intel_sprite_stop;
+	adapt->SetPortAttribute = intel_sprite_set_attr;
+	adapt->GetPortAttribute = intel_sprite_get_attr;
+	adapt->QueryBestSize = intel_sprite_best_size;
+	adapt->PutImage = intel_sprite_put;
+	adapt->QueryImageAttributes = intel_sprite_query_attrs;
+
+	adaptor_priv->textured = FALSE;
+	adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1);
+	adaptor_priv->brightness = -19;	/* (255/219) * -16 */
+	adaptor_priv->contrast = 75;	/* 255/219 * 64 */
+	adaptor_priv->saturation = 146;	/* 128/112 * 128 */
+	adaptor_priv->desired_crtc = NULL;
+	adaptor_priv->buf = NULL;
+	adaptor_priv->old_buf[0] = NULL;
+	adaptor_priv->old_buf[1] = NULL;
+	adaptor_priv->gamma5 = 0xc0c0c0;
+	adaptor_priv->gamma4 = 0x808080;
+	adaptor_priv->gamma3 = 0x404040;
+	adaptor_priv->gamma2 = 0x202020;
+	adaptor_priv->gamma1 = 0x101010;
+	adaptor_priv->gamma0 = 0x080808;
+	adaptor_priv->planes = planes;
+
+	adaptor_priv->rotation = RR_Rotate_0;
+
+	/* gotta uninit this someplace */
+	REGION_NULL(screen, &adaptor_priv->clip);
+
+	intel->sprite_adaptor = adapt;
+
+	free(plane_resources);
+
+	return adapt;
+
+err_free_res:
+	free(plane_resources);
+err_free_adaptor:
+	free(adapt);
+err:
+	return NULL;
+}
diff --git a/src/intel_video.c b/src/intel_video.c
index 021ca5f..c873d34 100644
--- a/src/intel_video.c
+++ b/src/intel_video.c
@@ -337,7 +337,8 @@ void I830InitVideo(ScreenPtr screen)
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
-	XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
+	XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL,
+		spriteAdaptor = NULL;
 	int num_adaptors;
 
 	num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
@@ -345,7 +346,7 @@ void I830InitVideo(ScreenPtr screen)
 	 * adaptors.
 	 */
 	newAdaptors =
-	    malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+	    malloc((num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr *));
 	if (newAdaptors == NULL)
 		return;
 
@@ -388,6 +389,13 @@ void I830InitVideo(ScreenPtr screen)
 		}
 	}
 
+
+	spriteAdaptor = intel_setup_sprite(screen);
+	if (spriteAdaptor) {
+		xf86DrvMsg(scrn->scrnIndex, X_INFO, "Set up video sprite\n");
+		adaptors[num_adaptors++] = spriteAdaptor;
+	}
+
 	if (overlayAdaptor && intel->XvPreferOverlay)
 		adaptors[num_adaptors++] = overlayAdaptor;
 
@@ -405,10 +413,9 @@ void I830InitVideo(ScreenPtr screen)
 		intel->XvEnabled = FALSE;
 	}
 
-#ifdef INTEL_XVMC
 	if (texturedAdaptor)
 		intel_xvmc_adaptor_init(screen);
-#endif
+
 	free(adaptors);
 }
 
@@ -1226,7 +1233,7 @@ intel_display_overlay(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
 					 src_w, src_h, drw_w, drw_h);
 }
 
-static Bool
+Bool
 intel_clip_video_helper(ScrnInfoPtr scrn,
 			intel_adaptor_private *adaptor_priv,
 			xf86CrtcPtr * crtc_ret,
diff --git a/src/intel_video.h b/src/intel_video.h
index f405d40..6dd7f88 100644
--- a/src/intel_video.h
+++ b/src/intel_video.h
@@ -55,6 +55,8 @@ typedef struct {
 	drm_intel_bo *buf, *old_buf[2];
 	Bool reusable;
 
+	struct _drmModePlane *planes;
+
 	Bool textured;
 	Rotation rotation;	/* should remove intel->rotation later */
 
@@ -67,6 +69,12 @@ intel_get_adaptor_private(intel_screen_private *intel)
 	return intel->adaptor->pPortPrivates[0].ptr;
 }
 
+static inline intel_adaptor_private *
+intel_get_sprite_adaptor_private(intel_screen_private *intel)
+{
+	return intel->sprite_adaptor->pPortPrivates[0].ptr;
+}
+
 void I915DisplayVideoTextured(ScrnInfoPtr scrn,
 			      intel_adaptor_private *adaptor_priv,
 			      int id, RegionPtr dstRegion, short width,
@@ -93,3 +101,16 @@ void i965_free_video(ScrnInfoPtr scrn);
 int is_planar_fourcc(int id);
 
 void intel_video_block_handler(intel_screen_private *intel);
+
+extern Bool intel_clip_video_helper(ScrnInfoPtr scrn,
+				    intel_adaptor_private *adaptor_priv,
+				    xf86CrtcPtr * crtc_ret,
+				    BoxPtr dst,
+				    short src_x, short src_y,
+				    short drw_x, short drw_y,
+				    short src_w, short src_h,
+				    short drw_w, short drw_h,
+				    int id,
+				    int *top, int* left, int* npixels,
+				    int *nlines,
+				    RegionPtr reg, INT32 width, INT32 height);
