103b705cfSriastradh/***************************************************************************
203b705cfSriastradh
303b705cfSriastradhCopyright 2000 Intel Corporation.  All Rights Reserved.
403b705cfSriastradh
503b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
603b705cfSriastradhcopy of this software and associated documentation files (the
703b705cfSriastradh"Software"), to deal in the Software without restriction, including
803b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish,
903b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to
1003b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to
1103b705cfSriastradhthe following conditions:
1203b705cfSriastradh
1303b705cfSriastradhThe above copyright notice and this permission notice (including the
1403b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions
1503b705cfSriastradhof the Software.
1603b705cfSriastradh
1703b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1803b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1903b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2003b705cfSriastradhIN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2103b705cfSriastradhDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2203b705cfSriastradhOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
2303b705cfSriastradhTHE USE OR OTHER DEALINGS IN THE SOFTWARE.
2403b705cfSriastradh
2503b705cfSriastradh**************************************************************************/
2603b705cfSriastradh
2703b705cfSriastradh/*
2803b705cfSriastradh * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
2903b705cfSriastradh *
3003b705cfSriastradh * Authors:
3103b705cfSriastradh * 	Jonathan Bian <jonathan.bian@intel.com>
3203b705cfSriastradh *      Offscreen Images:
3303b705cfSriastradh *        Matt Sottek <matthew.j.sottek@intel.com>
3403b705cfSriastradh */
3503b705cfSriastradh
3603b705cfSriastradh#ifdef HAVE_CONFIG_H
3703b705cfSriastradh#include "config.h"
3803b705cfSriastradh#endif
3903b705cfSriastradh
4003b705cfSriastradh#include <string.h>
4103b705cfSriastradh
4242542f5fSchristos#include "xorg-server.h"
4303b705cfSriastradh#include "xf86.h"
4403b705cfSriastradh#include "xf86_OSproc.h"
4503b705cfSriastradh#include "compiler.h"
4603b705cfSriastradh#include "xf86Pci.h"
4703b705cfSriastradh#include "xf86fbman.h"
4803b705cfSriastradh#include "regionstr.h"
4903b705cfSriastradh
5003b705cfSriastradh#include "i810.h"
5103b705cfSriastradh#include "xf86xv.h"
5203b705cfSriastradh#include <X11/extensions/Xv.h>
5303b705cfSriastradh#include "dixstruct.h"
5403b705cfSriastradh#include "fourcc.h"
5503b705cfSriastradh
5603b705cfSriastradh#define OFF_DELAY 	250  /* milliseconds */
5703b705cfSriastradh#define FREE_DELAY 	15000
5803b705cfSriastradh
5903b705cfSriastradh#define OFF_TIMER 	0x01
6003b705cfSriastradh#define FREE_TIMER	0x02
6103b705cfSriastradh#define CLIENT_VIDEO_ON	0x04
6203b705cfSriastradh
6303b705cfSriastradh#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
6403b705cfSriastradh
6503b705cfSriastradhstatic void I810InitOffscreenImages(ScreenPtr);
6603b705cfSriastradh
6703b705cfSriastradhstatic XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr);
6803b705cfSriastradhstatic void I810StopVideo(ScrnInfoPtr, pointer, Bool);
6903b705cfSriastradhstatic int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
7003b705cfSriastradhstatic int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
7103b705cfSriastradhstatic void I810QueryBestSize(ScrnInfoPtr, Bool,
7203b705cfSriastradh	short, short, short, short, unsigned int *, unsigned int *, pointer);
7303b705cfSriastradhstatic int I810PutImage( ScrnInfoPtr,
7403b705cfSriastradh	short, short, short, short, short, short, short, short,
7503b705cfSriastradh	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
7603b705cfSriastradh	DrawablePtr);
7703b705cfSriastradhstatic int I810QueryImageAttributes(ScrnInfoPtr,
7803b705cfSriastradh	int, unsigned short *, unsigned short *,  int *, int *);
7903b705cfSriastradh
80fe8aea9eSmrg#if !HAVE_NOTIFY_FD
8103b705cfSriastradhstatic void I810BlockHandler(BLOCKHANDLER_ARGS_DECL);
82fe8aea9eSmrg#else
83fe8aea9eSmrgstatic void I810BlockHandler(void *data, void *_timeout);
84fe8aea9eSmrg#endif
8503b705cfSriastradh
8603b705cfSriastradh#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
8703b705cfSriastradh
8803b705cfSriastradhstatic Atom xvBrightness, xvContrast, xvColorKey;
8903b705cfSriastradh
9003b705cfSriastradh#define IMAGE_MAX_WIDTH		1440
9103b705cfSriastradh#define IMAGE_FAST_WIDTH	720
9203b705cfSriastradh#define IMAGE_MAX_HEIGHT	1080
9303b705cfSriastradh#define Y_BUF_SIZE		(IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
9403b705cfSriastradh
9503b705cfSriastradh#define OVERLAY_UPDATE(p)	OUTREG(0x30000, p | 0x80000000);
9603b705cfSriastradh
9703b705cfSriastradh/*
9803b705cfSriastradh * OV0CMD - Overlay Command Register
9903b705cfSriastradh */
10003b705cfSriastradh#define	VERTICAL_CHROMINANCE_FILTER 	0x70000000
10103b705cfSriastradh#define VC_SCALING_OFF		0x00000000
10203b705cfSriastradh#define VC_LINE_REPLICATION	0x10000000
10303b705cfSriastradh#define VC_UP_INTERPOLATION	0x20000000
10403b705cfSriastradh#define VC_PIXEL_DROPPING	0x50000000
10503b705cfSriastradh#define VC_DOWN_INTERPOLATION	0x60000000
10603b705cfSriastradh#define VERTICAL_LUMINANCE_FILTER	0x0E000000
10703b705cfSriastradh#define VL_SCALING_OFF		0x00000000
10803b705cfSriastradh#define VL_LINE_REPLICATION	0x02000000
10903b705cfSriastradh#define VL_UP_INTERPOLATION	0x04000000
11003b705cfSriastradh#define VL_PIXEL_DROPPING	0x0A000000
11103b705cfSriastradh#define VL_DOWN_INTERPOLATION	0x0C000000
11203b705cfSriastradh#define	HORIZONTAL_CHROMINANCE_FILTER 	0x01C00000
11303b705cfSriastradh#define HC_SCALING_OFF		0x00000000
11403b705cfSriastradh#define HC_LINE_REPLICATION	0x00400000
11503b705cfSriastradh#define HC_UP_INTERPOLATION	0x00800000
11603b705cfSriastradh#define HC_PIXEL_DROPPING	0x01400000
11703b705cfSriastradh#define HC_DOWN_INTERPOLATION	0x01800000
11803b705cfSriastradh#define HORIZONTAL_LUMINANCE_FILTER	0x00380000
11903b705cfSriastradh#define HL_SCALING_OFF		0x00000000
12003b705cfSriastradh#define HL_LINE_REPLICATION	0x00080000
12103b705cfSriastradh#define HL_UP_INTERPOLATION	0x00100000
12203b705cfSriastradh#define HL_PIXEL_DROPPING	0x00280000
12303b705cfSriastradh#define HL_DOWN_INTERPOLATION	0x00300000
12403b705cfSriastradh
12503b705cfSriastradh#define Y_ADJUST		0x00010000
12603b705cfSriastradh#define OV_BYTE_ORDER		0x0000C000
12703b705cfSriastradh#define UV_SWAP			0x00004000
12803b705cfSriastradh#define Y_SWAP			0x00008000
12903b705cfSriastradh#define Y_AND_UV_SWAP		0x0000C000
13003b705cfSriastradh#define SOURCE_FORMAT		0x00003C00
13103b705cfSriastradh#define	RGB_555			0x00000800
13203b705cfSriastradh#define	RGB_565			0x00000C00
13303b705cfSriastradh#define	YUV_422			0x00002000
13403b705cfSriastradh#define	YUV_411			0x00002400
13503b705cfSriastradh#define	YUV_420			0x00003000
13603b705cfSriastradh#define	YUV_410			0x00003800
13703b705cfSriastradh#define BUFFER_AND_FIELD	0x00000006
13803b705cfSriastradh#define	BUFFER0_FIELD0		0x00000000
13903b705cfSriastradh#define	BUFFER1_FIELD0		0x00000004
14003b705cfSriastradh#define OVERLAY_ENABLE		0x00000001
14103b705cfSriastradh
14203b705cfSriastradh#define UV_VERT_BUF1 		0x02
14303b705cfSriastradh#define UV_VERT_BUF0 		0x04
14403b705cfSriastradh
14503b705cfSriastradh/*
14603b705cfSriastradh * DOV0STA - Display/Overlay 0 Status Register
14703b705cfSriastradh */
14803b705cfSriastradh#define	DOV0STA 	0x30008
14903b705cfSriastradh
15003b705cfSriastradh#define MINUV_SCALE	0x1
15103b705cfSriastradh
15203b705cfSriastradh#define RGB16ToColorKey(c) \
15303b705cfSriastradh	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
15403b705cfSriastradh
15503b705cfSriastradh#define RGB15ToColorKey(c) \
15603b705cfSriastradh        (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
15703b705cfSriastradh
15803b705cfSriastradhvoid I810InitVideo(ScreenPtr screen)
15903b705cfSriastradh{
16003b705cfSriastradh    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
16103b705cfSriastradh    XF86VideoAdaptorPtr *adaptors = NULL;
16203b705cfSriastradh    int num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
16303b705cfSriastradh
16403b705cfSriastradh    if (pScrn->bitsPerPixel != 8) {
16503b705cfSriastradh	XF86VideoAdaptorPtr newAdaptor;
16603b705cfSriastradh
16703b705cfSriastradh	newAdaptor = I810SetupImageVideo(screen);
16803b705cfSriastradh	I810InitOffscreenImages(screen);
16903b705cfSriastradh
17003b705cfSriastradh	if (newAdaptor) {
17103b705cfSriastradh	    XF86VideoAdaptorPtr *newAdaptors;
17203b705cfSriastradh
17303b705cfSriastradh	    newAdaptors =
17403b705cfSriastradh		realloc(adaptors,
17503b705cfSriastradh			(num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr));
17603b705cfSriastradh	    if (newAdaptors != NULL) {
17703b705cfSriastradh		newAdaptors[num_adaptors++] = newAdaptor;
17803b705cfSriastradh		adaptors = newAdaptors;
17903b705cfSriastradh	    }
18003b705cfSriastradh	}
18103b705cfSriastradh    }
18203b705cfSriastradh
18303b705cfSriastradh    if (num_adaptors)
18403b705cfSriastradh	xf86XVScreenInit(screen, adaptors, num_adaptors);
18503b705cfSriastradh
18603b705cfSriastradh    free(adaptors);
18703b705cfSriastradh}
18803b705cfSriastradh
18903b705cfSriastradh/* *INDENT-OFF* */
19003b705cfSriastradh/* client libraries expect an encoding */
19103b705cfSriastradhstatic XF86VideoEncodingRec DummyEncoding[1] =
19203b705cfSriastradh{
19303b705cfSriastradh {
19403b705cfSriastradh   0,
19503b705cfSriastradh   "XV_IMAGE",
19603b705cfSriastradh   IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
19703b705cfSriastradh   {1, 1}
19803b705cfSriastradh }
19903b705cfSriastradh};
20003b705cfSriastradh
20103b705cfSriastradh#define NUM_FORMATS 3
20203b705cfSriastradh
20303b705cfSriastradhstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
20403b705cfSriastradh{
20503b705cfSriastradh  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
20603b705cfSriastradh};
20703b705cfSriastradh
20803b705cfSriastradh#define NUM_ATTRIBUTES 3
20903b705cfSriastradh
21003b705cfSriastradhstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
21103b705cfSriastradh{
21203b705cfSriastradh   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
21303b705cfSriastradh   {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
21403b705cfSriastradh   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
21503b705cfSriastradh};
21603b705cfSriastradh
21703b705cfSriastradh#define NUM_IMAGES 6
21803b705cfSriastradh
21903b705cfSriastradh#define I810_RV15 0x35315652
22003b705cfSriastradh#define I810_RV16 0x36315652
22103b705cfSriastradh
22203b705cfSriastradhstatic XF86ImageRec Images[NUM_IMAGES] =
22303b705cfSriastradh{
22403b705cfSriastradh   {
22503b705cfSriastradh	I810_RV15,
22603b705cfSriastradh        XvRGB,
22703b705cfSriastradh	LSBFirst,
22803b705cfSriastradh	{'R','V','1','5',
22903b705cfSriastradh	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
23003b705cfSriastradh	16,
23103b705cfSriastradh	XvPacked,
23203b705cfSriastradh	1,
23303b705cfSriastradh	15, 0x7C00, 0x03E0, 0x001F,
23403b705cfSriastradh	0, 0, 0,
23503b705cfSriastradh	0, 0, 0,
23603b705cfSriastradh	0, 0, 0,
23703b705cfSriastradh	{'R','V','B',0,
23803b705cfSriastradh	  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
23903b705cfSriastradh	XvTopToBottom
24003b705cfSriastradh   },
24103b705cfSriastradh   {
24203b705cfSriastradh	I810_RV16,
24303b705cfSriastradh        XvRGB,
24403b705cfSriastradh	LSBFirst,
24503b705cfSriastradh	{'R','V','1','6',
24603b705cfSriastradh	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
24703b705cfSriastradh	16,
24803b705cfSriastradh	XvPacked,
24903b705cfSriastradh	1,
25003b705cfSriastradh	16, 0xF800, 0x07E0, 0x001F,
25103b705cfSriastradh	0, 0, 0,
25203b705cfSriastradh	0, 0, 0,
25303b705cfSriastradh	0, 0, 0,
25403b705cfSriastradh	{'R','V','B',0,
25503b705cfSriastradh	  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
25603b705cfSriastradh	XvTopToBottom
25703b705cfSriastradh   },
25803b705cfSriastradh	XVIMAGE_YUY2,
25903b705cfSriastradh	XVIMAGE_YV12,
26003b705cfSriastradh	XVIMAGE_I420,
26103b705cfSriastradh	XVIMAGE_UYVY
26203b705cfSriastradh};
26303b705cfSriastradh/* *INDENT-ON* */
26403b705cfSriastradh
26503b705cfSriastradhtypedef struct {
26603b705cfSriastradh    uint32_t OBUF_0Y;
26703b705cfSriastradh    uint32_t OBUF_1Y;
26803b705cfSriastradh    uint32_t OBUF_0U;
26903b705cfSriastradh    uint32_t OBUF_0V;
27003b705cfSriastradh    uint32_t OBUF_1U;
27103b705cfSriastradh    uint32_t OBUF_1V;
27203b705cfSriastradh    uint32_t OV0STRIDE;
27303b705cfSriastradh    uint32_t YRGB_VPH;
27403b705cfSriastradh    uint32_t UV_VPH;
27503b705cfSriastradh    uint32_t HORZ_PH;
27603b705cfSriastradh    uint32_t INIT_PH;
27703b705cfSriastradh    uint32_t DWINPOS;
27803b705cfSriastradh    uint32_t DWINSZ;
27903b705cfSriastradh    uint32_t SWID;
28003b705cfSriastradh    uint32_t SWIDQW;
28103b705cfSriastradh    uint32_t SHEIGHT;
28203b705cfSriastradh    uint32_t YRGBSCALE;
28303b705cfSriastradh    uint32_t UVSCALE;
28403b705cfSriastradh    uint32_t OV0CLRC0;
28503b705cfSriastradh    uint32_t OV0CLRC1;
28603b705cfSriastradh    uint32_t DCLRKV;
28703b705cfSriastradh    uint32_t DCLRKM;
28803b705cfSriastradh    uint32_t SCLRKVH;
28903b705cfSriastradh    uint32_t SCLRKVL;
29003b705cfSriastradh    uint32_t SCLRKM;
29103b705cfSriastradh    uint32_t OV0CONF;
29203b705cfSriastradh    uint32_t OV0CMD;
29303b705cfSriastradh} I810OverlayRegRec, *I810OverlayRegPtr;
29403b705cfSriastradh
29503b705cfSriastradhtypedef struct {
29603b705cfSriastradh	uint32_t     YBuf0offset;
29703b705cfSriastradh	uint32_t     UBuf0offset;
29803b705cfSriastradh	uint32_t     VBuf0offset;
29903b705cfSriastradh
30003b705cfSriastradh	uint32_t     YBuf1offset;
30103b705cfSriastradh	uint32_t     UBuf1offset;
30203b705cfSriastradh	uint32_t     VBuf1offset;
30303b705cfSriastradh
30403b705cfSriastradh	unsigned char currentBuf;
30503b705cfSriastradh
30603b705cfSriastradh	int          brightness;
30703b705cfSriastradh	int          contrast;
30803b705cfSriastradh
30903b705cfSriastradh	RegionRec    clip;
31003b705cfSriastradh	uint32_t     colorKey;
31103b705cfSriastradh
31203b705cfSriastradh	uint32_t     videoStatus;
31303b705cfSriastradh	Time         offTime;
31403b705cfSriastradh	Time         freeTime;
31503b705cfSriastradh	FBLinearPtr  linear;
31603b705cfSriastradh} I810PortPrivRec, *I810PortPrivPtr;
31703b705cfSriastradh
31803b705cfSriastradh#define GET_PORT_PRIVATE(pScrn) \
31903b705cfSriastradh   (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
32003b705cfSriastradh
32103b705cfSriastradhstatic void I810ResetVideo(ScrnInfoPtr pScrn)
32203b705cfSriastradh{
32303b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
32403b705cfSriastradh    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
32503b705cfSriastradh    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
32603b705cfSriastradh
32703b705cfSriastradh    /*
32803b705cfSriastradh     * Default to maximum image size in YV12
32903b705cfSriastradh     */
33003b705cfSriastradh
33103b705cfSriastradh    overlay->YRGB_VPH = 0;
33203b705cfSriastradh    overlay->UV_VPH = 0;
33303b705cfSriastradh    overlay->HORZ_PH = 0;
33403b705cfSriastradh    overlay->INIT_PH = 0;
33503b705cfSriastradh    overlay->DWINPOS = 0;
33603b705cfSriastradh    overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
33703b705cfSriastradh    overlay->SWID =  IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15);
33803b705cfSriastradh    overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
33903b705cfSriastradh    overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
34003b705cfSriastradh    overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */
34103b705cfSriastradh    overlay->UVSCALE = 0x80004000; /* scale factor 1 */
34203b705cfSriastradh    overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
34303b705cfSriastradh    overlay->OV0CLRC1 = 0x80; /* saturation: bypass */
34403b705cfSriastradh
34503b705cfSriastradh    /*
34603b705cfSriastradh     * Enable destination color keying
34703b705cfSriastradh     */
34803b705cfSriastradh    switch(pScrn->depth) {
34903b705cfSriastradh    case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
35003b705cfSriastradh             overlay->DCLRKM = 0x80070307;
35103b705cfSriastradh             break;
35203b705cfSriastradh    case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
35303b705cfSriastradh             overlay->DCLRKM = 0x80070707;
35403b705cfSriastradh             break;
35503b705cfSriastradh    default: overlay->DCLRKV = pPriv->colorKey;
35603b705cfSriastradh             overlay->DCLRKM = 0x80000000;
35703b705cfSriastradh             break;
35803b705cfSriastradh    }
35903b705cfSriastradh
36003b705cfSriastradh    overlay->SCLRKVH = 0;
36103b705cfSriastradh    overlay->SCLRKVL = 0;
36203b705cfSriastradh    overlay->SCLRKM = 0; /* source color key disable */
36303b705cfSriastradh    overlay->OV0CONF = 0; /* two 720 pixel line buffers */
36403b705cfSriastradh
36503b705cfSriastradh    overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
36603b705cfSriastradh		      YUV_420;
36703b705cfSriastradh
36803b705cfSriastradh    OVERLAY_UPDATE(pI810->OverlayPhysical);
36903b705cfSriastradh}
37003b705cfSriastradh
37103b705cfSriastradh
37203b705cfSriastradhstatic XF86VideoAdaptorPtr
37303b705cfSriastradhI810SetupImageVideo(ScreenPtr screen)
37403b705cfSriastradh{
37503b705cfSriastradh    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
37603b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
37703b705cfSriastradh    XF86VideoAdaptorPtr adapt;
37803b705cfSriastradh    I810PortPrivPtr pPriv;
37903b705cfSriastradh
38003b705cfSriastradh    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
38103b705cfSriastradh			    sizeof(I810PortPrivRec) +
38203b705cfSriastradh			    sizeof(DevUnion))))
38303b705cfSriastradh	return NULL;
38403b705cfSriastradh
38503b705cfSriastradh    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
38603b705cfSriastradh    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
38703b705cfSriastradh    adapt->name = "I810 Video Overlay";
38803b705cfSriastradh    adapt->nEncodings = 1;
38903b705cfSriastradh    adapt->pEncodings = DummyEncoding;
39003b705cfSriastradh    adapt->nFormats = NUM_FORMATS;
39103b705cfSriastradh    adapt->pFormats = Formats;
39203b705cfSriastradh    adapt->nPorts = 1;
39303b705cfSriastradh    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
39403b705cfSriastradh
39503b705cfSriastradh    pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]);
39603b705cfSriastradh
39703b705cfSriastradh    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
39803b705cfSriastradh    adapt->pAttributes = Attributes;
39903b705cfSriastradh    adapt->nImages = NUM_IMAGES;
40003b705cfSriastradh    adapt->nAttributes = NUM_ATTRIBUTES;
40103b705cfSriastradh    adapt->pImages = Images;
40203b705cfSriastradh    adapt->PutVideo = NULL;
40303b705cfSriastradh    adapt->PutStill = NULL;
40403b705cfSriastradh    adapt->GetVideo = NULL;
40503b705cfSriastradh    adapt->GetStill = NULL;
40603b705cfSriastradh    adapt->StopVideo = I810StopVideo;
40703b705cfSriastradh    adapt->SetPortAttribute = I810SetPortAttribute;
40803b705cfSriastradh    adapt->GetPortAttribute = I810GetPortAttribute;
40903b705cfSriastradh    adapt->QueryBestSize = I810QueryBestSize;
41003b705cfSriastradh    adapt->PutImage = I810PutImage;
41103b705cfSriastradh    adapt->QueryImageAttributes = I810QueryImageAttributes;
41203b705cfSriastradh
41303b705cfSriastradh    pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1);
41403b705cfSriastradh    pPriv->videoStatus = 0;
41503b705cfSriastradh    pPriv->brightness = 0;
41603b705cfSriastradh    pPriv->contrast = 64;
41703b705cfSriastradh    pPriv->linear = NULL;
41803b705cfSriastradh    pPriv->currentBuf = 0;
41903b705cfSriastradh
42003b705cfSriastradh    /* gotta uninit this someplace */
42103b705cfSriastradh    REGION_NULL(screen, &pPriv->clip);
42203b705cfSriastradh
42303b705cfSriastradh    pI810->adaptor = adapt;
42403b705cfSriastradh
425fe8aea9eSmrg#if !HAVE_NOTIFY_FD
42603b705cfSriastradh    pI810->BlockHandler = screen->BlockHandler;
42703b705cfSriastradh    screen->BlockHandler = I810BlockHandler;
428fe8aea9eSmrg#else
429fe8aea9eSmrg    RegisterBlockAndWakeupHandlers(I810BlockHandler,
430fe8aea9eSmrg				   (ServerWakeupHandlerProcPtr)NoopDDA,
431fe8aea9eSmrg				   pScrn);
432fe8aea9eSmrg#endif
43303b705cfSriastradh
43403b705cfSriastradh    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
43503b705cfSriastradh    xvContrast   = MAKE_ATOM("XV_CONTRAST");
43603b705cfSriastradh    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
43703b705cfSriastradh
43803b705cfSriastradh    I810ResetVideo(pScrn);
43903b705cfSriastradh
44003b705cfSriastradh    return adapt;
44103b705cfSriastradh}
44203b705cfSriastradh
44303b705cfSriastradh
44403b705cfSriastradh/* I810ClipVideo -
44503b705cfSriastradh
44603b705cfSriastradh   Takes the dst box in standard X BoxRec form (top and left
44703b705cfSriastradh   edges inclusive, bottom and right exclusive).  The new dst
44803b705cfSriastradh   box is returned.  The source boundaries are given (x1, y1
44903b705cfSriastradh   inclusive, x2, y2 exclusive) and returned are the new source
45003b705cfSriastradh   boundaries in 16.16 fixed point.
45103b705cfSriastradh*/
45203b705cfSriastradh
45303b705cfSriastradhstatic void
45403b705cfSriastradhI810ClipVideo(
45503b705cfSriastradh  BoxPtr dst,
45603b705cfSriastradh  INT32 *x1,
45703b705cfSriastradh  INT32 *x2,
45803b705cfSriastradh  INT32 *y1,
45903b705cfSriastradh  INT32 *y2,
46003b705cfSriastradh  BoxPtr extents,            /* extents of the clip region */
46103b705cfSriastradh  INT32 width,
46203b705cfSriastradh  INT32 height
46303b705cfSriastradh){
46403b705cfSriastradh    INT32 vscale, hscale, delta;
46503b705cfSriastradh    int diff;
46603b705cfSriastradh
46703b705cfSriastradh    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
46803b705cfSriastradh    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
46903b705cfSriastradh
47003b705cfSriastradh    *x1 <<= 16; *x2 <<= 16;
47103b705cfSriastradh    *y1 <<= 16; *y2 <<= 16;
47203b705cfSriastradh
47303b705cfSriastradh    diff = extents->x1 - dst->x1;
47403b705cfSriastradh    if(diff > 0) {
47503b705cfSriastradh	dst->x1 = extents->x1;
47603b705cfSriastradh	*x1 += diff * hscale;
47703b705cfSriastradh    }
47803b705cfSriastradh    diff = dst->x2 - extents->x2;
47903b705cfSriastradh    if(diff > 0) {
48003b705cfSriastradh	dst->x2 = extents->x2;
48103b705cfSriastradh	*x2 -= diff * hscale;
48203b705cfSriastradh    }
48303b705cfSriastradh    diff = extents->y1 - dst->y1;
48403b705cfSriastradh    if(diff > 0) {
48503b705cfSriastradh	dst->y1 = extents->y1;
48603b705cfSriastradh	*y1 += diff * vscale;
48703b705cfSriastradh    }
48803b705cfSriastradh    diff = dst->y2 - extents->y2;
48903b705cfSriastradh    if(diff > 0) {
49003b705cfSriastradh	dst->y2 = extents->y2;
49103b705cfSriastradh	*y2 -= diff * vscale;
49203b705cfSriastradh    }
49303b705cfSriastradh
49403b705cfSriastradh    if(*x1 < 0) {
49503b705cfSriastradh	diff =  (- *x1 + hscale - 1)/ hscale;
49603b705cfSriastradh	dst->x1 += diff;
49703b705cfSriastradh	*x1 += diff * hscale;
49803b705cfSriastradh    }
49903b705cfSriastradh    delta = *x2 - (width << 16);
50003b705cfSriastradh    if(delta > 0) {
50103b705cfSriastradh	diff = (delta + hscale - 1)/ hscale;
50203b705cfSriastradh	dst->x2 -= diff;
50303b705cfSriastradh	*x2 -= diff * hscale;
50403b705cfSriastradh    }
50503b705cfSriastradh    if(*y1 < 0) {
50603b705cfSriastradh	diff =  (- *y1 + vscale - 1)/ vscale;
50703b705cfSriastradh	dst->y1 += diff;
50803b705cfSriastradh	*y1 += diff * vscale;
50903b705cfSriastradh    }
51003b705cfSriastradh    delta = *y2 - (height << 16);
51103b705cfSriastradh    if(delta > 0) {
51203b705cfSriastradh	diff = (delta + vscale - 1)/ vscale;
51303b705cfSriastradh	dst->y2 -= diff;
51403b705cfSriastradh	*y2 -= diff * vscale;
51503b705cfSriastradh    }
51603b705cfSriastradh}
51703b705cfSriastradh
51803b705cfSriastradhstatic void
51903b705cfSriastradhI810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
52003b705cfSriastradh{
52103b705cfSriastradh  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
52203b705cfSriastradh  I810Ptr pI810 = I810PTR(pScrn);
52303b705cfSriastradh
52403b705cfSriastradh  I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
52503b705cfSriastradh
52603b705cfSriastradh  REGION_EMPTY(pScrn->screen, &pPriv->clip);
52703b705cfSriastradh
52803b705cfSriastradh  if(shutdown) {
52903b705cfSriastradh     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
53003b705cfSriastradh	overlay->OV0CMD &= 0xFFFFFFFE;
53103b705cfSriastradh	OVERLAY_UPDATE(pI810->OverlayPhysical);
53203b705cfSriastradh     }
53303b705cfSriastradh     if(pPriv->linear) {
53403b705cfSriastradh	xf86FreeOffscreenLinear(pPriv->linear);
53503b705cfSriastradh	pPriv->linear = NULL;
53603b705cfSriastradh     }
53703b705cfSriastradh     pPriv->videoStatus = 0;
53803b705cfSriastradh  } else {
53903b705cfSriastradh     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
54003b705cfSriastradh	pPriv->videoStatus |= OFF_TIMER;
54103b705cfSriastradh	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
54203b705cfSriastradh     }
54303b705cfSriastradh  }
54403b705cfSriastradh
54503b705cfSriastradh}
54603b705cfSriastradh
54703b705cfSriastradhstatic int
54803b705cfSriastradhI810SetPortAttribute(
54903b705cfSriastradh  ScrnInfoPtr pScrn,
55003b705cfSriastradh  Atom attribute,
55103b705cfSriastradh  INT32 value,
55203b705cfSriastradh  pointer data
55303b705cfSriastradh){
55403b705cfSriastradh  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
55503b705cfSriastradh  I810Ptr pI810 = I810PTR(pScrn);
55603b705cfSriastradh  I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
55703b705cfSriastradh
55803b705cfSriastradh  if(attribute == xvBrightness) {
55903b705cfSriastradh	if((value < -128) || (value > 127))
56003b705cfSriastradh	   return BadValue;
56103b705cfSriastradh	pPriv->brightness = value;
56203b705cfSriastradh	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
56303b705cfSriastradh	OVERLAY_UPDATE(pI810->OverlayPhysical);
56403b705cfSriastradh  } else
56503b705cfSriastradh  if(attribute == xvContrast) {
56603b705cfSriastradh	if((value < 0) || (value > 255))
56703b705cfSriastradh	   return BadValue;
56803b705cfSriastradh	pPriv->contrast = value;
56903b705cfSriastradh	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
57003b705cfSriastradh	OVERLAY_UPDATE(pI810->OverlayPhysical);
57103b705cfSriastradh  } else
57203b705cfSriastradh  if(attribute == xvColorKey) {
57303b705cfSriastradh	pPriv->colorKey = value;
57403b705cfSriastradh	switch(pScrn->depth) {
57503b705cfSriastradh	case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
57603b705cfSriastradh	         break;
57703b705cfSriastradh	case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
57803b705cfSriastradh                 break;
57903b705cfSriastradh	default: overlay->DCLRKV = pPriv->colorKey;
58003b705cfSriastradh                 break;
58103b705cfSriastradh	}
58203b705cfSriastradh	OVERLAY_UPDATE(pI810->OverlayPhysical);
58303b705cfSriastradh	REGION_EMPTY(pScrn->screen, &pPriv->clip);
58403b705cfSriastradh  } else return BadMatch;
58503b705cfSriastradh
58603b705cfSriastradh  return Success;
58703b705cfSriastradh}
58803b705cfSriastradh
58903b705cfSriastradhstatic int
59003b705cfSriastradhI810GetPortAttribute(
59103b705cfSriastradh  ScrnInfoPtr pScrn,
59203b705cfSriastradh  Atom attribute,
59303b705cfSriastradh  INT32 *value,
59403b705cfSriastradh  pointer data
59503b705cfSriastradh){
59603b705cfSriastradh  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
59703b705cfSriastradh
59803b705cfSriastradh  if(attribute == xvBrightness) {
59903b705cfSriastradh	*value = pPriv->brightness;
60003b705cfSriastradh  } else
60103b705cfSriastradh  if(attribute == xvContrast) {
60203b705cfSriastradh	*value = pPriv->contrast;
60303b705cfSriastradh  } else
60403b705cfSriastradh  if(attribute == xvColorKey) {
60503b705cfSriastradh	*value = pPriv->colorKey;
60603b705cfSriastradh  } else return BadMatch;
60703b705cfSriastradh
60803b705cfSriastradh  return Success;
60903b705cfSriastradh}
61003b705cfSriastradh
61103b705cfSriastradhstatic void
61203b705cfSriastradhI810QueryBestSize(
61303b705cfSriastradh  ScrnInfoPtr pScrn,
61403b705cfSriastradh  Bool motion,
61503b705cfSriastradh  short vid_w, short vid_h,
61603b705cfSriastradh  short drw_w, short drw_h,
61703b705cfSriastradh  unsigned int *p_w, unsigned int *p_h,
61803b705cfSriastradh  pointer data
61903b705cfSriastradh){
62003b705cfSriastradh   if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
62103b705cfSriastradh   if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
62203b705cfSriastradh
62303b705cfSriastradh  *p_w = drw_w;
62403b705cfSriastradh  *p_h = drw_h;
62503b705cfSriastradh}
62603b705cfSriastradh
62703b705cfSriastradh
62803b705cfSriastradhstatic void
62903b705cfSriastradhI810CopyPackedData(
63003b705cfSriastradh   ScrnInfoPtr pScrn,
63103b705cfSriastradh   unsigned char *buf,
63203b705cfSriastradh   int srcPitch,
63303b705cfSriastradh   int dstPitch,
63403b705cfSriastradh   int top,
63503b705cfSriastradh   int left,
63603b705cfSriastradh   int h,
63703b705cfSriastradh   int w
63803b705cfSriastradh   )
63903b705cfSriastradh{
64003b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
64103b705cfSriastradh    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
64203b705cfSriastradh    unsigned char *src, *dst;
64303b705cfSriastradh
64403b705cfSriastradh    src = buf + (top*srcPitch) + (left<<1);
64503b705cfSriastradh
64603b705cfSriastradh    if (pPriv->currentBuf == 0)
64703b705cfSriastradh	dst = pI810->FbBase + pPriv->YBuf0offset;
64803b705cfSriastradh    else
64903b705cfSriastradh	dst = pI810->FbBase + pPriv->YBuf1offset;
65003b705cfSriastradh
65103b705cfSriastradh    w <<= 1;
65203b705cfSriastradh    while(h--) {
65303b705cfSriastradh	memcpy(dst, src, w);
65403b705cfSriastradh	src += srcPitch;
65503b705cfSriastradh	dst += dstPitch;
65603b705cfSriastradh    }
65703b705cfSriastradh}
65803b705cfSriastradh
65903b705cfSriastradhstatic void
66003b705cfSriastradhI810CopyPlanarData(
66103b705cfSriastradh   ScrnInfoPtr pScrn,
66203b705cfSriastradh   unsigned char *buf,
66303b705cfSriastradh   int srcPitch,
66403b705cfSriastradh   int dstPitch,  /* of chroma */
66503b705cfSriastradh   int srcH,
66603b705cfSriastradh   int top,
66703b705cfSriastradh   int left,
66803b705cfSriastradh   int h,
66903b705cfSriastradh   int w,
67003b705cfSriastradh   int id
67103b705cfSriastradh   )
67203b705cfSriastradh{
67303b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
67403b705cfSriastradh    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
67503b705cfSriastradh    int i;
67603b705cfSriastradh    unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
67703b705cfSriastradh
67803b705cfSriastradh    /* Copy Y data */
67903b705cfSriastradh    src1 = buf + (top*srcPitch) + left;
68003b705cfSriastradh    if (pPriv->currentBuf == 0)
68103b705cfSriastradh	dst1 = pI810->FbBase + pPriv->YBuf0offset;
68203b705cfSriastradh    else
68303b705cfSriastradh	dst1 = pI810->FbBase + pPriv->YBuf1offset;
68403b705cfSriastradh
68503b705cfSriastradh    for (i = 0; i < h; i++) {
68603b705cfSriastradh	memcpy(dst1, src1, w);
68703b705cfSriastradh	src1 += srcPitch;
68803b705cfSriastradh	dst1 += dstPitch << 1;
68903b705cfSriastradh    }
69003b705cfSriastradh
69103b705cfSriastradh    /* Copy V data for YV12, or U data for I420 */
69203b705cfSriastradh    src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
69303b705cfSriastradh    if (pPriv->currentBuf == 0) {
69403b705cfSriastradh	if (id == FOURCC_I420)
69503b705cfSriastradh	    dst2 = pI810->FbBase + pPriv->UBuf0offset;
69603b705cfSriastradh	else
69703b705cfSriastradh	    dst2 = pI810->FbBase + pPriv->VBuf0offset;
69803b705cfSriastradh    } else {
69903b705cfSriastradh	if (id == FOURCC_I420)
70003b705cfSriastradh	    dst2 = pI810->FbBase + pPriv->UBuf1offset;
70103b705cfSriastradh	else
70203b705cfSriastradh	    dst2 = pI810->FbBase + pPriv->VBuf1offset;
70303b705cfSriastradh    }
70403b705cfSriastradh
70503b705cfSriastradh    for (i = 0; i < h/2; i++) {
70603b705cfSriastradh	memcpy(dst2, src2, w/2);
70703b705cfSriastradh	src2 += srcPitch>>1;
70803b705cfSriastradh	dst2 += dstPitch;
70903b705cfSriastradh    }
71003b705cfSriastradh
71103b705cfSriastradh    /* Copy U data for YV12, or V data for I420 */
71203b705cfSriastradh    src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
71303b705cfSriastradh    if (pPriv->currentBuf == 0) {
71403b705cfSriastradh	if (id == FOURCC_I420)
71503b705cfSriastradh	    dst3 = pI810->FbBase + pPriv->VBuf0offset;
71603b705cfSriastradh	else
71703b705cfSriastradh	    dst3 = pI810->FbBase + pPriv->UBuf0offset;
71803b705cfSriastradh    } else {
71903b705cfSriastradh	if (id == FOURCC_I420)
72003b705cfSriastradh	    dst3 = pI810->FbBase + pPriv->VBuf1offset;
72103b705cfSriastradh	else
72203b705cfSriastradh	    dst3 = pI810->FbBase + pPriv->UBuf1offset;
72303b705cfSriastradh    }
72403b705cfSriastradh
72503b705cfSriastradh    for (i = 0; i < h/2; i++) {
72603b705cfSriastradh	memcpy(dst3, src3, w/2);
72703b705cfSriastradh	src3 += srcPitch>>1;
72803b705cfSriastradh	dst3 += dstPitch;
72903b705cfSriastradh    }
73003b705cfSriastradh}
73103b705cfSriastradh
73203b705cfSriastradhstatic void
73303b705cfSriastradhI810DisplayVideo(
73403b705cfSriastradh    ScrnInfoPtr pScrn,
73503b705cfSriastradh    int id,
73603b705cfSriastradh    short width, short height,
73703b705cfSriastradh    int dstPitch,  /* of chroma for 4:2:0 */
73803b705cfSriastradh    int x1, int y1, int x2, int y2,
73903b705cfSriastradh    BoxPtr dstBox,
74003b705cfSriastradh    short src_w, short src_h,
74103b705cfSriastradh    short drw_w, short drw_h
74203b705cfSriastradh){
74303b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
74403b705cfSriastradh    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
74503b705cfSriastradh    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
74603b705cfSriastradh    int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
74703b705cfSriastradh    int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0;
74803b705cfSriastradh    unsigned int swidth;
74903b705cfSriastradh
75003b705cfSriastradh    switch(id) {
75103b705cfSriastradh    case FOURCC_YV12:
75203b705cfSriastradh    case FOURCC_I420:
75303b705cfSriastradh	swidth = ALIGN(width, 8);
75403b705cfSriastradh	overlay->SWID = (swidth << 15) | swidth;
75503b705cfSriastradh	overlay->SWIDQW = (swidth << 12) | (swidth >> 3);
75603b705cfSriastradh	break;
75703b705cfSriastradh    case FOURCC_UYVY:
75803b705cfSriastradh    case FOURCC_YUY2:
75903b705cfSriastradh    default:
76003b705cfSriastradh	swidth = ALIGN(width, 4) << 1;
76103b705cfSriastradh	overlay->SWID = swidth;
76203b705cfSriastradh	overlay->SWIDQW = swidth >> 3;
76303b705cfSriastradh	break;
76403b705cfSriastradh    }
76503b705cfSriastradh
76603b705cfSriastradh    /* wide video formats (>720 pixels) are special */
76703b705cfSriastradh    if( swidth > IMAGE_FAST_WIDTH ) {
76803b705cfSriastradh	overlay->OV0CONF = 1; /* one 1440 pixel line buffer */
76903b705cfSriastradh    } else {
77003b705cfSriastradh	overlay->OV0CONF = 0; /* two 720 pixel line buffers */
77103b705cfSriastradh    }
77203b705cfSriastradh
77303b705cfSriastradh    overlay->SHEIGHT = height | (height << 15);
77403b705cfSriastradh    overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1);
77503b705cfSriastradh    overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
77603b705cfSriastradh	              (dstBox->x2 - dstBox->x1);
77703b705cfSriastradh
77803b705cfSriastradh    /* buffer locations */
77903b705cfSriastradh    overlay->OBUF_0Y = pPriv->YBuf0offset;
78003b705cfSriastradh    overlay->OBUF_1Y = pPriv->YBuf1offset;
78103b705cfSriastradh    overlay->OBUF_0U = pPriv->UBuf0offset;
78203b705cfSriastradh    overlay->OBUF_0V = pPriv->VBuf0offset;
78303b705cfSriastradh    overlay->OBUF_1U = pPriv->UBuf1offset;
78403b705cfSriastradh    overlay->OBUF_1V = pPriv->VBuf1offset;
78503b705cfSriastradh
78603b705cfSriastradh    /*
78703b705cfSriastradh     * Calculate horizontal and vertical scaling factors, default to 1:1
78803b705cfSriastradh     */
78903b705cfSriastradh    overlay->YRGBSCALE = 0x80004000;
79003b705cfSriastradh    overlay->UVSCALE = 0x80004000;
79103b705cfSriastradh
79203b705cfSriastradh    /*
79303b705cfSriastradh     * Initially, YCbCr and Overlay Enable and
79403b705cfSriastradh     * vertical chrominance up interpolation and horozontal chrominance
79503b705cfSriastradh     * up interpolation
79603b705cfSriastradh     */
79703b705cfSriastradh    overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
79803b705cfSriastradh	              OVERLAY_ENABLE;
79903b705cfSriastradh
80003b705cfSriastradh    if ((drw_w != src_w) || (drw_h != src_h))
80103b705cfSriastradh    {
80203b705cfSriastradh	xscaleInt = (src_w / drw_w) & 0x3;
80303b705cfSriastradh	xscaleFract = (src_w << 12) / drw_w;
80403b705cfSriastradh	yscaleInt = (src_h / drw_h) & 0x3;
80503b705cfSriastradh	yscaleFract = (src_h << 12) / drw_h;
80603b705cfSriastradh
80703b705cfSriastradh	overlay->YRGBSCALE = (xscaleInt << 15) |
80803b705cfSriastradh	                     ((xscaleFract & 0xFFF) << 3) |
80903b705cfSriastradh	                     (yscaleInt) |
81003b705cfSriastradh			     ((yscaleFract & 0xFFF) << 20);
81103b705cfSriastradh
81203b705cfSriastradh	if (drw_w > src_w)
81303b705cfSriastradh	{
81403b705cfSriastradh	    /* horizontal up-scaling */
81503b705cfSriastradh	    overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
81603b705cfSriastradh	    overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
81703b705cfSriastradh	    overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
81803b705cfSriastradh	}
81903b705cfSriastradh
82003b705cfSriastradh	if (drw_h > src_h)
82103b705cfSriastradh	{
82203b705cfSriastradh	    /* vertical up-scaling */
82303b705cfSriastradh	    overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
82403b705cfSriastradh	    overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
82503b705cfSriastradh	    overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
82603b705cfSriastradh	}
82703b705cfSriastradh
82803b705cfSriastradh	if (drw_w < src_w)
82903b705cfSriastradh	{
83003b705cfSriastradh	    /* horizontal down-scaling */
83103b705cfSriastradh	    overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
83203b705cfSriastradh	    overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
83303b705cfSriastradh	    overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
83403b705cfSriastradh	}
83503b705cfSriastradh
83603b705cfSriastradh	if (drw_h < src_h)
83703b705cfSriastradh	{
83803b705cfSriastradh	    /* vertical down-scaling */
83903b705cfSriastradh	    overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
84003b705cfSriastradh	    overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
84103b705cfSriastradh	    overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
84203b705cfSriastradh	}
84303b705cfSriastradh
84403b705cfSriastradh	/* now calculate the UV scaling factor */
84503b705cfSriastradh
84603b705cfSriastradh	if (xscaleFract)
84703b705cfSriastradh	{
84803b705cfSriastradh	    xscaleFractUV = xscaleFract >> MINUV_SCALE;
84903b705cfSriastradh	    overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION;
85003b705cfSriastradh	    overlay->OV0CMD |= HC_UP_INTERPOLATION;
85103b705cfSriastradh	}
85203b705cfSriastradh
85303b705cfSriastradh	if (xscaleInt)
85403b705cfSriastradh	{
85503b705cfSriastradh	    xscaleIntUV = xscaleInt >> MINUV_SCALE;
85603b705cfSriastradh	    if (xscaleIntUV)
85703b705cfSriastradh	    {
85803b705cfSriastradh		overlay->OV0CMD &= ~HC_UP_INTERPOLATION;
85903b705cfSriastradh	    }
86003b705cfSriastradh	}
86103b705cfSriastradh
86203b705cfSriastradh	if (yscaleFract)
86303b705cfSriastradh	{
86403b705cfSriastradh	    yscaleFractUV = yscaleFract >> MINUV_SCALE;
86503b705cfSriastradh	    overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION;
86603b705cfSriastradh	    overlay->OV0CMD |= VC_UP_INTERPOLATION;
86703b705cfSriastradh	}
86803b705cfSriastradh
86903b705cfSriastradh	if (yscaleInt)
87003b705cfSriastradh	{
87103b705cfSriastradh	    yscaleIntUV = yscaleInt >> MINUV_SCALE;
87203b705cfSriastradh	    if (yscaleIntUV)
87303b705cfSriastradh	    {
87403b705cfSriastradh		overlay->OV0CMD &= ~VC_UP_INTERPOLATION;
87503b705cfSriastradh		overlay->OV0CMD |= VC_DOWN_INTERPOLATION;
87603b705cfSriastradh	    }
87703b705cfSriastradh	}
87803b705cfSriastradh
87903b705cfSriastradh	overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
88003b705cfSriastradh	                   ((yscaleFractUV & 0xFFF) << 20);
88103b705cfSriastradh    }
88203b705cfSriastradh
88303b705cfSriastradh    switch(id) {
88403b705cfSriastradh    case FOURCC_YV12:
88503b705cfSriastradh    case FOURCC_I420:
88603b705cfSriastradh	/* set UV vertical phase to -0.25 */
88703b705cfSriastradh	overlay->UV_VPH = 0x30003000;
88803b705cfSriastradh	overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1;
88903b705cfSriastradh	overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
89003b705cfSriastradh	overlay->OV0CMD &= ~SOURCE_FORMAT;
89103b705cfSriastradh	overlay->OV0CMD |= YUV_420;
89203b705cfSriastradh	break;
89303b705cfSriastradh    case I810_RV15:
89403b705cfSriastradh    case I810_RV16:
89503b705cfSriastradh	overlay->UV_VPH = 0;
89603b705cfSriastradh	overlay->INIT_PH = 0;
89703b705cfSriastradh	overlay->OV0STRIDE = dstPitch;
89803b705cfSriastradh	overlay->OV0CMD &= ~SOURCE_FORMAT;
89903b705cfSriastradh	overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565);
90003b705cfSriastradh	overlay->OV0CMD &= ~OV_BYTE_ORDER;
90103b705cfSriastradh	break;
90203b705cfSriastradh    case FOURCC_UYVY:
90303b705cfSriastradh    case FOURCC_YUY2:
90403b705cfSriastradh    default:
90503b705cfSriastradh	overlay->UV_VPH = 0;
90603b705cfSriastradh	overlay->INIT_PH = 0;
90703b705cfSriastradh	overlay->OV0STRIDE = dstPitch;
90803b705cfSriastradh	overlay->OV0CMD &= ~SOURCE_FORMAT;
90903b705cfSriastradh	overlay->OV0CMD |= YUV_422;
91003b705cfSriastradh	overlay->OV0CMD &= ~OV_BYTE_ORDER;
91103b705cfSriastradh	if (id == FOURCC_UYVY)
91203b705cfSriastradh	    overlay->OV0CMD |= Y_SWAP;
91303b705cfSriastradh	break;
91403b705cfSriastradh    }
91503b705cfSriastradh
91603b705cfSriastradh    overlay->OV0CMD &= ~BUFFER_AND_FIELD;
91703b705cfSriastradh    if (pPriv->currentBuf == 0)
91803b705cfSriastradh	overlay->OV0CMD |= BUFFER0_FIELD0;
91903b705cfSriastradh    else
92003b705cfSriastradh	overlay->OV0CMD |= BUFFER1_FIELD0;
92103b705cfSriastradh
92203b705cfSriastradh    OVERLAY_UPDATE(pI810->OverlayPhysical);
92303b705cfSriastradh
92403b705cfSriastradh}
92503b705cfSriastradh
92603b705cfSriastradhstatic FBLinearPtr
92703b705cfSriastradhI810AllocateMemory(
92803b705cfSriastradh  ScrnInfoPtr pScrn,
92903b705cfSriastradh  FBLinearPtr linear,
93003b705cfSriastradh  int size
93103b705cfSriastradh){
93203b705cfSriastradh   ScreenPtr screen;
93303b705cfSriastradh   FBLinearPtr new_linear;
93403b705cfSriastradh
93503b705cfSriastradh   if(linear) {
93603b705cfSriastradh	if(linear->size >= size)
93703b705cfSriastradh	   return linear;
93803b705cfSriastradh
93903b705cfSriastradh	if(xf86ResizeOffscreenLinear(linear, size))
94003b705cfSriastradh	   return linear;
94103b705cfSriastradh
94203b705cfSriastradh	xf86FreeOffscreenLinear(linear);
94303b705cfSriastradh   }
94403b705cfSriastradh
94503b705cfSriastradh   screen = xf86ScrnToScreen(pScrn);
94603b705cfSriastradh
94703b705cfSriastradh   new_linear = xf86AllocateOffscreenLinear(screen, size, 4,
94803b705cfSriastradh                                            NULL, NULL, NULL);
94903b705cfSriastradh
95003b705cfSriastradh   if(!new_linear) {
95103b705cfSriastradh        int max_size;
95203b705cfSriastradh
95303b705cfSriastradh        xf86QueryLargestOffscreenLinear(screen, &max_size, 4,
95403b705cfSriastradh				       PRIORITY_EXTREME);
95503b705cfSriastradh
95603b705cfSriastradh        if(max_size < size) return NULL;
95703b705cfSriastradh
95803b705cfSriastradh        xf86PurgeUnlockedOffscreenAreas(screen);
95903b705cfSriastradh        new_linear = xf86AllocateOffscreenLinear(screen, size, 4,
96003b705cfSriastradh                                                 NULL, NULL, NULL);
96103b705cfSriastradh   }
96203b705cfSriastradh
96303b705cfSriastradh   return new_linear;
96403b705cfSriastradh}
96503b705cfSriastradh
96603b705cfSriastradhstatic int
96703b705cfSriastradhI810PutImage(
96803b705cfSriastradh  ScrnInfoPtr pScrn,
96903b705cfSriastradh  short src_x, short src_y,
97003b705cfSriastradh  short drw_x, short drw_y,
97103b705cfSriastradh  short src_w, short src_h,
97203b705cfSriastradh  short drw_w, short drw_h,
97303b705cfSriastradh  int id, unsigned char* buf,
97403b705cfSriastradh  short width, short height,
97503b705cfSriastradh  Bool sync,
97603b705cfSriastradh  RegionPtr clipBoxes, pointer data,
97703b705cfSriastradh  DrawablePtr pDraw
97803b705cfSriastradh){
97903b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
98003b705cfSriastradh    I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
98103b705cfSriastradh    INT32 x1, x2, y1, y2;
98203b705cfSriastradh    int srcPitch, dstPitch;
98303b705cfSriastradh    int top, left, npixels, nlines, size, loops;
98403b705cfSriastradh    BoxRec dstBox;
98503b705cfSriastradh
98603b705cfSriastradh
98703b705cfSriastradh    /* Clip */
98803b705cfSriastradh    x1 = src_x;
98903b705cfSriastradh    x2 = src_x + src_w;
99003b705cfSriastradh    y1 = src_y;
99103b705cfSriastradh    y2 = src_y + src_h;
99203b705cfSriastradh
99303b705cfSriastradh    dstBox.x1 = drw_x;
99403b705cfSriastradh    dstBox.x2 = drw_x + drw_w;
99503b705cfSriastradh    dstBox.y1 = drw_y;
99603b705cfSriastradh    dstBox.y2 = drw_y + drw_h;
99703b705cfSriastradh
99803b705cfSriastradh    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
99903b705cfSriastradh		  REGION_EXTENTS(pScrn->screen, clipBoxes), width, height);
100003b705cfSriastradh
100103b705cfSriastradh    if((x1 >= x2) || (y1 >= y2))
100203b705cfSriastradh       return Success;
100303b705cfSriastradh    /*
100403b705cfSriastradh     * Fix for 4 pixel granularity of AdjustFrame
100503b705cfSriastradh     * unless boarder is clipped  by frame
100603b705cfSriastradh     */
100703b705cfSriastradh    dstBox.x1 -= (pScrn->frameX0 &
100803b705cfSriastradh		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
100903b705cfSriastradh    dstBox.x2 -= (pScrn->frameX0 & ~0x3);
101003b705cfSriastradh    dstBox.y1 -= pScrn->frameY0;
101103b705cfSriastradh    dstBox.y2 -= pScrn->frameY0;
101203b705cfSriastradh
101303b705cfSriastradh    switch(id) {
101403b705cfSriastradh    case FOURCC_YV12:
101503b705cfSriastradh    case FOURCC_I420:
101603b705cfSriastradh	 srcPitch = ALIGN(width, 4);
101703b705cfSriastradh	 dstPitch = ALIGN((width >> 1), 8);  /* of chroma */
101803b705cfSriastradh	 size =  dstPitch * height * 3;
101903b705cfSriastradh	 break;
102003b705cfSriastradh    case FOURCC_UYVY:
102103b705cfSriastradh    case FOURCC_YUY2:
102203b705cfSriastradh    default:
102303b705cfSriastradh	 srcPitch = (width << 1);
102403b705cfSriastradh	 dstPitch = ALIGN(srcPitch, 8);
102503b705cfSriastradh	 size = dstPitch * height;
102603b705cfSriastradh	 break;
102703b705cfSriastradh    }
102803b705cfSriastradh
102903b705cfSriastradh    if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear,
103003b705cfSriastradh		(pScrn->bitsPerPixel == 16) ? size : (size >> 1))))
103103b705cfSriastradh	return BadAlloc;
103203b705cfSriastradh
103303b705cfSriastradh    /* fixup pointers */
103403b705cfSriastradh    pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp;
103503b705cfSriastradh    pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
103603b705cfSriastradh    pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);
103703b705cfSriastradh
103803b705cfSriastradh    pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size;
103903b705cfSriastradh    pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
104003b705cfSriastradh    pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);
104103b705cfSriastradh
104203b705cfSriastradh
104303b705cfSriastradh    /* Make sure this buffer isn't in use */
104403b705cfSriastradh    loops = 0;
104503b705cfSriastradh    while (loops < 1000000) {
104603b705cfSriastradh          if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) {
104703b705cfSriastradh            break;
104803b705cfSriastradh          }
104903b705cfSriastradh          loops++;
105003b705cfSriastradh    }
105103b705cfSriastradh    if(loops >= 1000000) {
105203b705cfSriastradh      pPriv->currentBuf = !pPriv->currentBuf;
105303b705cfSriastradh    }
105403b705cfSriastradh
105503b705cfSriastradh
105603b705cfSriastradh    /* buffer swap */
105703b705cfSriastradh    if (pPriv->currentBuf == 0)
105803b705cfSriastradh        pPriv->currentBuf = 1;
105903b705cfSriastradh    else
106003b705cfSriastradh        pPriv->currentBuf = 0;
106103b705cfSriastradh
106203b705cfSriastradh    /* copy data */
106303b705cfSriastradh    top = y1 >> 16;
106403b705cfSriastradh    left = (x1 >> 16) & ~1;
106503b705cfSriastradh    npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - left;
106603b705cfSriastradh
106703b705cfSriastradh    switch(id) {
106803b705cfSriastradh    case FOURCC_YV12:
106903b705cfSriastradh    case FOURCC_I420:
107003b705cfSriastradh	top &= ~1;
107103b705cfSriastradh	nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - top;
107203b705cfSriastradh	I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch,  height, top, left,
107303b705cfSriastradh                           nlines, npixels, id);
107403b705cfSriastradh	break;
107503b705cfSriastradh    case FOURCC_UYVY:
107603b705cfSriastradh    case FOURCC_YUY2:
107703b705cfSriastradh    default:
107803b705cfSriastradh	nlines = ((y2 + 0xffff) >> 16) - top;
107903b705cfSriastradh	I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
108003b705cfSriastradh                                                              npixels);
108103b705cfSriastradh        break;
108203b705cfSriastradh    }
108303b705cfSriastradh
108403b705cfSriastradh    /* update cliplist */
108503b705cfSriastradh    if(!REGION_EQUAL(pScrn->screen, &pPriv->clip, clipBoxes)) {
108603b705cfSriastradh	REGION_COPY(pScrn->screen, &pPriv->clip, clipBoxes);
108703b705cfSriastradh	/* draw these */
108803b705cfSriastradh	xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
108903b705cfSriastradh    }
109003b705cfSriastradh
109103b705cfSriastradh    I810DisplayVideo(pScrn, id, width, height, dstPitch,
109203b705cfSriastradh	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
109303b705cfSriastradh
109403b705cfSriastradh    pPriv->videoStatus = CLIENT_VIDEO_ON;
109503b705cfSriastradh
109603b705cfSriastradh    return Success;
109703b705cfSriastradh}
109803b705cfSriastradh
109903b705cfSriastradh
110003b705cfSriastradhstatic int
110103b705cfSriastradhI810QueryImageAttributes(
110203b705cfSriastradh  ScrnInfoPtr pScrn,
110303b705cfSriastradh  int id,
110403b705cfSriastradh  unsigned short *w, unsigned short *h,
110503b705cfSriastradh  int *pitches, int *offsets
110603b705cfSriastradh){
110703b705cfSriastradh    int size, tmp;
110803b705cfSriastradh
110903b705cfSriastradh    if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH;
111003b705cfSriastradh    if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT;
111103b705cfSriastradh
111203b705cfSriastradh    *w = (*w + 1) & ~1;
111303b705cfSriastradh    if(offsets) offsets[0] = 0;
111403b705cfSriastradh
111503b705cfSriastradh    switch(id) {
111603b705cfSriastradh      /* IA44 is for XvMC only */
111703b705cfSriastradh    case FOURCC_IA44:
111803b705cfSriastradh    case FOURCC_AI44:
111903b705cfSriastradh	if(pitches) pitches[0] = *w;
112003b705cfSriastradh	size = *w * *h;
112103b705cfSriastradh	break;
112203b705cfSriastradh    case FOURCC_YV12:
112303b705cfSriastradh    case FOURCC_I420:
112403b705cfSriastradh	*h = (*h + 1) & ~1;
112503b705cfSriastradh	size = (*w + 3) & ~3;
112603b705cfSriastradh	if(pitches) pitches[0] = size;
112703b705cfSriastradh	size *= *h;
112803b705cfSriastradh	if(offsets) offsets[1] = size;
112903b705cfSriastradh	tmp = ((*w >> 1) + 3) & ~3;
113003b705cfSriastradh	if(pitches) pitches[1] = pitches[2] = tmp;
113103b705cfSriastradh	tmp *= (*h >> 1);
113203b705cfSriastradh	size += tmp;
113303b705cfSriastradh	if(offsets) offsets[2] = size;
113403b705cfSriastradh	size += tmp;
113503b705cfSriastradh	break;
113603b705cfSriastradh    case FOURCC_UYVY:
113703b705cfSriastradh    case FOURCC_YUY2:
113803b705cfSriastradh    default:
113903b705cfSriastradh	size = *w << 1;
114003b705cfSriastradh	if(pitches) pitches[0] = size;
114103b705cfSriastradh	size *= *h;
114203b705cfSriastradh	break;
114303b705cfSriastradh    }
114403b705cfSriastradh
114503b705cfSriastradh    return size;
114603b705cfSriastradh}
114703b705cfSriastradh
1148fe8aea9eSmrg#if !HAVE_NOTIFY_FD
114903b705cfSriastradhstatic void
115003b705cfSriastradhI810BlockHandler (BLOCKHANDLER_ARGS_DECL)
115103b705cfSriastradh{
115203b705cfSriastradh    SCREEN_PTR(arg);
115303b705cfSriastradh    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
115403b705cfSriastradh    I810Ptr      pI810 = I810PTR(pScrn);
115503b705cfSriastradh    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
115603b705cfSriastradh    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
115703b705cfSriastradh
115803b705cfSriastradh    screen->BlockHandler = pI810->BlockHandler;
115903b705cfSriastradh
116003b705cfSriastradh    (*screen->BlockHandler) (BLOCKHANDLER_ARGS);
116103b705cfSriastradh
116203b705cfSriastradh    screen->BlockHandler = I810BlockHandler;
116303b705cfSriastradh
116403b705cfSriastradh    if(pPriv->videoStatus & TIMER_MASK) {
116503b705cfSriastradh	UpdateCurrentTime();
116603b705cfSriastradh	if(pPriv->videoStatus & OFF_TIMER) {
116703b705cfSriastradh	    if(pPriv->offTime < currentTime.milliseconds) {
116803b705cfSriastradh		/* Turn off the overlay */
116903b705cfSriastradh		overlay->OV0CMD &= 0xFFFFFFFE;
117003b705cfSriastradh		OVERLAY_UPDATE(pI810->OverlayPhysical);
117103b705cfSriastradh
117203b705cfSriastradh		pPriv->videoStatus = FREE_TIMER;
117303b705cfSriastradh		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
117403b705cfSriastradh	    }
117503b705cfSriastradh	} else {  /* FREE_TIMER */
117603b705cfSriastradh	    if(pPriv->freeTime < currentTime.milliseconds) {
117703b705cfSriastradh		if(pPriv->linear) {
117803b705cfSriastradh		   xf86FreeOffscreenLinear(pPriv->linear);
117903b705cfSriastradh		   pPriv->linear = NULL;
118003b705cfSriastradh		}
118103b705cfSriastradh		pPriv->videoStatus = 0;
118203b705cfSriastradh	    }
118303b705cfSriastradh        }
118403b705cfSriastradh    }
118503b705cfSriastradh}
1186fe8aea9eSmrg#else
1187fe8aea9eSmrgstatic void
1188fe8aea9eSmrgI810BlockHandler(void *data, void *_timeout)
1189fe8aea9eSmrg{
1190fe8aea9eSmrg    ScrnInfoPtr pScrn = data;
1191fe8aea9eSmrg    I810Ptr      pI810 = I810PTR(pScrn);
1192fe8aea9eSmrg    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
1193fe8aea9eSmrg    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
1194fe8aea9eSmrg
1195fe8aea9eSmrg    if(pPriv->videoStatus & TIMER_MASK) {
1196fe8aea9eSmrg	UpdateCurrentTime();
1197fe8aea9eSmrg	if(pPriv->videoStatus & OFF_TIMER) {
1198fe8aea9eSmrg	    if(pPriv->offTime < currentTime.milliseconds) {
1199fe8aea9eSmrg		/* Turn off the overlay */
1200fe8aea9eSmrg		overlay->OV0CMD &= 0xFFFFFFFE;
1201fe8aea9eSmrg		OVERLAY_UPDATE(pI810->OverlayPhysical);
1202fe8aea9eSmrg
1203fe8aea9eSmrg		pPriv->videoStatus = FREE_TIMER;
1204fe8aea9eSmrg		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1205fe8aea9eSmrg	    }
1206fe8aea9eSmrg	} else {  /* FREE_TIMER */
1207fe8aea9eSmrg	    if(pPriv->freeTime < currentTime.milliseconds) {
1208fe8aea9eSmrg		if(pPriv->linear) {
1209fe8aea9eSmrg		   xf86FreeOffscreenLinear(pPriv->linear);
1210fe8aea9eSmrg		   pPriv->linear = NULL;
1211fe8aea9eSmrg		}
1212fe8aea9eSmrg		pPriv->videoStatus = 0;
1213fe8aea9eSmrg	    }
1214fe8aea9eSmrg        }
1215fe8aea9eSmrg    }
1216fe8aea9eSmrg}
1217fe8aea9eSmrg#endif
121803b705cfSriastradh
121903b705cfSriastradh
122003b705cfSriastradh/***************************************************************************
122103b705cfSriastradh * Offscreen Images
122203b705cfSriastradh ***************************************************************************/
122303b705cfSriastradh
122403b705cfSriastradhtypedef struct {
122503b705cfSriastradh  FBLinearPtr linear;
122603b705cfSriastradh  Bool isOn;
122703b705cfSriastradh} OffscreenPrivRec, * OffscreenPrivPtr;
122803b705cfSriastradh
122903b705cfSriastradhstatic int
123003b705cfSriastradhI810AllocateSurface(
123103b705cfSriastradh    ScrnInfoPtr pScrn,
123203b705cfSriastradh    int id,
123303b705cfSriastradh    unsigned short w,
123403b705cfSriastradh    unsigned short h,
123503b705cfSriastradh    XF86SurfacePtr surface
123603b705cfSriastradh){
123703b705cfSriastradh    FBLinearPtr linear;
123803b705cfSriastradh    int pitch, size, bpp;
123903b705cfSriastradh    OffscreenPrivPtr pPriv;
124003b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
124103b705cfSriastradh
124203b705cfSriastradh    if((w > 1024) || (h > 1024))
124303b705cfSriastradh	return BadAlloc;
124403b705cfSriastradh
124503b705cfSriastradh    w = ALIGN(w, 2);
124603b705cfSriastradh    pitch = ALIGN((w << 1), 16);
124703b705cfSriastradh    bpp = pScrn->bitsPerPixel >> 3;
124803b705cfSriastradh    size = ((pitch * h) + bpp - 1) / bpp;
124903b705cfSriastradh
125003b705cfSriastradh    if(!(linear = I810AllocateMemory(pScrn, NULL, size)))
125103b705cfSriastradh	return BadAlloc;
125203b705cfSriastradh
125303b705cfSriastradh    surface->width = w;
125403b705cfSriastradh    surface->height = h;
125503b705cfSriastradh
125603b705cfSriastradh    if(!(surface->pitches = malloc(sizeof(int)))) {
125703b705cfSriastradh	xf86FreeOffscreenLinear(linear);
125803b705cfSriastradh	return BadAlloc;
125903b705cfSriastradh    }
126003b705cfSriastradh    if(!(surface->offsets = malloc(sizeof(int)))) {
126103b705cfSriastradh	free(surface->pitches);
126203b705cfSriastradh	xf86FreeOffscreenLinear(linear);
126303b705cfSriastradh	return BadAlloc;
126403b705cfSriastradh    }
126503b705cfSriastradh    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
126603b705cfSriastradh	free(surface->pitches);
126703b705cfSriastradh	free(surface->offsets);
126803b705cfSriastradh	xf86FreeOffscreenLinear(linear);
126903b705cfSriastradh	return BadAlloc;
127003b705cfSriastradh    }
127103b705cfSriastradh
127203b705cfSriastradh    pPriv->linear = linear;
127303b705cfSriastradh    pPriv->isOn = FALSE;
127403b705cfSriastradh
127503b705cfSriastradh    surface->pScrn = pScrn;
127603b705cfSriastradh    surface->id = id;
127703b705cfSriastradh    surface->pitches[0] = pitch;
127803b705cfSriastradh    surface->offsets[0] = linear->offset * bpp;
127903b705cfSriastradh    surface->devPrivate.ptr = (pointer)pPriv;
128003b705cfSriastradh
128103b705cfSriastradh    memset(pI810->FbBase + surface->offsets[0],0,size);
128203b705cfSriastradh
128303b705cfSriastradh    return Success;
128403b705cfSriastradh}
128503b705cfSriastradh
128603b705cfSriastradhstatic int
128703b705cfSriastradhI810StopSurface(
128803b705cfSriastradh    XF86SurfacePtr surface
128903b705cfSriastradh){
129003b705cfSriastradh    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
129103b705cfSriastradh
129203b705cfSriastradh    if(pPriv->isOn) {
129303b705cfSriastradh      I810Ptr pI810 = I810PTR(surface->pScrn);
129403b705cfSriastradh
129503b705cfSriastradh      I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
129603b705cfSriastradh
129703b705cfSriastradh      overlay->OV0CMD &= 0xFFFFFFFE;
129803b705cfSriastradh      OVERLAY_UPDATE(pI810->OverlayPhysical);
129903b705cfSriastradh
130003b705cfSriastradh      pPriv->isOn = FALSE;
130103b705cfSriastradh    }
130203b705cfSriastradh
130303b705cfSriastradh    return Success;
130403b705cfSriastradh}
130503b705cfSriastradh
130603b705cfSriastradh
130703b705cfSriastradhstatic int
130803b705cfSriastradhI810FreeSurface(
130903b705cfSriastradh    XF86SurfacePtr surface
131003b705cfSriastradh){
131103b705cfSriastradh    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
131203b705cfSriastradh
131303b705cfSriastradh    if(pPriv->isOn) {
131403b705cfSriastradh	I810StopSurface(surface);
131503b705cfSriastradh    }
131603b705cfSriastradh    xf86FreeOffscreenLinear(pPriv->linear);
131703b705cfSriastradh    free(surface->pitches);
131803b705cfSriastradh    free(surface->offsets);
131903b705cfSriastradh    free(surface->devPrivate.ptr);
132003b705cfSriastradh
132103b705cfSriastradh    return Success;
132203b705cfSriastradh}
132303b705cfSriastradh
132403b705cfSriastradhstatic int
132503b705cfSriastradhI810GetSurfaceAttribute(
132603b705cfSriastradh    ScrnInfoPtr pScrn,
132703b705cfSriastradh    Atom attribute,
132803b705cfSriastradh    INT32 *value
132903b705cfSriastradh){
133003b705cfSriastradh    return I810GetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn));
133103b705cfSriastradh}
133203b705cfSriastradh
133303b705cfSriastradhstatic int
133403b705cfSriastradhI810SetSurfaceAttribute(
133503b705cfSriastradh    ScrnInfoPtr pScrn,
133603b705cfSriastradh    Atom attribute,
133703b705cfSriastradh    INT32 value
133803b705cfSriastradh){
133903b705cfSriastradh    return I810SetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn));
134003b705cfSriastradh}
134103b705cfSriastradh
134203b705cfSriastradh
134303b705cfSriastradhstatic int
134403b705cfSriastradhI810DisplaySurface(
134503b705cfSriastradh    XF86SurfacePtr surface,
134603b705cfSriastradh    short src_x, short src_y,
134703b705cfSriastradh    short drw_x, short drw_y,
134803b705cfSriastradh    short src_w, short src_h,
134903b705cfSriastradh    short drw_w, short drw_h,
135003b705cfSriastradh    RegionPtr clipBoxes
135103b705cfSriastradh){
135203b705cfSriastradh    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
135303b705cfSriastradh    ScrnInfoPtr pScrn = surface->pScrn;
135403b705cfSriastradh    I810Ptr      pI810 = I810PTR(pScrn);
135503b705cfSriastradh    I810PortPrivPtr pI810Priv =  GET_PORT_PRIVATE(pScrn);
135603b705cfSriastradh
135703b705cfSriastradh    INT32 x1, y1, x2, y2;
135803b705cfSriastradh    INT32 loops = 0;
135903b705cfSriastradh    BoxRec dstBox;
136003b705cfSriastradh
136103b705cfSriastradh    x1 = src_x;
136203b705cfSriastradh    x2 = src_x + src_w;
136303b705cfSriastradh    y1 = src_y;
136403b705cfSriastradh    y2 = src_y + src_h;
136503b705cfSriastradh
136603b705cfSriastradh    dstBox.x1 = drw_x;
136703b705cfSriastradh    dstBox.x2 = drw_x + drw_w;
136803b705cfSriastradh    dstBox.y1 = drw_y;
136903b705cfSriastradh    dstBox.y2 = drw_y + drw_h;
137003b705cfSriastradh
137103b705cfSriastradh    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
137203b705cfSriastradh		  REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
137303b705cfSriastradh		  surface->width, surface->height);
137403b705cfSriastradh
137503b705cfSriastradh    /*
137603b705cfSriastradh     * Fix for 4 pixel granularity of AdjustFrame
137703b705cfSriastradh     * unless boarder is clipped  by frame
137803b705cfSriastradh     */
137903b705cfSriastradh    dstBox.x1 -= (pScrn->frameX0 &
138003b705cfSriastradh		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
138103b705cfSriastradh    dstBox.x2 -= (pScrn->frameX0 & ~0x3);
138203b705cfSriastradh    dstBox.y1 -= pScrn->frameY0;
138303b705cfSriastradh    dstBox.y2 -= pScrn->frameY0;
138403b705cfSriastradh
138503b705cfSriastradh    /* fixup pointers */
138603b705cfSriastradh    pI810Priv->YBuf0offset = surface->offsets[0];
138703b705cfSriastradh    pI810Priv->YBuf1offset = pI810Priv->YBuf0offset;
138803b705cfSriastradh
138903b705cfSriastradh   /* wait for the last rendered buffer to be flipped in */
139003b705cfSriastradh    while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) {
139103b705cfSriastradh      if(loops == 200000) {
139203b705cfSriastradh	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
139303b705cfSriastradh	break;
139403b705cfSriastradh      }
139503b705cfSriastradh      loops++;
139603b705cfSriastradh    }
139703b705cfSriastradh
139803b705cfSriastradh    /* buffer swap */
139903b705cfSriastradh    if (pI810Priv->currentBuf == 0)
140003b705cfSriastradh      pI810Priv->currentBuf = 1;
140103b705cfSriastradh    else
140203b705cfSriastradh      pI810Priv->currentBuf = 0;
140303b705cfSriastradh
140403b705cfSriastradh    I810ResetVideo(pScrn);
140503b705cfSriastradh
140603b705cfSriastradh    I810DisplayVideo(pScrn, surface->id, surface->width, surface->height,
140703b705cfSriastradh		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
140803b705cfSriastradh		     src_w, src_h, drw_w, drw_h);
140903b705cfSriastradh
141003b705cfSriastradh    xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes);
141103b705cfSriastradh
141203b705cfSriastradh    pPriv->isOn = TRUE;
141303b705cfSriastradh    /* we've prempted the XvImage stream so set its free timer */
141403b705cfSriastradh    if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) {
141503b705cfSriastradh      REGION_EMPTY(pScrn->screen, & pI810Priv->clip);
141603b705cfSriastradh      UpdateCurrentTime();
141703b705cfSriastradh      pI810Priv->videoStatus = FREE_TIMER;
141803b705cfSriastradh      pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
141903b705cfSriastradh    }
142003b705cfSriastradh
142103b705cfSriastradh    return Success;
142203b705cfSriastradh}
142303b705cfSriastradh
142403b705cfSriastradh
142503b705cfSriastradhstatic void
142603b705cfSriastradhI810InitOffscreenImages(ScreenPtr screen)
142703b705cfSriastradh{
142803b705cfSriastradh    XF86OffscreenImagePtr offscreenImages;
142903b705cfSriastradh
143003b705cfSriastradh    /* need to free this someplace */
143103b705cfSriastradh    if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) {
143203b705cfSriastradh      return;
143303b705cfSriastradh    }
143403b705cfSriastradh
143503b705cfSriastradh    offscreenImages[0].image = &Images[0];
143603b705cfSriastradh    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
143703b705cfSriastradh			       VIDEO_CLIP_TO_VIEWPORT;
143803b705cfSriastradh    offscreenImages[0].alloc_surface = I810AllocateSurface;
143903b705cfSriastradh    offscreenImages[0].free_surface = I810FreeSurface;
144003b705cfSriastradh    offscreenImages[0].display = I810DisplaySurface;
144103b705cfSriastradh    offscreenImages[0].stop = I810StopSurface;
144203b705cfSriastradh    offscreenImages[0].setAttribute = I810SetSurfaceAttribute;
144303b705cfSriastradh    offscreenImages[0].getAttribute = I810GetSurfaceAttribute;
144403b705cfSriastradh    offscreenImages[0].max_width = 1024;
144503b705cfSriastradh    offscreenImages[0].max_height = 1024;
144603b705cfSriastradh    offscreenImages[0].num_attributes = 1;
144703b705cfSriastradh    offscreenImages[0].attributes = Attributes;
144803b705cfSriastradh
144903b705cfSriastradh    if (!xf86XVRegisterOffscreenImages(screen, offscreenImages, 1))
145003b705cfSriastradh	    free(offscreenImages);
145103b705cfSriastradh}
145203b705cfSriastradh
1453