1c06b6b69Smrg
2c06b6b69Smrg#ifdef HAVE_CONFIG_H
3c06b6b69Smrg#include "config.h"
4c06b6b69Smrg#endif
5c06b6b69Smrg
6c06b6b69Smrg#include "xf86.h"
7c06b6b69Smrg#include "xf86_OSproc.h"
8c06b6b69Smrg#include "compiler.h"
9c06b6b69Smrg#include "xf86Pci.h"
10c06b6b69Smrg#include "xf86fbman.h"
11c06b6b69Smrg#include "regionstr.h"
12c06b6b69Smrg
13c06b6b69Smrg#include "ct_driver.h"
14c06b6b69Smrg#include <X11/extensions/Xv.h>
15c06b6b69Smrg#include "dixstruct.h"
16c06b6b69Smrg#include "fourcc.h"
17c06b6b69Smrg
18c06b6b69Smrg#define OFF_DELAY 	200  /* milliseconds */
19c06b6b69Smrg#define FREE_DELAY 	60000
20c06b6b69Smrg
21c06b6b69Smrg#define OFF_TIMER 	0x01
22c06b6b69Smrg#define FREE_TIMER	0x02
23c06b6b69Smrg#define CLIENT_VIDEO_ON	0x04
24c06b6b69Smrg
25c06b6b69Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
26c06b6b69Smrg
27c06b6b69Smrgstatic XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr);
28c06b6b69Smrgstatic void CHIPSInitOffscreenImages(ScreenPtr);
29c06b6b69Smrgstatic void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool);
30c06b6b69Smrgstatic int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
31c06b6b69Smrgstatic int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
32c06b6b69Smrgstatic void CHIPSQueryBestSize(ScrnInfoPtr, Bool,
33c06b6b69Smrg	short, short, short, short, unsigned int *, unsigned int *, pointer);
34c06b6b69Smrgstatic int CHIPSPutImage( ScrnInfoPtr,
35c06b6b69Smrg	short, short, short, short, short, short, short, short,
36c06b6b69Smrg	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
37c06b6b69Smrg	DrawablePtr);
38c06b6b69Smrgstatic int CHIPSQueryImageAttributes(ScrnInfoPtr,
39c06b6b69Smrg	int, unsigned short *, unsigned short *,  int *, int *);
40c06b6b69Smrgstatic void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
41c06b6b69Smrg
42c06b6b69Smrg
43c06b6b69Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
44c06b6b69Smrg
45c06b6b69Smrgstatic Atom xvColorKey;
46c06b6b69Smrg
47c06b6b69Smrgvoid
48c06b6b69SmrgCHIPSInitVideo(ScreenPtr pScreen)
49c06b6b69Smrg{
50a1d73b4bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
51c06b6b69Smrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
52c06b6b69Smrg    XF86VideoAdaptorPtr newAdaptor = NULL;
53c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
54c06b6b69Smrg    int num_adaptors;
55c06b6b69Smrg
56a1d73b4bSmrg    if ((cPtr->Flags & ChipsVideoSupport)) {
57c06b6b69Smrg	newAdaptor = CHIPSSetupImageVideo(pScreen);
58c06b6b69Smrg	CHIPSInitOffscreenImages(pScreen);
59c06b6b69Smrg    }
60c06b6b69Smrg
61c06b6b69Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
62c06b6b69Smrg
63c06b6b69Smrg    if(newAdaptor) {
64c06b6b69Smrg	if(!num_adaptors) {
65c06b6b69Smrg	    num_adaptors = 1;
66c06b6b69Smrg	    adaptors = &newAdaptor;
67c06b6b69Smrg	} else {
68c06b6b69Smrg	    newAdaptors =  /* need to free this someplace */
693699b6c4Smrg		malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
70c06b6b69Smrg	    if(newAdaptors) {
71c06b6b69Smrg		memcpy(newAdaptors, adaptors, num_adaptors *
72c06b6b69Smrg					sizeof(XF86VideoAdaptorPtr));
73c06b6b69Smrg		newAdaptors[num_adaptors] = newAdaptor;
74c06b6b69Smrg		adaptors = newAdaptors;
75c06b6b69Smrg		num_adaptors++;
76c06b6b69Smrg	    }
77c06b6b69Smrg	}
78c06b6b69Smrg    }
79c06b6b69Smrg
80c06b6b69Smrg    if(num_adaptors)
81c06b6b69Smrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
82c06b6b69Smrg
833699b6c4Smrg    free(newAdaptors);
84c06b6b69Smrg}
85c06b6b69Smrg
86c06b6b69Smrg/* client libraries expect an encoding */
87c06b6b69Smrgstatic
88c06b6b69SmrgXF86VideoEncodingRec DummyEncoding[1] =
89c06b6b69Smrg{
90c06b6b69Smrg {
91c06b6b69Smrg   0,
92c06b6b69Smrg   "XV_IMAGE",
93c06b6b69Smrg   1024, 1024,
94c06b6b69Smrg   {1, 1}
95c06b6b69Smrg }
96c06b6b69Smrg};
97c06b6b69Smrg
98c06b6b69Smrg#define NUM_FORMATS 4
99c06b6b69Smrg
100c06b6b69Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
101c06b6b69Smrg{
102c06b6b69Smrg  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
103c06b6b69Smrg};
104c06b6b69Smrg
105c06b6b69Smrg#define NUM_ATTRIBUTES 1
106c06b6b69Smrg
107c06b6b69Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
108c06b6b69Smrg{
109c06b6b69Smrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}
110c06b6b69Smrg};
111c06b6b69Smrg
112c06b6b69Smrg#define NUM_IMAGES 4
113c06b6b69Smrg
114c06b6b69Smrgstatic XF86ImageRec Images[NUM_IMAGES] =
115c06b6b69Smrg{
116c06b6b69Smrg   {
117c06b6b69Smrg	0x35315652,
118c06b6b69Smrg        XvRGB,
119c06b6b69Smrg	LSBFirst,
120c06b6b69Smrg	{'R','V','1','5',
121c06b6b69Smrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
122c06b6b69Smrg	16,
123c06b6b69Smrg	XvPacked,
124c06b6b69Smrg	1,
125c06b6b69Smrg	15, 0x7C00, 0x03E0, 0x001F,
126c06b6b69Smrg	0, 0, 0,
127c06b6b69Smrg	0, 0, 0,
128c06b6b69Smrg	0, 0, 0,
129c06b6b69Smrg	{'R','V','B',0,
130c06b6b69Smrg	  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},
131c06b6b69Smrg	XvTopToBottom
132c06b6b69Smrg   },
133c06b6b69Smrg   {
134c06b6b69Smrg	0x36315652,
135c06b6b69Smrg        XvRGB,
136c06b6b69Smrg	LSBFirst,
137c06b6b69Smrg	{'R','V','1','6',
138c06b6b69Smrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
139c06b6b69Smrg	16,
140c06b6b69Smrg	XvPacked,
141c06b6b69Smrg	1,
142c06b6b69Smrg	16, 0xF800, 0x07E0, 0x001F,
143c06b6b69Smrg	0, 0, 0,
144c06b6b69Smrg	0, 0, 0,
145c06b6b69Smrg	0, 0, 0,
146c06b6b69Smrg	{'R','V','B',0,
147c06b6b69Smrg	  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},
148c06b6b69Smrg	XvTopToBottom
149c06b6b69Smrg   },
150c06b6b69Smrg   XVIMAGE_YV12,
151c06b6b69Smrg   XVIMAGE_YUY2
152c06b6b69Smrg};
153c06b6b69Smrg
154c06b6b69Smrgtypedef struct {
155c06b6b69Smrg   FBLinearPtr	linear;
156c06b6b69Smrg   RegionRec	clip;
157c06b6b69Smrg   CARD32	colorKey;
158c06b6b69Smrg   CARD32	videoStatus;
159c06b6b69Smrg   Time		offTime;
160c06b6b69Smrg   Time		freeTime;
161c06b6b69Smrg   Bool         doubleBuffer;
162c06b6b69Smrg   Bool         manualDoubleBuffer;
163c06b6b69Smrg   int          currentBuffer;
164c06b6b69Smrg} CHIPSPortPrivRec, *CHIPSPortPrivPtr;
165c06b6b69Smrg
166c06b6b69Smrg
167c06b6b69Smrg#define GET_PORT_PRIVATE(pScrn) \
168c06b6b69Smrg   (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
169c06b6b69Smrg
170c06b6b69Smrgvoid
171c06b6b69SmrgCHIPSResetVideo(ScrnInfoPtr pScrn)
172c06b6b69Smrg{
173c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
174c06b6b69Smrg    CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr;
175c06b6b69Smrg    unsigned char mr3c;
176c06b6b69Smrg    int red, green, blue;
177c06b6b69Smrg
17804109a1cSmacallan#ifdef HAVE_XAA_H
179c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
180c06b6b69Smrg	CHIPSHiQVSync(pScrn);
18104109a1cSmacallan#endif
182c06b6b69Smrg
183c06b6b69Smrg    mr3c = cPtr->readMR(cPtr, 0x3C);
184c06b6b69Smrg    cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6));
185c06b6b69Smrg    switch (pScrn->depth) {
186c06b6b69Smrg    case 8:
187c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3D, 0x00);
188c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3E, 0x00);
189c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF));
190c06b6b69Smrg	cPtr->writeMR(cPtr, 0x40, 0xFF);
191c06b6b69Smrg	cPtr->writeMR(cPtr, 0x41, 0xFF);
192c06b6b69Smrg	cPtr->writeMR(cPtr, 0x42, 0x00);
193c06b6b69Smrg	break;
194c06b6b69Smrg    default:
195c06b6b69Smrg	red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
196c06b6b69Smrg	green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
197c06b6b69Smrg	blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
198c06b6b69Smrg	switch (pScrn->depth) {
199c06b6b69Smrg	case 15:
200c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, (red << 3));
201c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, (green << 3));
202c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (blue << 3));
203c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x07);
204c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x07);
205c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x07);
206c06b6b69Smrg	    break;
207c06b6b69Smrg	case 16:
208c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, (red << 3));
209c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, (green << 2));
210c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (blue << 3));
211c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x07);
212c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x03);
213c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x07);
214c06b6b69Smrg	    break;
215c06b6b69Smrg	case 24:
216c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, red);
217c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, green);
218c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, blue);
219c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x40, 0x00);
220c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x41, 0x00);
221c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x42, 0x00);
222c06b6b69Smrg	    break;
223c06b6b69Smrg	}
224c06b6b69Smrg    }
225c06b6b69Smrg}
226c06b6b69Smrg
227c06b6b69Smrg
228c06b6b69Smrgstatic XF86VideoAdaptorPtr
229c06b6b69SmrgCHIPSSetupImageVideo(ScreenPtr pScreen)
230c06b6b69Smrg{
231a1d73b4bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
232c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
233c06b6b69Smrg    XF86VideoAdaptorPtr adapt;
234c06b6b69Smrg    CHIPSPortPrivPtr pPriv;
235c06b6b69Smrg
2363699b6c4Smrg    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
2373699b6c4Smrg			   sizeof(CHIPSPortPrivRec) +
2383699b6c4Smrg			   sizeof(DevUnion))))
239c06b6b69Smrg	return NULL;
240c06b6b69Smrg
241c06b6b69Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
242c06b6b69Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
243c06b6b69Smrg    adapt->name = "Chips and Technologies Backend Scaler";
244c06b6b69Smrg    adapt->nEncodings = 1;
245c06b6b69Smrg    adapt->pEncodings = DummyEncoding;
246c06b6b69Smrg    adapt->nFormats = NUM_FORMATS;
247c06b6b69Smrg    adapt->pFormats = Formats;
248c06b6b69Smrg    adapt->nPorts = 1;
249c06b6b69Smrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
250c06b6b69Smrg    pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]);
251c06b6b69Smrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
252c06b6b69Smrg    adapt->pAttributes = Attributes;
253c06b6b69Smrg    adapt->nImages = NUM_IMAGES;
254c06b6b69Smrg    adapt->nAttributes = NUM_ATTRIBUTES;
255c06b6b69Smrg    adapt->pImages = Images;
256c06b6b69Smrg    adapt->PutVideo = NULL;
257c06b6b69Smrg    adapt->PutStill = NULL;
258c06b6b69Smrg    adapt->GetVideo = NULL;
259c06b6b69Smrg    adapt->GetStill = NULL;
260c06b6b69Smrg    adapt->StopVideo = CHIPSStopVideo;
261c06b6b69Smrg    adapt->SetPortAttribute = CHIPSSetPortAttribute;
262c06b6b69Smrg    adapt->GetPortAttribute = CHIPSGetPortAttribute;
263c06b6b69Smrg    adapt->QueryBestSize = CHIPSQueryBestSize;
264c06b6b69Smrg    adapt->PutImage = CHIPSPutImage;
265c06b6b69Smrg    adapt->QueryImageAttributes = CHIPSQueryImageAttributes;
266c06b6b69Smrg
267c06b6b69Smrg    pPriv->colorKey = cPtr->videoKey;
268c06b6b69Smrg    pPriv->videoStatus = 0;
269c06b6b69Smrg    pPriv->manualDoubleBuffer = FALSE;
270c06b6b69Smrg    pPriv->currentBuffer	= 0;
271c06b6b69Smrg
272c06b6b69Smrg    /* gotta uninit this someplace */
273c06b6b69Smrg    REGION_NULL(pScreen, &pPriv->clip);
274c06b6b69Smrg
275c06b6b69Smrg    cPtr->adaptor = adapt;
276c06b6b69Smrg
277c06b6b69Smrg    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
278c06b6b69Smrg
279c06b6b69Smrg    CHIPSResetVideo(pScrn);
280c06b6b69Smrg
281c06b6b69Smrg    return adapt;
282c06b6b69Smrg}
283c06b6b69Smrg
284c06b6b69Smrg
285c06b6b69Smrgstatic void
286c06b6b69SmrgCHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow)
287c06b6b69Smrg{
288c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
289c06b6b69Smrg  CHIPSPtr cPtr = CHIPSPTR(pScrn);
290c06b6b69Smrg  unsigned char mr3c, tmp;
291c06b6b69Smrg
292c06b6b69Smrg  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
29304109a1cSmacallan#ifdef HAVE_XAA_H
294c06b6b69Smrg  if (cPtr->Flags & ChipsAccelSupport)
295c06b6b69Smrg      CHIPSHiQVSync(pScrn);
29604109a1cSmacallan#endif
297c06b6b69Smrg  if(shadow) {
298c06b6b69Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
299c06b6b69Smrg	mr3c = cPtr->readMR(cPtr, 0x3C);
300c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
301c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xD0);
302c06b6b69Smrg	cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf));
303c06b6b69Smrg     }
304c06b6b69Smrg     if(pPriv->linear) {
305c06b6b69Smrg	xf86FreeOffscreenLinear(pPriv->linear);
306c06b6b69Smrg	pPriv->linear = NULL;
307c06b6b69Smrg     }
308c06b6b69Smrg     pPriv->videoStatus = 0;
309c06b6b69Smrg  } else {
310c06b6b69Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
311c06b6b69Smrg	pPriv->videoStatus |= OFF_TIMER;
312c06b6b69Smrg	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
313c06b6b69Smrg	cPtr->VideoTimerCallback = CHIPSVideoTimerCallback;
314c06b6b69Smrg     }
315c06b6b69Smrg  }
316c06b6b69Smrg}
317c06b6b69Smrg
318c06b6b69Smrgstatic int
319c06b6b69SmrgCHIPSSetPortAttribute(
320c06b6b69Smrg  ScrnInfoPtr pScrn,
321c06b6b69Smrg  Atom attribute,
322c06b6b69Smrg  INT32 value,
323c06b6b69Smrg  pointer data
324c06b6b69Smrg){
325c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
326c06b6b69Smrg  CHIPSPtr cPtr = CHIPSPTR(pScrn);
327c06b6b69Smrg
32804109a1cSmacallan#ifdef HAVE_XAA_H
329c06b6b69Smrg  if (cPtr->Flags & ChipsAccelSupport)
330c06b6b69Smrg      CHIPSHiQVSync(pScrn);
33104109a1cSmacallan#endif
332c06b6b69Smrg  if(attribute == xvColorKey) {
333c06b6b69Smrg	int red, green, blue;
334c06b6b69Smrg	pPriv->colorKey = value;
335c06b6b69Smrg	switch (pScrn->depth) {
336c06b6b69Smrg	case 8:
337c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3D, 0x00);
338c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3E, 0x00);
339c06b6b69Smrg	    cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF));
340c06b6b69Smrg	    break;
341c06b6b69Smrg	default:
342c06b6b69Smrg	    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
343c06b6b69Smrg	    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
344c06b6b69Smrg	    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
345c06b6b69Smrg	    switch (pScrn->depth) {
346c06b6b69Smrg	    case 15:
347c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, (red << 3));
348c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, (green << 3));
349c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, (blue << 3));
350c06b6b69Smrg		break;
351c06b6b69Smrg	    case 16:
352c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, (red << 3));
353c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, (green << 2));
354c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, (blue << 3));
355c06b6b69Smrg		break;
356c06b6b69Smrg	    case 24:
357c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3D, red);
358c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3E, green);
359c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3F, blue);
360c06b6b69Smrg		break;
361c06b6b69Smrg	    }
362c06b6b69Smrg	}
363c06b6b69Smrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
364c06b6b69Smrg  } else return BadMatch;
365c06b6b69Smrg
366c06b6b69Smrg  return Success;
367c06b6b69Smrg}
368c06b6b69Smrg
369c06b6b69Smrgstatic int
370c06b6b69SmrgCHIPSGetPortAttribute(
371c06b6b69Smrg  ScrnInfoPtr pScrn,
372c06b6b69Smrg  Atom attribute,
373c06b6b69Smrg  INT32 *value,
374c06b6b69Smrg  pointer data
375c06b6b69Smrg){
376c06b6b69Smrg  CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
377c06b6b69Smrg
378c06b6b69Smrg  if(attribute == xvColorKey) {
379c06b6b69Smrg	*value = pPriv->colorKey;
380c06b6b69Smrg  } else return BadMatch;
381c06b6b69Smrg
382c06b6b69Smrg  return Success;
383c06b6b69Smrg}
384c06b6b69Smrg
385c06b6b69Smrgstatic void
386c06b6b69SmrgCHIPSQueryBestSize(
387c06b6b69Smrg  ScrnInfoPtr pScrn,
388c06b6b69Smrg  Bool motion,
389c06b6b69Smrg  short vid_w, short vid_h,
390c06b6b69Smrg  short drw_w, short drw_h,
391c06b6b69Smrg  unsigned int *p_w, unsigned int *p_h,
392c06b6b69Smrg  pointer data
393c06b6b69Smrg){
394c06b6b69Smrg  *p_w = drw_w;
395c06b6b69Smrg  *p_h = drw_h;
396c06b6b69Smrg
397c06b6b69Smrg  if(*p_w > 16384) *p_w = 16384;
398c06b6b69Smrg}
399c06b6b69Smrg
400c06b6b69Smrg
401c06b6b69Smrgstatic void
402c06b6b69SmrgCHIPSCopyData(
403c06b6b69Smrg  unsigned char *src,
404c06b6b69Smrg  unsigned char *dst,
405c06b6b69Smrg  int srcPitch,
406c06b6b69Smrg  int dstPitch,
407c06b6b69Smrg  int h,
408c06b6b69Smrg  int w
409c06b6b69Smrg){
410c06b6b69Smrg    w <<= 1;
411c06b6b69Smrg    while(h--) {
412c06b6b69Smrg	memcpy(dst, src, w);
413c06b6b69Smrg	src += srcPitch;
414c06b6b69Smrg	dst += dstPitch;
415c06b6b69Smrg    }
416c06b6b69Smrg}
417c06b6b69Smrg
418c06b6b69Smrgstatic void
419c06b6b69SmrgCHIPSCopyMungedData(
420c06b6b69Smrg   unsigned char *src1,
421c06b6b69Smrg   unsigned char *src2,
422c06b6b69Smrg   unsigned char *src3,
423c06b6b69Smrg   unsigned char *dst1,
424c06b6b69Smrg   int srcPitch,
425c06b6b69Smrg   int srcPitch2,
426c06b6b69Smrg   int dstPitch,
427c06b6b69Smrg   int h,
428c06b6b69Smrg   int w
429c06b6b69Smrg){
430c06b6b69Smrg   CARD32 *dst = (CARD32*)dst1;
431c06b6b69Smrg   int i, j;
432c06b6b69Smrg
433c06b6b69Smrg   dstPitch >>= 2;
434c06b6b69Smrg   w >>= 1;
435c06b6b69Smrg
436c06b6b69Smrg   for(j = 0; j < h; j++) {
437c06b6b69Smrg	for(i = 0; i < w; i++) {
438c06b6b69Smrg	    dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
439c06b6b69Smrg		     (src3[i] << 8) | (src2[i] << 24);
440c06b6b69Smrg	}
441c06b6b69Smrg	dst += dstPitch;
442c06b6b69Smrg	src1 += srcPitch;
443c06b6b69Smrg	if(j & 1) {
444c06b6b69Smrg	    src2 += srcPitch2;
445c06b6b69Smrg	    src3 += srcPitch2;
446c06b6b69Smrg	}
447c06b6b69Smrg   }
448c06b6b69Smrg}
449c06b6b69Smrg
450c06b6b69Smrgstatic FBLinearPtr
451c06b6b69SmrgCHIPSAllocateMemory(
452c06b6b69Smrg   ScrnInfoPtr pScrn,
453c06b6b69Smrg   FBLinearPtr linear,
454c06b6b69Smrg   int size
455c06b6b69Smrg){
456c06b6b69Smrg   ScreenPtr pScreen;
457c06b6b69Smrg   FBLinearPtr new_linear;
458c06b6b69Smrg
459c06b6b69Smrg   if(linear) {
460c06b6b69Smrg	if(linear->size >= size)
461c06b6b69Smrg	   return linear;
462c06b6b69Smrg
463c06b6b69Smrg        if(xf86ResizeOffscreenLinear(linear, size))
464c06b6b69Smrg	   return linear;
465c06b6b69Smrg
466c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
467c06b6b69Smrg   }
468c06b6b69Smrg
469a1d73b4bSmrg   pScreen = xf86ScrnToScreen(pScrn);
470c06b6b69Smrg
471c06b6b69Smrg   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
472c06b6b69Smrg   						NULL, NULL, NULL);
473c06b6b69Smrg
474c06b6b69Smrg   if(!new_linear) {
475c06b6b69Smrg	int max_size;
476c06b6b69Smrg
477c06b6b69Smrg	xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8,
478c06b6b69Smrg						PRIORITY_EXTREME);
479c06b6b69Smrg
480c06b6b69Smrg	if(max_size < size)
481c06b6b69Smrg	   return NULL;
482c06b6b69Smrg
483c06b6b69Smrg	xf86PurgeUnlockedOffscreenAreas(pScreen);
484c06b6b69Smrg	new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
485c06b6b69Smrg						NULL, NULL, NULL);
486c06b6b69Smrg   }
487c06b6b69Smrg
488c06b6b69Smrg   return new_linear;
489c06b6b69Smrg}
490c06b6b69Smrg
491c06b6b69Smrgstatic int
492c06b6b69SmrgCHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n)
493c06b6b69Smrg{
494c06b6b69Smrg
495c06b6b69Smrg    CARD8 mr20;
496c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
497c06b6b69Smrg    mr20 &= ~0x1B;
498c06b6b69Smrg    if (!n) mr20 |= 0x10;
499c06b6b69Smrg    cPtr->writeMR(cPtr, 0x22, mr20);
500c06b6b69Smrg    return n;
501c06b6b69Smrg}
502c06b6b69Smrg
503c06b6b69Smrgstatic int
504c06b6b69SmrgCHIPSWaitGetNextFrame(CHIPSPtr cPtr)
505c06b6b69Smrg{
506c06b6b69Smrg    volatile CARD8 mr20;
507c06b6b69Smrg    volatile CARD8 mr21;
508c06b6b69Smrg
509c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
510c06b6b69Smrg    while (1) {
511c06b6b69Smrg      mr21 = cPtr->readMR(cPtr, 0x21);
512c06b6b69Smrg      if (!(mr20 & (1 << 5)) || !(mr21 & 1))
513c06b6b69Smrg	break;
514c06b6b69Smrg    }
515c06b6b69Smrg    mr20 &= ~0x4;
516c06b6b69Smrg    mr20 = cPtr->readMR(cPtr, 0x20);
517c06b6b69Smrg    return (mr21 & 2)? 0 : 1;
518c06b6b69Smrg}
519c06b6b69Smrg
520c06b6b69Smrgstatic void
521c06b6b69SmrgCHIPSDisplayVideo(
522c06b6b69Smrg    ScrnInfoPtr pScrn,
523c06b6b69Smrg    int id,
524c06b6b69Smrg    int offset,
525c06b6b69Smrg    short width, short height,
526c06b6b69Smrg    int pitch,
527c06b6b69Smrg    int x1, int y1, int x2, int y2,
528c06b6b69Smrg    BoxPtr dstBox,
529c06b6b69Smrg    short src_w, short src_h,
530c06b6b69Smrg    short drw_w, short drw_h,
531c06b6b69Smrg    Bool triggerBufSwitch
532c06b6b69Smrg){
533c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
534c06b6b69Smrg    CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
535c06b6b69Smrg    DisplayModePtr mode = pScrn->currentMode;
536c06b6b69Smrg    unsigned char tmp, m1f, m1e;
537c06b6b69Smrg    int buffer = pPriv->currentBuffer;
538c06b6b69Smrg    Bool dblscan = (pScrn->currentMode->Flags & V_DBLSCAN) == V_DBLSCAN;
539c06b6b69Smrg    int val;
54004109a1cSmacallan
54104109a1cSmacallan#ifdef HAVE_XAA_H
542c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
543c06b6b69Smrg	CHIPSHiQVSync(pScrn);
54404109a1cSmacallan#endif
545c06b6b69Smrg    tmp = cPtr->readXR(cPtr, 0xD0);
546c06b6b69Smrg    cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10));
547c06b6b69Smrg
548c06b6b69Smrg    m1e = cPtr->readMR(cPtr, 0x1E);
549c06b6b69Smrg    m1e &= 0xE0;		/* Set Zoom and Direction */
550c06b6b69Smrg    if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE))
551c06b6b69Smrg	m1e |= 0x10;
552c06b6b69Smrg
553c06b6b69Smrg    m1f = cPtr->readMR(cPtr, 0x1F);
554c06b6b69Smrg    m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */
555c06b6b69Smrg    switch(id) {
556c06b6b69Smrg    case 0x35315652:		/* RGB15 */
557c06b6b69Smrg	m1f |= 0x09;
558c06b6b69Smrg	break;
559c06b6b69Smrg    case 0x36315652:		/* RGB16 */
560c06b6b69Smrg	m1f |= 0x08;
561c06b6b69Smrg	break;
562c06b6b69Smrg    case FOURCC_YV12:		/* YV12 */
563c06b6b69Smrg      /* m1f |= 0x03 */
564c06b6b69Smrg	m1f |= 0x00;
565c06b6b69Smrg	break;
566c06b6b69Smrg    case FOURCC_YUY2:		/* YUY2 */
567c06b6b69Smrg    default:
568c06b6b69Smrg	m1f |= 0x00;		/* Do nothing here */
569c06b6b69Smrg	break;
570c06b6b69Smrg    }
571c06b6b69Smrg
572c06b6b69Smrg    offset += (x1 >> 15) & ~0x01;
573c06b6b69Smrg    /* Setup Pointer 1 */
574c06b6b69Smrg    if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) {
575c06b6b69Smrg        cPtr->writeMR(cPtr, 0x22, (offset & 0xF8));
576c06b6b69Smrg	cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF));
577c06b6b69Smrg	cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF));
578c06b6b69Smrg    }
579c06b6b69Smrg
580c06b6b69Smrg    /* Setup Pointer 2 */
581c06b6b69Smrg    if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) {
582c06b6b69Smrg        cPtr->writeMR(cPtr, 0x25, (offset & 0xF8));
583c06b6b69Smrg	cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF));
584c06b6b69Smrg	cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF));
585c06b6b69Smrg    }
586c06b6b69Smrg
587c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x04);
588c06b6b69Smrg    if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch)
589c06b6b69Smrg      tmp |= 0x18;
590c06b6b69Smrg    cPtr->writeMR(cPtr, 0x04, tmp);
591c06b6b69Smrg
592c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x20);
593c06b6b69Smrg    tmp &= 0xC3;
594c06b6b69Smrg
595c06b6b69Smrg    if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch)
596c06b6b69Smrg	tmp |= ((1 << 2  | 1 << 5) | ((buffer) ? (1 << 4) : 0));
597c06b6b69Smrg    cPtr->writeMR(cPtr, 0x20, tmp);
598c06b6b69Smrg
599c06b6b69Smrg    cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */
600c06b6b69Smrg    cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1));
601c06b6b69Smrg
602c06b6b69Smrg    /* Left Edge of Overlay */
603c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF));
604c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2B);
605c06b6b69Smrg    tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07);
606c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2B, tmp);
607c06b6b69Smrg    /* Right Edge of Overlay */
608c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1)
609c06b6b69Smrg				& 0xFF));
610c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2D);
611c06b6b69Smrg    tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07);
612c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2D, tmp);
613c06b6b69Smrg    /* Top Edge of Overlay */
614c06b6b69Smrg    val = cPtr->OverlaySkewY + (dstBox->y1 << (dblscan ? 1 : 0));
615c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2E, ((val) & 0xFF));
616c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x2F);
617c06b6b69Smrg    tmp = (tmp & 0xF8) + (((val) >> 8) & 0x07);
618c06b6b69Smrg    cPtr->writeMR(cPtr, 0x2F, tmp);
619c06b6b69Smrg    /* Bottom Edge of Overlay*/
620c06b6b69Smrg    val = cPtr->OverlaySkewY + (dstBox->y2 << (dblscan ? 1 : 0));
621c06b6b69Smrg    cPtr->writeMR(cPtr, 0x30, ((val - 1) & 0xFF));
622c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x31);
623c06b6b69Smrg    tmp = (tmp & 0xF8) + (((val - 1) >> 8) & 0x07);
624c06b6b69Smrg    cPtr->writeMR(cPtr, 0x31, tmp);
625c06b6b69Smrg
626c06b6b69Smrg    /* Horizontal Zoom */
627c06b6b69Smrg    if (drw_w > src_w) {
628c06b6b69Smrg        m1f = m1f | 0x20; /* set H-interpolation */
629c06b6b69Smrg	m1e = m1e | 0x04;
630c06b6b69Smrg	tmp = cPtr->VideoZoomMax * src_w / drw_w;
631c06b6b69Smrg	cPtr->writeMR(cPtr, 0x32, tmp);
632c06b6b69Smrg    }
633c06b6b69Smrg
634c06b6b69Smrg    /* Vertical Zoom */
635c06b6b69Smrg    if (drw_h > src_h || dblscan) {
636c06b6b69Smrg        m1f = m1f | 0x80; /* set V-interpolation */
637c06b6b69Smrg	m1e = m1e | 0x08;
638c06b6b69Smrg	if (dblscan)
639c06b6b69Smrg	    tmp = cPtr->VideoZoomMax >> 1;
640c06b6b69Smrg	if (drw_h > src_h)
6419f4658d1Smrg           tmp = 256 * src_h / drw_h;
6429f4658d1Smrg       cPtr->writeMR(cPtr, 0x33, tmp & 0xFC);
643c06b6b69Smrg    }
644c06b6b69Smrg    cPtr->writeMR(cPtr, 0x1F, m1f);
645c06b6b69Smrg    cPtr->writeMR(cPtr, 0x1E, m1e);
646c06b6b69Smrg
647c06b6b69Smrg    tmp = cPtr->readMR(cPtr, 0x3C);
648c06b6b69Smrg    cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7));
64904109a1cSmacallan#ifdef HAVE_XAA_H
650c06b6b69Smrg    if (cPtr->Flags & ChipsAccelSupport)
651c06b6b69Smrg	CHIPSHiQVSync(pScrn);
65204109a1cSmacallan#endif
653c06b6b69Smrg}
654c06b6b69Smrg
655c06b6b69Smrgstatic int
656c06b6b69SmrgCHIPSPutImage(
657c06b6b69Smrg  ScrnInfoPtr pScrn,
658c06b6b69Smrg  short src_x, short src_y,
659c06b6b69Smrg  short drw_x, short drw_y,
660c06b6b69Smrg  short src_w, short src_h,
661c06b6b69Smrg  short drw_w, short drw_h,
662c06b6b69Smrg  int id, unsigned char* buf,
663c06b6b69Smrg  short width, short height,
664c06b6b69Smrg  Bool sync,
665c06b6b69Smrg  RegionPtr clipBoxes, pointer data,
666c06b6b69Smrg  DrawablePtr pDraw
667c06b6b69Smrg){
668c06b6b69Smrg   CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data;
669c06b6b69Smrg   CHIPSPtr cPtr = CHIPSPTR(pScrn);
670c06b6b69Smrg   INT32 x1, x2, y1, y2;
671c06b6b69Smrg   unsigned char *dst_start;
672c06b6b69Smrg   int new_size, offset, offset2 = 0, offset3 = 0;
673c06b6b69Smrg   int srcPitch, srcPitch2 = 0, dstPitch;
674c06b6b69Smrg   int top, left, npixels, nlines, bpp;
675c06b6b69Smrg   BoxRec dstBox;
676c06b6b69Smrg   CARD32 tmp;
677c06b6b69Smrg
678c06b6b69Smrg   if(drw_w > 16384) drw_w = 16384;
679c06b6b69Smrg
680c06b6b69Smrg   /* Clip */
681c06b6b69Smrg   x1 = src_x;
682c06b6b69Smrg   x2 = src_x + src_w;
683c06b6b69Smrg   y1 = src_y;
684c06b6b69Smrg   y2 = src_y + src_h;
685c06b6b69Smrg
686c06b6b69Smrg   dstBox.x1 = drw_x;
687c06b6b69Smrg   dstBox.x2 = drw_x + drw_w;
688c06b6b69Smrg   dstBox.y1 = drw_y;
689c06b6b69Smrg   dstBox.y2 = drw_y + drw_h;
690c06b6b69Smrg
691c06b6b69Smrg   if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
692c06b6b69Smrg			      clipBoxes, width, height))
693c06b6b69Smrg	return Success;
694c06b6b69Smrg
695c06b6b69Smrg   dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask;
696c06b6b69Smrg   dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask;
697c06b6b69Smrg   dstBox.y1 -= pScrn->frameY0;
698c06b6b69Smrg   dstBox.y2 -= pScrn->frameY0;
699c06b6b69Smrg
700c06b6b69Smrg   bpp = pScrn->bitsPerPixel >> 3;
701c06b6b69Smrg
702c06b6b69Smrg   dstPitch = ((width << 1) + 15) & ~15;
703c06b6b69Smrg   new_size = ((dstPitch * height) + bpp - 1) / bpp;
704c06b6b69Smrg
705c06b6b69Smrg   pPriv->doubleBuffer = (pScrn->currentMode->Flags & V_DBLSCAN) != V_DBLSCAN;
706c06b6b69Smrg
707c06b6b69Smrg   if (pPriv->doubleBuffer)
708c06b6b69Smrg       new_size <<= 1;
709c06b6b69Smrg
710c06b6b69Smrg   switch(id) {
711c06b6b69Smrg   case FOURCC_YV12:		/* YV12 */
712c06b6b69Smrg	srcPitch = (width + 3) & ~3;
713c06b6b69Smrg	offset2 = srcPitch * height;
714c06b6b69Smrg	srcPitch2 = ((width >> 1) + 3) & ~3;
715c06b6b69Smrg	offset3 = (srcPitch2 * (height >> 1)) + offset2;
716c06b6b69Smrg	break;
717c06b6b69Smrg   default:			/* RGB15, RGB16, YUY2 */
718c06b6b69Smrg	srcPitch = (width << 1);
719c06b6b69Smrg	break;
720c06b6b69Smrg   }
721c06b6b69Smrg
722c06b6b69Smrg   if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) {
723c06b6b69Smrg       if (pPriv->doubleBuffer
724c06b6b69Smrg	   && (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear,
725c06b6b69Smrg					      new_size >> 1))) {
726c06b6b69Smrg         new_size >>= 1;
727c06b6b69Smrg	 pPriv->doubleBuffer = FALSE;
728c06b6b69Smrg   } else
729c06b6b69Smrg	return BadAlloc;
730c06b6b69Smrg   }
731c06b6b69Smrg
732c06b6b69Smrg   /* copy data */
733c06b6b69Smrg   top = y1 >> 16;
734c06b6b69Smrg   left = (x1 >> 16) & ~1;
735c06b6b69Smrg   npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
736c06b6b69Smrg   left <<= 1;
737c06b6b69Smrg
738c06b6b69Smrg   offset = pPriv->linear->offset * bpp;
739c06b6b69Smrg   if (!pPriv->manualDoubleBuffer)
740c06b6b69Smrg     pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr);
741c06b6b69Smrg   if(pPriv->doubleBuffer && pPriv->currentBuffer)
742c06b6b69Smrg	offset += (new_size * bpp) >> 1;
743c06b6b69Smrg
744c06b6b69Smrg   dst_start = cPtr->FbBase + offset + left + (top * dstPitch);
745c06b6b69Smrg
746c06b6b69Smrg   switch(id) {
747c06b6b69Smrg   case FOURCC_YV12:		/* YV12 */
748c06b6b69Smrg        top &= ~1;
749c06b6b69Smrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
750c06b6b69Smrg	offset2 += tmp;
751c06b6b69Smrg	offset3 += tmp;
752c06b6b69Smrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
753c06b6b69Smrg	CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1),
754c06b6b69Smrg			  buf + offset2, buf + offset3, dst_start,
755c06b6b69Smrg			  srcPitch, srcPitch2, dstPitch, nlines, npixels);
756c06b6b69Smrg	break;
757c06b6b69Smrg   default:			/* RGB15, RGB16, YUY2 */
758c06b6b69Smrg	buf += (top * srcPitch) + left;
759c06b6b69Smrg	nlines = ((y2 + 0xffff) >> 16) - top;
760c06b6b69Smrg	CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
761c06b6b69Smrg	break;
762c06b6b69Smrg   }
763c06b6b69Smrg
764c06b6b69Smrg   /* update cliplist */
765c06b6b69Smrg   if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
766c06b6b69Smrg	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
767c06b6b69Smrg        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
768c06b6b69Smrg   }
769c06b6b69Smrg
770c06b6b69Smrg   offset += top * dstPitch;
771c06b6b69Smrg   CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch,
772c06b6b69Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE);
773c06b6b69Smrg
774c06b6b69Smrg   pPriv->videoStatus = CLIENT_VIDEO_ON;
775c06b6b69Smrg
776c06b6b69Smrg   if (pPriv->manualDoubleBuffer)
777c06b6b69Smrg     pPriv->currentBuffer ^= 1;
778c06b6b69Smrg
779c06b6b69Smrg   return Success;
780c06b6b69Smrg}
781c06b6b69Smrg
782c06b6b69Smrgstatic int
783c06b6b69SmrgCHIPSQueryImageAttributes(
784c06b6b69Smrg  ScrnInfoPtr pScrn,
785c06b6b69Smrg  int id,
786c06b6b69Smrg  unsigned short *w, unsigned short *h,
787c06b6b69Smrg  int *pitches, int *offsets
788c06b6b69Smrg){
789c06b6b69Smrg    int size, tmp;
790c06b6b69Smrg
791c06b6b69Smrg    if(*w > 1024) *w = 1024;
792c06b6b69Smrg    if(*h > 1024) *h = 1024;
793c06b6b69Smrg
794c06b6b69Smrg    *w = (*w + 1) & ~1;
795c06b6b69Smrg    if(offsets) offsets[0] = 0;
796c06b6b69Smrg
797c06b6b69Smrg    switch(id) {
798c06b6b69Smrg    case FOURCC_YV12:		/* YV12 */
799c06b6b69Smrg	*h = (*h + 1) & ~1;
800c06b6b69Smrg	size = (*w + 3) & ~3;
801c06b6b69Smrg	if(pitches) pitches[0] = size;
802c06b6b69Smrg	size *= *h;
803c06b6b69Smrg	if(offsets) offsets[1] = size;
804c06b6b69Smrg	tmp = ((*w >> 1) + 3) & ~3;
805c06b6b69Smrg	if(pitches) pitches[1] = pitches[2] = tmp;
806c06b6b69Smrg	tmp *= (*h >> 1);
807c06b6b69Smrg	size += tmp;
808c06b6b69Smrg	if(offsets) offsets[2] = size;
809c06b6b69Smrg	size += tmp;
810c06b6b69Smrg	break;
811c06b6b69Smrg    default:			/* RGB15, RGB16, YUY2 */
812c06b6b69Smrg	size = *w << 1;
813c06b6b69Smrg	if(pitches) pitches[0] = size;
814c06b6b69Smrg	size *= *h;
815c06b6b69Smrg	break;
816c06b6b69Smrg    }
817c06b6b69Smrg
818c06b6b69Smrg    return size;
819c06b6b69Smrg}
820c06b6b69Smrg
821c06b6b69Smrg
822c06b6b69Smrgstatic void
823c06b6b69SmrgCHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
824c06b6b69Smrg{
825c06b6b69Smrg    CHIPSPtr    cPtr = CHIPSPTR(pScrn);
826c06b6b69Smrg    CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
827c06b6b69Smrg    unsigned char mr3c;
828c06b6b69Smrg
829c06b6b69Smrg    if(pPriv->videoStatus & TIMER_MASK) {
830c06b6b69Smrg	if(pPriv->videoStatus & OFF_TIMER) {
831c06b6b69Smrg	    if(pPriv->offTime < time) {
83204109a1cSmacallan#ifdef HAVE_XAA_H
833c06b6b69Smrg		if (cPtr->Flags & ChipsAccelSupport)
834c06b6b69Smrg		    CHIPSHiQVSync(pScrn);
83504109a1cSmacallan#endif
836c06b6b69Smrg		mr3c = cPtr->readMR(cPtr, 0x3C);
837c06b6b69Smrg		cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
838c06b6b69Smrg		pPriv->videoStatus = FREE_TIMER;
839c06b6b69Smrg		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
840c06b6b69Smrg	    }
841c06b6b69Smrg	} else {  /* FREE_TIMER */
842c06b6b69Smrg	    if(pPriv->freeTime < time) {
843c06b6b69Smrg		if(pPriv->linear) {
844c06b6b69Smrg		   xf86FreeOffscreenLinear(pPriv->linear);
845c06b6b69Smrg		   pPriv->linear = NULL;
846c06b6b69Smrg		}
847c06b6b69Smrg		pPriv->videoStatus = 0;
848c06b6b69Smrg	        cPtr->VideoTimerCallback = NULL;
849c06b6b69Smrg	    }
850c06b6b69Smrg        }
851c06b6b69Smrg    } else  /* shouldn't get here */
852c06b6b69Smrg	cPtr->VideoTimerCallback = NULL;
853c06b6b69Smrg}
854c06b6b69Smrg
855c06b6b69Smrg
856c06b6b69Smrg/****************** Offscreen stuff ***************/
857c06b6b69Smrg
858c06b6b69Smrgtypedef struct {
859c06b6b69Smrg  FBLinearPtr linear;
860c06b6b69Smrg  Bool isOn;
861c06b6b69Smrg} OffscreenPrivRec, * OffscreenPrivPtr;
862c06b6b69Smrg
863c06b6b69Smrgstatic int
864c06b6b69SmrgCHIPSAllocateSurface(
865c06b6b69Smrg    ScrnInfoPtr pScrn,
866c06b6b69Smrg    int id,
867c06b6b69Smrg    unsigned short w,
868c06b6b69Smrg    unsigned short h,
869c06b6b69Smrg    XF86SurfacePtr surface
870c06b6b69Smrg){
871c06b6b69Smrg    FBLinearPtr linear;
872c06b6b69Smrg    int pitch, size, bpp;
873c06b6b69Smrg    OffscreenPrivPtr pPriv;
874c06b6b69Smrg
875c06b6b69Smrg    if((w > 1024) || (h > 1024))
876c06b6b69Smrg	return BadAlloc;
877c06b6b69Smrg
878c06b6b69Smrg    w = (w + 1) & ~1;
879c06b6b69Smrg    pitch = ((w << 1) + 15) & ~15;
880c06b6b69Smrg    bpp = pScrn->bitsPerPixel >> 3;
881c06b6b69Smrg    size = ((pitch * h) + bpp - 1) / bpp;
882c06b6b69Smrg
883c06b6b69Smrg    if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size)))
884c06b6b69Smrg	return BadAlloc;
885c06b6b69Smrg
886c06b6b69Smrg    surface->width = w;
887c06b6b69Smrg    surface->height = h;
888c06b6b69Smrg
8893699b6c4Smrg    if(!(surface->pitches = malloc(sizeof(int)))) {
890c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
891c06b6b69Smrg	return BadAlloc;
892c06b6b69Smrg    }
8933699b6c4Smrg    if(!(surface->offsets = malloc(sizeof(int)))) {
8943699b6c4Smrg	free(surface->pitches);
895c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
896c06b6b69Smrg	return BadAlloc;
897c06b6b69Smrg    }
8983699b6c4Smrg    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
8993699b6c4Smrg	free(surface->pitches);
9003699b6c4Smrg	free(surface->offsets);
901c06b6b69Smrg	xf86FreeOffscreenLinear(linear);
902c06b6b69Smrg	return BadAlloc;
903c06b6b69Smrg    }
904c06b6b69Smrg
905c06b6b69Smrg    pPriv->linear = linear;
906c06b6b69Smrg    pPriv->isOn = FALSE;
907c06b6b69Smrg
908c06b6b69Smrg    surface->pScrn = pScrn;
909c06b6b69Smrg    surface->id = id;
910c06b6b69Smrg    surface->pitches[0] = pitch;
911c06b6b69Smrg    surface->offsets[0] = linear->offset * bpp;
912c06b6b69Smrg    surface->devPrivate.ptr = (pointer)pPriv;
913c06b6b69Smrg
914c06b6b69Smrg    return Success;
915c06b6b69Smrg}
916c06b6b69Smrg
917c06b6b69Smrgstatic int
918c06b6b69SmrgCHIPSStopSurface(
919c06b6b69Smrg    XF86SurfacePtr surface
920c06b6b69Smrg){
921c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
922c06b6b69Smrg
923c06b6b69Smrg    if(pPriv->isOn) {
924c06b6b69Smrg	CHIPSPtr cPtr = CHIPSPTR(surface->pScrn);
925c06b6b69Smrg	unsigned char mr3c, tmp;
926c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xD0);
927c06b6b69Smrg	cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf));
928c06b6b69Smrg	mr3c = cPtr->readMR(cPtr, 0x3C);
929c06b6b69Smrg	cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE));
930c06b6b69Smrg	pPriv->isOn = FALSE;
931c06b6b69Smrg    }
932c06b6b69Smrg
933c06b6b69Smrg    return Success;
934c06b6b69Smrg}
935c06b6b69Smrg
936c06b6b69Smrg
937c06b6b69Smrgstatic int
938c06b6b69SmrgCHIPSFreeSurface(
939c06b6b69Smrg    XF86SurfacePtr surface
940c06b6b69Smrg){
941c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
942c06b6b69Smrg
943c06b6b69Smrg    if(pPriv->isOn)
944c06b6b69Smrg	CHIPSStopSurface(surface);
945c06b6b69Smrg    xf86FreeOffscreenLinear(pPriv->linear);
9463699b6c4Smrg    free(surface->pitches);
9473699b6c4Smrg    free(surface->offsets);
9483699b6c4Smrg    free(surface->devPrivate.ptr);
949c06b6b69Smrg
950c06b6b69Smrg    return Success;
951c06b6b69Smrg}
952c06b6b69Smrg
953c06b6b69Smrgstatic int
954c06b6b69SmrgCHIPSGetSurfaceAttribute(
955c06b6b69Smrg    ScrnInfoPtr pScrn,
956c06b6b69Smrg    Atom attribute,
957c06b6b69Smrg    INT32 *value
958c06b6b69Smrg){
959c06b6b69Smrg    return CHIPSGetPortAttribute(pScrn, attribute, value,
960c06b6b69Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
961c06b6b69Smrg}
962c06b6b69Smrg
963c06b6b69Smrgstatic int
964c06b6b69SmrgCHIPSSetSurfaceAttribute(
965c06b6b69Smrg    ScrnInfoPtr pScrn,
966c06b6b69Smrg    Atom attribute,
967c06b6b69Smrg    INT32 value
968c06b6b69Smrg){
969c06b6b69Smrg    return CHIPSSetPortAttribute(pScrn, attribute, value,
970c06b6b69Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
971c06b6b69Smrg}
972c06b6b69Smrg
973c06b6b69Smrg
974c06b6b69Smrgstatic int
975c06b6b69SmrgCHIPSDisplaySurface(
976c06b6b69Smrg    XF86SurfacePtr surface,
977c06b6b69Smrg    short src_x, short src_y,
978c06b6b69Smrg    short drw_x, short drw_y,
979c06b6b69Smrg    short src_w, short src_h,
980c06b6b69Smrg    short drw_w, short drw_h,
981c06b6b69Smrg    RegionPtr clipBoxes
982c06b6b69Smrg){
983c06b6b69Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
984c06b6b69Smrg    ScrnInfoPtr pScrn = surface->pScrn;
985c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
986c06b6b69Smrg    CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn);
987c06b6b69Smrg    INT32 x1, y1, x2, y2;
988c06b6b69Smrg    BoxRec dstBox;
989c06b6b69Smrg
990c06b6b69Smrg    x1 = src_x;
991c06b6b69Smrg    x2 = src_x + src_w;
992c06b6b69Smrg    y1 = src_y;
993c06b6b69Smrg    y2 = src_y + src_h;
994c06b6b69Smrg
995c06b6b69Smrg    dstBox.x1 = drw_x;
996c06b6b69Smrg    dstBox.x2 = drw_x + drw_w;
997c06b6b69Smrg    dstBox.y1 = drw_y;
998c06b6b69Smrg    dstBox.y2 = drw_y + drw_h;
999c06b6b69Smrg
1000c06b6b69Smrg    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
1001c06b6b69Smrg			      surface->width, surface->height))
1002c06b6b69Smrg	return Success;
1003c06b6b69Smrg
1004c06b6b69Smrg    dstBox.x1 -= pScrn->frameX0;
1005c06b6b69Smrg    dstBox.x2 -= pScrn->frameX0;
1006c06b6b69Smrg    dstBox.y1 -= pScrn->frameY0;
1007c06b6b69Smrg    dstBox.y2 -= pScrn->frameY0;
1008c06b6b69Smrg
1009c06b6b69Smrg    if (portPriv->doubleBuffer)
1010c06b6b69Smrg      portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0);
1011c06b6b69Smrg    else
1012c06b6b69Smrg      portPriv->currentBuffer = 0;
1013c06b6b69Smrg
1014c06b6b69Smrg    CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0],
1015c06b6b69Smrg	     surface->width, surface->height, surface->pitches[0],
1016c06b6b69Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE);
1017c06b6b69Smrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1018c06b6b69Smrg
1019c06b6b69Smrg    pPriv->isOn = TRUE;
1020c06b6b69Smrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
1021c06b6b69Smrg	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1022c06b6b69Smrg	UpdateCurrentTime();
1023c06b6b69Smrg	portPriv->videoStatus = FREE_TIMER;
1024c06b6b69Smrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1025c06b6b69Smrg	cPtr->VideoTimerCallback = CHIPSVideoTimerCallback;
1026c06b6b69Smrg    }
1027c06b6b69Smrg
1028c06b6b69Smrg    return Success;
1029c06b6b69Smrg}
1030c06b6b69Smrg
1031c06b6b69Smrg
1032c06b6b69Smrgstatic void
1033c06b6b69SmrgCHIPSInitOffscreenImages(ScreenPtr pScreen)
1034c06b6b69Smrg{
1035c06b6b69Smrg    XF86OffscreenImagePtr offscreenImages;
1036c06b6b69Smrg
1037c06b6b69Smrg    /* need to free this someplace */
10383699b6c4Smrg    if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
1039c06b6b69Smrg	return;
1040c06b6b69Smrg
1041c06b6b69Smrg    offscreenImages[0].image = &Images[0];
1042c06b6b69Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1043c06b6b69Smrg			       VIDEO_CLIP_TO_VIEWPORT;
1044c06b6b69Smrg    offscreenImages[0].alloc_surface = CHIPSAllocateSurface;
1045c06b6b69Smrg    offscreenImages[0].free_surface = CHIPSFreeSurface;
1046c06b6b69Smrg    offscreenImages[0].display = CHIPSDisplaySurface;
1047c06b6b69Smrg    offscreenImages[0].stop = CHIPSStopSurface;
1048c06b6b69Smrg    offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute;
1049c06b6b69Smrg    offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute;
1050c06b6b69Smrg    offscreenImages[0].max_width = 1024;
1051c06b6b69Smrg    offscreenImages[0].max_height = 1024;
1052c06b6b69Smrg    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1053c06b6b69Smrg    offscreenImages[0].attributes = Attributes;
1054c06b6b69Smrg
1055c06b6b69Smrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1056c06b6b69Smrg}
1057