1fa225cbcSrjs/***************************************************************************
2fa225cbcSrjs
3fa225cbcSrjsCopyright 2000 Intel Corporation.  All Rights Reserved.
4fa225cbcSrjs
5fa225cbcSrjsPermission is hereby granted, free of charge, to any person obtaining a
6fa225cbcSrjscopy of this software and associated documentation files (the
7fa225cbcSrjs"Software"), to deal in the Software without restriction, including
8fa225cbcSrjswithout limitation the rights to use, copy, modify, merge, publish,
9fa225cbcSrjsdistribute, sub license, and/or sell copies of the Software, and to
10fa225cbcSrjspermit persons to whom the Software is furnished to do so, subject to
11fa225cbcSrjsthe following conditions:
12fa225cbcSrjs
13fa225cbcSrjsThe above copyright notice and this permission notice (including the
14fa225cbcSrjsnext paragraph) shall be included in all copies or substantial portions
15fa225cbcSrjsof the Software.
16fa225cbcSrjs
17fa225cbcSrjsTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18fa225cbcSrjsOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19fa225cbcSrjsMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20fa225cbcSrjsIN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21fa225cbcSrjsDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22fa225cbcSrjsOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23fa225cbcSrjsTHE USE OR OTHER DEALINGS IN THE SOFTWARE.
24fa225cbcSrjs
25fa225cbcSrjs**************************************************************************/
26fa225cbcSrjs
27fa225cbcSrjs/*
28fa225cbcSrjs * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
29fa225cbcSrjs *
30fa225cbcSrjs * Authors:
31fa225cbcSrjs * 	Jonathan Bian <jonathan.bian@intel.com>
32fa225cbcSrjs *      Offscreen Images:
33fa225cbcSrjs *        Matt Sottek <matthew.j.sottek@intel.com>
34fa225cbcSrjs */
35fa225cbcSrjs
36fa225cbcSrjs#ifdef HAVE_CONFIG_H
37fa225cbcSrjs#include "config.h"
38fa225cbcSrjs#endif
39fa225cbcSrjs
40fa225cbcSrjs#include <string.h>
41fa225cbcSrjs
42fa225cbcSrjs#include "xf86.h"
43fa225cbcSrjs#include "xf86_OSproc.h"
44fa225cbcSrjs#include "compiler.h"
45fa225cbcSrjs#include "xf86PciInfo.h"
46fa225cbcSrjs#include "xf86Pci.h"
47fa225cbcSrjs#include "xf86fbman.h"
48fa225cbcSrjs#include "regionstr.h"
49fa225cbcSrjs
50fa225cbcSrjs#include "i810.h"
51fa225cbcSrjs#include "xf86xv.h"
52fa225cbcSrjs#include <X11/extensions/Xv.h>
53fa225cbcSrjs#include "xaa.h"
54fa225cbcSrjs#include "xaalocal.h"
55fa225cbcSrjs#include "dixstruct.h"
56fa225cbcSrjs#include "fourcc.h"
57fa225cbcSrjs
58fa225cbcSrjs#define OFF_DELAY 	250  /* milliseconds */
59fa225cbcSrjs#define FREE_DELAY 	15000
60fa225cbcSrjs
61fa225cbcSrjs#define OFF_TIMER 	0x01
62fa225cbcSrjs#define FREE_TIMER	0x02
63fa225cbcSrjs#define CLIENT_VIDEO_ON	0x04
64fa225cbcSrjs
65fa225cbcSrjs#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
66fa225cbcSrjs
67fa225cbcSrjsstatic void I810InitOffscreenImages(ScreenPtr);
68fa225cbcSrjs
69fa225cbcSrjsstatic XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr);
70fa225cbcSrjsstatic void I810StopVideo(ScrnInfoPtr, pointer, Bool);
71fa225cbcSrjsstatic int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
72fa225cbcSrjsstatic int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
73fa225cbcSrjsstatic void I810QueryBestSize(ScrnInfoPtr, Bool,
74fa225cbcSrjs	short, short, short, short, unsigned int *, unsigned int *, pointer);
75fa225cbcSrjsstatic int I810PutImage( ScrnInfoPtr,
76fa225cbcSrjs	short, short, short, short, short, short, short, short,
77fa225cbcSrjs	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
78fa225cbcSrjs	DrawablePtr);
79fa225cbcSrjsstatic int I810QueryImageAttributes(ScrnInfoPtr,
80fa225cbcSrjs	int, unsigned short *, unsigned short *,  int *, int *);
81fa225cbcSrjs
82fa225cbcSrjsstatic void I810BlockHandler(int, pointer, pointer, pointer);
83fa225cbcSrjs
84fa225cbcSrjs#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
85fa225cbcSrjs
86fa225cbcSrjsstatic Atom xvBrightness, xvContrast, xvColorKey;
87fa225cbcSrjs
88fa225cbcSrjs#define IMAGE_MAX_WIDTH		1440
89fa225cbcSrjs#define IMAGE_FAST_WIDTH	720
90fa225cbcSrjs#define IMAGE_MAX_HEIGHT	1080
91fa225cbcSrjs#define Y_BUF_SIZE		(IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
92fa225cbcSrjs
93fa225cbcSrjs#define OVERLAY_UPDATE(p)	OUTREG(0x30000, p | 0x80000000);
94fa225cbcSrjs
95fa225cbcSrjs/*
96fa225cbcSrjs * OV0CMD - Overlay Command Register
97fa225cbcSrjs */
98fa225cbcSrjs#define	VERTICAL_CHROMINANCE_FILTER 	0x70000000
99fa225cbcSrjs#define VC_SCALING_OFF		0x00000000
100fa225cbcSrjs#define VC_LINE_REPLICATION	0x10000000
101fa225cbcSrjs#define VC_UP_INTERPOLATION	0x20000000
102fa225cbcSrjs#define VC_PIXEL_DROPPING	0x50000000
103fa225cbcSrjs#define VC_DOWN_INTERPOLATION	0x60000000
104fa225cbcSrjs#define VERTICAL_LUMINANCE_FILTER	0x0E000000
105fa225cbcSrjs#define VL_SCALING_OFF		0x00000000
106fa225cbcSrjs#define VL_LINE_REPLICATION	0x02000000
107fa225cbcSrjs#define VL_UP_INTERPOLATION	0x04000000
108fa225cbcSrjs#define VL_PIXEL_DROPPING	0x0A000000
109fa225cbcSrjs#define VL_DOWN_INTERPOLATION	0x0C000000
110fa225cbcSrjs#define	HORIZONTAL_CHROMINANCE_FILTER 	0x01C00000
111fa225cbcSrjs#define HC_SCALING_OFF		0x00000000
112fa225cbcSrjs#define HC_LINE_REPLICATION	0x00400000
113fa225cbcSrjs#define HC_UP_INTERPOLATION	0x00800000
114fa225cbcSrjs#define HC_PIXEL_DROPPING	0x01400000
115fa225cbcSrjs#define HC_DOWN_INTERPOLATION	0x01800000
116fa225cbcSrjs#define HORIZONTAL_LUMINANCE_FILTER	0x00380000
117fa225cbcSrjs#define HL_SCALING_OFF		0x00000000
118fa225cbcSrjs#define HL_LINE_REPLICATION	0x00080000
119fa225cbcSrjs#define HL_UP_INTERPOLATION	0x00100000
120fa225cbcSrjs#define HL_PIXEL_DROPPING	0x00280000
121fa225cbcSrjs#define HL_DOWN_INTERPOLATION	0x00300000
122fa225cbcSrjs
123fa225cbcSrjs#define Y_ADJUST		0x00010000
124fa225cbcSrjs#define OV_BYTE_ORDER		0x0000C000
125fa225cbcSrjs#define UV_SWAP			0x00004000
126fa225cbcSrjs#define Y_SWAP			0x00008000
127fa225cbcSrjs#define Y_AND_UV_SWAP		0x0000C000
128fa225cbcSrjs#define SOURCE_FORMAT		0x00003C00
129fa225cbcSrjs#define	RGB_555			0x00000800
130fa225cbcSrjs#define	RGB_565			0x00000C00
131fa225cbcSrjs#define	YUV_422			0x00002000
132fa225cbcSrjs#define	YUV_411			0x00002400
133fa225cbcSrjs#define	YUV_420			0x00003000
134fa225cbcSrjs#define	YUV_410			0x00003800
135fa225cbcSrjs#define BUFFER_AND_FIELD	0x00000006
136fa225cbcSrjs#define	BUFFER0_FIELD0		0x00000000
137fa225cbcSrjs#define	BUFFER1_FIELD0		0x00000004
138fa225cbcSrjs#define OVERLAY_ENABLE		0x00000001
139fa225cbcSrjs
140fa225cbcSrjs#define UV_VERT_BUF1 		0x02
141fa225cbcSrjs#define UV_VERT_BUF0 		0x04
142fa225cbcSrjs
143fa225cbcSrjs/*
144fa225cbcSrjs * DOV0STA - Display/Overlay 0 Status Register
145fa225cbcSrjs */
146fa225cbcSrjs#define	DOV0STA 	0x30008
147fa225cbcSrjs
148fa225cbcSrjs#define MINUV_SCALE	0x1
149fa225cbcSrjs
150fa225cbcSrjs#define RGB16ToColorKey(c) \
151fa225cbcSrjs	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
152fa225cbcSrjs
153fa225cbcSrjs#define RGB15ToColorKey(c) \
154fa225cbcSrjs        (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
155fa225cbcSrjs
156fa225cbcSrjsvoid I810InitVideo(ScreenPtr pScreen)
157fa225cbcSrjs{
158fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
159fa225cbcSrjs    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
160fa225cbcSrjs    XF86VideoAdaptorPtr newAdaptor = NULL;
161fa225cbcSrjs    int num_adaptors;
162fa225cbcSrjs
163fa225cbcSrjs    if (pScrn->bitsPerPixel != 8)
164fa225cbcSrjs    {
165fa225cbcSrjs	newAdaptor = I810SetupImageVideo(pScreen);
166fa225cbcSrjs	I810InitOffscreenImages(pScreen);
167fa225cbcSrjs    }
168fa225cbcSrjs
169fa225cbcSrjs    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
170fa225cbcSrjs
171fa225cbcSrjs    if(newAdaptor) {
172fa225cbcSrjs	if(!num_adaptors) {
173fa225cbcSrjs	    num_adaptors = 1;
174fa225cbcSrjs	    adaptors = &newAdaptor;
175fa225cbcSrjs	} else {
176fa225cbcSrjs	    newAdaptors =  /* need to free this someplace */
177fa225cbcSrjs		xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
178fa225cbcSrjs	    if(newAdaptors) {
179fa225cbcSrjs		memcpy(newAdaptors, adaptors, num_adaptors *
180fa225cbcSrjs					sizeof(XF86VideoAdaptorPtr));
181fa225cbcSrjs		newAdaptors[num_adaptors] = newAdaptor;
182fa225cbcSrjs		adaptors = newAdaptors;
183fa225cbcSrjs		num_adaptors++;
184fa225cbcSrjs	    }
185fa225cbcSrjs	}
186fa225cbcSrjs    }
187fa225cbcSrjs
188fa225cbcSrjs    if(num_adaptors)
189fa225cbcSrjs        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
190fa225cbcSrjs
191fa225cbcSrjs    if(newAdaptors)
192fa225cbcSrjs	xfree(newAdaptors);
193fa225cbcSrjs}
194fa225cbcSrjs
195fa225cbcSrjs/* *INDENT-OFF* */
196fa225cbcSrjs/* client libraries expect an encoding */
197fa225cbcSrjsstatic XF86VideoEncodingRec DummyEncoding[1] =
198fa225cbcSrjs{
199fa225cbcSrjs {
200fa225cbcSrjs   0,
201fa225cbcSrjs   "XV_IMAGE",
202fa225cbcSrjs   IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
203fa225cbcSrjs   {1, 1}
204fa225cbcSrjs }
205fa225cbcSrjs};
206fa225cbcSrjs
207fa225cbcSrjs#define NUM_FORMATS 3
208fa225cbcSrjs
209fa225cbcSrjsstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
210fa225cbcSrjs{
211fa225cbcSrjs  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
212fa225cbcSrjs};
213fa225cbcSrjs
214fa225cbcSrjs#define NUM_ATTRIBUTES 3
215fa225cbcSrjs
216fa225cbcSrjsstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
217fa225cbcSrjs{
218fa225cbcSrjs   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
219fa225cbcSrjs   {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
220fa225cbcSrjs   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
221fa225cbcSrjs};
222fa225cbcSrjs
223fa225cbcSrjs#define NUM_IMAGES 6
224fa225cbcSrjs
225fa225cbcSrjs#define I810_RV15 0x35315652
226fa225cbcSrjs#define I810_RV16 0x36315652
227fa225cbcSrjs
228fa225cbcSrjsstatic XF86ImageRec Images[NUM_IMAGES] =
229fa225cbcSrjs{
230fa225cbcSrjs   {
231fa225cbcSrjs	I810_RV15,
232fa225cbcSrjs        XvRGB,
233fa225cbcSrjs	LSBFirst,
234fa225cbcSrjs	{'R','V','1','5',
235fa225cbcSrjs	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
236fa225cbcSrjs	16,
237fa225cbcSrjs	XvPacked,
238fa225cbcSrjs	1,
239fa225cbcSrjs	15, 0x7C00, 0x03E0, 0x001F,
240fa225cbcSrjs	0, 0, 0,
241fa225cbcSrjs	0, 0, 0,
242fa225cbcSrjs	0, 0, 0,
243fa225cbcSrjs	{'R','V','B',0,
244fa225cbcSrjs	  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},
245fa225cbcSrjs	XvTopToBottom
246fa225cbcSrjs   },
247fa225cbcSrjs   {
248fa225cbcSrjs	I810_RV16,
249fa225cbcSrjs        XvRGB,
250fa225cbcSrjs	LSBFirst,
251fa225cbcSrjs	{'R','V','1','6',
252fa225cbcSrjs	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
253fa225cbcSrjs	16,
254fa225cbcSrjs	XvPacked,
255fa225cbcSrjs	1,
256fa225cbcSrjs	16, 0xF800, 0x07E0, 0x001F,
257fa225cbcSrjs	0, 0, 0,
258fa225cbcSrjs	0, 0, 0,
259fa225cbcSrjs	0, 0, 0,
260fa225cbcSrjs	{'R','V','B',0,
261fa225cbcSrjs	  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},
262fa225cbcSrjs	XvTopToBottom
263fa225cbcSrjs   },
264fa225cbcSrjs	XVIMAGE_YUY2,
265fa225cbcSrjs	XVIMAGE_YV12,
266fa225cbcSrjs	XVIMAGE_I420,
267fa225cbcSrjs	XVIMAGE_UYVY
268fa225cbcSrjs};
269fa225cbcSrjs/* *INDENT-ON* */
270fa225cbcSrjs
271fa225cbcSrjstypedef struct {
272fa225cbcSrjs    uint32_t OBUF_0Y;
273fa225cbcSrjs    uint32_t OBUF_1Y;
274fa225cbcSrjs    uint32_t OBUF_0U;
275fa225cbcSrjs    uint32_t OBUF_0V;
276fa225cbcSrjs    uint32_t OBUF_1U;
277fa225cbcSrjs    uint32_t OBUF_1V;
278fa225cbcSrjs    uint32_t OV0STRIDE;
279fa225cbcSrjs    uint32_t YRGB_VPH;
280fa225cbcSrjs    uint32_t UV_VPH;
281fa225cbcSrjs    uint32_t HORZ_PH;
282fa225cbcSrjs    uint32_t INIT_PH;
283fa225cbcSrjs    uint32_t DWINPOS;
284fa225cbcSrjs    uint32_t DWINSZ;
285fa225cbcSrjs    uint32_t SWID;
286fa225cbcSrjs    uint32_t SWIDQW;
287fa225cbcSrjs    uint32_t SHEIGHT;
288fa225cbcSrjs    uint32_t YRGBSCALE;
289fa225cbcSrjs    uint32_t UVSCALE;
290fa225cbcSrjs    uint32_t OV0CLRC0;
291fa225cbcSrjs    uint32_t OV0CLRC1;
292fa225cbcSrjs    uint32_t DCLRKV;
293fa225cbcSrjs    uint32_t DCLRKM;
294fa225cbcSrjs    uint32_t SCLRKVH;
295fa225cbcSrjs    uint32_t SCLRKVL;
296fa225cbcSrjs    uint32_t SCLRKM;
297fa225cbcSrjs    uint32_t OV0CONF;
298fa225cbcSrjs    uint32_t OV0CMD;
299fa225cbcSrjs} I810OverlayRegRec, *I810OverlayRegPtr;
300fa225cbcSrjs
301fa225cbcSrjstypedef struct {
302fa225cbcSrjs	uint32_t     YBuf0offset;
303fa225cbcSrjs	uint32_t     UBuf0offset;
304fa225cbcSrjs	uint32_t     VBuf0offset;
305fa225cbcSrjs
306fa225cbcSrjs	uint32_t     YBuf1offset;
307fa225cbcSrjs	uint32_t     UBuf1offset;
308fa225cbcSrjs	uint32_t     VBuf1offset;
309fa225cbcSrjs
310fa225cbcSrjs	unsigned char currentBuf;
311fa225cbcSrjs
312fa225cbcSrjs	int          brightness;
313fa225cbcSrjs	int          contrast;
314fa225cbcSrjs
315fa225cbcSrjs	RegionRec    clip;
316fa225cbcSrjs	uint32_t     colorKey;
317fa225cbcSrjs
318fa225cbcSrjs	uint32_t     videoStatus;
319fa225cbcSrjs	Time         offTime;
320fa225cbcSrjs	Time         freeTime;
321fa225cbcSrjs	FBLinearPtr  linear;
322fa225cbcSrjs} I810PortPrivRec, *I810PortPrivPtr;
323fa225cbcSrjs
324fa225cbcSrjs#define GET_PORT_PRIVATE(pScrn) \
325fa225cbcSrjs   (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
326fa225cbcSrjs
327fa225cbcSrjsstatic void I810ResetVideo(ScrnInfoPtr pScrn)
328fa225cbcSrjs{
329fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
330fa225cbcSrjs    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
331fa225cbcSrjs    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
332fa225cbcSrjs
333fa225cbcSrjs    /*
334fa225cbcSrjs     * Default to maximum image size in YV12
335fa225cbcSrjs     */
336fa225cbcSrjs
337fa225cbcSrjs    overlay->YRGB_VPH = 0;
338fa225cbcSrjs    overlay->UV_VPH = 0;
339fa225cbcSrjs    overlay->HORZ_PH = 0;
340fa225cbcSrjs    overlay->INIT_PH = 0;
341fa225cbcSrjs    overlay->DWINPOS = 0;
342fa225cbcSrjs    overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
343fa225cbcSrjs    overlay->SWID =  IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15);
344fa225cbcSrjs    overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
345fa225cbcSrjs    overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
346fa225cbcSrjs    overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */
347fa225cbcSrjs    overlay->UVSCALE = 0x80004000; /* scale factor 1 */
348fa225cbcSrjs    overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
349fa225cbcSrjs    overlay->OV0CLRC1 = 0x80; /* saturation: bypass */
350fa225cbcSrjs
351fa225cbcSrjs    /*
352fa225cbcSrjs     * Enable destination color keying
353fa225cbcSrjs     */
354fa225cbcSrjs    switch(pScrn->depth) {
355fa225cbcSrjs    case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
356fa225cbcSrjs             overlay->DCLRKM = 0x80070307;
357fa225cbcSrjs             break;
358fa225cbcSrjs    case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
359fa225cbcSrjs             overlay->DCLRKM = 0x80070707;
360fa225cbcSrjs             break;
361fa225cbcSrjs    default: overlay->DCLRKV = pPriv->colorKey;
362fa225cbcSrjs             overlay->DCLRKM = 0x80000000;
363fa225cbcSrjs             break;
364fa225cbcSrjs    }
365fa225cbcSrjs
366fa225cbcSrjs    overlay->SCLRKVH = 0;
367fa225cbcSrjs    overlay->SCLRKVL = 0;
368fa225cbcSrjs    overlay->SCLRKM = 0; /* source color key disable */
369fa225cbcSrjs    overlay->OV0CONF = 0; /* two 720 pixel line buffers */
370fa225cbcSrjs
371fa225cbcSrjs    overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
372fa225cbcSrjs		      YUV_420;
373fa225cbcSrjs
374fa225cbcSrjs    OVERLAY_UPDATE(pI810->OverlayPhysical);
375fa225cbcSrjs}
376fa225cbcSrjs
377fa225cbcSrjs
378fa225cbcSrjsstatic XF86VideoAdaptorPtr
379fa225cbcSrjsI810SetupImageVideo(ScreenPtr pScreen)
380fa225cbcSrjs{
381fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
382fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
383fa225cbcSrjs    XF86VideoAdaptorPtr adapt;
384fa225cbcSrjs    I810PortPrivPtr pPriv;
385fa225cbcSrjs
386fa225cbcSrjs    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
387fa225cbcSrjs			    sizeof(I810PortPrivRec) +
388fa225cbcSrjs			    sizeof(DevUnion))))
389fa225cbcSrjs	return NULL;
390fa225cbcSrjs
391fa225cbcSrjs    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
392fa225cbcSrjs    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
393fa225cbcSrjs    adapt->name = "I810 Video Overlay";
394fa225cbcSrjs    adapt->nEncodings = 1;
395fa225cbcSrjs    adapt->pEncodings = DummyEncoding;
396fa225cbcSrjs    adapt->nFormats = NUM_FORMATS;
397fa225cbcSrjs    adapt->pFormats = Formats;
398fa225cbcSrjs    adapt->nPorts = 1;
399fa225cbcSrjs    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
400fa225cbcSrjs
401fa225cbcSrjs    pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]);
402fa225cbcSrjs
403fa225cbcSrjs    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
404fa225cbcSrjs    adapt->pAttributes = Attributes;
405fa225cbcSrjs    adapt->nImages = NUM_IMAGES;
406fa225cbcSrjs    adapt->nAttributes = NUM_ATTRIBUTES;
407fa225cbcSrjs    adapt->pImages = Images;
408fa225cbcSrjs    adapt->PutVideo = NULL;
409fa225cbcSrjs    adapt->PutStill = NULL;
410fa225cbcSrjs    adapt->GetVideo = NULL;
411fa225cbcSrjs    adapt->GetStill = NULL;
412fa225cbcSrjs    adapt->StopVideo = I810StopVideo;
413fa225cbcSrjs    adapt->SetPortAttribute = I810SetPortAttribute;
414fa225cbcSrjs    adapt->GetPortAttribute = I810GetPortAttribute;
415fa225cbcSrjs    adapt->QueryBestSize = I810QueryBestSize;
416fa225cbcSrjs    adapt->PutImage = I810PutImage;
417fa225cbcSrjs    adapt->QueryImageAttributes = I810QueryImageAttributes;
418fa225cbcSrjs
419fa225cbcSrjs    pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1);
420fa225cbcSrjs    pPriv->videoStatus = 0;
421fa225cbcSrjs    pPriv->brightness = 0;
422fa225cbcSrjs    pPriv->contrast = 64;
423fa225cbcSrjs    pPriv->linear = NULL;
424fa225cbcSrjs    pPriv->currentBuf = 0;
425fa225cbcSrjs
426fa225cbcSrjs    /* gotta uninit this someplace */
427fa225cbcSrjs    REGION_NULL(pScreen, &pPriv->clip);
428fa225cbcSrjs
429fa225cbcSrjs    pI810->adaptor = adapt;
430fa225cbcSrjs
431fa225cbcSrjs    pI810->BlockHandler = pScreen->BlockHandler;
432fa225cbcSrjs    pScreen->BlockHandler = I810BlockHandler;
433fa225cbcSrjs
434fa225cbcSrjs    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
435fa225cbcSrjs    xvContrast   = MAKE_ATOM("XV_CONTRAST");
436fa225cbcSrjs    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
437fa225cbcSrjs
438fa225cbcSrjs    I810ResetVideo(pScrn);
439fa225cbcSrjs
440fa225cbcSrjs    return adapt;
441fa225cbcSrjs}
442fa225cbcSrjs
443fa225cbcSrjs
444fa225cbcSrjs/* I810ClipVideo -
445fa225cbcSrjs
446fa225cbcSrjs   Takes the dst box in standard X BoxRec form (top and left
447fa225cbcSrjs   edges inclusive, bottom and right exclusive).  The new dst
448fa225cbcSrjs   box is returned.  The source boundaries are given (x1, y1
449fa225cbcSrjs   inclusive, x2, y2 exclusive) and returned are the new source
450fa225cbcSrjs   boundaries in 16.16 fixed point.
451fa225cbcSrjs*/
452fa225cbcSrjs
453fa225cbcSrjsstatic void
454fa225cbcSrjsI810ClipVideo(
455fa225cbcSrjs  BoxPtr dst,
456fa225cbcSrjs  INT32 *x1,
457fa225cbcSrjs  INT32 *x2,
458fa225cbcSrjs  INT32 *y1,
459fa225cbcSrjs  INT32 *y2,
460fa225cbcSrjs  BoxPtr extents,            /* extents of the clip region */
461fa225cbcSrjs  INT32 width,
462fa225cbcSrjs  INT32 height
463fa225cbcSrjs){
464fa225cbcSrjs    INT32 vscale, hscale, delta;
465fa225cbcSrjs    int diff;
466fa225cbcSrjs
467fa225cbcSrjs    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
468fa225cbcSrjs    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
469fa225cbcSrjs
470fa225cbcSrjs    *x1 <<= 16; *x2 <<= 16;
471fa225cbcSrjs    *y1 <<= 16; *y2 <<= 16;
472fa225cbcSrjs
473fa225cbcSrjs    diff = extents->x1 - dst->x1;
474fa225cbcSrjs    if(diff > 0) {
475fa225cbcSrjs	dst->x1 = extents->x1;
476fa225cbcSrjs	*x1 += diff * hscale;
477fa225cbcSrjs    }
478fa225cbcSrjs    diff = dst->x2 - extents->x2;
479fa225cbcSrjs    if(diff > 0) {
480fa225cbcSrjs	dst->x2 = extents->x2;
481fa225cbcSrjs	*x2 -= diff * hscale;
482fa225cbcSrjs    }
483fa225cbcSrjs    diff = extents->y1 - dst->y1;
484fa225cbcSrjs    if(diff > 0) {
485fa225cbcSrjs	dst->y1 = extents->y1;
486fa225cbcSrjs	*y1 += diff * vscale;
487fa225cbcSrjs    }
488fa225cbcSrjs    diff = dst->y2 - extents->y2;
489fa225cbcSrjs    if(diff > 0) {
490fa225cbcSrjs	dst->y2 = extents->y2;
491fa225cbcSrjs	*y2 -= diff * vscale;
492fa225cbcSrjs    }
493fa225cbcSrjs
494fa225cbcSrjs    if(*x1 < 0) {
495fa225cbcSrjs	diff =  (- *x1 + hscale - 1)/ hscale;
496fa225cbcSrjs	dst->x1 += diff;
497fa225cbcSrjs	*x1 += diff * hscale;
498fa225cbcSrjs    }
499fa225cbcSrjs    delta = *x2 - (width << 16);
500fa225cbcSrjs    if(delta > 0) {
501fa225cbcSrjs	diff = (delta + hscale - 1)/ hscale;
502fa225cbcSrjs	dst->x2 -= diff;
503fa225cbcSrjs	*x2 -= diff * hscale;
504fa225cbcSrjs    }
505fa225cbcSrjs    if(*y1 < 0) {
506fa225cbcSrjs	diff =  (- *y1 + vscale - 1)/ vscale;
507fa225cbcSrjs	dst->y1 += diff;
508fa225cbcSrjs	*y1 += diff * vscale;
509fa225cbcSrjs    }
510fa225cbcSrjs    delta = *y2 - (height << 16);
511fa225cbcSrjs    if(delta > 0) {
512fa225cbcSrjs	diff = (delta + vscale - 1)/ vscale;
513fa225cbcSrjs	dst->y2 -= diff;
514fa225cbcSrjs	*y2 -= diff * vscale;
515fa225cbcSrjs    }
516fa225cbcSrjs}
517fa225cbcSrjs
518fa225cbcSrjsstatic void
519fa225cbcSrjsI810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
520fa225cbcSrjs{
521fa225cbcSrjs  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
522fa225cbcSrjs  I810Ptr pI810 = I810PTR(pScrn);
523fa225cbcSrjs
524fa225cbcSrjs  I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
525fa225cbcSrjs
526fa225cbcSrjs  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
527fa225cbcSrjs
528fa225cbcSrjs  if(shutdown) {
529fa225cbcSrjs     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
530fa225cbcSrjs	overlay->OV0CMD &= 0xFFFFFFFE;
531fa225cbcSrjs	OVERLAY_UPDATE(pI810->OverlayPhysical);
532fa225cbcSrjs     }
533fa225cbcSrjs     if(pPriv->linear) {
534fa225cbcSrjs	xf86FreeOffscreenLinear(pPriv->linear);
535fa225cbcSrjs	pPriv->linear = NULL;
536fa225cbcSrjs     }
537fa225cbcSrjs     pPriv->videoStatus = 0;
538fa225cbcSrjs  } else {
539fa225cbcSrjs     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
540fa225cbcSrjs	pPriv->videoStatus |= OFF_TIMER;
541fa225cbcSrjs	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
542fa225cbcSrjs     }
543fa225cbcSrjs  }
544fa225cbcSrjs
545fa225cbcSrjs}
546fa225cbcSrjs
547fa225cbcSrjsstatic int
548fa225cbcSrjsI810SetPortAttribute(
549fa225cbcSrjs  ScrnInfoPtr pScrn,
550fa225cbcSrjs  Atom attribute,
551fa225cbcSrjs  INT32 value,
552fa225cbcSrjs  pointer data
553fa225cbcSrjs){
554fa225cbcSrjs  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
555fa225cbcSrjs  I810Ptr pI810 = I810PTR(pScrn);
556fa225cbcSrjs  I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
557fa225cbcSrjs
558fa225cbcSrjs  if(attribute == xvBrightness) {
559fa225cbcSrjs	if((value < -128) || (value > 127))
560fa225cbcSrjs	   return BadValue;
561fa225cbcSrjs	pPriv->brightness = value;
562fa225cbcSrjs	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
563fa225cbcSrjs	OVERLAY_UPDATE(pI810->OverlayPhysical);
564fa225cbcSrjs  } else
565fa225cbcSrjs  if(attribute == xvContrast) {
566fa225cbcSrjs	if((value < 0) || (value > 255))
567fa225cbcSrjs	   return BadValue;
568fa225cbcSrjs	pPriv->contrast = value;
569fa225cbcSrjs	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
570fa225cbcSrjs	OVERLAY_UPDATE(pI810->OverlayPhysical);
571fa225cbcSrjs  } else
572fa225cbcSrjs  if(attribute == xvColorKey) {
573fa225cbcSrjs	pPriv->colorKey = value;
574fa225cbcSrjs	switch(pScrn->depth) {
575fa225cbcSrjs	case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
576fa225cbcSrjs	         break;
577fa225cbcSrjs	case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
578fa225cbcSrjs                 break;
579fa225cbcSrjs	default: overlay->DCLRKV = pPriv->colorKey;
580fa225cbcSrjs                 break;
581fa225cbcSrjs	}
582fa225cbcSrjs	OVERLAY_UPDATE(pI810->OverlayPhysical);
583fa225cbcSrjs	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
584fa225cbcSrjs  } else return BadMatch;
585fa225cbcSrjs
586fa225cbcSrjs  return Success;
587fa225cbcSrjs}
588fa225cbcSrjs
589fa225cbcSrjsstatic int
590fa225cbcSrjsI810GetPortAttribute(
591fa225cbcSrjs  ScrnInfoPtr pScrn,
592fa225cbcSrjs  Atom attribute,
593fa225cbcSrjs  INT32 *value,
594fa225cbcSrjs  pointer data
595fa225cbcSrjs){
596fa225cbcSrjs  I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
597fa225cbcSrjs
598fa225cbcSrjs  if(attribute == xvBrightness) {
599fa225cbcSrjs	*value = pPriv->brightness;
600fa225cbcSrjs  } else
601fa225cbcSrjs  if(attribute == xvContrast) {
602fa225cbcSrjs	*value = pPriv->contrast;
603fa225cbcSrjs  } else
604fa225cbcSrjs  if(attribute == xvColorKey) {
605fa225cbcSrjs	*value = pPriv->colorKey;
606fa225cbcSrjs  } else return BadMatch;
607fa225cbcSrjs
608fa225cbcSrjs  return Success;
609fa225cbcSrjs}
610fa225cbcSrjs
611fa225cbcSrjsstatic void
612fa225cbcSrjsI810QueryBestSize(
613fa225cbcSrjs  ScrnInfoPtr pScrn,
614fa225cbcSrjs  Bool motion,
615fa225cbcSrjs  short vid_w, short vid_h,
616fa225cbcSrjs  short drw_w, short drw_h,
617fa225cbcSrjs  unsigned int *p_w, unsigned int *p_h,
618fa225cbcSrjs  pointer data
619fa225cbcSrjs){
620fa225cbcSrjs   if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
621fa225cbcSrjs   if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
622fa225cbcSrjs
623fa225cbcSrjs  *p_w = drw_w;
624fa225cbcSrjs  *p_h = drw_h;
625fa225cbcSrjs}
626fa225cbcSrjs
627fa225cbcSrjs
628fa225cbcSrjsstatic void
629fa225cbcSrjsI810CopyPackedData(
630fa225cbcSrjs   ScrnInfoPtr pScrn,
631fa225cbcSrjs   unsigned char *buf,
632fa225cbcSrjs   int srcPitch,
633fa225cbcSrjs   int dstPitch,
634fa225cbcSrjs   int top,
635fa225cbcSrjs   int left,
636fa225cbcSrjs   int h,
637fa225cbcSrjs   int w
638fa225cbcSrjs   )
639fa225cbcSrjs{
640fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
641fa225cbcSrjs    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
642fa225cbcSrjs    unsigned char *src, *dst;
643fa225cbcSrjs
644fa225cbcSrjs    src = buf + (top*srcPitch) + (left<<1);
645fa225cbcSrjs
646fa225cbcSrjs    if (pPriv->currentBuf == 0)
647fa225cbcSrjs	dst = pI810->FbBase + pPriv->YBuf0offset;
648fa225cbcSrjs    else
649fa225cbcSrjs	dst = pI810->FbBase + pPriv->YBuf1offset;
650fa225cbcSrjs
651fa225cbcSrjs    w <<= 1;
652fa225cbcSrjs    while(h--) {
653fa225cbcSrjs	memcpy(dst, src, w);
654fa225cbcSrjs	src += srcPitch;
655fa225cbcSrjs	dst += dstPitch;
656fa225cbcSrjs    }
657fa225cbcSrjs}
658fa225cbcSrjs
659fa225cbcSrjsstatic void
660fa225cbcSrjsI810CopyPlanarData(
661fa225cbcSrjs   ScrnInfoPtr pScrn,
662fa225cbcSrjs   unsigned char *buf,
663fa225cbcSrjs   int srcPitch,
664fa225cbcSrjs   int dstPitch,  /* of chroma */
665fa225cbcSrjs   int srcH,
666fa225cbcSrjs   int top,
667fa225cbcSrjs   int left,
668fa225cbcSrjs   int h,
669fa225cbcSrjs   int w,
670fa225cbcSrjs   int id
671fa225cbcSrjs   )
672fa225cbcSrjs{
673fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
674fa225cbcSrjs    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
675fa225cbcSrjs    int i;
676fa225cbcSrjs    unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
677fa225cbcSrjs
678fa225cbcSrjs    /* Copy Y data */
679fa225cbcSrjs    src1 = buf + (top*srcPitch) + left;
680fa225cbcSrjs    if (pPriv->currentBuf == 0)
681fa225cbcSrjs	dst1 = pI810->FbBase + pPriv->YBuf0offset;
682fa225cbcSrjs    else
683fa225cbcSrjs	dst1 = pI810->FbBase + pPriv->YBuf1offset;
684fa225cbcSrjs
685fa225cbcSrjs    for (i = 0; i < h; i++) {
686fa225cbcSrjs	memcpy(dst1, src1, w);
687fa225cbcSrjs	src1 += srcPitch;
688fa225cbcSrjs	dst1 += dstPitch << 1;
689fa225cbcSrjs    }
690fa225cbcSrjs
691fa225cbcSrjs    /* Copy V data for YV12, or U data for I420 */
692fa225cbcSrjs    src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
693fa225cbcSrjs    if (pPriv->currentBuf == 0) {
694fa225cbcSrjs	if (id == FOURCC_I420)
695fa225cbcSrjs	    dst2 = pI810->FbBase + pPriv->UBuf0offset;
696fa225cbcSrjs	else
697fa225cbcSrjs	    dst2 = pI810->FbBase + pPriv->VBuf0offset;
698fa225cbcSrjs    } else {
699fa225cbcSrjs	if (id == FOURCC_I420)
700fa225cbcSrjs	    dst2 = pI810->FbBase + pPriv->UBuf1offset;
701fa225cbcSrjs	else
702fa225cbcSrjs	    dst2 = pI810->FbBase + pPriv->VBuf1offset;
703fa225cbcSrjs    }
704fa225cbcSrjs
705fa225cbcSrjs    for (i = 0; i < h/2; i++) {
706fa225cbcSrjs	memcpy(dst2, src2, w/2);
707fa225cbcSrjs	src2 += srcPitch>>1;
708fa225cbcSrjs	dst2 += dstPitch;
709fa225cbcSrjs    }
710fa225cbcSrjs
711fa225cbcSrjs    /* Copy U data for YV12, or V data for I420 */
712fa225cbcSrjs    src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
713fa225cbcSrjs    if (pPriv->currentBuf == 0) {
714fa225cbcSrjs	if (id == FOURCC_I420)
715fa225cbcSrjs	    dst3 = pI810->FbBase + pPriv->VBuf0offset;
716fa225cbcSrjs	else
717fa225cbcSrjs	    dst3 = pI810->FbBase + pPriv->UBuf0offset;
718fa225cbcSrjs    } else {
719fa225cbcSrjs	if (id == FOURCC_I420)
720fa225cbcSrjs	    dst3 = pI810->FbBase + pPriv->VBuf1offset;
721fa225cbcSrjs	else
722fa225cbcSrjs	    dst3 = pI810->FbBase + pPriv->UBuf1offset;
723fa225cbcSrjs    }
724fa225cbcSrjs
725fa225cbcSrjs    for (i = 0; i < h/2; i++) {
726fa225cbcSrjs	memcpy(dst3, src3, w/2);
727fa225cbcSrjs	src3 += srcPitch>>1;
728fa225cbcSrjs	dst3 += dstPitch;
729fa225cbcSrjs    }
730fa225cbcSrjs}
731fa225cbcSrjs
732fa225cbcSrjsstatic void
733fa225cbcSrjsI810DisplayVideo(
734fa225cbcSrjs    ScrnInfoPtr pScrn,
735fa225cbcSrjs    int id,
736fa225cbcSrjs    short width, short height,
737fa225cbcSrjs    int dstPitch,  /* of chroma for 4:2:0 */
738fa225cbcSrjs    int x1, int y1, int x2, int y2,
739fa225cbcSrjs    BoxPtr dstBox,
740fa225cbcSrjs    short src_w, short src_h,
741fa225cbcSrjs    short drw_w, short drw_h
742fa225cbcSrjs){
743fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
744fa225cbcSrjs    I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
745fa225cbcSrjs    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
746fa225cbcSrjs    int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
747fa225cbcSrjs    int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0;
748fa225cbcSrjs    unsigned int swidth;
749fa225cbcSrjs
750fa225cbcSrjs    switch(id) {
751fa225cbcSrjs    case FOURCC_YV12:
752fa225cbcSrjs    case FOURCC_I420:
753fa225cbcSrjs	swidth = (width + 7) & ~7;
754fa225cbcSrjs	overlay->SWID = (swidth << 15) | swidth;
755fa225cbcSrjs	overlay->SWIDQW = (swidth << 12) | (swidth >> 3);
756fa225cbcSrjs	break;
757fa225cbcSrjs    case FOURCC_UYVY:
758fa225cbcSrjs    case FOURCC_YUY2:
759fa225cbcSrjs    default:
760fa225cbcSrjs	swidth = ((width + 3) & ~3) << 1;
761fa225cbcSrjs	overlay->SWID = swidth;
762fa225cbcSrjs	overlay->SWIDQW = swidth >> 3;
763fa225cbcSrjs	break;
764fa225cbcSrjs    }
765fa225cbcSrjs
766fa225cbcSrjs    /* wide video formats (>720 pixels) are special */
767fa225cbcSrjs    if( swidth > IMAGE_FAST_WIDTH ) {
768fa225cbcSrjs	overlay->OV0CONF = 1; /* one 1440 pixel line buffer */
769fa225cbcSrjs    } else {
770fa225cbcSrjs	overlay->OV0CONF = 0; /* two 720 pixel line buffers */
771fa225cbcSrjs    }
772fa225cbcSrjs
773fa225cbcSrjs    overlay->SHEIGHT = height | (height << 15);
774fa225cbcSrjs    overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1);
775fa225cbcSrjs    overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
776fa225cbcSrjs	              (dstBox->x2 - dstBox->x1);
777fa225cbcSrjs
778fa225cbcSrjs    /* buffer locations */
779fa225cbcSrjs    overlay->OBUF_0Y = pPriv->YBuf0offset;
780fa225cbcSrjs    overlay->OBUF_1Y = pPriv->YBuf1offset;
781fa225cbcSrjs    overlay->OBUF_0U = pPriv->UBuf0offset;
782fa225cbcSrjs    overlay->OBUF_0V = pPriv->VBuf0offset;
783fa225cbcSrjs    overlay->OBUF_1U = pPriv->UBuf1offset;
784fa225cbcSrjs    overlay->OBUF_1V = pPriv->VBuf1offset;
785fa225cbcSrjs
786fa225cbcSrjs    /*
787fa225cbcSrjs     * Calculate horizontal and vertical scaling factors, default to 1:1
788fa225cbcSrjs     */
789fa225cbcSrjs    overlay->YRGBSCALE = 0x80004000;
790fa225cbcSrjs    overlay->UVSCALE = 0x80004000;
791fa225cbcSrjs
792fa225cbcSrjs    /*
793fa225cbcSrjs     * Initially, YCbCr and Overlay Enable and
794fa225cbcSrjs     * vertical chrominance up interpolation and horozontal chrominance
795fa225cbcSrjs     * up interpolation
796fa225cbcSrjs     */
797fa225cbcSrjs    overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
798fa225cbcSrjs	              OVERLAY_ENABLE;
799fa225cbcSrjs
800fa225cbcSrjs    if ((drw_w != src_w) || (drw_h != src_h))
801fa225cbcSrjs    {
802fa225cbcSrjs	xscaleInt = (src_w / drw_w) & 0x3;
803fa225cbcSrjs	xscaleFract = (src_w << 12) / drw_w;
804fa225cbcSrjs	yscaleInt = (src_h / drw_h) & 0x3;
805fa225cbcSrjs	yscaleFract = (src_h << 12) / drw_h;
806fa225cbcSrjs
807fa225cbcSrjs	overlay->YRGBSCALE = (xscaleInt << 15) |
808fa225cbcSrjs	                     ((xscaleFract & 0xFFF) << 3) |
809fa225cbcSrjs	                     (yscaleInt) |
810fa225cbcSrjs			     ((yscaleFract & 0xFFF) << 20);
811fa225cbcSrjs
812fa225cbcSrjs	if (drw_w > src_w)
813fa225cbcSrjs	{
814fa225cbcSrjs	    /* horizontal up-scaling */
815fa225cbcSrjs	    overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
816fa225cbcSrjs	    overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
817fa225cbcSrjs	    overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
818fa225cbcSrjs	}
819fa225cbcSrjs
820fa225cbcSrjs	if (drw_h > src_h)
821fa225cbcSrjs	{
822fa225cbcSrjs	    /* vertical up-scaling */
823fa225cbcSrjs	    overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
824fa225cbcSrjs	    overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
825fa225cbcSrjs	    overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
826fa225cbcSrjs	}
827fa225cbcSrjs
828fa225cbcSrjs	if (drw_w < src_w)
829fa225cbcSrjs	{
830fa225cbcSrjs	    /* horizontal down-scaling */
831fa225cbcSrjs	    overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
832fa225cbcSrjs	    overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
833fa225cbcSrjs	    overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
834fa225cbcSrjs	}
835fa225cbcSrjs
836fa225cbcSrjs	if (drw_h < src_h)
837fa225cbcSrjs	{
838fa225cbcSrjs	    /* vertical down-scaling */
839fa225cbcSrjs	    overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
840fa225cbcSrjs	    overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
841fa225cbcSrjs	    overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
842fa225cbcSrjs	}
843fa225cbcSrjs
844fa225cbcSrjs	/* now calculate the UV scaling factor */
845fa225cbcSrjs
846fa225cbcSrjs	if (xscaleFract)
847fa225cbcSrjs	{
848fa225cbcSrjs	    xscaleFractUV = xscaleFract >> MINUV_SCALE;
849fa225cbcSrjs	    overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION;
850fa225cbcSrjs	    overlay->OV0CMD |= HC_UP_INTERPOLATION;
851fa225cbcSrjs	}
852fa225cbcSrjs
853fa225cbcSrjs	if (xscaleInt)
854fa225cbcSrjs	{
855fa225cbcSrjs	    xscaleIntUV = xscaleInt >> MINUV_SCALE;
856fa225cbcSrjs	    if (xscaleIntUV)
857fa225cbcSrjs	    {
858fa225cbcSrjs		overlay->OV0CMD &= ~HC_UP_INTERPOLATION;
859fa225cbcSrjs	    }
860fa225cbcSrjs	}
861fa225cbcSrjs
862fa225cbcSrjs	if (yscaleFract)
863fa225cbcSrjs	{
864fa225cbcSrjs	    yscaleFractUV = yscaleFract >> MINUV_SCALE;
865fa225cbcSrjs	    overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION;
866fa225cbcSrjs	    overlay->OV0CMD |= VC_UP_INTERPOLATION;
867fa225cbcSrjs	}
868fa225cbcSrjs
869fa225cbcSrjs	if (yscaleInt)
870fa225cbcSrjs	{
871fa225cbcSrjs	    yscaleIntUV = yscaleInt >> MINUV_SCALE;
872fa225cbcSrjs	    if (yscaleIntUV)
873fa225cbcSrjs	    {
874fa225cbcSrjs		overlay->OV0CMD &= ~VC_UP_INTERPOLATION;
875fa225cbcSrjs		overlay->OV0CMD |= VC_DOWN_INTERPOLATION;
876fa225cbcSrjs	    }
877fa225cbcSrjs	}
878fa225cbcSrjs
879fa225cbcSrjs	overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
880fa225cbcSrjs	                   ((yscaleFractUV & 0xFFF) << 20);
881fa225cbcSrjs    }
882fa225cbcSrjs
883fa225cbcSrjs    switch(id) {
884fa225cbcSrjs    case FOURCC_YV12:
885fa225cbcSrjs    case FOURCC_I420:
886fa225cbcSrjs	/* set UV vertical phase to -0.25 */
887fa225cbcSrjs	overlay->UV_VPH = 0x30003000;
888fa225cbcSrjs	overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1;
889fa225cbcSrjs	overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
890fa225cbcSrjs	overlay->OV0CMD &= ~SOURCE_FORMAT;
891fa225cbcSrjs	overlay->OV0CMD |= YUV_420;
892fa225cbcSrjs	break;
893fa225cbcSrjs    case I810_RV15:
894fa225cbcSrjs    case I810_RV16:
895fa225cbcSrjs	overlay->UV_VPH = 0;
896fa225cbcSrjs	overlay->INIT_PH = 0;
897fa225cbcSrjs	overlay->OV0STRIDE = dstPitch;
898fa225cbcSrjs	overlay->OV0CMD &= ~SOURCE_FORMAT;
899fa225cbcSrjs	overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565);
900fa225cbcSrjs	overlay->OV0CMD &= ~OV_BYTE_ORDER;
901fa225cbcSrjs	break;
902fa225cbcSrjs    case FOURCC_UYVY:
903fa225cbcSrjs    case FOURCC_YUY2:
904fa225cbcSrjs    default:
905fa225cbcSrjs	overlay->UV_VPH = 0;
906fa225cbcSrjs	overlay->INIT_PH = 0;
907fa225cbcSrjs	overlay->OV0STRIDE = dstPitch;
908fa225cbcSrjs	overlay->OV0CMD &= ~SOURCE_FORMAT;
909fa225cbcSrjs	overlay->OV0CMD |= YUV_422;
910fa225cbcSrjs	overlay->OV0CMD &= ~OV_BYTE_ORDER;
911fa225cbcSrjs	if (id == FOURCC_UYVY)
912fa225cbcSrjs	    overlay->OV0CMD |= Y_SWAP;
913fa225cbcSrjs	break;
914fa225cbcSrjs    }
915fa225cbcSrjs
916fa225cbcSrjs    overlay->OV0CMD &= ~BUFFER_AND_FIELD;
917fa225cbcSrjs    if (pPriv->currentBuf == 0)
918fa225cbcSrjs	overlay->OV0CMD |= BUFFER0_FIELD0;
919fa225cbcSrjs    else
920fa225cbcSrjs	overlay->OV0CMD |= BUFFER1_FIELD0;
921fa225cbcSrjs
922fa225cbcSrjs    OVERLAY_UPDATE(pI810->OverlayPhysical);
923fa225cbcSrjs
924fa225cbcSrjs}
925fa225cbcSrjs
926fa225cbcSrjsstatic FBLinearPtr
927fa225cbcSrjsI810AllocateMemory(
928fa225cbcSrjs  ScrnInfoPtr pScrn,
929fa225cbcSrjs  FBLinearPtr linear,
930fa225cbcSrjs  int size
931fa225cbcSrjs){
932fa225cbcSrjs   ScreenPtr pScreen;
933fa225cbcSrjs   FBLinearPtr new_linear;
934fa225cbcSrjs
935fa225cbcSrjs   if(linear) {
936fa225cbcSrjs	if(linear->size >= size)
937fa225cbcSrjs	   return linear;
938fa225cbcSrjs
939fa225cbcSrjs	if(xf86ResizeOffscreenLinear(linear, size))
940fa225cbcSrjs	   return linear;
941fa225cbcSrjs
942fa225cbcSrjs	xf86FreeOffscreenLinear(linear);
943fa225cbcSrjs   }
944fa225cbcSrjs
945fa225cbcSrjs   pScreen = screenInfo.screens[pScrn->scrnIndex];
946fa225cbcSrjs
947fa225cbcSrjs   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
948fa225cbcSrjs                                            NULL, NULL, NULL);
949fa225cbcSrjs
950fa225cbcSrjs   if(!new_linear) {
951fa225cbcSrjs        int max_size;
952fa225cbcSrjs
953fa225cbcSrjs        xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
954fa225cbcSrjs				       PRIORITY_EXTREME);
955fa225cbcSrjs
956fa225cbcSrjs        if(max_size < size) return NULL;
957fa225cbcSrjs
958fa225cbcSrjs        xf86PurgeUnlockedOffscreenAreas(pScreen);
959fa225cbcSrjs        new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
960fa225cbcSrjs                                                 NULL, NULL, NULL);
961fa225cbcSrjs   }
962fa225cbcSrjs
963fa225cbcSrjs   return new_linear;
964fa225cbcSrjs}
965fa225cbcSrjs
966fa225cbcSrjsstatic int
967fa225cbcSrjsI810PutImage(
968fa225cbcSrjs  ScrnInfoPtr pScrn,
969fa225cbcSrjs  short src_x, short src_y,
970fa225cbcSrjs  short drw_x, short drw_y,
971fa225cbcSrjs  short src_w, short src_h,
972fa225cbcSrjs  short drw_w, short drw_h,
973fa225cbcSrjs  int id, unsigned char* buf,
974fa225cbcSrjs  short width, short height,
975fa225cbcSrjs  Bool sync,
976fa225cbcSrjs  RegionPtr clipBoxes, pointer data,
977fa225cbcSrjs  DrawablePtr pDraw
978fa225cbcSrjs){
979fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
980fa225cbcSrjs    I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
981fa225cbcSrjs    INT32 x1, x2, y1, y2;
982fa225cbcSrjs    int srcPitch, dstPitch;
983fa225cbcSrjs    int top, left, npixels, nlines, size, loops;
984fa225cbcSrjs    BoxRec dstBox;
985fa225cbcSrjs
986fa225cbcSrjs
987fa225cbcSrjs    /* Clip */
988fa225cbcSrjs    x1 = src_x;
989fa225cbcSrjs    x2 = src_x + src_w;
990fa225cbcSrjs    y1 = src_y;
991fa225cbcSrjs    y2 = src_y + src_h;
992fa225cbcSrjs
993fa225cbcSrjs    dstBox.x1 = drw_x;
994fa225cbcSrjs    dstBox.x2 = drw_x + drw_w;
995fa225cbcSrjs    dstBox.y1 = drw_y;
996fa225cbcSrjs    dstBox.y2 = drw_y + drw_h;
997fa225cbcSrjs
998fa225cbcSrjs    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
999fa225cbcSrjs		  REGION_EXTENTS(pScrn->pScreen, clipBoxes), width, height);
1000fa225cbcSrjs
1001fa225cbcSrjs    if((x1 >= x2) || (y1 >= y2))
1002fa225cbcSrjs       return Success;
1003fa225cbcSrjs    /*
1004fa225cbcSrjs     * Fix for 4 pixel granularity of AdjustFrame
1005fa225cbcSrjs     * unless boarder is clipped  by frame
1006fa225cbcSrjs     */
1007fa225cbcSrjs    dstBox.x1 -= (pScrn->frameX0 &
1008fa225cbcSrjs		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
1009fa225cbcSrjs    dstBox.x2 -= (pScrn->frameX0 & ~0x3);
1010fa225cbcSrjs    dstBox.y1 -= pScrn->frameY0;
1011fa225cbcSrjs    dstBox.y2 -= pScrn->frameY0;
1012fa225cbcSrjs
1013fa225cbcSrjs    switch(id) {
1014fa225cbcSrjs    case FOURCC_YV12:
1015fa225cbcSrjs    case FOURCC_I420:
1016fa225cbcSrjs	 srcPitch = (width + 3) & ~3;
1017fa225cbcSrjs	 dstPitch = ((width >> 1) + 7) & ~7;  /* of chroma */
1018fa225cbcSrjs	 size =  dstPitch * height * 3;
1019fa225cbcSrjs	 break;
1020fa225cbcSrjs    case FOURCC_UYVY:
1021fa225cbcSrjs    case FOURCC_YUY2:
1022fa225cbcSrjs    default:
1023fa225cbcSrjs	 srcPitch = (width << 1);
1024fa225cbcSrjs	 dstPitch = (srcPitch + 7) & ~7;
1025fa225cbcSrjs	 size = dstPitch * height;
1026fa225cbcSrjs	 break;
1027fa225cbcSrjs    }
1028fa225cbcSrjs
1029fa225cbcSrjs    if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear,
1030fa225cbcSrjs		(pScrn->bitsPerPixel == 16) ? size : (size >> 1))))
1031fa225cbcSrjs	return BadAlloc;
1032fa225cbcSrjs
1033fa225cbcSrjs    /* fixup pointers */
1034fa225cbcSrjs    pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp;
1035fa225cbcSrjs    pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
1036fa225cbcSrjs    pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);
1037fa225cbcSrjs
1038fa225cbcSrjs    pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size;
1039fa225cbcSrjs    pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
1040fa225cbcSrjs    pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);
1041fa225cbcSrjs
1042fa225cbcSrjs
1043fa225cbcSrjs    /* Make sure this buffer isn't in use */
1044fa225cbcSrjs    loops = 0;
1045fa225cbcSrjs    while (loops < 1000000) {
1046fa225cbcSrjs          if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) {
1047fa225cbcSrjs            break;
1048fa225cbcSrjs          }
1049fa225cbcSrjs          loops++;
1050fa225cbcSrjs    }
1051fa225cbcSrjs    if(loops >= 1000000) {
1052fa225cbcSrjs      pPriv->currentBuf = !pPriv->currentBuf;
1053fa225cbcSrjs    }
1054fa225cbcSrjs
1055fa225cbcSrjs
1056fa225cbcSrjs    /* buffer swap */
1057fa225cbcSrjs    if (pPriv->currentBuf == 0)
1058fa225cbcSrjs        pPriv->currentBuf = 1;
1059fa225cbcSrjs    else
1060fa225cbcSrjs        pPriv->currentBuf = 0;
1061fa225cbcSrjs
1062fa225cbcSrjs    /* copy data */
1063fa225cbcSrjs    top = y1 >> 16;
1064fa225cbcSrjs    left = (x1 >> 16) & ~1;
1065fa225cbcSrjs    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
1066fa225cbcSrjs
1067fa225cbcSrjs    switch(id) {
1068fa225cbcSrjs    case FOURCC_YV12:
1069fa225cbcSrjs    case FOURCC_I420:
1070fa225cbcSrjs	top &= ~1;
1071fa225cbcSrjs	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
1072fa225cbcSrjs	I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch,  height, top, left,
1073fa225cbcSrjs                           nlines, npixels, id);
1074fa225cbcSrjs	break;
1075fa225cbcSrjs    case FOURCC_UYVY:
1076fa225cbcSrjs    case FOURCC_YUY2:
1077fa225cbcSrjs    default:
1078fa225cbcSrjs	nlines = ((y2 + 0xffff) >> 16) - top;
1079fa225cbcSrjs	I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
1080fa225cbcSrjs                                                              npixels);
1081fa225cbcSrjs        break;
1082fa225cbcSrjs    }
1083fa225cbcSrjs
1084fa225cbcSrjs    /* update cliplist */
1085fa225cbcSrjs    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
1086fa225cbcSrjs	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
1087fa225cbcSrjs	/* draw these */
1088fa225cbcSrjs	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1089fa225cbcSrjs    }
1090fa225cbcSrjs
1091fa225cbcSrjs    I810DisplayVideo(pScrn, id, width, height, dstPitch,
1092fa225cbcSrjs	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
1093fa225cbcSrjs
1094fa225cbcSrjs    pPriv->videoStatus = CLIENT_VIDEO_ON;
1095fa225cbcSrjs
1096fa225cbcSrjs    return Success;
1097fa225cbcSrjs}
1098fa225cbcSrjs
1099fa225cbcSrjs
1100fa225cbcSrjsstatic int
1101fa225cbcSrjsI810QueryImageAttributes(
1102fa225cbcSrjs  ScrnInfoPtr pScrn,
1103fa225cbcSrjs  int id,
1104fa225cbcSrjs  unsigned short *w, unsigned short *h,
1105fa225cbcSrjs  int *pitches, int *offsets
1106fa225cbcSrjs){
1107fa225cbcSrjs    int size, tmp;
1108fa225cbcSrjs
1109fa225cbcSrjs    if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH;
1110fa225cbcSrjs    if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT;
1111fa225cbcSrjs
1112fa225cbcSrjs    *w = (*w + 1) & ~1;
1113fa225cbcSrjs    if(offsets) offsets[0] = 0;
1114fa225cbcSrjs
1115fa225cbcSrjs    switch(id) {
1116fa225cbcSrjs      /* IA44 is for XvMC only */
1117fa225cbcSrjs    case FOURCC_IA44:
1118fa225cbcSrjs    case FOURCC_AI44:
1119fa225cbcSrjs	if(pitches) pitches[0] = *w;
1120fa225cbcSrjs	size = *w * *h;
1121fa225cbcSrjs	break;
1122fa225cbcSrjs    case FOURCC_YV12:
1123fa225cbcSrjs    case FOURCC_I420:
1124fa225cbcSrjs	*h = (*h + 1) & ~1;
1125fa225cbcSrjs	size = (*w + 3) & ~3;
1126fa225cbcSrjs	if(pitches) pitches[0] = size;
1127fa225cbcSrjs	size *= *h;
1128fa225cbcSrjs	if(offsets) offsets[1] = size;
1129fa225cbcSrjs	tmp = ((*w >> 1) + 3) & ~3;
1130fa225cbcSrjs	if(pitches) pitches[1] = pitches[2] = tmp;
1131fa225cbcSrjs	tmp *= (*h >> 1);
1132fa225cbcSrjs	size += tmp;
1133fa225cbcSrjs	if(offsets) offsets[2] = size;
1134fa225cbcSrjs	size += tmp;
1135fa225cbcSrjs	break;
1136fa225cbcSrjs    case FOURCC_UYVY:
1137fa225cbcSrjs    case FOURCC_YUY2:
1138fa225cbcSrjs    default:
1139fa225cbcSrjs	size = *w << 1;
1140fa225cbcSrjs	if(pitches) pitches[0] = size;
1141fa225cbcSrjs	size *= *h;
1142fa225cbcSrjs	break;
1143fa225cbcSrjs    }
1144fa225cbcSrjs
1145fa225cbcSrjs    return size;
1146fa225cbcSrjs}
1147fa225cbcSrjs
1148fa225cbcSrjsstatic void
1149fa225cbcSrjsI810BlockHandler (
1150fa225cbcSrjs    int i,
1151fa225cbcSrjs    pointer     blockData,
1152fa225cbcSrjs    pointer     pTimeout,
1153fa225cbcSrjs    pointer     pReadmask
1154fa225cbcSrjs){
1155fa225cbcSrjs    ScreenPtr   pScreen = screenInfo.screens[i];
1156fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[i];
1157fa225cbcSrjs    I810Ptr      pI810 = I810PTR(pScrn);
1158fa225cbcSrjs    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
1159fa225cbcSrjs    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
1160fa225cbcSrjs
1161fa225cbcSrjs    pScreen->BlockHandler = pI810->BlockHandler;
1162fa225cbcSrjs
1163fa225cbcSrjs    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
1164fa225cbcSrjs
1165fa225cbcSrjs    pScreen->BlockHandler = I810BlockHandler;
1166fa225cbcSrjs
1167fa225cbcSrjs    if(pPriv->videoStatus & TIMER_MASK) {
1168fa225cbcSrjs	UpdateCurrentTime();
1169fa225cbcSrjs	if(pPriv->videoStatus & OFF_TIMER) {
1170fa225cbcSrjs	    if(pPriv->offTime < currentTime.milliseconds) {
1171fa225cbcSrjs		/* Turn off the overlay */
1172fa225cbcSrjs		overlay->OV0CMD &= 0xFFFFFFFE;
1173fa225cbcSrjs		OVERLAY_UPDATE(pI810->OverlayPhysical);
1174fa225cbcSrjs
1175fa225cbcSrjs		pPriv->videoStatus = FREE_TIMER;
1176fa225cbcSrjs		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1177fa225cbcSrjs	    }
1178fa225cbcSrjs	} else {  /* FREE_TIMER */
1179fa225cbcSrjs	    if(pPriv->freeTime < currentTime.milliseconds) {
1180fa225cbcSrjs		if(pPriv->linear) {
1181fa225cbcSrjs		   xf86FreeOffscreenLinear(pPriv->linear);
1182fa225cbcSrjs		   pPriv->linear = NULL;
1183fa225cbcSrjs		}
1184fa225cbcSrjs		pPriv->videoStatus = 0;
1185fa225cbcSrjs	    }
1186fa225cbcSrjs        }
1187fa225cbcSrjs    }
1188fa225cbcSrjs}
1189fa225cbcSrjs
1190fa225cbcSrjs
1191fa225cbcSrjs/***************************************************************************
1192fa225cbcSrjs * Offscreen Images
1193fa225cbcSrjs ***************************************************************************/
1194fa225cbcSrjs
1195fa225cbcSrjstypedef struct {
1196fa225cbcSrjs  FBLinearPtr linear;
1197fa225cbcSrjs  Bool isOn;
1198fa225cbcSrjs} OffscreenPrivRec, * OffscreenPrivPtr;
1199fa225cbcSrjs
1200fa225cbcSrjsstatic int
1201fa225cbcSrjsI810AllocateSurface(
1202fa225cbcSrjs    ScrnInfoPtr pScrn,
1203fa225cbcSrjs    int id,
1204fa225cbcSrjs    unsigned short w,
1205fa225cbcSrjs    unsigned short h,
1206fa225cbcSrjs    XF86SurfacePtr surface
1207fa225cbcSrjs){
1208fa225cbcSrjs    FBLinearPtr linear;
1209fa225cbcSrjs    int pitch, fbpitch, size, bpp;
1210fa225cbcSrjs    OffscreenPrivPtr pPriv;
1211fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
1212fa225cbcSrjs
1213fa225cbcSrjs    if((w > 1024) || (h > 1024))
1214fa225cbcSrjs	return BadAlloc;
1215fa225cbcSrjs
1216fa225cbcSrjs    w = (w + 1) & ~1;
1217fa225cbcSrjs    pitch = ((w << 1) + 15) & ~15;
1218fa225cbcSrjs    bpp = pScrn->bitsPerPixel >> 3;
1219fa225cbcSrjs    fbpitch = bpp * pScrn->displayWidth;
1220fa225cbcSrjs    size = ((pitch * h) + bpp - 1) / bpp;
1221fa225cbcSrjs
1222fa225cbcSrjs    if(!(linear = I810AllocateMemory(pScrn, NULL, size)))
1223fa225cbcSrjs	return BadAlloc;
1224fa225cbcSrjs
1225fa225cbcSrjs    surface->width = w;
1226fa225cbcSrjs    surface->height = h;
1227fa225cbcSrjs
1228fa225cbcSrjs    if(!(surface->pitches = xalloc(sizeof(int)))) {
1229fa225cbcSrjs	xf86FreeOffscreenLinear(linear);
1230fa225cbcSrjs	return BadAlloc;
1231fa225cbcSrjs    }
1232fa225cbcSrjs    if(!(surface->offsets = xalloc(sizeof(int)))) {
1233fa225cbcSrjs	xfree(surface->pitches);
1234fa225cbcSrjs	xf86FreeOffscreenLinear(linear);
1235fa225cbcSrjs	return BadAlloc;
1236fa225cbcSrjs    }
1237fa225cbcSrjs    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
1238fa225cbcSrjs	xfree(surface->pitches);
1239fa225cbcSrjs	xfree(surface->offsets);
1240fa225cbcSrjs	xf86FreeOffscreenLinear(linear);
1241fa225cbcSrjs	return BadAlloc;
1242fa225cbcSrjs    }
1243fa225cbcSrjs
1244fa225cbcSrjs    pPriv->linear = linear;
1245fa225cbcSrjs    pPriv->isOn = FALSE;
1246fa225cbcSrjs
1247fa225cbcSrjs    surface->pScrn = pScrn;
1248fa225cbcSrjs    surface->id = id;
1249fa225cbcSrjs    surface->pitches[0] = pitch;
1250fa225cbcSrjs    surface->offsets[0] = linear->offset * bpp;
1251fa225cbcSrjs    surface->devPrivate.ptr = (pointer)pPriv;
1252fa225cbcSrjs
1253fa225cbcSrjs    memset(pI810->FbBase + surface->offsets[0],0,size);
1254fa225cbcSrjs
1255fa225cbcSrjs    return Success;
1256fa225cbcSrjs}
1257fa225cbcSrjs
1258fa225cbcSrjsstatic int
1259fa225cbcSrjsI810StopSurface(
1260fa225cbcSrjs    XF86SurfacePtr surface
1261fa225cbcSrjs){
1262fa225cbcSrjs    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1263fa225cbcSrjs
1264fa225cbcSrjs    if(pPriv->isOn) {
1265fa225cbcSrjs      I810Ptr pI810 = I810PTR(surface->pScrn);
1266fa225cbcSrjs
1267fa225cbcSrjs      I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
1268fa225cbcSrjs
1269fa225cbcSrjs      overlay->OV0CMD &= 0xFFFFFFFE;
1270fa225cbcSrjs      OVERLAY_UPDATE(pI810->OverlayPhysical);
1271fa225cbcSrjs
1272fa225cbcSrjs      pPriv->isOn = FALSE;
1273fa225cbcSrjs    }
1274fa225cbcSrjs
1275fa225cbcSrjs    return Success;
1276fa225cbcSrjs}
1277fa225cbcSrjs
1278fa225cbcSrjs
1279fa225cbcSrjsstatic int
1280fa225cbcSrjsI810FreeSurface(
1281fa225cbcSrjs    XF86SurfacePtr surface
1282fa225cbcSrjs){
1283fa225cbcSrjs    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1284fa225cbcSrjs
1285fa225cbcSrjs    if(pPriv->isOn) {
1286fa225cbcSrjs	I810StopSurface(surface);
1287fa225cbcSrjs    }
1288fa225cbcSrjs    xf86FreeOffscreenLinear(pPriv->linear);
1289fa225cbcSrjs    xfree(surface->pitches);
1290fa225cbcSrjs    xfree(surface->offsets);
1291fa225cbcSrjs    xfree(surface->devPrivate.ptr);
1292fa225cbcSrjs
1293fa225cbcSrjs    return Success;
1294fa225cbcSrjs}
1295fa225cbcSrjs
1296fa225cbcSrjsstatic int
1297fa225cbcSrjsI810GetSurfaceAttribute(
1298fa225cbcSrjs    ScrnInfoPtr pScrn,
1299fa225cbcSrjs    Atom attribute,
1300fa225cbcSrjs    INT32 *value
1301fa225cbcSrjs){
1302fa225cbcSrjs    return I810GetPortAttribute(pScrn, attribute, value, NULL);
1303fa225cbcSrjs}
1304fa225cbcSrjs
1305fa225cbcSrjsstatic int
1306fa225cbcSrjsI810SetSurfaceAttribute(
1307fa225cbcSrjs    ScrnInfoPtr pScrn,
1308fa225cbcSrjs    Atom attribute,
1309fa225cbcSrjs    INT32 value
1310fa225cbcSrjs){
1311fa225cbcSrjs    return I810SetPortAttribute(pScrn, attribute, value, NULL);
1312fa225cbcSrjs}
1313fa225cbcSrjs
1314fa225cbcSrjs
1315fa225cbcSrjsstatic int
1316fa225cbcSrjsI810DisplaySurface(
1317fa225cbcSrjs    XF86SurfacePtr surface,
1318fa225cbcSrjs    short src_x, short src_y,
1319fa225cbcSrjs    short drw_x, short drw_y,
1320fa225cbcSrjs    short src_w, short src_h,
1321fa225cbcSrjs    short drw_w, short drw_h,
1322fa225cbcSrjs    RegionPtr clipBoxes
1323fa225cbcSrjs){
1324fa225cbcSrjs    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1325fa225cbcSrjs    ScrnInfoPtr pScrn = surface->pScrn;
1326fa225cbcSrjs    I810Ptr      pI810 = I810PTR(pScrn);
1327fa225cbcSrjs    I810PortPrivPtr pI810Priv =  GET_PORT_PRIVATE(pScrn);
1328fa225cbcSrjs
1329fa225cbcSrjs    INT32 x1, y1, x2, y2;
1330fa225cbcSrjs    INT32 loops = 0;
1331fa225cbcSrjs    BoxRec dstBox;
1332fa225cbcSrjs
1333fa225cbcSrjs    x1 = src_x;
1334fa225cbcSrjs    x2 = src_x + src_w;
1335fa225cbcSrjs    y1 = src_y;
1336fa225cbcSrjs    y2 = src_y + src_h;
1337fa225cbcSrjs
1338fa225cbcSrjs    dstBox.x1 = drw_x;
1339fa225cbcSrjs    dstBox.x2 = drw_x + drw_w;
1340fa225cbcSrjs    dstBox.y1 = drw_y;
1341fa225cbcSrjs    dstBox.y2 = drw_y + drw_h;
1342fa225cbcSrjs
1343fa225cbcSrjs    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1344fa225cbcSrjs		  REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
1345fa225cbcSrjs		  surface->width, surface->height);
1346fa225cbcSrjs
1347fa225cbcSrjs    /*
1348fa225cbcSrjs     * Fix for 4 pixel granularity of AdjustFrame
1349fa225cbcSrjs     * unless boarder is clipped  by frame
1350fa225cbcSrjs     */
1351fa225cbcSrjs    dstBox.x1 -= (pScrn->frameX0 &
1352fa225cbcSrjs		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
1353fa225cbcSrjs    dstBox.x2 -= (pScrn->frameX0 & ~0x3);
1354fa225cbcSrjs    dstBox.y1 -= pScrn->frameY0;
1355fa225cbcSrjs    dstBox.y2 -= pScrn->frameY0;
1356fa225cbcSrjs
1357fa225cbcSrjs    /* fixup pointers */
1358fa225cbcSrjs    pI810Priv->YBuf0offset = surface->offsets[0];
1359fa225cbcSrjs    pI810Priv->YBuf1offset = pI810Priv->YBuf0offset;
1360fa225cbcSrjs
1361fa225cbcSrjs   /* wait for the last rendered buffer to be flipped in */
1362fa225cbcSrjs    while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) {
1363fa225cbcSrjs      if(loops == 200000) {
1364fa225cbcSrjs	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
1365fa225cbcSrjs	break;
1366fa225cbcSrjs      }
1367fa225cbcSrjs      loops++;
1368fa225cbcSrjs    }
1369fa225cbcSrjs
1370fa225cbcSrjs    /* buffer swap */
1371fa225cbcSrjs    if (pI810Priv->currentBuf == 0)
1372fa225cbcSrjs      pI810Priv->currentBuf = 1;
1373fa225cbcSrjs    else
1374fa225cbcSrjs      pI810Priv->currentBuf = 0;
1375fa225cbcSrjs
1376fa225cbcSrjs    I810ResetVideo(pScrn);
1377fa225cbcSrjs
1378fa225cbcSrjs    I810DisplayVideo(pScrn, surface->id, surface->width, surface->height,
1379fa225cbcSrjs		     surface->pitches[0], x1, y1, x2, y2, &dstBox,
1380fa225cbcSrjs		     src_w, src_h, drw_w, drw_h);
1381fa225cbcSrjs
1382fa225cbcSrjs    xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes);
1383fa225cbcSrjs
1384fa225cbcSrjs    pPriv->isOn = TRUE;
1385fa225cbcSrjs    /* we've prempted the XvImage stream so set its free timer */
1386fa225cbcSrjs    if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) {
1387fa225cbcSrjs      REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip);
1388fa225cbcSrjs      UpdateCurrentTime();
1389fa225cbcSrjs      pI810Priv->videoStatus = FREE_TIMER;
1390fa225cbcSrjs      pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
1391fa225cbcSrjs      pScrn->pScreen->BlockHandler = I810BlockHandler;
1392fa225cbcSrjs    }
1393fa225cbcSrjs
1394fa225cbcSrjs    return Success;
1395fa225cbcSrjs}
1396fa225cbcSrjs
1397fa225cbcSrjs
1398fa225cbcSrjsstatic void
1399fa225cbcSrjsI810InitOffscreenImages(ScreenPtr pScreen)
1400fa225cbcSrjs{
1401fa225cbcSrjs    XF86OffscreenImagePtr offscreenImages;
1402fa225cbcSrjs
1403fa225cbcSrjs    /* need to free this someplace */
1404fa225cbcSrjs    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
1405fa225cbcSrjs      return;
1406fa225cbcSrjs    }
1407fa225cbcSrjs
1408fa225cbcSrjs    offscreenImages[0].image = &Images[0];
1409fa225cbcSrjs    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1410fa225cbcSrjs			       VIDEO_CLIP_TO_VIEWPORT;
1411fa225cbcSrjs    offscreenImages[0].alloc_surface = I810AllocateSurface;
1412fa225cbcSrjs    offscreenImages[0].free_surface = I810FreeSurface;
1413fa225cbcSrjs    offscreenImages[0].display = I810DisplaySurface;
1414fa225cbcSrjs    offscreenImages[0].stop = I810StopSurface;
1415fa225cbcSrjs    offscreenImages[0].setAttribute = I810SetSurfaceAttribute;
1416fa225cbcSrjs    offscreenImages[0].getAttribute = I810GetSurfaceAttribute;
1417fa225cbcSrjs    offscreenImages[0].max_width = 1024;
1418fa225cbcSrjs    offscreenImages[0].max_height = 1024;
1419fa225cbcSrjs    offscreenImages[0].num_attributes = 1;
1420fa225cbcSrjs    offscreenImages[0].attributes = Attributes;
1421fa225cbcSrjs
1422fa225cbcSrjs    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1423fa225cbcSrjs}
1424fa225cbcSrjs
1425