Home | History | Annotate | Line # | Download | only in src
      1 /***************************************************************************
      2 
      3  Copyright 2000 Intel Corporation.  All Rights Reserved.
      4 
      5  Permission is hereby granted, free of charge, to any person obtaining a
      6  copy of this software and associated documentation files (the
      7  "Software"), to deal in the Software without restriction, including
      8  without limitation the rights to use, copy, modify, merge, publish,
      9  distribute, sub license, and/or sell copies of the Software, and to
     10  permit persons to whom the Software is furnished to do so, subject to
     11  the following conditions:
     12 
     13  The above copyright notice and this permission notice (including the
     14  next paragraph) shall be included in all copies or substantial portions
     15  of the Software.
     16 
     17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     20  IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     21  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     22  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
     23  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24 
     25  **************************************************************************/
     26 
     27 /*
     28  * i830_video.c: i830/i845 Xv driver.
     29  *
     30  * Copyright  2002 by Alan Hourihane and David Dawes
     31  *
     32  * Authors:
     33  *	Alan Hourihane <alanh (at) tungstengraphics.com>
     34  *	David Dawes <dawes (at) xfree86.org>
     35  *
     36  * Derived from i810 Xv driver:
     37  *
     38  * Authors of i810 code:
     39  * 	Jonathan Bian <jonathan.bian (at) intel.com>
     40  *      Offscreen Images:
     41  *        Matt Sottek <matthew.j.sottek (at) intel.com>
     42  */
     43 
     44 /*
     45  * XXX Could support more formats.
     46  */
     47 
     48 #ifdef HAVE_CONFIG_H
     49 #include "config.h"
     50 #endif
     51 
     52 #include <inttypes.h>
     53 #include <math.h>
     54 #include <string.h>
     55 #include <assert.h>
     56 
     57 #include "xf86.h"
     58 #include "xf86_OSproc.h"
     59 #include "compiler.h"
     60 #include "xf86PciInfo.h"
     61 #include "xf86Pci.h"
     62 #include "xf86fbman.h"
     63 #include "regionstr.h"
     64 #include "randrstr.h"
     65 #include "windowstr.h"
     66 #include "damage.h"
     67 #include "i830.h"
     68 #include "i830_video.h"
     69 #include "xf86xv.h"
     70 #include <X11/extensions/Xv.h>
     71 #include "dixstruct.h"
     72 #include "fourcc.h"
     73 
     74 #ifdef INTEL_XVMC
     75 #define _INTEL_XVMC_SERVER_
     76 #include "i830_hwmc.h"
     77 #include "i915_hwmc.h"
     78 #endif
     79 
     80 #define OFF_DELAY 	250		/* milliseconds */
     81 #define FREE_DELAY 	15000
     82 
     83 #define OFF_TIMER 	0x01
     84 #define FREE_TIMER	0x02
     85 #define CLIENT_VIDEO_ON	0x04
     86 
     87 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
     88 
     89 static void I830InitOffscreenImages(ScreenPtr);
     90 
     91 static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr);
     92 static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr);
     93 static void I830StopVideo(ScrnInfoPtr, pointer, Bool);
     94 static int I830SetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
     95 static int I830SetPortAttributeTextured(ScrnInfoPtr, Atom, INT32, pointer);
     96 static int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
     97 static void I830QueryBestSize(ScrnInfoPtr, Bool,
     98 			      short, short, short, short, unsigned int *,
     99 			      unsigned int *, pointer);
    100 static int I830PutImage(ScrnInfoPtr, short, short, short, short, short, short,
    101 			short, short, int, unsigned char *, short, short,
    102 			Bool, RegionPtr, pointer, DrawablePtr);
    103 static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
    104 					   unsigned short *, int *, int *);
    105 
    106 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
    107 
    108 static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
    109 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
    110 static Atom xvSyncToVblank;
    111 
    112 /* Limits for the overlay/textured video source sizes.  The documented hardware
    113  * limits are 2048x2048 or better for overlay and both of our textured video
    114  * implementations.  Additionally, on the 830 and 845, larger sizes resulted in
    115  * the card hanging, so we keep the limits lower there.
    116  */
    117 #define IMAGE_MAX_WIDTH		2048
    118 #define IMAGE_MAX_HEIGHT	2048
    119 #define IMAGE_MAX_WIDTH_LEGACY	1024
    120 #define IMAGE_MAX_HEIGHT_LEGACY	1088
    121 
    122 /* overlay debugging printf function */
    123 #if 0
    124 #define OVERLAY_DEBUG ErrorF
    125 #else
    126 #define OVERLAY_DEBUG if (0) ErrorF
    127 #endif
    128 
    129 /*
    130  * OCMD - Overlay Command Register
    131  */
    132 #define OCMD_REGISTER		0x30168
    133 #define MIRROR_MODE		(0x3<<17)
    134 #define MIRROR_HORIZONTAL	(0x1<<17)
    135 #define MIRROR_VERTICAL		(0x2<<17)
    136 #define MIRROR_BOTH		(0x3<<17)
    137 #define OV_BYTE_ORDER		(0x3<<14)
    138 #define UV_SWAP			(0x1<<14)
    139 #define Y_SWAP			(0x2<<14)
    140 #define Y_AND_UV_SWAP		(0x3<<14)
    141 #define SOURCE_FORMAT		(0xf<<10)
    142 #define RGB_888			(0x1<<10)
    143 #define	RGB_555			(0x2<<10)
    144 #define	RGB_565			(0x3<<10)
    145 #define	YUV_422			(0x8<<10)
    146 #define	YUV_411			(0x9<<10)
    147 #define	YUV_420			(0xc<<10)
    148 #define	YUV_422_PLANAR		(0xd<<10)
    149 #define	YUV_410			(0xe<<10)
    150 #define TVSYNC_FLIP_PARITY	(0x1<<9)
    151 #define TVSYNC_FLIP_ENABLE	(0x1<<7)
    152 #define BUF_TYPE		(0x1<<5)
    153 #define BUF_TYPE_FRAME		(0x0<<5)
    154 #define BUF_TYPE_FIELD		(0x1<<5)
    155 #define TEST_MODE		(0x1<<4)
    156 #define BUFFER_SELECT		(0x3<<2)
    157 #define BUFFER0			(0x0<<2)
    158 #define BUFFER1			(0x1<<2)
    159 #define FIELD_SELECT		(0x1<<1)
    160 #define FIELD0			(0x0<<1)
    161 #define FIELD1			(0x1<<1)
    162 #define OVERLAY_ENABLE		0x1
    163 
    164 #define OFC_UPDATE		0x1
    165 
    166 /* OCONFIG register */
    167 #define CC_OUT_8BIT		(0x1<<3)
    168 #define OVERLAY_PIPE_MASK	(0x1<<18)
    169 #define OVERLAY_PIPE_A		(0x0<<18)
    170 #define OVERLAY_PIPE_B		(0x1<<18)
    171 #define GAMMA2_ENBL		(0x1<<16)
    172 #define CSC_MODE_BT709		(0x1<<5)
    173 #define CSC_MODE_BT601		(0x0<<5)
    174 #define THREE_LINE_BUFFERS	(0x1<<0)
    175 #define TWO_LINE_BUFFERS	(0x0<<0)
    176 
    177 /* DCLRKM register */
    178 #define DEST_KEY_ENABLE		(0x1<<31)
    179 
    180 /* Polyphase filter coefficients */
    181 #define N_HORIZ_Y_TAPS		5
    182 #define N_VERT_Y_TAPS		3
    183 #define N_HORIZ_UV_TAPS		3
    184 #define N_VERT_UV_TAPS		3
    185 #define N_PHASES		17
    186 #define MAX_TAPS		5
    187 
    188 /* Filter cutoff frequency limits. */
    189 #define MIN_CUTOFF_FREQ		1.0
    190 #define MAX_CUTOFF_FREQ		3.0
    191 
    192 #define RGB16ToColorKey(c) \
    193 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
    194 
    195 #define RGB15ToColorKey(c) \
    196 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
    197 
    198 /* client libraries expect an encoding */
    199 static XF86VideoEncodingRec DummyEncoding[1] = {
    200     {
    201 	0,
    202 	"XV_IMAGE",
    203 	IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
    204 	{1, 1}
    205     }
    206 };
    207 
    208 #define NUM_FORMATS 3
    209 
    210 static XF86VideoFormatRec Formats[NUM_FORMATS] = {
    211     {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
    212 };
    213 
    214 #define CLONE_ATTRIBUTES 1
    215 static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
    216     {XvSettable | XvGettable, -1, 1, "XV_PIPE"}
    217 };
    218 
    219 #define NUM_ATTRIBUTES 5
    220 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
    221     {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    222     {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
    223     {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
    224     {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
    225     {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
    226 };
    227 
    228 #define NUM_TEXTURED_ATTRIBUTES 3
    229 static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
    230     {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
    231     {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
    232     {XvSettable | XvGettable, -1, 1, "XV_SYNC_TO_VBLANK"},
    233 };
    234 
    235 #define GAMMA_ATTRIBUTES 6
    236 static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = {
    237     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
    238     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
    239     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
    240     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
    241     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
    242     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
    243 };
    244 
    245 #define NUM_IMAGES 5
    246 
    247 static XF86ImageRec Images[NUM_IMAGES] = {
    248     XVIMAGE_YUY2,
    249     XVIMAGE_YV12,
    250     XVIMAGE_I420,
    251     XVIMAGE_UYVY,
    252 #ifdef INTEL_XVMC
    253     {
    254         /*
    255          * Below, a dummy picture type that is used in XvPutImage only to do
    256          * an overlay update. Introduced for the XvMC client lib.
    257          * Defined to have a zero data size.
    258          */
    259         FOURCC_XVMC,
    260         XvYUV,
    261         LSBFirst,
    262         {'X', 'V', 'M', 'C',
    263          0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
    264          0x38, 0x9B, 0x71},
    265         12,
    266         XvPlanar,
    267         3,
    268         0, 0, 0, 0,
    269         8, 8, 8,
    270         1, 2, 2,
    271         1, 2, 2,
    272         {'Y', 'V', 'U',
    273          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    274          0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    275         XvTopToBottom
    276     },
    277 #endif
    278 };
    279 
    280 typedef struct {
    281     uint32_t OBUF_0Y;
    282     uint32_t OBUF_1Y;
    283     uint32_t OBUF_0U;
    284     uint32_t OBUF_0V;
    285     uint32_t OBUF_1U;
    286     uint32_t OBUF_1V;
    287     uint32_t OSTRIDE;
    288     uint32_t YRGB_VPH;
    289     uint32_t UV_VPH;
    290     uint32_t HORZ_PH;
    291     uint32_t INIT_PHS;
    292     uint32_t DWINPOS;
    293     uint32_t DWINSZ;
    294     uint32_t SWIDTH;
    295     uint32_t SWIDTHSW;
    296     uint32_t SHEIGHT;
    297     uint32_t YRGBSCALE;
    298     uint32_t UVSCALE;
    299     uint32_t OCLRC0;
    300     uint32_t OCLRC1;
    301     uint32_t DCLRKV;
    302     uint32_t DCLRKM;
    303     uint32_t SCLRKVH;
    304     uint32_t SCLRKVL;
    305     uint32_t SCLRKEN;
    306     uint32_t OCONFIG;
    307     uint32_t OCMD;
    308     uint32_t RESERVED1;			/* 0x6C */
    309     uint32_t OSTART_0Y; 		/* for i965 */
    310     uint32_t OSTART_1Y;		/* for i965 */
    311     uint32_t OSTART_0U;
    312     uint32_t OSTART_0V;
    313     uint32_t OSTART_1U;
    314     uint32_t OSTART_1V;
    315     uint32_t OTILEOFF_0Y;
    316     uint32_t OTILEOFF_1Y;
    317     uint32_t OTILEOFF_0U;
    318     uint32_t OTILEOFF_0V;
    319     uint32_t OTILEOFF_1U;
    320     uint32_t OTILEOFF_1V;
    321     uint32_t FASTHSCALE;			/* 0xA0 */
    322     uint32_t UVSCALEV;			/* 0xA4 */
    323 
    324     uint32_t RESERVEDC[(0x200 - 0xA8) / 4];		   /* 0xA8 - 0x1FC */
    325     uint16_t Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES];		   /* 0x200 */
    326     uint16_t RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
    327     uint16_t Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES];		   /* 0x300 */
    328     uint16_t RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
    329     uint16_t UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES];		   /* 0x500 */
    330     uint16_t RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
    331     uint16_t UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES];	   /* 0x600 */
    332     uint16_t RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
    333 } I830OverlayRegRec, *I830OverlayRegPtr;
    334 
    335 #define I830OVERLAYREG(pI830) ((I830OverlayRegPtr)\
    336 			       ((pI830)->FbBase + \
    337 				(pI830)->overlay_regs->offset))
    338 #if VIDEO_DEBUG
    339 static void
    340 CompareOverlay(I830Ptr pI830, uint32_t * overlay, int size)
    341 {
    342     int i;
    343     uint32_t val;
    344     int bad = 0;
    345 
    346     for (i = 0; i < size; i += 4) {
    347 	val = INREG(0x30100 + i);
    348 	if (val != overlay[i / 4]) {
    349 	    OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
    350 			  0x30100 + i, val, overlay[i / 4]);
    351 	    bad++;
    352 	}
    353     }
    354     if (!bad)
    355 	OVERLAY_DEBUG("CompareOverlay: no differences\n");
    356 }
    357 #endif
    358 
    359 static void
    360 I830SetOneLineModeRatio(ScrnInfoPtr pScrn);
    361 
    362 static void
    363 i830_overlay_switch_to_crtc (ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
    364 {
    365     I830Ptr		pI830 = I830PTR(pScrn);
    366     I830PortPrivPtr	pPriv = GET_PORT_PRIVATE(pScrn);
    367     I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
    368     int			pipeconf_reg = intel_crtc->pipe == 0 ? PIPEACONF : PIPEBCONF;
    369 
    370     /* overlay can't be used on pipe with double wide, and pipe must be enabled. */
    371     if ((!IS_I965G(pI830) && (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE))
    372 	    || (intel_crtc->dpms_mode == DPMSModeOff))
    373 	pPriv->overlayOK = FALSE;
    374     else
    375 	pPriv->overlayOK = TRUE;
    376 
    377     if (!pPriv->overlayOK)
    378 	return;
    379 
    380     /* Check we have an LFP connected */
    381     if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
    382     {
    383 
    384 	int	vtotal_reg = intel_crtc->pipe == 0 ? VTOTAL_A : VTOTAL_B;
    385 	uint32_t size = intel_crtc->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
    386 	uint32_t active;
    387 	uint32_t hsize, vsize;
    388 
    389 	hsize = (size >> 16) & 0x7FF;
    390 	vsize = size & 0x7FF;
    391 	active = INREG(vtotal_reg) & 0x7FF;
    392 
    393 	if (vsize < active && hsize > 1024)
    394 	    I830SetOneLineModeRatio(pScrn);
    395 
    396 	if (pPriv->scaleRatio & 0xFFFE0000)
    397 	{
    398 	    /* Possible bogus ratio, using in-accurate fallback */
    399 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    400 		       "Bogus panel fit register, Xvideo positioning may not "
    401 		       "be accurate.\n");
    402 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    403 		       "Using fallback ratio - was 0x%x, now 0x%x\n",
    404 		       pPriv->scaleRatio,
    405 		       (int)(((float)active * 65536)/(float)vsize));
    406 
    407 	    pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
    408 	}
    409     }
    410 }
    411 
    412 /*
    413  * This is more or less the correct way to initalise, update, and shut down
    414  * the overlay.
    415  *
    416  * XXX Need to make sure that the overlay engine is cleanly shutdown in
    417  * all modes of server exit.
    418  */
    419 
    420 static void
    421 i830_overlay_on(ScrnInfoPtr pScrn)
    422 {
    423     I830Ptr		pI830 = I830PTR(pScrn);
    424     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
    425     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    426     Bool		deactivate = FALSE;
    427 
    428     if (pI830->overlayOn)
    429 	return;
    430 
    431     /*
    432      * On I830, if pipe A is off when the overlayis enabled, it will fail to
    433      * turn on and blank the entire screen or lock up the ring. Light up pipe
    434      * A in this case to provide a clock for the overlay hardware
    435      */
    436     if (pPriv->current_crtc && i830_crtc_pipe (pPriv->current_crtc) != 0)
    437 	deactivate = i830_pipe_a_require_activate (pScrn);
    438 
    439     overlay->OCMD &= ~OVERLAY_ENABLE;
    440     BEGIN_BATCH(6);
    441     OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE);
    442     OUT_BATCH(MI_NOOP);
    443     OUT_BATCH(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);
    444     if (OVERLAY_NOPHYSICAL(pI830))
    445 	OUT_BATCH(pI830->overlay_regs->offset | OFC_UPDATE);
    446     else
    447 	OUT_BATCH(pI830->overlay_regs->bus_addr | OFC_UPDATE);
    448     /* Wait for the overlay to light up before attempting to use it */
    449     OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
    450     OUT_BATCH(MI_NOOP);
    451     ADVANCE_BATCH();
    452     I830Sync(pScrn);
    453 
    454     /*
    455      * If we turned pipe A on up above, turn it
    456      * back off
    457      */
    458     if (deactivate)
    459 	i830_pipe_a_require_deactivate (pScrn);
    460 
    461     OVERLAY_DEBUG("overlay_on\n");
    462     pI830->overlayOn = TRUE;
    463 
    464     overlay->OCMD |= OVERLAY_ENABLE;
    465 }
    466 
    467 static void
    468 i830_overlay_continue(ScrnInfoPtr pScrn, Bool update_filter)
    469 {
    470     I830Ptr		pI830 = I830PTR(pScrn);
    471     uint32_t		flip_addr;
    472     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
    473 
    474     if (!pI830->overlayOn)
    475 	return;
    476 
    477     if (OVERLAY_NOPHYSICAL(pI830))
    478 	flip_addr = pI830->overlay_regs->offset;
    479     else
    480 	flip_addr = pI830->overlay_regs->bus_addr;
    481     if (update_filter)
    482 	flip_addr |= OFC_UPDATE;
    483     OVERLAY_DEBUG ("overlay_continue cmd 0x%08x  -> 0x%08x sta 0x%08x\n",
    484 		   overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
    485     BEGIN_BATCH(4);
    486     OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE);
    487     OUT_BATCH(MI_NOOP);
    488     OUT_BATCH(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
    489     OUT_BATCH(flip_addr);
    490     ADVANCE_BATCH();
    491     OVERLAY_DEBUG("overlay_continue\n");
    492 }
    493 
    494 static void
    495 i830_overlay_off(ScrnInfoPtr pScrn)
    496 {
    497     I830Ptr pI830 = I830PTR(pScrn);
    498     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
    499 
    500     if (!pI830->overlayOn)
    501 	return;
    502 
    503     /*
    504      * Wait for overlay to go idle. This has to be
    505      * separated from the turning off state by a Sync
    506      * to ensure the overlay will not read OCMD early and
    507      * disable the overlay before the commands here are
    508      * executed
    509      */
    510     {
    511 	BEGIN_BATCH(2);
    512 	OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
    513 	OUT_BATCH(MI_NOOP);
    514 	ADVANCE_BATCH();
    515 	I830Sync(pScrn);
    516     }
    517 
    518     /*
    519      * Turn overlay off
    520      */
    521     {
    522 	overlay->OCMD &= ~OVERLAY_ENABLE;
    523 	OVERLAY_DEBUG ("overlay_off cmd 0x%08x -> 0x%08x sta 0x%08x\n",
    524 		       overlay->OCMD, INREG(OCMD_REGISTER), INREG(DOVSTA));
    525 	BEGIN_BATCH(6);
    526 	OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE);
    527 	OUT_BATCH(MI_NOOP);
    528 	OUT_BATCH(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);
    529 	if (OVERLAY_NOPHYSICAL(pI830))
    530 	    OUT_BATCH(pI830->overlay_regs->offset);
    531 	else
    532 	    OUT_BATCH(pI830->overlay_regs->bus_addr);
    533 	OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
    534 	OUT_BATCH(MI_NOOP);
    535 	ADVANCE_BATCH();
    536 	I830Sync(pScrn);
    537     }
    538     pI830->overlayOn = FALSE;
    539     OVERLAY_DEBUG("overlay_off\n");
    540 }
    541 
    542 void
    543 I830InitVideo(ScreenPtr pScreen)
    544 {
    545     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    546     I830Ptr pI830 = I830PTR(pScrn);
    547     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
    548     XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
    549     int num_adaptors;
    550 #ifdef INTEL_XVMC
    551     Bool xvmc_status = FALSE;
    552 #endif
    553 
    554 #if 0
    555     {
    556 	I830OverlayRegRec tmp;
    557 
    558 	ErrorF("sizeof I830OverlayRegRec is 0x%x\n", sizeof(I830OverlayRegRec));
    559 	ErrorF("Reserved C, D, E, F, G are %x, %x, %x, %x, %x\n",
    560 	       (unsigned long)&(tmp.RESERVEDC[0]) - (unsigned long)&tmp,
    561 	       (unsigned long)&(tmp.RESERVEDD[0]) - (unsigned long)&tmp,
    562 	       (unsigned long)&(tmp.RESERVEDE[0]) - (unsigned long)&tmp,
    563 	       (unsigned long)&(tmp.RESERVEDF[0]) - (unsigned long)&tmp,
    564 	       (unsigned long)&(tmp.RESERVEDG[0]) - (unsigned long)&tmp);
    565     }
    566 #endif
    567 
    568     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
    569     /* Give our adaptor list enough space for the overlay and/or texture video
    570      * adaptors.
    571      */
    572     newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
    573     if (newAdaptors == NULL)
    574 	return;
    575 
    576     memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
    577     adaptors = newAdaptors;
    578 
    579     /* Add the adaptors supported by our hardware.  First, set up the atoms
    580      * that will be used by both output adaptors.
    581      */
    582     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    583     xvContrast = MAKE_ATOM("XV_CONTRAST");
    584 
    585     /* Set up textured video if we can do it at this depth and we are on
    586      * supported hardware.
    587      */
    588     if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) &&
    589 	!(!IS_I965G(pI830) && pScrn->displayWidth > 2048))
    590     {
    591 	texturedAdaptor = I830SetupImageVideoTextured(pScreen);
    592 	if (texturedAdaptor != NULL) {
    593 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
    594 	} else {
    595 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    596 		       "Failed to set up textured video\n");
    597 	}
    598     }
    599 
    600     /* Set up overlay video if we can do it at this depth. */
    601     if (!OVERLAY_NOEXIST(pI830) && pScrn->bitsPerPixel != 8 &&
    602 	!pI830->use_drm_mode && pI830->overlay_regs != NULL)
    603     {
    604 	overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
    605 	if (overlayAdaptor != NULL) {
    606 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
    607 	} else {
    608 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    609 		       "Failed to set up overlay video\n");
    610 	}
    611 	I830InitOffscreenImages(pScreen);
    612     }
    613 
    614     if (overlayAdaptor && pI830->XvPreferOverlay)
    615        adaptors[num_adaptors++] = overlayAdaptor;
    616 
    617     if (texturedAdaptor)
    618        adaptors[num_adaptors++] = texturedAdaptor;
    619 
    620     if (overlayAdaptor && !pI830->XvPreferOverlay)
    621        adaptors[num_adaptors++] = overlayAdaptor;
    622 
    623 #ifdef INTEL_XVMC
    624     if (intel_xvmc_probe(pScrn)) {
    625 	if (texturedAdaptor)
    626 	    xvmc_status = intel_xvmc_driver_init(pScreen, texturedAdaptor);
    627     }
    628 #endif
    629 
    630     if (num_adaptors) {
    631 	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
    632     } else {
    633 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    634 		   "Disabling Xv because no adaptors could be initialized.\n");
    635 	pI830->XvEnabled = FALSE;
    636     }
    637 
    638 #ifdef INTEL_XVMC
    639     if (xvmc_status)
    640 	intel_xvmc_screen_init(pScreen);
    641 #endif
    642     xfree(adaptors);
    643 }
    644 
    645 static void
    646 I830ResetVideo(ScrnInfoPtr pScrn)
    647 {
    648     I830Ptr pI830 = I830PTR(pScrn);
    649     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    650     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
    651 
    652     OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
    653 		  pI830->FbBase, pI830->overlay_regs->offset, overlay);
    654     /*
    655      * Default to maximum image size in YV12
    656      */
    657 
    658     memset(overlay, 0, sizeof(*overlay));
    659     overlay->YRGB_VPH = 0;
    660     overlay->UV_VPH = 0;
    661     overlay->HORZ_PH = 0;
    662     overlay->INIT_PHS = 0;
    663     overlay->DWINPOS = 0;
    664     overlay->DWINSZ = 0;
    665     overlay->SWIDTH = 0;
    666     overlay->SWIDTHSW = 0;
    667     overlay->SHEIGHT = 0;
    668     overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
    669     overlay->OCLRC1 = pPriv->saturation;
    670 #if 0
    671     overlay->AWINPOS = 0;
    672     overlay->AWINSZ = 0;
    673 #endif
    674     overlay->FASTHSCALE = 0;
    675 
    676     /*
    677      * Enable destination color keying
    678      */
    679     switch (pScrn->depth) {
    680     case 8:
    681 	overlay->DCLRKV = 0;
    682 	overlay->DCLRKM = 0xffffff | DEST_KEY_ENABLE;
    683 	break;
    684     case 15:
    685 	overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
    686 	overlay->DCLRKM = 0x070707 | DEST_KEY_ENABLE;
    687 	break;
    688     case 16:
    689 	overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
    690 	overlay->DCLRKM = 0x070307 | DEST_KEY_ENABLE;
    691 	break;
    692     default:
    693 	overlay->DCLRKV = pPriv->colorKey;
    694 	overlay->DCLRKM = DEST_KEY_ENABLE;
    695 	break;
    696     }
    697 
    698     overlay->SCLRKVH = 0;
    699     overlay->SCLRKVL = 0;
    700     overlay->SCLRKEN = 0;		/* source color key disable */
    701     overlay->OCONFIG = CC_OUT_8BIT;
    702     if (IS_I965GM(pI830))
    703 	overlay->OCONFIG |= CSC_MODE_BT709;
    704 
    705     /*
    706      * Select which pipe the overlay is enabled on.
    707      */
    708     overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
    709     if (i830_crtc_pipe (pPriv->current_crtc) == 0)
    710 	overlay->OCONFIG |= OVERLAY_PIPE_A;
    711     else
    712 	overlay->OCONFIG |= OVERLAY_PIPE_B;
    713 
    714 #if 0
    715     /*
    716      * XXX DUMP REGISTER CODE !!!
    717      * This allows us to dump the complete i845 registers and compare
    718      * with warm boot situations before we upload our first copy.
    719      */
    720     {
    721 	int i;
    722 	for (i = 0x30000; i < 0x31000; i += 4)
    723 	    ErrorF("0x%x 0x%" PRIx32 "\n", i, INREG(i));
    724     }
    725 #endif
    726 }
    727 
    728 #define PFIT_CONTROLS 0x61230
    729 #define PFIT_AUTOVSCALE_MASK 0x200
    730 #define PFIT_ON_MASK 0x80000000
    731 #define PFIT_AUTOSCALE_RATIO 0x61238
    732 #define PFIT_PROGRAMMED_SCALE_RATIO 0x61234
    733 
    734 static void
    735 I830SetOneLineModeRatio(ScrnInfoPtr pScrn)
    736 {
    737     I830Ptr pI830 = I830PTR(pScrn);
    738     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    739     uint32_t panelFitControl = INREG(PFIT_CONTROLS);
    740     int vertScale;
    741 
    742     pPriv->scaleRatio = 0x10000;
    743 
    744     if (panelFitControl & PFIT_ON_MASK) {
    745 	if (panelFitControl & PFIT_AUTOVSCALE_MASK) {
    746 	    vertScale = INREG(PFIT_AUTOSCALE_RATIO) >> 16;
    747 	} else {
    748 	    vertScale = INREG(PFIT_PROGRAMMED_SCALE_RATIO) >> 16;
    749 	}
    750 
    751 	if (vertScale != 0)
    752 	    pPriv->scaleRatio = ((double) 0x10000 / (double)vertScale) * 0x10000;
    753 
    754 	pPriv->oneLineMode = TRUE;
    755 
    756 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Xvideo one-line mode\n");
    757     }
    758 
    759     if (pPriv->scaleRatio == 0x10000)
    760 	pPriv->oneLineMode = FALSE;
    761 }
    762 
    763 static uint32_t I830BoundGammaElt (uint32_t elt, uint32_t eltPrev)
    764 {
    765     elt &= 0xff;
    766     eltPrev &= 0xff;
    767     if (elt < eltPrev)
    768 	elt = eltPrev;
    769     else if ((elt - eltPrev) > 0x7e)
    770 	elt = eltPrev + 0x7e;
    771     return elt;
    772 }
    773 
    774 static uint32_t I830BoundGamma (uint32_t gamma, uint32_t gammaPrev)
    775 {
    776     return (I830BoundGammaElt (gamma >> 16, gammaPrev >> 16) << 16 |
    777 	    I830BoundGammaElt (gamma >>  8, gammaPrev >>  8) <<  8 |
    778 	    I830BoundGammaElt (gamma      , gammaPrev      ));
    779 }
    780 
    781 static uint32_t I830Gamma5Errata(uint32_t gamma)
    782 {
    783     int i;
    784 
    785     for (i = 0; i < 3; i++) {
    786 	if ((gamma >> i*8 & 0xff) == 0x80) {
    787 	    /* According to Intel docs, overlay fails if GAMMA5 is 0x80.
    788 	     * In this case, change the value to 0x81 */
    789 	    gamma += 1 << i*8;
    790 	}
    791     }
    792 
    793     return gamma;
    794 }
    795 
    796 static void
    797 I830UpdateGamma(ScrnInfoPtr pScrn)
    798 {
    799     I830Ptr pI830 = I830PTR(pScrn);
    800     I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    801     uint32_t gamma0 = pPriv->gamma0;
    802     uint32_t gamma1 = pPriv->gamma1;
    803     uint32_t gamma2 = pPriv->gamma2;
    804     uint32_t gamma3 = pPriv->gamma3;
    805     uint32_t gamma4 = pPriv->gamma4;
    806     uint32_t gamma5 = pPriv->gamma5;
    807 
    808 #if 0
    809     ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
    810 	    gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
    811 #endif
    812     gamma1 = I830BoundGamma (gamma1, gamma0);
    813     gamma2 = I830BoundGamma (gamma2, gamma1);
    814     gamma3 = I830BoundGamma (gamma3, gamma2);
    815     gamma4 = I830BoundGamma (gamma4, gamma3);
    816     gamma5 = I830BoundGamma (gamma5, gamma4);
    817     gamma5 = I830Gamma5Errata(gamma5);
    818 #if 0
    819     ErrorF ("Bounded  gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
    820 	    gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
    821 #endif
    822 
    823     OUTREG(OGAMC5, gamma5);
    824     OUTREG(OGAMC4, gamma4);
    825     OUTREG(OGAMC3, gamma3);
    826     OUTREG(OGAMC2, gamma2);
    827     OUTREG(OGAMC1, gamma1);
    828     OUTREG(OGAMC0, gamma0);
    829 }
    830 
    831 static XF86VideoAdaptorPtr
    832 I830SetupImageVideoOverlay(ScreenPtr pScreen)
    833 {
    834     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    835     I830Ptr pI830 = I830PTR(pScrn);
    836     XF86VideoAdaptorPtr adapt;
    837     I830PortPrivPtr pPriv;
    838     XF86AttributePtr att;
    839 
    840     OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
    841 
    842     if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
    843 			  sizeof(I830PortPrivRec) + sizeof(DevUnion))))
    844 	return NULL;
    845 
    846     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
    847     adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
    848     adapt->name = "Intel(R) Video Overlay";
    849     adapt->nEncodings = 1;
    850     adapt->pEncodings = DummyEncoding;
    851     /* update the DummyEncoding for these two chipsets */
    852     if (IS_845G(pI830) || IS_I830(pI830)) {
    853 	adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
    854 	adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
    855     }
    856     adapt->nFormats = NUM_FORMATS;
    857     adapt->pFormats = Formats;
    858     adapt->nPorts = 1;
    859     adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
    860 
    861     pPriv = (I830PortPrivPtr) (&adapt->pPortPrivates[1]);
    862 
    863     adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
    864     adapt->nAttributes = NUM_ATTRIBUTES;
    865     adapt->nAttributes += CLONE_ATTRIBUTES;
    866     if (IS_I9XX(pI830))
    867 	adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
    868     adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
    869     /* Now copy the attributes */
    870     att = adapt->pAttributes;
    871     memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
    872     att+=NUM_ATTRIBUTES;
    873     memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
    874     att+=CLONE_ATTRIBUTES;
    875     if (IS_I9XX(pI830)) {
    876 	memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
    877 	att+=GAMMA_ATTRIBUTES;
    878     }
    879     adapt->nImages = NUM_IMAGES;
    880     adapt->pImages = Images;
    881     adapt->PutVideo = NULL;
    882     adapt->PutStill = NULL;
    883     adapt->GetVideo = NULL;
    884     adapt->GetStill = NULL;
    885     adapt->StopVideo = I830StopVideo;
    886     adapt->SetPortAttribute = I830SetPortAttributeOverlay;
    887     adapt->GetPortAttribute = I830GetPortAttribute;
    888     adapt->QueryBestSize = I830QueryBestSize;
    889     adapt->PutImage = I830PutImage;
    890     adapt->QueryImageAttributes = I830QueryImageAttributes;
    891 
    892     pPriv->textured = FALSE;
    893     pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1);
    894     pPriv->videoStatus = 0;
    895     pPriv->brightness = -19; /* (255/219) * -16 */
    896     pPriv->contrast = 75;  /* 255/219 * 64 */
    897     pPriv->saturation = 146; /* 128/112 * 128 */
    898     pPriv->current_crtc = NULL;
    899     pPriv->desired_crtc = NULL;
    900     pPriv->buf = NULL;
    901     pPriv->currentBuf = 0;
    902     pPriv->gamma5 = 0xc0c0c0;
    903     pPriv->gamma4 = 0x808080;
    904     pPriv->gamma3 = 0x404040;
    905     pPriv->gamma2 = 0x202020;
    906     pPriv->gamma1 = 0x101010;
    907     pPriv->gamma0 = 0x080808;
    908     pPriv->doubleBuffer = 1;
    909 
    910     pPriv->rotation = RR_Rotate_0;
    911 
    912     /* gotta uninit this someplace */
    913     REGION_NULL(pScreen, &pPriv->clip);
    914 
    915     pI830->adaptor = adapt;
    916 
    917     /* With LFP's we need to detect whether we're in One Line Mode, which
    918      * essentially means a resolution greater than 1024x768, and fix up
    919      * the scaler accordingly. */
    920     pPriv->scaleRatio = 0x10000;
    921     pPriv->oneLineMode = FALSE;
    922 
    923     /*
    924      * Initialise pPriv->overlayOK.  Set it to TRUE here so that a warning will
    925      * be generated if i830_crtc_dpms_video() sets it to FALSE during mode
    926      * setup.
    927      */
    928     pPriv->overlayOK = TRUE;
    929 
    930     xvColorKey = MAKE_ATOM("XV_COLORKEY");
    931     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    932     xvContrast = MAKE_ATOM("XV_CONTRAST");
    933     xvSaturation = MAKE_ATOM("XV_SATURATION");
    934     xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
    935 
    936     /* Allow the pipe to be switched from pipe A to B when in clone mode */
    937     xvPipe = MAKE_ATOM("XV_PIPE");
    938 
    939     if (IS_I9XX(pI830)) {
    940 	xvGamma0 = MAKE_ATOM("XV_GAMMA0");
    941 	xvGamma1 = MAKE_ATOM("XV_GAMMA1");
    942 	xvGamma2 = MAKE_ATOM("XV_GAMMA2");
    943 	xvGamma3 = MAKE_ATOM("XV_GAMMA3");
    944 	xvGamma4 = MAKE_ATOM("XV_GAMMA4");
    945 	xvGamma5 = MAKE_ATOM("XV_GAMMA5");
    946     }
    947 
    948     I830ResetVideo(pScrn);
    949 
    950     I830UpdateGamma(pScrn);
    951 
    952     return adapt;
    953 }
    954 
    955 static XF86VideoAdaptorPtr
    956 I830SetupImageVideoTextured(ScreenPtr pScreen)
    957 {
    958     XF86VideoAdaptorPtr adapt;
    959     XF86AttributePtr attrs;
    960     I830PortPrivPtr portPrivs;
    961     DevUnion *devUnions;
    962     int nports = 16, i;
    963     int nAttributes;
    964 
    965     OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
    966 
    967     nAttributes = NUM_TEXTURED_ATTRIBUTES;
    968 
    969     adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec));
    970     portPrivs = xcalloc(nports, sizeof(I830PortPrivRec));
    971     devUnions = xcalloc(nports, sizeof(DevUnion));
    972     attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec));
    973     if (adapt == NULL || portPrivs == NULL || devUnions == NULL ||
    974 	attrs == NULL)
    975     {
    976 	xfree(adapt);
    977 	xfree(portPrivs);
    978 	xfree(devUnions);
    979 	xfree(attrs);
    980 	return NULL;
    981     }
    982 
    983     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
    984     adapt->flags = 0;
    985     adapt->name = "Intel(R) Textured Video";
    986     adapt->nEncodings = 1;
    987     adapt->pEncodings = DummyEncoding;
    988     adapt->nFormats = NUM_FORMATS;
    989     adapt->pFormats = Formats;
    990     adapt->nPorts = nports;
    991     adapt->pPortPrivates = devUnions;
    992     adapt->nAttributes = nAttributes;
    993     adapt->pAttributes = attrs;
    994     memcpy(attrs, TexturedAttributes, nAttributes * sizeof(XF86AttributeRec));
    995     adapt->nImages = NUM_IMAGES;
    996     adapt->pImages = Images;
    997     adapt->PutVideo = NULL;
    998     adapt->PutStill = NULL;
    999     adapt->GetVideo = NULL;
   1000     adapt->GetStill = NULL;
   1001     adapt->StopVideo = I830StopVideo;
   1002     adapt->SetPortAttribute = I830SetPortAttributeTextured;
   1003     adapt->GetPortAttribute = I830GetPortAttribute;
   1004     adapt->QueryBestSize = I830QueryBestSize;
   1005     adapt->PutImage = I830PutImage;
   1006     adapt->QueryImageAttributes = I830QueryImageAttributes;
   1007 
   1008     for (i = 0; i < nports; i++) {
   1009 	I830PortPrivPtr pPriv = &portPrivs[i];
   1010 
   1011 	pPriv->textured = TRUE;
   1012 	pPriv->videoStatus = 0;
   1013 	pPriv->buf = NULL;
   1014 	pPriv->currentBuf = 0;
   1015 	pPriv->doubleBuffer = 0;
   1016 
   1017 	pPriv->rotation = RR_Rotate_0;
   1018 	pPriv->SyncToVblank = 1;
   1019 
   1020 	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
   1021 	REGION_NULL(pScreen, &pPriv->clip);
   1022 
   1023 	adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
   1024     }
   1025 
   1026     xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
   1027 
   1028     return adapt;
   1029 }
   1030 
   1031 static void
   1032 I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
   1033 {
   1034     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
   1035 
   1036     if (pPriv->textured)
   1037 	return;
   1038 
   1039     OVERLAY_DEBUG("I830StopVideo\n");
   1040 
   1041     REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
   1042 
   1043     if (shutdown) {
   1044 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
   1045 	    i830_overlay_off(pScrn);
   1046 	}
   1047 
   1048 	if (pPriv->buf) {
   1049 	    drm_intel_bo_unpin(pPriv->buf);
   1050 	    drm_intel_bo_unreference(pPriv->buf);
   1051 	    pPriv->buf = NULL;
   1052 	    pPriv->videoStatus = 0;
   1053 	}
   1054     } else {
   1055 	if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
   1056 	    pPriv->videoStatus |= OFF_TIMER;
   1057 	    pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
   1058 	}
   1059     }
   1060 
   1061 }
   1062 
   1063 static int
   1064 I830SetPortAttributeTextured(ScrnInfoPtr pScrn,
   1065 			     Atom attribute, INT32 value, pointer data)
   1066 {
   1067     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
   1068 
   1069     if (attribute == xvBrightness) {
   1070 	if ((value < -128) || (value > 127))
   1071 	    return BadValue;
   1072 	pPriv->brightness = value;
   1073 	return Success;
   1074     } else if (attribute == xvContrast) {
   1075 	if ((value < 0) || (value > 255))
   1076 	    return BadValue;
   1077 	pPriv->contrast = value;
   1078 	return Success;
   1079     } else if (attribute == xvSyncToVblank) {
   1080         if ((value < -1) || (value > 1))
   1081             return BadValue;
   1082 
   1083         pPriv->SyncToVblank = value;
   1084         return Success;
   1085     } else {
   1086 	return BadMatch;
   1087     }
   1088 }
   1089 
   1090 static int
   1091 I830SetPortAttributeOverlay(ScrnInfoPtr pScrn,
   1092 		     Atom attribute, INT32 value, pointer data)
   1093 {
   1094     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
   1095     I830Ptr pI830 = I830PTR(pScrn);
   1096     I830OverlayRegPtr overlay;
   1097 
   1098     overlay = I830OVERLAYREG(pI830);
   1099 
   1100     if (attribute == xvBrightness) {
   1101 	if ((value < -128) || (value > 127))
   1102 	    return BadValue;
   1103 	pPriv->brightness = value;
   1104 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
   1105 	OVERLAY_DEBUG("BRIGHTNESS\n");
   1106 	i830_overlay_continue (pScrn, FALSE);
   1107     } else if (attribute == xvContrast) {
   1108 	if ((value < 0) || (value > 255))
   1109 	    return BadValue;
   1110 	pPriv->contrast = value;
   1111 	overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
   1112 	OVERLAY_DEBUG("CONTRAST\n");
   1113 	i830_overlay_continue (pScrn, FALSE);
   1114     } else if (attribute == xvSaturation) {
   1115 	if ((value < 0) || (value > 1023))
   1116 	    return BadValue;
   1117 	pPriv->saturation = value;
   1118 	overlay->OCLRC1 = pPriv->saturation;
   1119 	i830_overlay_continue (pScrn, FALSE);
   1120     } else if (attribute == xvPipe) {
   1121 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1122 	if ((value < -1) || (value > xf86_config->num_crtc))
   1123 	    return BadValue;
   1124 	if (value < 0)
   1125 	    pPriv->desired_crtc = NULL;
   1126 	else
   1127 	    pPriv->desired_crtc = xf86_config->crtc[value];
   1128 	/*
   1129 	 * Leave this to be updated at the next frame
   1130 	 */
   1131     } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
   1132 	pPriv->gamma0 = value;
   1133     } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
   1134 	pPriv->gamma1 = value;
   1135     } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
   1136 	pPriv->gamma2 = value;
   1137     } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
   1138 	pPriv->gamma3 = value;
   1139     } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
   1140 	pPriv->gamma4 = value;
   1141     } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
   1142 	pPriv->gamma5 = value;
   1143     } else if (attribute == xvColorKey) {
   1144 	pPriv->colorKey = value;
   1145 	switch (pScrn->depth) {
   1146 	case 16:
   1147 	    overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
   1148 	    break;
   1149 	case 15:
   1150 	    overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
   1151 	    break;
   1152 	default:
   1153 	    overlay->DCLRKV = pPriv->colorKey;
   1154 	    break;
   1155 	}
   1156 	OVERLAY_DEBUG("COLORKEY\n");
   1157 	i830_overlay_continue (pScrn, FALSE);
   1158 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
   1159     } else if(attribute == xvDoubleBuffer) {
   1160 	if ((value < 0) || (value > 1))
   1161 	    return BadValue;
   1162 	/* Do not allow buffer change while playing video */
   1163 	if(!pI830->overlayOn)
   1164 	    pPriv->doubleBuffer = value;
   1165     } else
   1166 	return BadMatch;
   1167 
   1168     /* Ensure that the overlay is off, ready for updating */
   1169     if ((attribute == xvGamma0 ||
   1170 	 attribute == xvGamma1 ||
   1171 	 attribute == xvGamma2 ||
   1172 	 attribute == xvGamma3 ||
   1173 	 attribute == xvGamma4 ||
   1174 	 attribute == xvGamma5) && (IS_I9XX(pI830))) {
   1175 	OVERLAY_DEBUG("GAMMA\n");
   1176 	I830UpdateGamma(pScrn);
   1177     }
   1178 
   1179     return Success;
   1180 }
   1181 
   1182 static int
   1183 I830GetPortAttribute(ScrnInfoPtr pScrn,
   1184 		     Atom attribute, INT32 * value, pointer data)
   1185 {
   1186     I830Ptr pI830 = I830PTR(pScrn);
   1187     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
   1188 
   1189     if (attribute == xvBrightness) {
   1190 	*value = pPriv->brightness;
   1191     } else if (attribute == xvContrast) {
   1192 	*value = pPriv->contrast;
   1193     } else if (attribute == xvSaturation) {
   1194 	*value = pPriv->saturation;
   1195     } else if (attribute == xvPipe) {
   1196 	int		c;
   1197 	xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1198 	for (c = 0; c < xf86_config->num_crtc; c++)
   1199 	    if (xf86_config->crtc[c] == pPriv->desired_crtc)
   1200 		break;
   1201 	if (c == xf86_config->num_crtc)
   1202 	    c = -1;
   1203 	*value = c;
   1204     } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
   1205 	*value = pPriv->gamma0;
   1206     } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
   1207 	*value = pPriv->gamma1;
   1208     } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
   1209 	*value = pPriv->gamma2;
   1210     } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
   1211 	*value = pPriv->gamma3;
   1212     } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
   1213 	*value = pPriv->gamma4;
   1214     } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
   1215 	*value = pPriv->gamma5;
   1216     } else if (attribute == xvColorKey) {
   1217 	*value = pPriv->colorKey;
   1218     } else if (attribute == xvDoubleBuffer) {
   1219 	*value = pPriv->doubleBuffer;
   1220     } else if (attribute == xvSyncToVblank) {
   1221         *value = pPriv->SyncToVblank;
   1222     } else
   1223 	return BadMatch;
   1224 
   1225     return Success;
   1226 }
   1227 
   1228 static void
   1229 I830QueryBestSize(ScrnInfoPtr pScrn,
   1230 		  Bool motion,
   1231 		  short vid_w, short vid_h,
   1232 		  short drw_w, short drw_h,
   1233 		  unsigned int *p_w, unsigned int *p_h, pointer data)
   1234 {
   1235     if (vid_w > (drw_w << 1))
   1236 	drw_w = vid_w >> 1;
   1237     if (vid_h > (drw_h << 1))
   1238 	drw_h = vid_h >> 1;
   1239 
   1240     *p_w = drw_w;
   1241     *p_h = drw_h;
   1242 }
   1243 
   1244 static void
   1245 I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
   1246 		   unsigned char *buf,
   1247 		   int srcPitch,
   1248 		   int dstPitch, int top, int left, int h, int w)
   1249 {
   1250     I830Ptr pI830 = I830PTR(pScrn);
   1251     unsigned char *src, *dst, *dst_base;
   1252     int i,j;
   1253     unsigned char *s;
   1254 
   1255 #if 0
   1256     ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
   1257 	   "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
   1258 	   srcPitch, dstPitch);
   1259 #endif
   1260 
   1261     src = buf + (top * srcPitch) + (left << 1);
   1262 
   1263     if (pPriv->textured) {
   1264 	drm_intel_bo_map(pPriv->buf, TRUE);
   1265 	dst_base = pPriv->buf->virtual;
   1266     } else {
   1267 	drm_intel_gem_bo_start_gtt_access(pPriv->buf, TRUE);
   1268 	dst_base = pI830->FbBase;
   1269     }
   1270 
   1271     if (pPriv->currentBuf == 0)
   1272 	dst = dst_base + pPriv->YBuf0offset;
   1273     else
   1274 	dst = dst_base + pPriv->YBuf1offset;
   1275 
   1276     switch (pPriv->rotation) {
   1277     case RR_Rotate_0:
   1278 	w <<= 1;
   1279 	for (i = 0; i < h; i++) {
   1280 	    memcpy(dst, src, w);
   1281 	    src += srcPitch;
   1282 	    dst += dstPitch;
   1283 	}
   1284 	break;
   1285     case RR_Rotate_90:
   1286 	h <<= 1;
   1287 	for (i = 0; i < h; i+=2) {
   1288 	    s = src;
   1289 	    for (j = 0; j < w; j++) {
   1290 		/* Copy Y */
   1291 		dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++;
   1292 		(void)*s++;
   1293 	    }
   1294 	    src += srcPitch;
   1295 	}
   1296 	h >>= 1;
   1297 	src = buf + (top * srcPitch) + (left << 1);
   1298 	for (i = 0; i < h; i+=2) {
   1299 	    for (j = 0; j < w; j+=2) {
   1300 		/* Copy U */
   1301 		dst[((i*2) + 1) + ((w - j - 1) * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
   1302 		dst[((i*2) + 1) + ((w - j - 2) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
   1303 		/* Copy V */
   1304 		dst[((i*2) + 3) + ((w - j - 1) * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
   1305 		dst[((i*2) + 3) + ((w - j - 2) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
   1306 	    }
   1307 	}
   1308 	break;
   1309     case RR_Rotate_180:
   1310 	w <<= 1;
   1311 	for (i = 0; i < h; i++) {
   1312 	    s = src;
   1313 	    for (j = 0; j < w; j+=4) {
   1314 		dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++;
   1315 		dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++;
   1316 		dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++;
   1317 		dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++;
   1318 	    }
   1319 	    src += srcPitch;
   1320 	}
   1321 	break;
   1322     case RR_Rotate_270:
   1323 	h <<= 1;
   1324 	for (i = 0; i < h; i+=2) {
   1325 	    s = src;
   1326 	    for (j = 0; j < w; j++) {
   1327 		/* Copy Y */
   1328 		dst[(h - i - 2) + (j * dstPitch)] = *s++;
   1329 		(void)*s++;
   1330 	    }
   1331 	    src += srcPitch;
   1332 	}
   1333 	h >>= 1;
   1334 	src = buf + (top * srcPitch) + (left << 1);
   1335 	for (i = 0; i < h; i+=2) {
   1336 	    for (j = 0; j < w; j+=2) {
   1337 		/* Copy U */
   1338 		dst[(((h - i)*2) - 3) + (j * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
   1339 		dst[(((h - i)*2) - 3) + ((j - 1) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
   1340 		/* Copy V */
   1341 		dst[(((h - i)*2) - 1) + (j * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
   1342 		dst[(((h - i)*2) - 1) + ((j - 1) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
   1343 	    }
   1344 	}
   1345 	break;
   1346     }
   1347 
   1348     if (pPriv->textured)
   1349 	drm_intel_bo_unmap(pPriv->buf);
   1350 }
   1351 
   1352 static void
   1353 I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv,
   1354 		   unsigned char *buf, int srcPitch,
   1355 		   int srcPitch2, int dstPitch, int srcH, int top, int left,
   1356 		   int h, int w, int id)
   1357 {
   1358     I830Ptr pI830 = I830PTR(pScrn);
   1359     int i, j = 0;
   1360     unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3;
   1361     unsigned char *s;
   1362     int dstPitch2 = dstPitch << 1;
   1363 
   1364 #if 0
   1365     ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
   1366 	   "nlines %d, npixels %d, top %d, left %d\n",
   1367 	   srcPitch, srcPitch2, dstPitch,
   1368 	   h, w, top, left);
   1369 #endif
   1370 
   1371     /* Copy Y data */
   1372     src1 = buf + (top * srcPitch) + left;
   1373 #if 0
   1374     ErrorF("src1 is %p, offset is %ld\n", src1,
   1375 	   (unsigned long)src1 - (unsigned long)buf);
   1376 #endif
   1377 
   1378     if (pPriv->textured) {
   1379 	drm_intel_bo_map(pPriv->buf, TRUE);
   1380 	dst_base = pPriv->buf->virtual;
   1381     } else {
   1382 	drm_intel_gem_bo_start_gtt_access(pPriv->buf, TRUE);
   1383 	dst_base = pI830->FbBase;
   1384     }
   1385 
   1386     if (pPriv->currentBuf == 0)
   1387 	dst1 = dst_base + pPriv->YBuf0offset;
   1388     else
   1389 	dst1 = dst_base + pPriv->YBuf1offset;
   1390 
   1391     switch (pPriv->rotation) {
   1392     case RR_Rotate_0:
   1393        /* optimise for the case of no clipping */
   1394 	if (srcPitch == dstPitch2 && srcPitch == w)
   1395 	    memcpy (dst1, src1, srcPitch * h);
   1396 	else
   1397 	    for (i = 0; i < h; i++) {
   1398 		memcpy(dst1, src1, w);
   1399 		src1 += srcPitch;
   1400 		dst1 += dstPitch2;
   1401 	    }
   1402 	break;
   1403     case RR_Rotate_90:
   1404 	for (i = 0; i < h; i++) {
   1405 	    s = src1;
   1406 	    for (j = 0; j < w; j++) {
   1407 		dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++;
   1408 	    }
   1409 	    src1 += srcPitch;
   1410 	}
   1411 	break;
   1412     case RR_Rotate_180:
   1413 	for (i = 0; i < h; i++) {
   1414 	    s = src1;
   1415 	    for (j = 0; j < w; j++) {
   1416 		dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++;
   1417 	    }
   1418 	    src1 += srcPitch;
   1419 	}
   1420 	break;
   1421     case RR_Rotate_270:
   1422 	for (i = 0; i < h; i++) {
   1423 	    s = src1;
   1424 	    for (j = 0; j < w; j++) {
   1425 		dst1[(h - i - 1) + (j * dstPitch2)] = *s++;
   1426 	    }
   1427 	    src1 += srcPitch;
   1428 	}
   1429 	break;
   1430     }
   1431 
   1432     /* Copy V data for YV12, or U data for I420 */
   1433     src2 = buf +                            /* start of YUV data */
   1434                 (srcH * srcPitch) +         /* move over Luma plane */
   1435                 ((top * srcPitch) >> 2) +   /* move down from by top lines */
   1436                     (left >> 1);            /* move left by left pixels */
   1437 
   1438 #if 0
   1439     ErrorF("src2 is %p, offset is %ld\n", src2,
   1440 	   (unsigned long)src2 - (unsigned long)buf);
   1441 #endif
   1442     if (pPriv->currentBuf == 0) {
   1443 	if (id == FOURCC_I420)
   1444 	    dst2 = dst_base + pPriv->UBuf0offset;
   1445 	else
   1446 	    dst2 = dst_base + pPriv->VBuf0offset;
   1447     } else {
   1448 	if (id == FOURCC_I420)
   1449 	    dst2 = dst_base + pPriv->UBuf1offset;
   1450 	else
   1451 	    dst2 = dst_base + pPriv->VBuf1offset;
   1452     }
   1453 
   1454     switch (pPriv->rotation) {
   1455     case RR_Rotate_0:
   1456        /* optimise for the case of no clipping */
   1457 	if (srcPitch2 == dstPitch && srcPitch2 == (w/2))
   1458 	    memcpy (dst2, src2, h/2 * srcPitch2);
   1459 	else
   1460 	    for (i = 0; i < h / 2; i++) {
   1461 		memcpy(dst2, src2, w / 2);
   1462 		src2 += srcPitch2;
   1463 		dst2 += dstPitch;
   1464 	    }
   1465 	break;
   1466     case RR_Rotate_90:
   1467 	for (i = 0; i < (h/2); i++) {
   1468 	    s = src2;
   1469 	    for (j = 0; j < (w/2); j++) {
   1470 		dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
   1471 	    }
   1472 	    src2 += srcPitch2;
   1473 	}
   1474 	break;
   1475     case RR_Rotate_180:
   1476 	for (i = 0; i < (h/2); i++) {
   1477 	    s = src2;
   1478 	    for (j = 0; j < (w/2); j++) {
   1479 		dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
   1480 	    }
   1481 	    src2 += srcPitch2;
   1482 	}
   1483 	break;
   1484     case RR_Rotate_270:
   1485 	for (i = 0; i < (h/2); i++) {
   1486 	    s = src2;
   1487 	    for (j = 0; j < (w/2); j++) {
   1488 		dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++;
   1489 	    }
   1490 	    src2 += srcPitch2;
   1491 	}
   1492 	break;
   1493     }
   1494 
   1495     /* Copy U data for YV12, or V data for I420 */
   1496     src3 = buf +                            /* start of YUV data */
   1497                 (srcH * srcPitch) +         /* move over Luma plane */
   1498                 ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */
   1499                 ((top * srcPitch) >> 2) +   /* move down from by top lines */
   1500                     (left >> 1);            /* move left by left pixels */
   1501 #if 0
   1502     ErrorF("src3 is %p, offset is %ld\n", src3,
   1503 	   (unsigned long)src3 - (unsigned long)buf);
   1504 #endif
   1505     if (pPriv->currentBuf == 0) {
   1506 	if (id == FOURCC_I420)
   1507 	    dst3 = dst_base + pPriv->VBuf0offset;
   1508 	else
   1509 	    dst3 = dst_base + pPriv->UBuf0offset;
   1510     } else {
   1511 	if (id == FOURCC_I420)
   1512 	    dst3 = dst_base + pPriv->VBuf1offset;
   1513 	else
   1514 	    dst3 = dst_base + pPriv->UBuf1offset;
   1515     }
   1516 
   1517     switch (pPriv->rotation) {
   1518     case RR_Rotate_0:
   1519        /* optimise for the case of no clipping */
   1520 	if (srcPitch2 == dstPitch && srcPitch2 == (w/2))
   1521 	    memcpy (dst3, src3, srcPitch2 * h/2);
   1522 	else
   1523 	    for (i = 0; i < h / 2; i++) {
   1524 		memcpy(dst3, src3, w / 2);
   1525 		src3 += srcPitch2;
   1526 		dst3 += dstPitch;
   1527 	    }
   1528 	break;
   1529     case RR_Rotate_90:
   1530 	for (i = 0; i < (h/2); i++) {
   1531 	    s = src3;
   1532 	    for (j = 0; j < (w/2); j++) {
   1533 		dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
   1534 	    }
   1535 	    src3 += srcPitch2;
   1536 	}
   1537 	break;
   1538     case RR_Rotate_180:
   1539 	for (i = 0; i < (h/2); i++) {
   1540 	    s = src3;
   1541 	    for (j = 0; j < (w/2); j++) {
   1542 		dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
   1543 	    }
   1544 	    src3 += srcPitch2;
   1545 	}
   1546 	break;
   1547     case RR_Rotate_270:
   1548 	for (i = 0; i < (h/2); i++) {
   1549 	    s = src3;
   1550 	    for (j = 0; j < (w/2); j++) {
   1551 		dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++;
   1552 	    }
   1553 	    src3 += srcPitch2;
   1554 	}
   1555 	break;
   1556     }
   1557 
   1558     if (pPriv->textured)
   1559 	drm_intel_bo_unmap(pPriv->buf);
   1560 }
   1561 
   1562 typedef struct {
   1563     uint8_t sign;
   1564     uint16_t mantissa;
   1565     uint8_t exponent;
   1566 } coeffRec, *coeffPtr;
   1567 
   1568 static Bool
   1569 SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos)
   1570 {
   1571     int maxVal, icoeff, res;
   1572     int sign;
   1573     double c;
   1574 
   1575     sign = 0;
   1576     maxVal = 1 << mantSize;
   1577     c = *coeff;
   1578     if (c < 0.0) {
   1579 	sign = 1;
   1580 	c = -c;
   1581     }
   1582 
   1583     res = 12 - mantSize;
   1584     if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
   1585 	pCoeff[pos].exponent = 3;
   1586 	pCoeff[pos].mantissa = icoeff << res;
   1587 	*coeff = (double)icoeff / (double)(4 * maxVal);
   1588     } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
   1589 	pCoeff[pos].exponent = 2;
   1590 	pCoeff[pos].mantissa = icoeff << res;
   1591 	*coeff = (double)icoeff / (double)(2 * maxVal);
   1592     } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
   1593 	pCoeff[pos].exponent = 1;
   1594 	pCoeff[pos].mantissa = icoeff << res;
   1595 	*coeff = (double)icoeff / (double)(maxVal);
   1596     } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
   1597 	pCoeff[pos].exponent = 0;
   1598 	pCoeff[pos].mantissa = icoeff << res;
   1599 	*coeff = (double)icoeff / (double)(maxVal / 2);
   1600     } else {
   1601 	/* Coeff out of range */
   1602 	return FALSE;
   1603     }
   1604 
   1605     pCoeff[pos].sign = sign;
   1606     if (sign)
   1607 	*coeff = -(*coeff);
   1608     return TRUE;
   1609 }
   1610 
   1611 static void
   1612 UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
   1613 {
   1614     int i, j, j1, num, pos, mantSize;
   1615     double pi = 3.1415926535, val, sinc, window, sum;
   1616     double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
   1617     double diff;
   1618     int tapAdjust[MAX_TAPS], tap2Fix;
   1619     Bool isVertAndUV;
   1620 
   1621     if (isHoriz)
   1622 	mantSize = 7;
   1623     else
   1624 	mantSize = 6;
   1625 
   1626     isVertAndUV = !isHoriz && !isY;
   1627     num = taps * 16;
   1628     for (i = 0; i < num  * 2; i++) {
   1629 	val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
   1630 	if (val == 0.0)
   1631 	    sinc = 1.0;
   1632 	else
   1633 	    sinc = sin(val) / val;
   1634 
   1635 	/* Hamming window */
   1636 	window = (0.5 - 0.5 * cos(i * pi / num));
   1637 	rawCoeff[i] = sinc * window;
   1638     }
   1639 
   1640     for (i = 0; i < N_PHASES; i++) {
   1641 	/* Normalise the coefficients. */
   1642 	sum = 0.0;
   1643 	for (j = 0; j < taps; j++) {
   1644 	    pos = i + j * 32;
   1645 	    sum += rawCoeff[pos];
   1646 	}
   1647 	for (j = 0; j < taps; j++) {
   1648 	    pos = i + j * 32;
   1649 	    coeffs[i][j] = rawCoeff[pos] / sum;
   1650 	}
   1651 
   1652 	/* Set the register values. */
   1653 	for (j = 0; j < taps; j++) {
   1654 	    pos = j + i * taps;
   1655 	    if ((j == (taps - 1) / 2) && !isVertAndUV)
   1656 		SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
   1657 	    else
   1658 		SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
   1659 	}
   1660 
   1661 	tapAdjust[0] = (taps - 1) / 2;
   1662 	for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
   1663 	    tapAdjust[j1] = tapAdjust[0] - j;
   1664 	    tapAdjust[++j1] = tapAdjust[0] + j;
   1665 	}
   1666 
   1667 	/* Adjust the coefficients. */
   1668 	sum = 0.0;
   1669 	for (j = 0; j < taps; j++)
   1670 	    sum += coeffs[i][j];
   1671 	if (sum != 1.0) {
   1672 	    for (j1 = 0; j1 < taps; j1++) {
   1673 		tap2Fix = tapAdjust[j1];
   1674 		diff = 1.0 - sum;
   1675 		coeffs[i][tap2Fix] += diff;
   1676 		pos = tap2Fix + i * taps;
   1677 		if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
   1678 		    SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
   1679 		else
   1680 		    SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
   1681 
   1682 		sum = 0.0;
   1683 		for (j = 0; j < taps; j++)
   1684 		    sum += coeffs[i][j];
   1685 		if (sum == 1.0)
   1686 		    break;
   1687 	    }
   1688 	}
   1689     }
   1690 }
   1691 
   1692 static void
   1693 i830_box_intersect (BoxPtr dest, BoxPtr a, BoxPtr b)
   1694 {
   1695     dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
   1696     dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
   1697     dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
   1698     dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
   1699     if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
   1700 	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
   1701 }
   1702 
   1703 static void
   1704 i830_crtc_box (xf86CrtcPtr crtc, BoxPtr crtc_box)
   1705 {
   1706     if (crtc->enabled)
   1707     {
   1708 	crtc_box->x1 = crtc->x;
   1709 	crtc_box->x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
   1710 	crtc_box->y1 = crtc->y;
   1711 	crtc_box->y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
   1712     }
   1713     else
   1714 	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
   1715 }
   1716 
   1717 static int
   1718 i830_box_area (BoxPtr box)
   1719 {
   1720     return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
   1721 }
   1722 
   1723 /*
   1724  * Return the crtc covering 'box'. If two crtcs cover a portion of
   1725  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
   1726  * with greater coverage
   1727  */
   1728 
   1729 xf86CrtcPtr
   1730 i830_covering_crtc (ScrnInfoPtr pScrn,
   1731 		    BoxPtr	box,
   1732 		    xf86CrtcPtr desired,
   1733 		    BoxPtr	crtc_box_ret)
   1734 {
   1735     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1736     xf86CrtcPtr		crtc, best_crtc;
   1737     int			coverage, best_coverage;
   1738     int			c;
   1739     BoxRec		crtc_box, cover_box;
   1740 
   1741     best_crtc = NULL;
   1742     best_coverage = 0;
   1743     crtc_box_ret->x1 = 0;
   1744     crtc_box_ret->x2 = 0;
   1745     crtc_box_ret->y1 = 0;
   1746     crtc_box_ret->y2 = 0;
   1747     for (c = 0; c < xf86_config->num_crtc; c++)
   1748     {
   1749 	crtc = xf86_config->crtc[c];
   1750 
   1751 	/* If the CRTC is off, treat it as not covering */
   1752 	if (!i830_crtc_on(crtc))
   1753 	    continue;
   1754 
   1755 	i830_crtc_box (crtc, &crtc_box);
   1756 	i830_box_intersect (&cover_box, &crtc_box, box);
   1757 	coverage = i830_box_area (&cover_box);
   1758 	if (coverage && crtc == desired)
   1759 	{
   1760 	    *crtc_box_ret = crtc_box;
   1761 	    return crtc;
   1762 	}
   1763 	if (coverage > best_coverage)
   1764 	{
   1765 	    *crtc_box_ret = crtc_box;
   1766 	    best_crtc = crtc;
   1767 	    best_coverage = coverage;
   1768 	}
   1769     }
   1770     return best_crtc;
   1771 }
   1772 
   1773 static int
   1774 i830_swidth (I830Ptr pI830, unsigned int offset,
   1775 	     unsigned int width, unsigned int mask, int shift)
   1776 {
   1777     int	swidth = ((offset + width + mask) >> shift) - (offset >> shift);
   1778     if (IS_I9XX(pI830))
   1779 	swidth <<= 1;
   1780     swidth -= 1;
   1781     return swidth << 2;
   1782 }
   1783 
   1784 static void
   1785 i830_update_dst_box_to_crtc_coords(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
   1786 		BoxPtr dstBox)
   1787 {
   1788     int tmp;
   1789 
   1790     /* for overlay, we should take it from crtc's screen
   1791      * coordinate to current crtc's display mode.
   1792      * yeah, a bit confusing.
   1793      */
   1794     switch (crtc->rotation & 0xf) {
   1795     case RR_Rotate_0:
   1796 	dstBox->x1 -= crtc->x;
   1797 	dstBox->x2 -= crtc->x;
   1798 	dstBox->y1 -= crtc->y;
   1799 	dstBox->y2 -= crtc->y;
   1800 	break;
   1801     case RR_Rotate_90:
   1802 	tmp = dstBox->x1;
   1803 	dstBox->x1 = dstBox->y1 - crtc->x;
   1804 	dstBox->y1 = pScrn->virtualX - tmp - crtc->y;
   1805 	tmp = dstBox->x2;
   1806 	dstBox->x2 = dstBox->y2 - crtc->x;
   1807 	dstBox->y2 = pScrn->virtualX - tmp - crtc->y;
   1808 	tmp = dstBox->y1;
   1809 	dstBox->y1 = dstBox->y2;
   1810 	dstBox->y2 = tmp;
   1811 	break;
   1812     case RR_Rotate_180:
   1813 	tmp = dstBox->x1;
   1814 	dstBox->x1 = pScrn->virtualX - dstBox->x2 - crtc->x;
   1815 	dstBox->x2 = pScrn->virtualX - tmp - crtc->x;
   1816 	tmp = dstBox->y1;
   1817 	dstBox->y1 = pScrn->virtualY - dstBox->y2 - crtc->y;
   1818 	dstBox->y2 = pScrn->virtualY - tmp - crtc->y;
   1819 	break;
   1820     case RR_Rotate_270:
   1821 	tmp = dstBox->x1;
   1822 	dstBox->x1 = pScrn->virtualY - dstBox->y1 - crtc->x;
   1823 	dstBox->y1 = tmp - crtc->y;
   1824 	tmp = dstBox->x2;
   1825 	dstBox->x2 = pScrn->virtualY - dstBox->y2 - crtc->x;
   1826 	dstBox->y2 = tmp - crtc->y;
   1827 	tmp = dstBox->x1;
   1828 	dstBox->x1 = dstBox->x2;
   1829 	dstBox->x2 = tmp;
   1830 	break;
   1831     }
   1832 
   1833     return;
   1834 }
   1835 
   1836 static void
   1837 i830_store_coeffs_in_overlay_regs(uint16_t *reg_coeffs, coeffPtr new_coeffs,
   1838 	int max_taps)
   1839 {
   1840     int i, j, pos;
   1841 
   1842     for (i = 0; i < N_PHASES; i++) {
   1843 	for (j = 0; j < max_taps; j++) {
   1844 	    pos = i * max_taps + j;
   1845 	    reg_coeffs[pos] = (new_coeffs[pos].sign << 15 |
   1846 				      new_coeffs[pos].exponent << 12 |
   1847 				      new_coeffs[pos].mantissa);
   1848 	}
   1849     }
   1850 }
   1851 
   1852 static double
   1853 i830_limit_coeff(double coeff)
   1854 {
   1855     /* Limit to between 1.0 and 3.0. */
   1856     if (coeff < MIN_CUTOFF_FREQ)
   1857 	coeff = MIN_CUTOFF_FREQ;
   1858     if (coeff > MAX_CUTOFF_FREQ)
   1859 	coeff = MAX_CUTOFF_FREQ;
   1860 
   1861     return coeff;
   1862 }
   1863 
   1864 static void
   1865 i830_update_polyphase_coeffs(I830OverlayRegPtr	overlay,
   1866 	int xscaleFract, int xscaleFractUV)
   1867 {
   1868     /*
   1869      * Only Horizontal coefficients so far.
   1870      */
   1871     double fCutoffY;
   1872     double fCutoffUV;
   1873     coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
   1874     coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
   1875 
   1876     fCutoffY = xscaleFract / 4096.0;
   1877     fCutoffUV = xscaleFractUV / 4096.0;
   1878 
   1879     fCutoffUV = i830_limit_coeff(fCutoffUV);
   1880     fCutoffY = i830_limit_coeff(fCutoffY);
   1881 
   1882     UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
   1883     UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
   1884 
   1885     i830_store_coeffs_in_overlay_regs(overlay->Y_HCOEFS, xcoeffY,
   1886 		    N_HORIZ_Y_TAPS);
   1887     i830_store_coeffs_in_overlay_regs(overlay->UV_HCOEFS, xcoeffUV,
   1888 		    N_HORIZ_UV_TAPS);
   1889 }
   1890 
   1891 /*
   1892  * Calculate horizontal and vertical scaling factors and polyphase
   1893  * coefficients.
   1894  */
   1895 
   1896 static Bool
   1897 i830_update_scaling_factors(I830OverlayRegPtr overlay,
   1898 	short src_w, short src_h, short drw_w, short drw_h)
   1899 {
   1900     int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
   1901     int xscaleIntUV, xscaleFractUV;
   1902     int yscaleIntUV, yscaleFractUV;
   1903     uint32_t newval;
   1904     Bool scaleChanged = FALSE;
   1905 
   1906     /*
   1907      * Y down-scale factor as a multiple of 4096.
   1908      */
   1909     xscaleFract = ((src_w - 1) << 12) / drw_w;
   1910     yscaleFract = ((src_h - 1) << 12) / drw_h;
   1911 
   1912     /* Calculate the UV scaling factor.
   1913      * UV is half the size of Y -- YUV420 */
   1914     xscaleFractUV = xscaleFract / 2;
   1915     yscaleFractUV = yscaleFract / 2;
   1916 
   1917     /*
   1918      * To keep the relative Y and UV ratios exact, round the Y scales
   1919      * to a multiple of the Y/UV ratio.
   1920      */
   1921     xscaleFract = xscaleFractUV * 2;
   1922     yscaleFract = yscaleFractUV * 2;
   1923 
   1924     /* Integer (un-multiplied) values. */
   1925     xscaleInt = xscaleFract >> 12;
   1926     yscaleInt = yscaleFract >> 12;
   1927 
   1928     xscaleIntUV = xscaleFractUV >> 12;
   1929     yscaleIntUV = yscaleFractUV >> 12;
   1930 
   1931     OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
   1932 		  xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
   1933     OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
   1934 		  xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
   1935 
   1936     /* shouldn't get here */
   1937     if (xscaleInt > 7) {
   1938 	OVERLAY_DEBUG("xscale: bad scale\n");
   1939 	return FALSE;
   1940     }
   1941 
   1942     /* shouldn't get here */
   1943     if (xscaleIntUV > 7) {
   1944 	OVERLAY_DEBUG("xscaleUV: bad scale\n");
   1945 	return FALSE;
   1946     }
   1947 
   1948     newval = (xscaleInt << 16) |
   1949     ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
   1950     if (newval != overlay->YRGBSCALE) {
   1951 	scaleChanged = TRUE;
   1952 	overlay->YRGBSCALE = newval;
   1953     }
   1954 
   1955     newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
   1956     ((yscaleFractUV & 0xFFF) << 20);
   1957     if (newval != overlay->UVSCALE) {
   1958 	scaleChanged = TRUE;
   1959 	overlay->UVSCALE = newval;
   1960     }
   1961 
   1962     newval = yscaleInt << 16 | yscaleIntUV;
   1963     if (newval != overlay->UVSCALEV) {
   1964 	scaleChanged = TRUE;
   1965 	overlay->UVSCALEV = newval;
   1966     }
   1967 
   1968     if (scaleChanged) {
   1969 	i830_update_polyphase_coeffs(overlay, xscaleFract, xscaleFractUV);
   1970     }
   1971 
   1972     return scaleChanged;
   1973 }
   1974 
   1975 static void
   1976 i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc,
   1977 		   int id, short width, short height,
   1978 		   int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
   1979 		   short src_w, short src_h, short drw_w, short drw_h)
   1980 {
   1981     I830Ptr		pI830 = I830PTR(pScrn);
   1982     I830PortPrivPtr	pPriv = pI830->adaptor->pPortPrivates[0].ptr;
   1983     I830OverlayRegPtr	overlay = I830OVERLAYREG(pI830);
   1984     unsigned int	swidth, swidthy, swidthuv;
   1985     unsigned int	mask, shift, offsety, offsetu;
   1986     int			tmp;
   1987     uint32_t		OCMD;
   1988     Bool		scaleChanged = FALSE;
   1989 
   1990     OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
   1991 		  dstPitch);
   1992 
   1993 #if VIDEO_DEBUG
   1994     CompareOverlay(pI830, (uint32_t *) overlay, 0x100);
   1995 #endif
   1996 
   1997     /*
   1998      * If the video isn't visible on any CRTC, turn it off
   1999      */
   2000     if (!crtc)
   2001     {
   2002 	pPriv->current_crtc = NULL;
   2003 	i830_overlay_off (pScrn);
   2004 	return;
   2005     }
   2006 
   2007     if (crtc != pPriv->current_crtc)
   2008     {
   2009 	i830_overlay_switch_to_crtc (pScrn, crtc);
   2010 	if (pPriv->overlayOK) {
   2011 	    pPriv->current_crtc = crtc;
   2012 	    I830ResetVideo (pScrn);
   2013 	}
   2014     }
   2015 
   2016     if (!pPriv->overlayOK)
   2017 	return;
   2018 
   2019     i830_update_dst_box_to_crtc_coords(pScrn, crtc, dstBox);
   2020 
   2021     if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   2022 	tmp = width;
   2023 	width = height;
   2024 	height = tmp;
   2025 	tmp = drw_w;
   2026 	drw_w = drw_h;
   2027 	drw_h = tmp;
   2028 	tmp = src_w;
   2029 	src_w = src_h;
   2030 	src_h = tmp;
   2031     }
   2032 
   2033     if (pPriv->oneLineMode) {
   2034 	/* change the coordinates with panel fitting active */
   2035 	dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
   2036 	dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
   2037 
   2038 	/* Now, alter the height, so we scale to the correct size */
   2039 	drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
   2040     }
   2041 
   2042     if (IS_I9XX(pI830)) {
   2043 	shift = 6;
   2044 	mask = 0x3f;
   2045     } else {
   2046 	shift = 5;
   2047 	mask = 0x1f;
   2048     }
   2049 
   2050     if (pPriv->currentBuf == 0) {
   2051 	offsety = pPriv->YBuf0offset;
   2052 	offsetu = pPriv->UBuf0offset;
   2053     } else {
   2054 	offsety = pPriv->YBuf1offset;
   2055 	offsetu = pPriv->UBuf1offset;
   2056     }
   2057 
   2058     switch (id) {
   2059     case FOURCC_YV12:
   2060     case FOURCC_I420:
   2061 	overlay->SWIDTH = width | ((width/2 & 0x7ff) << 16);
   2062 	swidthy  = i830_swidth (pI830, offsety, width, mask, shift);
   2063 	swidthuv = i830_swidth (pI830, offsetu, width/2, mask, shift);
   2064 	overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
   2065 	overlay->SHEIGHT = height | ((height / 2) << 16);
   2066 	break;
   2067     case FOURCC_UYVY:
   2068     case FOURCC_YUY2:
   2069     default:
   2070 	overlay->SWIDTH = width;
   2071 	swidth = ((offsety + (width << 1) + mask) >> shift) -
   2072 	(offsety >> shift);
   2073 
   2074 	if (IS_I9XX(pI830))
   2075 	    swidth <<= 1;
   2076 
   2077 	swidth -= 1;
   2078 
   2079 	swidth <<= 2;
   2080 
   2081 	OVERLAY_DEBUG("swidthsw is old %d new %d\n",
   2082 		      swidth,
   2083 		      i830_swidth (pI830, offsety, width << 1,
   2084 				   mask, shift));
   2085 
   2086 	overlay->SWIDTHSW = swidth;
   2087 	overlay->SHEIGHT = height;
   2088 	break;
   2089     }
   2090 
   2091     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
   2092 
   2093     overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) |
   2094 		       (dstBox->x2 - dstBox->x1));
   2095 
   2096     OVERLAY_DEBUG("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n",
   2097 		  dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2);
   2098 
   2099     /* buffer locations */
   2100     overlay->OBUF_0Y = pPriv->YBuf0offset;
   2101     overlay->OBUF_0U = pPriv->UBuf0offset;
   2102     overlay->OBUF_0V = pPriv->VBuf0offset;
   2103     if(pPriv->doubleBuffer) {
   2104 	overlay->OBUF_1Y = pPriv->YBuf1offset;
   2105 	overlay->OBUF_1U = pPriv->UBuf1offset;
   2106 	overlay->OBUF_1V = pPriv->VBuf1offset;
   2107     }
   2108 
   2109     OVERLAY_DEBUG("pos: 0x%x, size: 0x%x\n",
   2110 		  overlay->DWINPOS, overlay->DWINSZ);
   2111     OVERLAY_DEBUG("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
   2112 
   2113     scaleChanged = i830_update_scaling_factors(overlay,
   2114 	    src_w, src_h, drw_w, drw_h);
   2115 
   2116     OCMD = OVERLAY_ENABLE;
   2117 
   2118     switch (id) {
   2119     case FOURCC_YV12:
   2120     case FOURCC_I420:
   2121 #ifdef INTEL_XVMC
   2122     case FOURCC_XVMC:
   2123 #endif
   2124 	OVERLAY_DEBUG("YUV420\n");
   2125 #if 0
   2126 	/* set UV vertical phase to -0.25 */
   2127 	overlay->UV_VPH = 0x30003000;
   2128 #endif
   2129 	OVERLAY_DEBUG("UV stride is %d, Y stride is %d\n",
   2130 		      dstPitch, dstPitch * 2);
   2131 	overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
   2132 	OCMD &= ~SOURCE_FORMAT;
   2133 	OCMD &= ~OV_BYTE_ORDER;
   2134 	OCMD |= YUV_420;
   2135 	break;
   2136     case FOURCC_UYVY:
   2137     case FOURCC_YUY2:
   2138 	OVERLAY_DEBUG("YUV422\n");
   2139 	overlay->OSTRIDE = dstPitch;
   2140 	OCMD &= ~SOURCE_FORMAT;
   2141 	OCMD |= YUV_422;
   2142 	OCMD &= ~OV_BYTE_ORDER;
   2143 	if (id == FOURCC_UYVY)
   2144 	    OCMD |= Y_SWAP;
   2145 	break;
   2146     }
   2147 
   2148     OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
   2149     if (pPriv->currentBuf == 0)
   2150 	OCMD |= BUFFER0;
   2151     else
   2152 	OCMD |= BUFFER1;
   2153 
   2154     overlay->OCMD = OCMD;
   2155     OVERLAY_DEBUG("OCMD is 0x%x\n", OCMD);
   2156 
   2157     /* make sure the overlay is on */
   2158     i830_overlay_on (pScrn);
   2159     /* and show this frame */
   2160     i830_overlay_continue (pScrn, scaleChanged);
   2161 }
   2162 
   2163 static Bool
   2164 i830_clip_video_helper (ScrnInfoPtr pScrn,
   2165 			I830PortPrivPtr pPriv,
   2166 			xf86CrtcPtr *crtc_ret,
   2167 			BoxPtr	    dst,
   2168 			INT32	    *xa,
   2169 			INT32	    *xb,
   2170 			INT32	    *ya,
   2171 			INT32	    *yb,
   2172 			RegionPtr   reg,
   2173 			INT32	    width,
   2174 			INT32	    height)
   2175 {
   2176     Bool	ret;
   2177     RegionRec	crtc_region_local;
   2178     RegionPtr	crtc_region = reg;
   2179 
   2180     /*
   2181      * For overlay video, compute the relevant CRTC and
   2182      * clip video to that
   2183      */
   2184     if (crtc_ret)
   2185     {
   2186 	BoxRec		crtc_box;
   2187 	xf86CrtcPtr	crtc = i830_covering_crtc (pScrn, dst,
   2188 						   pPriv->desired_crtc,
   2189 						   &crtc_box);
   2190 
   2191 	/* For textured video, we don't actually want to clip at all. */
   2192 	if (crtc && !pPriv->textured)
   2193 	{
   2194 	    REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
   2195 	    crtc_region = &crtc_region_local;
   2196 	    REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
   2197 	}
   2198 	*crtc_ret = crtc;
   2199     }
   2200     ret = xf86XVClipVideoHelper (dst, xa, xb, ya, yb,
   2201 				 crtc_region, width, height);
   2202     if (crtc_region != reg)
   2203 	REGION_UNINIT (pScreen, &crtc_region_local);
   2204     return ret;
   2205 }
   2206 
   2207 /*
   2208  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
   2209  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
   2210  * id is a fourcc code for the format of the video.
   2211  * buf is the pointer to the source data in system memory.
   2212  * width and height are the w/h of the source data.
   2213  * If "sync" is TRUE, then we must be finished with *buf at the point of return
   2214  * (which we always are).
   2215  * clipBoxes is the clipping region in screen space.
   2216  * data is a pointer to our port private.
   2217  * pDraw is a Drawable, which might not be the screen in the case of
   2218  * compositing.  It's a new argument to the function in the 1.1 server.
   2219  */
   2220 static int
   2221 I830PutImage(ScrnInfoPtr pScrn,
   2222 	     short src_x, short src_y,
   2223 	     short drw_x, short drw_y,
   2224 	     short src_w, short src_h,
   2225 	     short drw_w, short drw_h,
   2226 	     int id, unsigned char *buf,
   2227 	     short width, short height,
   2228 	     Bool sync, RegionPtr clipBoxes, pointer data,
   2229 	     DrawablePtr pDraw)
   2230 {
   2231     I830Ptr pI830 = I830PTR(pScrn);
   2232     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
   2233     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
   2234     I830OverlayRegPtr overlay;
   2235     PixmapPtr pPixmap = get_drawable_pixmap(pDraw);;
   2236     INT32 x1, x2, y1, y2;
   2237     int srcPitch = 0, srcPitch2 = 0, dstPitch, destId;
   2238     int dstPitch2 = 0;
   2239     int top, left, npixels, nlines, size;
   2240     BoxRec dstBox;
   2241     int pitchAlignMask;
   2242     int alloc_size;
   2243     xf86CrtcPtr	crtc;
   2244 
   2245     if (pPriv->textured)
   2246 	overlay = NULL;
   2247     else
   2248 	overlay = I830OVERLAYREG(pI830);
   2249 
   2250 #if 0
   2251     ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
   2252 	   "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y,
   2253 	   drw_w, drw_h, width, height);
   2254 #endif
   2255 
   2256     if (!pPriv->textured) {
   2257         /* If dst width and height are less than 1/8th the src size, the
   2258          * src/dst scale factor becomes larger than 8 and doesn't fit in
   2259          * the scale register. */
   2260         if(src_w >= (drw_w * 8))
   2261             drw_w = src_w/7;
   2262 
   2263         if(src_h >= (drw_h * 8))
   2264             drw_h = src_h/7;
   2265     }
   2266 
   2267     /* Clip */
   2268     x1 = src_x;
   2269     x2 = src_x + src_w;
   2270     y1 = src_y;
   2271     y2 = src_y + src_h;
   2272 
   2273     dstBox.x1 = drw_x;
   2274     dstBox.x2 = drw_x + drw_w;
   2275     dstBox.y1 = drw_y;
   2276     dstBox.y2 = drw_y + drw_h;
   2277 
   2278     if (!i830_clip_video_helper(pScrn,
   2279 				pPriv,
   2280 				&crtc,
   2281 				&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
   2282 				width, height))
   2283 	return Success;
   2284 
   2285      if (!pPriv->textured) {
   2286 	 /* texture video handles rotation differently. */
   2287 	if (crtc)
   2288 	    pPriv->rotation = crtc->rotation;
   2289 	else {
   2290 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   2291 		    "Fail to clip video to any crtc!\n");
   2292 	    return Success;
   2293 	}
   2294      }
   2295 
   2296     destId = id;
   2297     switch (id) {
   2298     case FOURCC_YV12:
   2299     case FOURCC_I420:
   2300 	srcPitch = (width + 0x3) & ~0x3;
   2301 	srcPitch2 = ((width >> 1) + 0x3) & ~0x3;
   2302 	break;
   2303 #ifdef INTEL_XVMC
   2304     case FOURCC_XVMC:
   2305 	srcPitch = (width + 0x3) & ~0x3;
   2306 	srcPitch2 = ((width >> 1) + 0x3) & ~0x3;
   2307 	break;
   2308 #endif
   2309     case FOURCC_UYVY:
   2310     case FOURCC_YUY2:
   2311     default:
   2312 	srcPitch = width << 1;
   2313 	break;
   2314     }
   2315 
   2316     /* Only needs to be DWORD-aligned for textured on i915, but overlay has
   2317      * stricter requirements.
   2318      */
   2319     if (pPriv->textured) {
   2320 	pitchAlignMask = 3;
   2321 #ifdef INTEL_XVMC
   2322 	/* for i915 xvmc, hw requires at least 1kb aligned surface */
   2323 	if ((id == FOURCC_XVMC) && IS_I915(pI830))
   2324 	    pitchAlignMask = 0x3ff;
   2325 #endif
   2326     } else {
   2327 	if (IS_I965G(pI830))
   2328 	    pitchAlignMask = 255;
   2329 	else
   2330 	    pitchAlignMask = 63;
   2331     }
   2332 
   2333     /* Determine the desired destination pitch (representing the chroma's pitch,
   2334      * in the planar case.
   2335      */
   2336     switch (destId) {
   2337     case FOURCC_YV12:
   2338     case FOURCC_I420:
   2339 	if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   2340 	    dstPitch = ((height / 2) + pitchAlignMask) & ~pitchAlignMask;
   2341 	    size = dstPitch * width * 3;
   2342 	} else {
   2343 	    dstPitch = ((width / 2) + pitchAlignMask) & ~pitchAlignMask;
   2344 	    size = dstPitch * height * 3;
   2345 	}
   2346 	break;
   2347     case FOURCC_UYVY:
   2348     case FOURCC_YUY2:
   2349 
   2350 	if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   2351 	    dstPitch = ((height << 1) + pitchAlignMask) & ~pitchAlignMask;
   2352 	    size = dstPitch * width;
   2353 	} else {
   2354 	    dstPitch = ((width << 1) + pitchAlignMask) & ~pitchAlignMask;
   2355 	    size = dstPitch * height;
   2356 	}
   2357 	break;
   2358 #ifdef INTEL_XVMC
   2359     case FOURCC_XVMC:
   2360 	dstPitch = ((width / 2) + pitchAlignMask ) & ~pitchAlignMask;
   2361 	dstPitch2 = (width + pitchAlignMask ) & ~pitchAlignMask;
   2362 	size = 0;
   2363 	break;
   2364 #endif
   2365     default:
   2366 	dstPitch = 0;
   2367 	size = 0;
   2368 	break;
   2369     }
   2370 #if 0
   2371     ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
   2372 #endif
   2373 
   2374     alloc_size = size;
   2375     if (pPriv->doubleBuffer)
   2376 	alloc_size *= 2;
   2377 
   2378     /* Free the current buffer if we're going to have to reallocate */
   2379     if (pPriv->buf && pPriv->buf->size < alloc_size) {
   2380 	if (!pPriv->textured)
   2381 	    drm_intel_bo_unpin(pPriv->buf);
   2382 	drm_intel_bo_unreference(pPriv->buf);
   2383 	pPriv->buf = NULL;
   2384     }
   2385 
   2386 #ifdef INTEL_XVMC
   2387     if (id == FOURCC_XVMC &&
   2388         pPriv->rotation == RR_Rotate_0) {
   2389         if (pPriv->buf) {
   2390             assert(pPriv->textured);
   2391             drm_intel_bo_unreference(pPriv->buf);
   2392             pPriv->buf = NULL;
   2393         }
   2394     } else {
   2395 #endif
   2396         if (pPriv->buf == NULL) {
   2397             pPriv->buf = drm_intel_bo_alloc(pI830->bufmgr,
   2398                                          "xv buffer", alloc_size, 4096);
   2399             if (pPriv->buf == NULL)
   2400                 return BadAlloc;
   2401             if (!pPriv->textured && drm_intel_bo_pin(pPriv->buf, 4096) != 0) {
   2402                 drm_intel_bo_unreference(pPriv->buf);
   2403                 pPriv->buf = NULL;
   2404                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   2405                            "Failed to pin xv buffer\n");
   2406                 return BadAlloc;
   2407             }
   2408         }
   2409 #ifdef INTEL_XVMC
   2410     }
   2411 #endif
   2412 
   2413     /* fixup pointers */
   2414 #ifdef INTEL_XVMC
   2415     if (id == FOURCC_XVMC && IS_I915(pI830)) {
   2416 	pPriv->YBuf0offset = (uint32_t)((uintptr_t)buf);
   2417 	pPriv->VBuf0offset = pPriv->YBuf0offset + (dstPitch2 * height);
   2418 	pPriv->UBuf0offset = pPriv->VBuf0offset + (dstPitch * height / 2);
   2419 	destId = FOURCC_YV12;
   2420     } else {
   2421 #endif
   2422 	if (pPriv->textured)
   2423 	    pPriv->YBuf0offset = 0;
   2424 	else
   2425 	    pPriv->YBuf0offset = pPriv->buf->offset;
   2426 
   2427 	if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   2428 	    pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
   2429 	    pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2);
   2430 	    if(pPriv->doubleBuffer) {
   2431 		pPriv->YBuf1offset = pPriv->YBuf0offset + size;
   2432 		pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width);
   2433 		pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2);
   2434 	    }
   2435 	} else {
   2436 	    pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
   2437 	    pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
   2438 	    if(pPriv->doubleBuffer) {
   2439 		pPriv->YBuf1offset = pPriv->YBuf0offset + size;
   2440 		pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
   2441 		pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
   2442 	    }
   2443 	}
   2444 #ifdef INTEL_XVMC
   2445     }
   2446 #endif
   2447 
   2448     /* Pick the idle buffer */
   2449     if (!pPriv->textured && pI830->overlayOn && pPriv->doubleBuffer)
   2450 	pPriv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
   2451 
   2452     /* copy data */
   2453     top = y1 >> 16;
   2454     left = (x1 >> 16) & ~1;
   2455     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
   2456 
   2457     switch (id) {
   2458     case FOURCC_YV12:
   2459     case FOURCC_I420:
   2460 	top &= ~1;
   2461 	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
   2462 	I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch,
   2463 	    	       height, top, left, nlines, npixels, id);
   2464 	break;
   2465     case FOURCC_UYVY:
   2466     case FOURCC_YUY2:
   2467 	nlines = ((y2 + 0xffff) >> 16) - top;
   2468 	I830CopyPackedData(pScrn, pPriv, buf, srcPitch, dstPitch, top, left,
   2469 			   nlines, npixels);
   2470 	break;
   2471 #ifdef INTEL_XVMC
   2472     case FOURCC_XVMC:
   2473 	if (pPriv->rotation != RR_Rotate_0) {
   2474 	    top &= ~1;
   2475 	    nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
   2476 	    I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch,
   2477 		    height, top, left, nlines, npixels, id);
   2478 	}
   2479 
   2480 	break;
   2481 #endif
   2482     default:
   2483 	break;
   2484     }
   2485 
   2486     if (!pPriv->textured) {
   2487 	i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
   2488 			   x1, y1, x2, y2, &dstBox, src_w, src_h,
   2489 			   drw_w, drw_h);
   2490 
   2491 	/* update cliplist */
   2492 	if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
   2493 	    REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
   2494 	    xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
   2495 	}
   2496     } else {
   2497         Bool sync = TRUE;
   2498 
   2499         if (crtc == NULL) {
   2500             sync = FALSE;
   2501         } else if (pPriv->SyncToVblank == 0) {
   2502             sync = FALSE;
   2503         }
   2504 
   2505         if (sync) {
   2506 	    BoxPtr box;
   2507 	    pixman_box16_t box_in_crtc_coordinates;
   2508 	    int pipe = -1, event, load_scan_lines_pipe;
   2509 
   2510 	    if (pixmap_is_scanout(pPixmap))
   2511 		pipe = i830_crtc_to_pipe(crtc);
   2512 
   2513 	    if (pipe >= 0) {
   2514 		if (pipe == 0) {
   2515 		    event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
   2516 		    load_scan_lines_pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA;
   2517 		} else {
   2518 		    event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
   2519 		    load_scan_lines_pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEB;
   2520 		}
   2521 
   2522 		box = REGION_EXTENTS(unused, clipBoxes);
   2523 		box_in_crtc_coordinates = *box;
   2524 		if (crtc->transform_in_use)
   2525 		    pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &box_in_crtc_coordinates);
   2526 
   2527 		BEGIN_BATCH(5);
   2528 		/* The documentation says that the LOAD_SCAN_LINES command
   2529 		 * always comes in pairs. Don't ask me why. */
   2530 		OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | load_scan_lines_pipe);
   2531 		OUT_BATCH((box_in_crtc_coordinates.y1 << 16) | box_in_crtc_coordinates.y2);
   2532 		OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | load_scan_lines_pipe);
   2533 		OUT_BATCH((box_in_crtc_coordinates.y1 << 16) | box_in_crtc_coordinates.y2);
   2534 		OUT_BATCH(MI_WAIT_FOR_EVENT | event);
   2535 		ADVANCE_BATCH();
   2536 	    }
   2537         }
   2538 
   2539         if (IS_I965G(pI830)) {
   2540 #ifdef INTEL_XVMC
   2541             if (id == FOURCC_XVMC && pPriv->rotation == RR_Rotate_0) {
   2542                 pPriv->YBuf0offset = buf -  pI830->FbBase;
   2543                 pPriv->UBuf0offset = pPriv->YBuf0offset + height*width;
   2544                 pPriv->VBuf0offset = pPriv->UBuf0offset + height*width/4;
   2545             }
   2546 #endif
   2547             I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
   2548                                      dstPitch, x1, y1, x2, y2,
   2549                                      src_w, src_h, drw_w, drw_h, pPixmap);
   2550         } else {
   2551             I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height,
   2552                                      dstPitch, dstPitch2, x1, y1, x2, y2,
   2553                                      src_w, src_h, drw_w, drw_h, pPixmap);
   2554         }
   2555     }
   2556     if (pPriv->textured) {
   2557 	DamageDamageRegion(pDraw, clipBoxes);
   2558     }
   2559 
   2560     pPriv->videoStatus = CLIENT_VIDEO_ON;
   2561 
   2562     return Success;
   2563 }
   2564 
   2565 static int
   2566 I830QueryImageAttributes(ScrnInfoPtr pScrn,
   2567 			 int id,
   2568 			 unsigned short *w, unsigned short *h,
   2569 			 int *pitches, int *offsets)
   2570 {
   2571     I830Ptr pI830 = I830PTR(pScrn);
   2572     int size, tmp;
   2573 
   2574 #if 0
   2575     ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
   2576 #endif
   2577 
   2578     if (IS_845G(pI830) || IS_I830(pI830)) {
   2579 	if (*w > IMAGE_MAX_WIDTH_LEGACY)
   2580 	    *w = IMAGE_MAX_WIDTH_LEGACY;
   2581 	if (*h > IMAGE_MAX_HEIGHT_LEGACY)
   2582 	    *h = IMAGE_MAX_HEIGHT_LEGACY;
   2583     } else {
   2584 	if (*w > IMAGE_MAX_WIDTH)
   2585 	    *w = IMAGE_MAX_WIDTH;
   2586 	if (*h > IMAGE_MAX_HEIGHT)
   2587 	    *h = IMAGE_MAX_HEIGHT;
   2588     }
   2589 
   2590     *w = (*w + 1) & ~1;
   2591     if (offsets)
   2592 	offsets[0] = 0;
   2593 
   2594     switch (id) {
   2595 	/* IA44 is for XvMC only */
   2596     case FOURCC_IA44:
   2597     case FOURCC_AI44:
   2598 	if (pitches)
   2599 	    pitches[0] = *w;
   2600 	size = *w * *h;
   2601 	break;
   2602     case FOURCC_YV12:
   2603     case FOURCC_I420:
   2604 	*h = (*h + 1) & ~1;
   2605 	size = (*w + 3) & ~3;
   2606 	if (pitches)
   2607 	    pitches[0] = size;
   2608 	size *= *h;
   2609 	if (offsets)
   2610 	    offsets[1] = size;
   2611 	tmp = ((*w >> 1) + 3) & ~3;
   2612 	if (pitches)
   2613 	    pitches[1] = pitches[2] = tmp;
   2614 	tmp *= (*h >> 1);
   2615 	size += tmp;
   2616 	if (offsets)
   2617 	    offsets[2] = size;
   2618 	size += tmp;
   2619 #if 0
   2620 	if (pitches)
   2621 	    ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0],
   2622 		   pitches[1], pitches[2]);
   2623 	if (offsets)
   2624 	    ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], offsets[2]);
   2625 	if (offsets)
   2626 	    ErrorF("size is %d\n", size);
   2627 #endif
   2628 	break;
   2629 #ifdef INTEL_XVMC
   2630     case FOURCC_XVMC:
   2631         *h = (*h + 1) & ~1;
   2632         size = sizeof(struct intel_xvmc_command);
   2633         if (pitches)
   2634             pitches[0] = size;
   2635         break;
   2636 #endif
   2637     case FOURCC_UYVY:
   2638     case FOURCC_YUY2:
   2639     default:
   2640 	size = *w << 1;
   2641 	if (pitches)
   2642 	    pitches[0] = size;
   2643 	size *= *h;
   2644 	break;
   2645     }
   2646 
   2647     return size;
   2648 }
   2649 
   2650 void
   2651 I830VideoBlockHandler(int i, pointer blockData, pointer pTimeout,
   2652 		      pointer pReadmask)
   2653 {
   2654     ScrnInfoPtr pScrn = xf86Screens[i];
   2655     I830Ptr pI830 = I830PTR(pScrn);
   2656     I830PortPrivPtr pPriv;
   2657 
   2658     /* no overlay */
   2659     if (pI830->adaptor == NULL)
   2660         return;
   2661 
   2662     pPriv = GET_PORT_PRIVATE(pScrn);
   2663 
   2664     if (pPriv->videoStatus & TIMER_MASK) {
   2665 #if 1
   2666 	Time now = currentTime.milliseconds;
   2667 #else
   2668 	UpdateCurrentTime();
   2669 #endif
   2670 	if (pPriv->videoStatus & OFF_TIMER) {
   2671 	    if (pPriv->offTime < now) {
   2672 		/* Turn off the overlay */
   2673 		OVERLAY_DEBUG("BLOCKHANDLER\n");
   2674 
   2675 		i830_overlay_off (pScrn);
   2676 
   2677 		pPriv->videoStatus = FREE_TIMER;
   2678 		pPriv->freeTime = now + FREE_DELAY;
   2679 	    }
   2680 	} else {				/* FREE_TIMER */
   2681 	    if (pPriv->freeTime < now) {
   2682 		if (!pPriv->textured)
   2683 		    drm_intel_bo_unpin(pPriv->buf);
   2684 		drm_intel_bo_unreference(pPriv->buf);
   2685 		pPriv->buf = NULL;
   2686 		pPriv->videoStatus = 0;
   2687 	    }
   2688 	}
   2689     }
   2690 }
   2691 
   2692 /***************************************************************************
   2693  * Offscreen Images
   2694  ***************************************************************************/
   2695 
   2696 typedef struct {
   2697     Bool isOn;
   2698 } OffscreenPrivRec, *OffscreenPrivPtr;
   2699 
   2700 static int
   2701 I830AllocateSurface(ScrnInfoPtr pScrn,
   2702 		    int id,
   2703 		    unsigned short w,
   2704 		    unsigned short h, XF86SurfacePtr surface)
   2705 {
   2706     int pitch, fbpitch, size;
   2707     OffscreenPrivPtr pPriv;
   2708     I830Ptr pI830 = I830PTR(pScrn);
   2709 
   2710     OVERLAY_DEBUG("I830AllocateSurface\n");
   2711 
   2712     if (IS_845G(pI830) || IS_I830(pI830)) {
   2713 	if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY))
   2714 	    return BadAlloc;
   2715     } else {
   2716 	if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
   2717 	    return BadAlloc;
   2718     }
   2719 
   2720     if (!(surface->pitches = xalloc(sizeof(int))))
   2721 	return BadAlloc;
   2722     if (!(surface->offsets = xalloc(sizeof(int)))) {
   2723 	xfree(surface->pitches);
   2724 	return BadAlloc;
   2725     }
   2726     if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
   2727 	xfree(surface->pitches);
   2728 	xfree(surface->offsets);
   2729 	return BadAlloc;
   2730     }
   2731 
   2732     w = (w + 1) & ~1;
   2733     pitch = ((w << 1) + 15) & ~15;
   2734     fbpitch = pI830->cpp * pScrn->displayWidth;
   2735     size = pitch * h;
   2736 
   2737     surface->width = w;
   2738     surface->height = h;
   2739 
   2740     pPriv->isOn = FALSE;
   2741 
   2742     surface->pScrn = pScrn;
   2743     surface->id = id;
   2744     surface->pitches[0] = pitch;
   2745     surface->offsets[0] = 0;
   2746     surface->devPrivate.ptr = (pointer) pPriv;
   2747 
   2748     return Success;
   2749 }
   2750 
   2751 static int
   2752 I830StopSurface(XF86SurfacePtr surface)
   2753 {
   2754     OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
   2755     ScrnInfoPtr pScrn = surface->pScrn;
   2756 
   2757     if (pPriv->isOn) {
   2758 	OVERLAY_DEBUG("StopSurface\n");
   2759 
   2760 	i830_overlay_off (pScrn);
   2761 
   2762 	pPriv->isOn = FALSE;
   2763     }
   2764 
   2765     return Success;
   2766 }
   2767 
   2768 static int
   2769 I830FreeSurface(XF86SurfacePtr surface)
   2770 {
   2771     I830StopSurface(surface);
   2772     xfree(surface->pitches);
   2773     xfree(surface->offsets);
   2774     xfree(surface->devPrivate.ptr);
   2775 
   2776     return Success;
   2777 }
   2778 
   2779 static int
   2780 I830GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value)
   2781 {
   2782     return I830GetPortAttribute(pScrn, attribute, value, NULL);
   2783 }
   2784 
   2785 static int
   2786 I830SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
   2787 {
   2788     return I830SetPortAttributeOverlay(pScrn, attribute, value, NULL);
   2789 }
   2790 
   2791 static int
   2792 I830DisplaySurface(XF86SurfacePtr surface,
   2793 		   short src_x, short src_y,
   2794 		   short drw_x, short drw_y,
   2795 		   short src_w, short src_h,
   2796 		   short drw_w, short drw_h, RegionPtr clipBoxes)
   2797 {
   2798     OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
   2799     ScrnInfoPtr pScrn = surface->pScrn;
   2800     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
   2801     I830Ptr pI830 = I830PTR(pScrn);
   2802     I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
   2803     INT32 x1, y1, x2, y2;
   2804     BoxRec dstBox;
   2805     xf86CrtcPtr crtc;
   2806 
   2807     OVERLAY_DEBUG("I830DisplaySurface\n");
   2808 
   2809     x1 = src_x;
   2810     x2 = src_x + src_w;
   2811     y1 = src_y;
   2812     y2 = src_y + src_h;
   2813 
   2814     dstBox.x1 = drw_x;
   2815     dstBox.x2 = drw_x + drw_w;
   2816     dstBox.y1 = drw_y;
   2817     dstBox.y2 = drw_y + drw_h;
   2818 
   2819     if (!i830_clip_video_helper (pScrn, pI830Priv, &crtc, &dstBox,
   2820 				 &x1, &x2, &y1, &y2, clipBoxes,
   2821 				 surface->width, surface->height))
   2822 	return Success;
   2823 
   2824     /* fixup pointers */
   2825     pI830Priv->YBuf0offset = surface->offsets[0];
   2826     pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
   2827 
   2828     /* Pick the idle buffer */
   2829     if (!pI830Priv->textured && pI830->overlayOn && pI830Priv->doubleBuffer)
   2830 	pI830Priv->currentBuf = !((INREG(DOVSTA) & OC_BUF) >> 20);
   2831 
   2832     i830_display_video(pScrn, crtc, surface->id, surface->width, surface->height,
   2833 		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
   2834 		     src_w, src_h, drw_w, drw_h);
   2835 
   2836     xf86XVFillKeyHelper(pScrn->pScreen, pI830Priv->colorKey, clipBoxes);
   2837 
   2838     pPriv->isOn = TRUE;
   2839     /* we've prempted the XvImage stream so set its free timer */
   2840     if (pI830Priv->videoStatus & CLIENT_VIDEO_ON) {
   2841 	REGION_EMPTY(pScrn->pScreen, &pI830Priv->clip);
   2842 	UpdateCurrentTime();
   2843 	pI830Priv->videoStatus = FREE_TIMER;
   2844 	pI830Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
   2845     }
   2846 
   2847     return Success;
   2848 }
   2849 
   2850 static void
   2851 I830InitOffscreenImages(ScreenPtr pScreen)
   2852 {
   2853     XF86OffscreenImagePtr offscreenImages;
   2854     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
   2855     I830Ptr pI830 = I830PTR(pScrn);
   2856 
   2857     if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
   2858 	return;
   2859     }
   2860 
   2861     pI830->offscreenImages = offscreenImages;
   2862 
   2863     offscreenImages[0].image = &Images[0];
   2864     offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
   2865     offscreenImages[0].alloc_surface = I830AllocateSurface;
   2866     offscreenImages[0].free_surface = I830FreeSurface;
   2867     offscreenImages[0].display = I830DisplaySurface;
   2868     offscreenImages[0].stop = I830StopSurface;
   2869     offscreenImages[0].setAttribute = I830SetSurfaceAttribute;
   2870     offscreenImages[0].getAttribute = I830GetSurfaceAttribute;
   2871     if (IS_845G(pI830) || IS_I830(pI830)) {
   2872 	offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY;
   2873 	offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY;
   2874     } else {
   2875 	offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
   2876 	offscreenImages[0].max_height = IMAGE_MAX_HEIGHT;
   2877     }
   2878     offscreenImages[0].num_attributes = 1;
   2879     offscreenImages[0].attributes = Attributes;
   2880 
   2881     xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
   2882 }
   2883 
   2884 void
   2885 i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on)
   2886 {
   2887     ScrnInfoPtr pScrn = crtc->scrn;
   2888     I830Ptr pI830 = I830PTR(pScrn);
   2889     I830PortPrivPtr pPriv;
   2890 
   2891     /* no overlay */
   2892     if (pI830->adaptor == NULL)
   2893 	return;
   2894 
   2895     pPriv = GET_PORT_PRIVATE(pScrn);
   2896 
   2897     if (crtc != pPriv->current_crtc)
   2898 	return;
   2899 
   2900     /* Check if it's the crtc the overlay is off */
   2901     if (!on) {
   2902 	/* We stop the video when mode switching, so we don't lock up
   2903 	 * the engine. The overlayOK will determine whether we can re-enable
   2904 	 * with the current video on completion of the mode switch.
   2905 	 */
   2906 	I830StopVideo(pScrn, pPriv, TRUE);
   2907 	pPriv->current_crtc = NULL;
   2908 	pPriv->overlayOK = FALSE;
   2909 	pPriv->oneLineMode = FALSE;
   2910     }
   2911 }
   2912