1 /*
2  *  Permedia 2 Xv Driver
3  *
4  *  Copyright (C) 1998-2000 Michael H. Schimek <m.schimek@netway.at>
5  *
6  *  Permission is hereby granted, free of charge, to any person obtaining a copy
7  *  of this software and associated documentation files (the "Software"), to deal
8  *  in the Software without restriction, including without limitation the rights
9  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  *  copies of the Software, and to permit persons to whom the Software is
11  *  furnished to do so, subject to the following conditions:
12  *
13  *  The above copyright notice and this permission notice shall be included in
14  *  all copies or substantial portions of the Software.
15  *
16  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "xf86.h"
29 #include "xf86_OSproc.h"
30 #include "xf86Pci.h"
31 #include "xf86fbman.h"
32 #include "xf86i2c.h"
33 #include "xf86xv.h"
34 #include <X11/extensions/Xv.h>
35 
36 #include "glint_regs.h"
37 #include "glint.h"
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <sys/ioctl.h>
42 #include <unistd.h>
43 
44 #undef MIN
45 #undef ABS
46 #undef CLAMP
47 #undef ENTRIES
48 
49 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
50 #define ABS(n) (((n) < 0) ? -(n) : (n))
51 #define CLAMP(v, min, max) (((v) < (min)) ? (min) : MIN(v, max))
52 #define ENTRIES(array) (sizeof(array) / sizeof((array)[0]))
53 
54 #define ADAPTORS 3
55 #define PORTS 6
56 
57 #define PCI_SUBSYSTEM_ID_WINNER_2000_P2C	0x0a311048
58 #define PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2C	0x0a321048
59 #define PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2A	0x0a351048
60 #define PCI_SUBSYSTEM_ID_WINNER_2000_P2A	0x0a441048
61 
62 /*
63  *  Proprietary kernel backbone interface
64  */
65 
66 #define XVIPC_MAGIC		0x6A5D70E6
67 #define XVIPC_VERSION		1
68 #define VIDIOC_PM2_XVIPC	0x00007F7F
69 
70 typedef enum {
71     OP_ATTR = 0,
72     OP_RESET = 8,	/* unused */
73     OP_START,
74     OP_STOP,
75     OP_PLUG,
76     OP_VIDEOSTD,
77     OP_WINDOW,		/* unused */
78     OP_CONNECT,
79     OP_EVENT,
80     OP_ALLOC,
81     OP_FREE,
82     OP_UPDATE,
83     OP_NOP,		/* ignored */
84     OP_ENTER,
85     OP_LEAVE,
86     OP_DISCONNECT
87 } xvipc_op;
88 
89 typedef struct _pm2_xvipc {
90     int			magic;
91     void 		*pm2p, *pAPriv;
92     int			port, op, time, block;
93     int			a, b, c, d, e, f;
94 } pm2_xvipc;
95 
96 static pm2_xvipc xvipc;
97 static int xvipc_fd = -1;
98 
99 
100 #define MAX_BUFFERS 2
101 
102 typedef struct {
103     CARD32			xy, wh;				/* 16.0 16.0 */
104     INT32			s, t;				/* 12.20 fp */
105     short			y1, y2;
106 } CookieRec, *CookiePtr;
107 
108 typedef struct _PortPrivRec {
109     struct _AdaptorPrivRec *    pAdaptor;
110     I2CDevRec                   I2CDev;
111 
112     INT32			Attribute[8];			/* Brig, Con, Sat, Hue, Int, Filt, BkgCol, Alpha */
113 
114     int				BuffersRequested;
115     int				BuffersAllocated;
116     FBAreaPtr			pFBArea[MAX_BUFFERS];
117     CARD32			BufferBase[MAX_BUFFERS];	/* FB byte offset */
118     CARD32			BufferStride;			/* bytes */
119     CARD32			BufferPProd;			/* PProd(BufferStride in buffer pixels) */
120 
121     INT32			vx, vy, vw, vh;			/* 12.10 fp */
122     int				dx, dy, dw, dh;
123     int				fw, fh;
124 
125     CookiePtr			pCookies;
126     int				nCookies;
127     INT32			dS, dT;				/* 12.20 fp */
128 
129     int				Id, Bpp;			/* Scaler */
130 
131     int                         Plug;
132     int				BkgCol;				/* RGB 5:6:5; 5:6:5 */
133     Bool			StreamOn;			/* buffer <-> hardware */
134     int				VideoOn;			/* buffer <-> screen */
135     int				VideoStdReq;
136 
137     int				StopDelay;
138 
139     int				FramesPerSec, FrameAcc;
140 
141 } PortPrivRec, *PortPrivPtr;
142 
143 enum { VIDEO_OFF, VIDEO_ONE_SHOT, VIDEO_ON };
144 
145 typedef struct _LFBAreaRec {
146     struct _LFBAreaRec *	Next;
147     int				Linear;
148     FBAreaPtr			pFBArea;
149 } LFBAreaRec, *LFBAreaPtr;
150 
151 typedef struct _AdaptorPrivRec {
152     struct _AdaptorPrivRec *	Next;
153     ScrnInfoPtr			pScrn;
154 
155     void *			pm2p;
156     LFBAreaPtr			LFBList;
157 
158     CARD32			dFifoControl;
159     CARD32			dDitherMode;
160     CARD32			dAlphaBlendMode;
161     CARD32			dTextureDataFormat;
162 
163     OsTimerPtr			Timer;
164     int				TimerUsers;
165     int				Delay, Instant;
166 
167     int				FramesPerSec;
168     int				FrameLines;
169     int				IntLine;			/* Frame, not field */
170     int				LinePer;			/* nsec */
171 
172     Bool			VideoIO;
173     int                         VideoStd;
174 
175     PortPrivRec                 Port[PORTS];
176 
177 } AdaptorPrivRec, *AdaptorPrivPtr;
178 
179 static AdaptorPrivPtr AdaptorPrivList = NULL;
180 
181 #define FreeCookies(pPPriv)		\
182 do {					\
183 	free((pPPriv)->pCookies);	\
184 	(pPPriv)->pCookies = NULL;	\
185 } while (0)
186 
187 #define PORTNUM(p) ((int)((p) - &pAPriv->Port[0]))
188 #define BPPSHIFT(g) (2 - (g)->BppShift)	/* Bytes per pixel = 1 << BPPSHIFT(pGlint) */
189 
190 #define DEBUG(x)
191 
192 static const Bool ColorBars = FALSE;
193 
194 
195 /*
196  *  XF86Config VideoAdaptor options
197  */
198 
199 typedef enum {
200     OPTION_DEVICE,
201     OPTION_IN_FPS,
202     OPTION_IN_BUFFERS,
203     OPTION_IN_ENCODING,
204     OPTION_OUT_FPS,
205     OPTION_OUT_BUFFERS,
206     OPTION_OUT_ENCODING,
207 } OptToken;
208 
209 static const OptionInfoRec pm2Options[] = {
210     { OPTION_DEVICE,		"Device",	OPTV_STRING,	{0}, FALSE },
211     { OPTION_IN_BUFFERS,		"InputBuffers",	OPTV_INTEGER,	{0}, FALSE },
212     { OPTION_IN_FPS,		"InputFramesPerSec", OPTV_INTEGER,	{0}, FALSE },
213     { OPTION_IN_ENCODING,		"InputEncoding",	OPTV_STRING,	{0}, FALSE },
214     { OPTION_OUT_BUFFERS,		"OutputBuffers",	OPTV_INTEGER,	{0}, FALSE },
215     { OPTION_OUT_FPS,		"OutputFramesPerSec", OPTV_INTEGER,	{0}, FALSE },
216     { OPTION_OUT_ENCODING,		"OutputEncoding",	OPTV_STRING,	{0}, FALSE },
217     { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
218 };
219 
220 
221 /*
222  *  Attributes
223  */
224 
225 #define XV_ENCODING	"XV_ENCODING"
226 #define XV_BRIGHTNESS	"XV_BRIGHTNESS"
227 #define XV_CONTRAST 	"XV_CONTRAST"
228 #define XV_SATURATION	"XV_SATURATION"
229 #define XV_HUE		"XV_HUE"
230 
231 /* Proprietary */
232 
233 #define XV_INTERLACE	"XV_INTERLACE"	/* Interlaced (bool) */
234 #define XV_FILTER	"XV_FILTER"	/* Bilinear filter (bool) */
235 #define XV_BKGCOLOR	"XV_BKGCOLOR"	/* Output background (0x00RRGGBB) */
236 #define XV_ALPHA	"XV_ALPHA"	/* Scaler alpha channel (bool) */
237 
238 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
239 
240 static Atom xvEncoding, xvBrightness, xvContrast, xvSaturation, xvHue;
241 static Atom xvInterlace, xvFilter, xvBkgColor, xvAlpha;
242 
243 /* Input */
244 
245 static XF86VideoEncodingRec
246 InputVideoEncodings[] =
247 {
248     { 0, "pal-composite",		704, 576, { 1, 50 }},
249     { 1, "pal-composite_adaptor",	704, 576, { 1, 50 }},
250     { 2, "pal-svideo",			704, 576, { 1, 50 }},
251     { 3, "ntsc-composite",		704, 480, { 1001, 60000 }},
252     { 4, "ntsc-composite_adaptor",	704, 480, { 1001, 60000 }},
253     { 5, "ntsc-svideo",			704, 480, { 1001, 60000 }},
254     { 6, "secam-composite",		704, 576, { 1, 50 }},
255     { 7, "secam-composite_adaptor",	704, 576, { 1, 50 }},
256     { 8, "secam-svideo",		704, 576, { 1, 50 }},
257 };
258 
259 static XF86AttributeRec
260 InputVideoAttributes[] =
261 {
262     { XvSettable | XvGettable, -1000, +1000, XV_BRIGHTNESS },
263     { XvSettable | XvGettable, -3000, +1000, XV_CONTRAST },
264     { XvSettable | XvGettable, -3000, +1000, XV_SATURATION },
265     { XvSettable | XvGettable, -1000, +1000, XV_HUE },
266     { XvSettable | XvGettable, 0, 2, XV_INTERLACE },
267     { XvSettable | XvGettable, 0, 1, XV_FILTER },
268 };
269 
270 static XF86VideoFormatRec
271 InputVideoFormats[] =
272 {
273     { 8,  TrueColor }, /* Dithered */
274     { 15, TrueColor },
275     { 16, TrueColor },
276     { 24, TrueColor },
277 };
278 
279 /* Output */
280 
281 static XF86VideoEncodingRec
282 OutputVideoEncodings[] =
283 {
284     { 0, "pal-composite_adaptor",	704, 576, { 1, 50 }},
285     { 1, "pal-svideo",			704, 576, { 1, 50 }},
286     { 2, "ntsc-composite_adaptor",	704, 480, { 1001, 60000 }},
287     { 3, "ntsc-svideo",			704, 480, { 1001, 60000 }},
288 };
289 
290 static XF86AttributeRec
291 OutputVideoAttributes[] =
292 {
293     { XvSettable | XvGettable, 0, 2, XV_INTERLACE },
294     { XvSettable | XvGettable, 0, 1, XV_FILTER },
295     { XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_BKGCOLOR },
296 };
297 
298 static XF86VideoFormatRec
299 OutputVideoFormats[] =
300 {
301     { 8,  TrueColor },
302     { 8,  PseudoColor }, /* Using .. */
303     { 8,  StaticColor },
304     { 8,  GrayScale },
305     { 8,  StaticGray }, /* .. TexelLUT */
306     { 15, TrueColor },
307     { 16, TrueColor },
308     { 24, TrueColor },
309 };
310 
311 /* Scaler */
312 
313 static XF86VideoEncodingRec
314 ScalerEncodings[] =
315 {
316     { 0, "XV_IMAGE", 2047, 2047, { 1, 1 }},
317 };
318 
319 static XF86AttributeRec
320 ScalerAttributes[] =
321 {
322     { XvSettable | XvGettable, 0, 1, XV_FILTER },
323     { XvSettable | XvGettable, 0, 1, XV_ALPHA },
324 };
325 
326 #define ScalerVideoFormats InputVideoFormats
327 
328 /*
329  *  FOURCC from http://www.webartz.com/fourcc
330  *  Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71
331  */
332 #define LE4CC(a,b,c,d) (((CARD32)(a)&0xFF)|(((CARD32)(b)&0xFF)<<8)|(((CARD32)(c)&0xFF)<<16)|(((CARD32)(d)&0xFF)<<24))
333 #define GUID4CC(a,b,c,d) { a,b,c,d,0,0,0,0x10,0x80,0,0,0xAA,0,0x38,0x9B,0x71 }
334 
335 #define NoOrder LSBFirst
336 
337 static XF86ImageRec
338 ScalerImages[] =
339 {
340     /* Planar YVU 4:2:0 (emulated) */
341     { LE4CC('Y','V','1','2'), XvYUV, NoOrder, GUID4CC('Y','V','1','2'),
342       12, XvPlanar, 3, 0, 0, 0, 0,
343       8, 8, 8,  1, 2, 2,  1, 2, 2, "YVU", XvTopToBottom },
344 
345     /* Packed YUYV 4:2:2 */
346     { LE4CC('Y','U','Y','2'), XvYUV, NoOrder, GUID4CC('Y','U','Y','2'),
347       16, XvPacked, 1, 0, 0, 0, 0,
348       8, 8, 8,  1, 2, 2,  1, 1, 1, "YUYV", XvTopToBottom },
349 
350     /* Packed UYVY 4:2:2 */
351     { LE4CC('U','Y','V','Y'), XvYUV, NoOrder, GUID4CC('U','Y','V','Y'),
352       16, XvPacked, 1, 0, 0, 0, 0,
353       8, 8, 8,  1, 2, 2,  1, 1, 1, "UYVY", XvTopToBottom },
354 
355     /* Packed YUVA 4:4:4 */
356     { LE4CC('Y','U','V','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
357       32, XvPacked, 1, 0, 0, 0, 0,
358       8, 8, 8,  1, 1, 1,  1, 1, 1, "YUVA", XvTopToBottom },
359 
360     /* Packed VUYA 4:4:4 */
361     { LE4CC('V','U','Y','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
362       32, XvPacked, 1, 0, 0, 0, 0,
363       8, 8, 8,  1, 1, 1,  1, 1, 1, "VUYA", XvTopToBottom },
364 
365     /* RGBA 8:8:8:8 */
366     { 0x41, XvRGB, LSBFirst, { 0 },
367       32, XvPacked, 1, 24, 0x0000FF, 0x00FF00, 0xFF0000,
368       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
369 
370     /* RGB 5:6:5 */
371     { 0x42, XvRGB, LSBFirst, { 0 },
372       16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800,
373       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
374 
375     /* RGBA 5:5:5:1 */
376     { 0x43, XvRGB, LSBFirst, { 0 },
377       16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00,
378       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
379 
380     /* RGBA 4:4:4:4 */
381     { 0x44, XvRGB, LSBFirst, { 0 },
382       16, XvPacked, 1, 12, 0x000F, 0x00F0, 0x0F00,
383       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
384 
385     /* RGBA 2:3:2:1 */
386     { 0x45, XvRGB, NoOrder, { 0 },
387       8, XvPacked, 1, 7, 0x03, 0x1C, 0x60,
388       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
389 
390     /* RGB 3:3:2 */
391     { 0x46, XvRGB, NoOrder, { 0 },
392       8, XvPacked, 1, 8, 0x07, 0x38, 0xC0,
393       0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
394 
395     /* BGRA 8:8:8:8 */
396     { 0x47, XvRGB, LSBFirst, { 0 },
397       32, XvPacked, 1, 24, 0xFF0000, 0x00FF00, 0x0000FF,
398       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
399 
400     /* BGR 5:6:5 */
401     { 0x48, XvRGB, LSBFirst, { 0 },
402       16, XvPacked, 1, 16, 0xF800, 0x07E0, 0x001F,
403       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
404 
405     /* BGRA 5:5:5:1 */
406     { 0x49, XvRGB, LSBFirst, { 0 },
407       16, XvPacked, 1, 15, 0x7C00, 0x03E0, 0x001F,
408       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
409 
410     /* BGRA 4:4:4:4 */
411     { 0x4A, XvRGB, LSBFirst, { 0 },
412       16, XvPacked, 1, 12, 0x0F00, 0x00F0, 0x000F,
413       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
414 
415     /* BGRA 2:3:2:1 */
416     { 0x4B, XvRGB, NoOrder, { 0 },
417       8, XvPacked, 1, 7, 0x60, 0x1C, 0x03,
418       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
419 
420     /* BGR 2:3:3 */
421     { 0x4C, XvRGB, NoOrder, { 0 },
422       8, XvPacked, 1, 8, 0xC0, 0x38, 0x07,
423       0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
424 };
425 
426 
427 /*
428  *  Video codec tables
429  */
430 
431 #define SAA7111_SLAVE_ADDRESS 0x48
432 #define SAA7125_SLAVE_ADDRESS 0x88
433 
434 static I2CByte
435 DecInitVec[] =
436 {
437     0x11, 0x00,
438     0x02, 0xC1, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
439     0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x4A,
440     0x0A, 0x80, 0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x00,
441     0x0E, 0x01, 0x10, 0xC8, 0x12, 0x20,
442     0x13, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
443 };
444 
445 static I2CByte
446 EncInitVec[] =
447 {
448     0x3A, 0x83, 0x61, 0xC2,
449     0x5A, 119,  0x5B, 0x7D,
450     0x5C, 0xAF, 0x5D, 0x3C, 0x5E, 0x3F, 0x5F, 0x3F,
451     0x60, 0x70, 0x62, 0x4B, 0x67, 0x00,
452     0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B, 0x20,
453     0x6C, 0x03, 0x6D, 0x30, 0x6E, 0xA0, 0x6F, 0x00,
454     0x70, 0x80, 0x71, 0xE8, 0x72, 0x10,
455     0x7A, 0x13, 0x7B, 0xFB, 0x7C, 0x00, 0x7D, 0x00,
456 };
457 
458 static I2CByte Dec02[3] = { 0xC1, 0xC0, 0xC4 };
459 static I2CByte Dec09[3] = { 0x4A, 0x4A, 0xCA };
460 static I2CByte Enc3A[3] = { 0x03, 0x03, 0x23 };
461 static I2CByte Enc61[3] = { 0x06, 0x01, 0xC2 };
462 
463 static I2CByte
464 DecVS[3][8] =
465 {
466     { 0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01 },
467     { 0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01 },
468     { 0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51 }
469 };
470 
471 #define FSC(n) ((CARD32)((n) / 27e6 * 4294967296.0 + .5))
472 #define SUBCARRIER_FREQ_PAL  (4.433619e6)
473 #define SUBCARRIER_FREQ_NTSC (3.579545e6)
474 
475 static I2CByte
476 EncVS[2][14] =
477 {
478     { 0x62, 0x4B, 0x6B, 0x28, 0x6E, 0xA0,
479       0x63, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 0),
480       0x64, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 8),
481       0x65, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 16),
482       0x66, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 24) },
483     { 0x62, 0x6A, 0x6B, 0x20, 0x6E, 0x20,
484       0x63, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 0),
485       0x64, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 8),
486       0x65, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 16),
487       0x66, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 24) }
488 };
489 
490 /* Forward */
491 static void StopVideoStream(PortPrivPtr pPPriv, Bool shutdown);
492 static void RestoreVideoStd(AdaptorPrivPtr pAPriv);
493 static Bool xvipcHandshake(PortPrivPtr pPPriv, int op, Bool block);
494 
495 
496 /*
497  *  Video codec controls
498  */
499 
500 static int
SetAttr(PortPrivPtr pPPriv,int i,int value)501 SetAttr(PortPrivPtr pPPriv, int i, int value)
502 {
503     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
504     int v;
505 
506     if (value < InputVideoAttributes[i].min_value)
507 	value = InputVideoAttributes[i].min_value;
508     else
509     if (value > InputVideoAttributes[i].max_value)
510 	value = InputVideoAttributes[i].max_value;
511 
512     switch (i) {
513     case 0:
514         v = 128 + (MIN(value, 999) * 128) / 1000;
515         break;
516 
517     case 1:
518     case 2:
519         v = 64 + (MIN(value, 999) * 64) / 1000;
520         break;
521 
522     default:
523         v = (MIN(value, 999) * 128) / 1000;
524         break;
525     }
526 
527     if (pAPriv->pm2p) {
528 	xvipc.a = v << 8;
529 
530 	if (!xvipcHandshake(pPPriv, OP_ATTR + i, TRUE))
531 	    return XvBadAlloc;
532     } else
533 	if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x0A + i, v))
534 	    return XvBadAlloc;
535 
536     pPPriv->Attribute[i] = value;
537 
538     return Success;
539 }
540 
541 static int
SetPlug(PortPrivPtr pPPriv,int Plug)542 SetPlug(PortPrivPtr pPPriv, int Plug)
543 {
544     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
545 
546     if (pAPriv->pm2p) {
547 	xvipc.a = Plug - (pPPriv == &pAPriv->Port[1]);
548 
549 	if (!xvipcHandshake(pPPriv, OP_PLUG, TRUE))
550 	    return XvBadAlloc;
551     } else {
552 	if (pPPriv == &pAPriv->Port[0]) {
553 	    if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x02, Dec02[Plug]) ||
554 		!xf86I2CWriteByte(&pPPriv->I2CDev, 0x09, Dec09[Plug]))
555 		return XvBadAlloc;
556 	} else {
557 	    if (pPPriv->StreamOn) {
558 		if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x3A, Enc3A[Plug]))
559 		    return XvBadAlloc;
560 	    } else
561 		if (ColorBars)
562 		    xf86I2CWriteByte(&pPPriv->I2CDev, 0x3A, 0x83);
563 	}
564     }
565 
566     pPPriv->Plug = Plug;
567 
568     return Success;
569 }
570 
571 enum { PAL, NTSC, SECAM };
572 
573 static int
SetVideoStd(PortPrivPtr pPPriv,int VideoStd)574 SetVideoStd(PortPrivPtr pPPriv, int VideoStd)
575 {
576     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
577     int r = Success;
578 
579     if (pAPriv->pm2p) {
580 	xvipc.a = VideoStd;
581 
582 	if (!xvipcHandshake(&pAPriv->Port[0], OP_VIDEOSTD, TRUE))
583 	    return XvBadAlloc;
584 
585 	VideoStd = xvipc.a; /* Actual */
586     } else {
587 	if (VideoStd == SECAM)
588 	    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2);
589 	    /* Disable output, SECAM not supported */
590 
591 	if (!xf86I2CWriteVec(&pAPriv->Port[0].I2CDev, &DecVS[VideoStd][0], 4)) {
592 	    pAPriv->VideoStd = -1;
593 	    return XvBadAlloc;
594 	}
595 
596 	if (VideoStd != SECAM)
597 	    if (!xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, &EncVS[VideoStd][0], 7)) {
598 		pAPriv->VideoStd = -1;
599 		return XvBadAlloc;
600 	    }
601     }
602 
603     pAPriv->VideoStd = VideoStd;
604     pPPriv->VideoStdReq = VideoStd;
605 
606     if (VideoStd == NTSC) {
607 	pAPriv->FramesPerSec = 30;
608 	pAPriv->FrameLines = 525;
609 	pAPriv->IntLine = 513;
610 	pAPriv->LinePer = 63555;
611     } else {
612 	pAPriv->FramesPerSec = 25;
613 	pAPriv->FrameLines = 625;
614 	pAPriv->IntLine = 613;
615 	pAPriv->LinePer = 64000;
616     }
617 
618 #if 0 /* XF86Config option */
619 
620     pAPriv->Port[0].FramesPerSec = pAPriv->FramesPerSec;
621     pAPriv->Port[1].FramesPerSec = pAPriv->FramesPerSec;
622 
623 #endif
624 
625     return r;
626 }
627 
628 
629 /*
630  *  Buffer management
631  */
632 
633 static void
RemoveAreaCallback(FBAreaPtr pFBArea)634 RemoveAreaCallback(FBAreaPtr pFBArea)
635 {
636     PortPrivPtr pPPriv = (PortPrivPtr) pFBArea->devPrivate.ptr;
637     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
638     DEBUG(ScrnInfoPtr pScrn = pAPriv->pScrn;)
639     int i;
640 
641     for (i = 0; i < MAX_BUFFERS && pPPriv->pFBArea[i] != pFBArea; i++);
642 
643     if (i >= MAX_BUFFERS)
644 	return;
645 
646     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
647 	"RemoveAreaCallback port #%d, buffer #%d, pFB=%p, off=0x%08x\n",
648 	PORTNUM(pPPriv), i, pPPriv->pFBArea[i], pPPriv->BufferBase[i]));
649 
650     if (pAPriv->VideoIO && PORTNUM(pPPriv) < 2) {
651         StopVideoStream(pPPriv, FALSE);
652     }
653 
654     for (; i < MAX_BUFFERS - 1; i++)
655 	pPPriv->pFBArea[i] = pPPriv->pFBArea[i + 1];
656 
657     pPPriv->pFBArea[MAX_BUFFERS - 1] = NULL;
658 
659     pPPriv->BuffersAllocated--;
660 }
661 
662 static void
RemoveableBuffers(PortPrivPtr pPPriv,Bool remove)663 RemoveableBuffers(PortPrivPtr pPPriv, Bool remove)
664 {
665     int i;
666 
667     for (i = 0; i < MAX_BUFFERS; i++)
668 	if (pPPriv->pFBArea[i])
669 	    pPPriv->pFBArea[i]->RemoveAreaCallback =
670 		remove ? RemoveAreaCallback : NULL;
671 }
672 
673 static void
FreeBuffers(PortPrivPtr pPPriv)674 FreeBuffers(PortPrivPtr pPPriv)
675 {
676     DEBUG(AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;)
677     DEBUG(ScrnInfoPtr pScrn = pAPriv->pScrn;)
678     int i;
679 
680     RemoveableBuffers(pPPriv, FALSE);
681 
682     for (i = MAX_BUFFERS - 1; i >= 0; i--)
683 	if (pPPriv->pFBArea[i]) {
684 	    DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
685 		"FreeBuffers port #%d, buffer #%d, pFB=%p, off=0x%08x\n",
686 		PORTNUM(pPPriv), i, pPPriv->pFBArea[i], pPPriv->BufferBase[i]));
687 
688 	    xf86FreeOffscreenArea(pPPriv->pFBArea[i]);
689 
690 	    pPPriv->pFBArea[i] = NULL;
691 	}
692 
693     pPPriv->BuffersAllocated = 0;
694 }
695 
696 enum { FORCE_LINEAR = 1, FORCE_RECT };
697 
698 static int
AllocateBuffers(PortPrivPtr pPPriv,int w,int h,int bytespp,int num,int force)699 AllocateBuffers(PortPrivPtr pPPriv,
700     int w, int h, int bytespp,
701     int num, int force)
702 {
703     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
704     ScrnInfoPtr pScrn = pAPriv->pScrn;
705     GLINTPtr pGlint = GLINTPTR(pScrn);
706     Bool linear = (force != FORCE_RECT);
707     int i, j, retry = 0;
708 
709     FreeBuffers(pPPriv);
710 
711     for (i = 0; i < num; i++) {
712 	if (linear) {
713 	    for (j = (w + 31) >> 5; partprodPermedia[j] < 0; j++);
714 
715 	    pPPriv->BufferStride = j * bytespp * 32;
716 	    pPPriv->BufferPProd = partprodPermedia[j];
717 
718 	    pPPriv->pFBArea[i] = xf86AllocateLinearOffscreenArea(pScrn->pScreen,
719     		(pPPriv->BufferStride * h + (1 << BPPSHIFT(pGlint)) - 1) >> BPPSHIFT(pGlint),
720 		8 >> BPPSHIFT(pGlint), NULL, NULL, (pointer) pPPriv);
721 
722 	    if (pPPriv->pFBArea[i])
723 		/* pPPriv->BufferBase[i] = pPPriv->pFBArea[i].linear; */
724 		pPPriv->BufferBase[i] =
725 		    ((pPPriv->pFBArea[i]->box.y1 * pScrn->displayWidth) +
726 		     pPPriv->pFBArea[i]->box.x1) << BPPSHIFT(pGlint);
727 
728 	    DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
729 		"New linear buffer %dx%d, rec %dx%d -> pFB=%p, off=0x%08x\n",
730 		w, h, pPPriv->BufferStride, h, pPPriv->pFBArea[i], pPPriv->BufferBase[i]));
731 	} else {
732 	    pPPriv->BufferStride = pScrn->displayWidth << BPPSHIFT(pGlint);
733 
734 	    j = pPPriv->BufferStride / bytespp;
735 
736 	    if (j <= w && j <= 2048 && (j & 31) == 0 &&
737 		partprodPermedia[j >> 5] >= 0)
738 	    {
739 		pPPriv->BufferPProd = partprodPermedia[j >> 5];
740 		pPPriv->pFBArea[i] = xf86AllocateOffscreenArea(pScrn->pScreen,
741     		    w, h, 8 >> BPPSHIFT(pGlint), NULL, NULL, (pointer) pPPriv);
742 
743 		if (pPPriv->pFBArea[i])
744 		    pPPriv->BufferBase[i] =
745 			((pPPriv->pFBArea[i]->box.y1 * pScrn->displayWidth) +
746 		         pPPriv->pFBArea[i]->box.x1) << BPPSHIFT(pGlint);
747 
748 		DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
749 		    "New rect buffer %dx%d, stride %d, %d -> pFB=%p, off=0x%08x\n",
750 		    w, h, pPPriv->BufferStride, j, pPPriv->pFBArea[i], pPPriv->BufferBase[i]));
751 	    }
752 	}
753 
754 	if (pPPriv->pFBArea[i])
755 	    continue;
756 
757 	if (!force && i == 0 && retry++ < 1) {
758 	    linear ^= TRUE;
759 	    i = -1;
760 	} else
761 	    break;
762     }
763 
764     return pPPriv->BuffersAllocated = i;
765 }
766 
767 
768 /*
769  *  Blitter
770  */
771 
772 static Bool
RemakePutCookies(PortPrivPtr pPPriv,RegionPtr pRegion)773 RemakePutCookies(PortPrivPtr pPPriv, RegionPtr pRegion)
774 {
775     BoxPtr pBox;
776     CookiePtr pCookie;
777     int nBox;
778 
779     if (!pRegion) {
780 	pBox = (BoxPtr) NULL;
781 	nBox = pPPriv->nCookies;
782     } else {
783 	pBox = REGION_RECTS(pRegion);
784 	nBox = REGION_NUM_RECTS(pRegion);
785 
786 	if (!pPPriv->pCookies || pPPriv->nCookies < nBox) {
787 	    if (!(pCookie = (CookiePtr) realloc(pPPriv->pCookies, nBox * sizeof(CookieRec))))
788     		return FALSE;
789 
790 	    pPPriv->pCookies = pCookie;
791 	}
792     }
793 
794     pPPriv->dS = (pPPriv->vw << 10) / pPPriv->dw;
795     pPPriv->dT = (pPPriv->vh << 10) / pPPriv->dh;
796 
797     for (pCookie = pPPriv->pCookies; nBox--; pCookie++, pBox++) {
798 	if (pRegion) {
799 	    pCookie->y1 = pBox->y1;
800 	    pCookie->y2 = pBox->x1;
801 	    pCookie->xy = (pBox->y1 << 16) | pBox->x1;
802 	    pCookie->wh = ((pBox->y2 - pBox->y1) << 16) |
803 			   (pBox->x2 - pBox->x1);
804 	}
805 
806 	pCookie->s = (pPPriv->vx << 10) + (pCookie->y2 - pPPriv->dx) * pPPriv->dS;
807 	pCookie->t = (pPPriv->vy << 10) + (pCookie->y1 - pPPriv->dy) * pPPriv->dT;
808     }
809 
810     pPPriv->nCookies = pCookie - pPPriv->pCookies;
811 
812     return TRUE;
813 }
814 
815 #define FORMAT_YUYV ((0 << 5) + (1 << 4) + ((19 & 0x10) << 2) + ((19 & 0x0F) << 0))
816 #define FORMAT_UYVY ((1 << 5) + (1 << 4) + ((19 & 0x10) << 2) + ((19 & 0x0F) << 0))
817 #define FORMAT_YUVA ((0 << 5) + ((18 & 0x10) << 2) + ((18 & 0x0F) << 0))
818 #define FORMAT_VUYA ((1 << 5) + ((18 & 0x10) << 2) + ((18 & 0x0F) << 0))
819 
820 static void
PutYUV(PortPrivPtr pPPriv,int BufferBase,int format,int bptshift,int alpha)821 PutYUV(PortPrivPtr pPPriv, int BufferBase,
822     int format, int bptshift, int alpha)
823 {
824     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
825     ScrnInfoPtr pScrn = pAPriv->pScrn;
826     GLINTPtr pGlint = GLINTPTR(pScrn);
827     CookiePtr pCookie = pPPriv->pCookies;
828     int nCookies = pPPriv->nCookies;
829 
830     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "PutYUV %08x %08x\n",
831 	BufferBase, format));
832 
833     if (!nCookies || (GLINT_READ_REG(InFIFOSpace) < 200))
834 	return; /* Denial of service fix, N/A for scaler */
835 
836     CHECKCLIPPING;
837 
838     GLINT_WRITE_REG(1 << 16, dY);
839     GLINT_WRITE_REG(0, RasterizerMode);
840     GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode);
841     GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode);
842     GLINT_WRITE_REG(pPPriv->dS, dSdx);
843     GLINT_WRITE_REG(0, dSdyDom);
844     GLINT_WRITE_REG(0, dTdx);
845     GLINT_WRITE_REG(pPPriv->dT, dTdyDom);
846     GLINT_WRITE_REG(BufferBase >> bptshift, PMTextureBaseAddress);
847     GLINT_WRITE_REG((bptshift << 19) | pPPriv->BufferPProd, PMTextureMapFormat);
848     GLINT_WRITE_REG(format, PMTextureDataFormat);
849     GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */
850 		    (11 << 13) | (11 << 9) | /* TextureSize log2 */
851 		    UNIT_ENABLE, PMTextureReadMode);
852     GLINT_WRITE_REG((0 << 4) /* RGB */ |
853 		    (3 << 1) /* Copy */ |
854 		    UNIT_ENABLE, TextureColorMode);
855     if (alpha)
856 	GLINT_WRITE_REG(pAPriv->dAlphaBlendMode, AlphaBlendMode);
857     GLINT_WRITE_REG(pAPriv->dDitherMode, DitherMode);
858     GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode);
859     GLINT_WRITE_REG((alpha << 10) | /* ReadDestination */
860 		    pGlint->pprod, FBReadMode);
861     GLINT_WRITE_REG(0xFFFFFFFF, FBHardwareWriteMask);
862     GLINT_WRITE_REG(UNIT_ENABLE, YUVMode);
863 
864     for (; nCookies--; pCookie++) {
865 	GLINT_WAIT(5);
866 	GLINT_WRITE_REG(pCookie->xy, RectangleOrigin);
867 	GLINT_WRITE_REG(pCookie->wh, RectangleSize);
868 	GLINT_WRITE_REG(pCookie->s, SStart);
869 	GLINT_WRITE_REG(pCookie->t, TStart);
870         GLINT_WRITE_REG(PrimitiveRectangle |
871 			XPositive |
872 			YPositive |
873 			TextureEnable, Render);
874     }
875 
876     pGlint->x = pGlint->y = -1; /* Force reload */
877     pGlint->w = pGlint->h = -1;
878     pGlint->ROP = 0xFF;
879     pGlint->planemask = 0xFFFFFFFF;
880 
881     GLINT_WAIT(8);
882     GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode);
883     GLINT_WRITE_REG(pGlint->TexMapFormat, PMTextureMapFormat);
884     GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode);
885     GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode);
886     GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
887     if (alpha) {
888 	GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode);
889 	GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
890     }
891     GLINT_WRITE_REG(UNIT_DISABLE, YUVMode);
892 }
893 
894 #define FORMAT_RGB8888 ((0 << 5) + (0 << 4) + ((0 & 0x10) << 2) + ((0 & 0x0F) << 0))
895 #define FORMAT_RGB565  ((0 << 5) + (1 << 4) + ((16 & 0x10) << 2) + ((16 & 0x0F) << 0))
896 #define FORMAT_RGB5551 ((0 << 5) + (0 << 4) + ((1 & 0x10) << 2) + ((1 & 0x0F) << 0))
897 #define FORMAT_RGB4444 ((0 << 5) + (0 << 4) + ((2 & 0x10) << 2) + ((2 & 0x0F) << 0))
898 #define FORMAT_RGB332  ((0 << 5) + (1 << 4) + ((5 & 0x10) << 2) + ((5 & 0x0F) << 0))
899 #define FORMAT_RGB2321 ((0 << 5) + (0 << 4) + ((9 & 0x10) << 2) + ((9 & 0x0F) << 0))
900 #define FORMAT_BGR8888 ((1 << 5) + (0 << 4) + ((0 & 0x10) << 2) + ((0 & 0x0F) << 0))
901 #define FORMAT_BGR565  ((1 << 5) + (1 << 4) + ((16 & 0x10) << 2) + ((16 & 0x0F) << 0))
902 #define FORMAT_BGR5551 ((1 << 5) + (0 << 4) + ((1 & 0x10) << 2) + ((1 & 0x0F) << 0))
903 #define FORMAT_BGR4444 ((1 << 5) + (0 << 4) + ((2 & 0x10) << 2) + ((2 & 0x0F) << 0))
904 #define FORMAT_BGR332  ((1 << 5) + (1 << 4) + ((5 & 0x10) << 2) + ((5 & 0x0F) << 0))
905 #define FORMAT_BGR2321 ((1 << 5) + (0 << 4) + ((9 & 0x10) << 2) + ((9 & 0x0F) << 0))
906 
907 static void
PutRGB(PortPrivPtr pPPriv,int BufferBase,int format,int bptshift,int alpha)908 PutRGB(PortPrivPtr pPPriv, int BufferBase, int format, int bptshift, int alpha)
909 {
910     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
911     ScrnInfoPtr pScrn = pAPriv->pScrn;
912     GLINTPtr pGlint = GLINTPTR(pScrn);
913     CookiePtr pCookie = pPPriv->pCookies;
914     int nCookies = pPPriv->nCookies;
915 
916     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "PutRGB %08x %08x\n",
917 	BufferBase, format));
918 
919     if (!nCookies)
920 	return;
921 
922     CHECKCLIPPING;
923 
924     GLINT_WRITE_REG(1 << 16, dY);
925     GLINT_WRITE_REG(0, RasterizerMode);
926     GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode);
927     GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode);
928     GLINT_WRITE_REG(pPPriv->dS, dSdx);
929     GLINT_WRITE_REG(0, dSdyDom);
930     GLINT_WRITE_REG(0, dTdx);
931     GLINT_WRITE_REG(pPPriv->dT, dTdyDom);
932     GLINT_WRITE_REG(BufferBase >> bptshift, PMTextureBaseAddress);
933     GLINT_WRITE_REG((bptshift << 19) | pPPriv->BufferPProd, PMTextureMapFormat);
934     GLINT_WRITE_REG(format, PMTextureDataFormat);
935     GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */
936 		    (11 << 13) | (11 << 9) | /* TextureSize log2 */
937 		    UNIT_ENABLE, PMTextureReadMode);
938     GLINT_WRITE_REG((0 << 4) /* RGB */ |
939 		    (3 << 1) /* Copy */ |
940 		    UNIT_ENABLE, TextureColorMode);
941     if (alpha)
942 	GLINT_WRITE_REG(pAPriv->dAlphaBlendMode, AlphaBlendMode);
943     GLINT_WRITE_REG(pAPriv->dDitherMode, DitherMode);
944     GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode);
945     GLINT_WRITE_REG((alpha << 10) | /* ReadDestination */
946 		    pGlint->pprod, FBReadMode);
947     GLINT_WRITE_REG(0xFFFFFFFF, FBHardwareWriteMask);
948 
949     for (; nCookies--; pCookie++) {
950 	GLINT_WAIT(5);
951 	GLINT_WRITE_REG(pCookie->xy, RectangleOrigin);
952 	GLINT_WRITE_REG(pCookie->wh, RectangleSize);
953 	GLINT_WRITE_REG(pCookie->s, SStart);
954 	GLINT_WRITE_REG(pCookie->t, TStart);
955         GLINT_WRITE_REG(PrimitiveRectangle |
956 			XPositive |
957 			YPositive |
958 			TextureEnable, Render);
959     }
960 
961     pGlint->x = pGlint->y = -1; /* Force reload */
962     pGlint->w = pGlint->h = -1;
963     pGlint->ROP = 0xFF;
964     pGlint->planemask = 0xFFFFFFFF;
965 
966     GLINT_WAIT(7);
967     GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode);
968     GLINT_WRITE_REG(pGlint->TexMapFormat, PMTextureMapFormat);
969     GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode);
970     GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode);
971     GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
972     if (alpha) {
973 	GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode);
974 	GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
975     }
976 }
977 
978 static void
BlackOut(PortPrivPtr pPPriv,RegionPtr pRegion)979 BlackOut(PortPrivPtr pPPriv, RegionPtr pRegion)
980 {
981     ScrnInfoPtr pScrn = pPPriv->pAdaptor->pScrn;
982     ScreenPtr pScreen = pScrn->pScreen;
983     GLINTPtr pGlint = GLINTPTR(pScrn);
984     RegionRec DRegion;
985     BoxRec DBox;
986     BoxPtr pBox;
987     int nBox;
988 
989     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
990 	"BlackOut %d,%d,%d,%d -- %d,%d,%d,%d\n",
991 	pPPriv->vx, pPPriv->vy, pPPriv->vw, pPPriv->vh,
992 	pPPriv->dx, pPPriv->dy, pPPriv->dw, pPPriv->dh));
993 
994     DBox.x1 = pPPriv->dx - (pPPriv->vx * pPPriv->dw) / pPPriv->vw;
995     DBox.y1 = pPPriv->dy - (pPPriv->vy * pPPriv->dh) / pPPriv->vh;
996     DBox.x2 = DBox.x1 + (pPPriv->fw * pPPriv->dw) / pPPriv->vw;
997     DBox.y2 = DBox.y1 + (pPPriv->fh * pPPriv->dh) / pPPriv->vh;
998 
999     REGION_INIT(pScreen, &DRegion, &DBox, 1);
1000 
1001     if (pRegion)
1002 	REGION_SUBTRACT(pScreen, &DRegion, &DRegion, pRegion);
1003 
1004     nBox = REGION_NUM_RECTS(&DRegion);
1005     pBox = REGION_RECTS(&DRegion);
1006 
1007     GLINT_WAIT(15);
1008     CHECKCLIPPING;
1009 
1010     GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
1011     GLINT_WRITE_REG(pPPriv->BufferPProd, FBReadMode);
1012     GLINT_WRITE_REG(0x1, FBReadPixel); /* 16 */
1013     GLINT_WRITE_REG(pPPriv->BkgCol, FBBlockColor);
1014     GLINT_WRITE_REG(pPPriv->BufferBase[0] >> 1 /* 16 */, FBWindowBase);
1015     GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode);
1016 
1017     for (; nBox--; pBox++) {
1018         int w = ((pBox->x2 - pBox->x1) * pPPriv->vw + pPPriv->dw) / pPPriv->dw + 1;
1019 	int h = ((pBox->y2 - pBox->y1) * pPPriv->vh + pPPriv->dh) / pPPriv->dh + 1;
1020 	int x = ((pBox->x1 - DBox.x1) * pPPriv->vw + (pPPriv->dw >> 1)) / pPPriv->dw;
1021 	int y = ((pBox->y1 - DBox.y1) * pPPriv->vh + (pPPriv->dh >> 1)) / pPPriv->dh;
1022 
1023 	if ((x + w) > pPPriv->fw)
1024 	    w = pPPriv->fw - x;
1025 	if ((y + h) > pPPriv->fh)
1026 	    h = pPPriv->fh - y;
1027 
1028 	GLINT_WAIT(3);
1029 	GLINT_WRITE_REG((y << 16) | x, RectangleOrigin);
1030 	GLINT_WRITE_REG((h << 16) | w, RectangleSize);
1031 	GLINT_WRITE_REG(PrimitiveRectangle |
1032 	    XPositive | YPositive | FastFillEnable, Render);
1033     }
1034 
1035     REGION_UNINIT(pScreen, &DRegion);
1036 
1037     pGlint->x = pGlint->y = -1; /* Force reload */
1038     pGlint->w = pGlint->h = -1;
1039     pGlint->ROP = 0xFF;
1040     GLINT_WAIT(3);
1041     GLINT_WRITE_REG(0, FBWindowBase);
1042     GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
1043     GLINT_WRITE_REG(pGlint->PixelWidth, FBReadPixel);
1044 }
1045 
1046 static Bool
RemakeGetCookies(PortPrivPtr pPPriv,RegionPtr pRegion)1047 RemakeGetCookies(PortPrivPtr pPPriv, RegionPtr pRegion)
1048 {
1049     BoxPtr pBox;
1050     CookiePtr pCookie;
1051     int nBox;
1052     int dw1 = pPPriv->dw - 1;
1053     int dh1 = pPPriv->dh - 1;
1054 
1055     if (!pRegion) {
1056 	pBox = (BoxPtr) NULL;
1057 	nBox = pPPriv->nCookies;
1058     } else {
1059 	pBox = REGION_RECTS(pRegion);
1060 	nBox = REGION_NUM_RECTS(pRegion);
1061 
1062 	if (!pPPriv->pCookies || pPPriv->nCookies < nBox) {
1063 	    if (!(pCookie = (CookiePtr) realloc(pPPriv->pCookies, nBox * sizeof(CookieRec))))
1064     		return FALSE;
1065 
1066 	    pPPriv->pCookies = pCookie;
1067 	}
1068     }
1069 
1070     pPPriv->dS = (pPPriv->dw << 20) / pPPriv->vw;
1071     pPPriv->dT = (pPPriv->dh << 20) / pPPriv->vh;
1072 
1073     for (pCookie = pPPriv->pCookies; nBox--; pBox++) {
1074 	int n1, n2;
1075 
1076 	if (pRegion) {
1077 	    n1 = ((pBox->x1 - pPPriv->dx) * pPPriv->vw + dw1) / pPPriv->dw;
1078             n2 = ((pBox->x2 - pPPriv->dx) * pPPriv->vw - 1) / pPPriv->dw;
1079 
1080 	    if (n1 > n2)
1081 		continue; /* Clip is subpixel */
1082 
1083 	    pCookie->xy = n1 + pPPriv->vx;
1084 	    pCookie->wh = n2 - n1 + 1;
1085 	    pCookie->s = n1 * pPPriv->dS + (pPPriv->dx << 20);
1086 	    pCookie->y1 = pBox->y1;
1087 	    pCookie->y2 = pBox->y2;
1088 	}
1089 
1090 	n1 = ((pCookie->y1 - pPPriv->dy) * pPPriv->vh + dh1) / pPPriv->dh;
1091 	n2 = ((pCookie->y2 - pPPriv->dy) * pPPriv->vh - 1) / pPPriv->dh;
1092 	pCookie->xy = (pCookie->xy & 0xFFFF) | ((n1 + pPPriv->vy) << 16);
1093 	pCookie->wh = (pCookie->wh & 0xFFFF) | ((n2 - n1 + 1) << 16);
1094 	pCookie->t = n1 * pPPriv->dT + (pPPriv->dy << 20);
1095 	if (n1 > n2) pCookie->t = -1;
1096 
1097 	pCookie++;
1098     }
1099 
1100     pPPriv->nCookies = pCookie - pPPriv->pCookies;
1101     return TRUE;
1102 }
1103 
1104 static void
GetYUV(PortPrivPtr pPPriv)1105 GetYUV(PortPrivPtr pPPriv)
1106 {
1107     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1108     ScrnInfoPtr pScrn = pAPriv->pScrn;
1109     GLINTPtr pGlint = GLINTPTR(pScrn);
1110     CookiePtr pCookie = pPPriv->pCookies;
1111     int nCookies = pPPriv->nCookies;
1112 
1113     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "GetYUV\n"));
1114 
1115     if (!nCookies || (GLINT_READ_REG(InFIFOSpace) < 200))
1116 	return;
1117 
1118     GLINT_WAIT(25);
1119     CHECKCLIPPING;
1120 
1121     GLINT_WRITE_REG(1 << 16, dY);
1122     GLINT_WRITE_REG(0, RasterizerMode);
1123     GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode);
1124     GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode);
1125     GLINT_WRITE_REG(pPPriv->dS, dSdx);
1126     GLINT_WRITE_REG(0, dSdyDom);
1127     GLINT_WRITE_REG(0, dTdx);
1128     GLINT_WRITE_REG(pPPriv->dT, dTdyDom);
1129     GLINT_WRITE_REG(0, PMTextureBaseAddress);
1130     GLINT_WRITE_REG(pAPriv->dTextureDataFormat, PMTextureDataFormat);
1131     GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */
1132 		    (11 << 13) | (11 << 9) | /* TextureSize log2 */
1133 		    UNIT_ENABLE, PMTextureReadMode);
1134     if (pScrn->depth == 8)
1135 	GLINT_WRITE_REG(UNIT_ENABLE, TexelLUTMode);
1136     GLINT_WRITE_REG((0 << 4) /* RGB */ |
1137 		    (3 << 1) /* Copy */ |
1138 		    UNIT_ENABLE, TextureColorMode);
1139     GLINT_WRITE_REG((1 << 10) |			/* RGB */
1140 		    ((16 & 0x10) << 12) |
1141 		    ((16 & 0x0F) << 2) |	/* 5:6:5f */
1142 		    UNIT_ENABLE, DitherMode);
1143     GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode);
1144     GLINT_WRITE_REG(pPPriv->BufferPProd, FBReadMode);
1145     GLINT_WRITE_REG(pPPriv->BufferBase[0] >> 1 /* 16 */, FBWindowBase);
1146     GLINT_WRITE_REG(0x1, FBReadPixel); /* 16 */
1147     GLINT_WRITE_REG(UNIT_DISABLE, YUVMode);
1148 
1149     for (; nCookies--; pCookie++)
1150 	if (pCookie->t >= 0) {
1151 	    GLINT_WAIT(5);
1152 	    GLINT_WRITE_REG(pCookie->xy, RectangleOrigin);
1153 	    GLINT_WRITE_REG(pCookie->wh, RectangleSize);
1154 	    GLINT_WRITE_REG(pCookie->s, SStart);
1155 	    GLINT_WRITE_REG(pCookie->t, TStart);
1156     	    GLINT_WRITE_REG(PrimitiveRectangle |
1157 			    XPositive |
1158 			    YPositive |
1159 			    TextureEnable, Render);
1160 	}
1161 
1162     pGlint->x = pGlint->y = -1; /* Force reload */
1163     pGlint->w = pGlint->h = -1;
1164     pGlint->ROP = 0xFF;
1165 
1166     GLINT_WAIT(9);
1167     GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode);
1168     GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode);
1169     GLINT_WRITE_REG(UNIT_DISABLE, DitherMode);
1170     if (pScrn->depth == 8)
1171 	GLINT_WRITE_REG(UNIT_DISABLE, TexelLUTMode);
1172     GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode);
1173     GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
1174     GLINT_WRITE_REG(0, FBWindowBase);
1175     GLINT_WRITE_REG(pGlint->PixelWidth, FBReadPixel);
1176     GLINT_WRITE_REG(UNIT_DISABLE, YUVMode);
1177 }
1178 
1179 static int
SetBkgCol(PortPrivPtr pPPriv,int value)1180 SetBkgCol(PortPrivPtr pPPriv, int value)
1181 {
1182     pPPriv->Attribute[6] = value;
1183 
1184     pPPriv->BkgCol = ((value & 0xF80000) >> 8) |
1185 		     ((value & 0x00FC00) >> 5) |
1186 		     ((value & 0x0000F8) >> 3);
1187 
1188     pPPriv->BkgCol += pPPriv->BkgCol << 16;
1189 
1190     if (pPPriv->VideoOn) {
1191 	BlackOut(pPPriv, NULL);
1192 	GetYUV(pPPriv);
1193     }
1194 
1195     return Success;
1196 }
1197 
1198 /* os/WaitFor.c */
1199 
1200 static CARD32
TimerCallback(OsTimerPtr pTim,CARD32 now,pointer p)1201 TimerCallback(OsTimerPtr pTim, CARD32 now, pointer p)
1202 {
1203     AdaptorPrivPtr pAPriv = (AdaptorPrivPtr) p;
1204     GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn);
1205     PortPrivPtr pPPriv;
1206     int i, delay;
1207 
1208     if (!pAPriv->pm2p) {
1209 	pPPriv = &pAPriv->Port[0];
1210 
1211 	if (pPPriv->VideoOn > VIDEO_OFF) {
1212 	    pPPriv->FrameAcc += pPPriv->FramesPerSec;
1213 
1214 	    if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) {
1215 		pPPriv->FrameAcc -= pAPriv->FramesPerSec;
1216 
1217 		PutYUV(pPPriv, (!pPPriv->pFBArea[1]) ?
1218 		    pPPriv->BufferBase[0] : pPPriv->BufferBase[1 -
1219 			GLINT_READ_REG(VSABase + VSVideoAddressIndex)], FORMAT_YUYV, 1, 0);
1220 	    }
1221 	} else
1222 	    if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) {
1223 		StopVideoStream(pPPriv, TRUE);
1224 		RestoreVideoStd(pAPriv);
1225 	    }
1226 
1227 	pPPriv = &pAPriv->Port[1];
1228 
1229 	if (pPPriv->VideoOn > VIDEO_OFF) {
1230 	    pPPriv->FrameAcc += pPPriv->FramesPerSec;
1231 
1232 	    if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) {
1233 		pPPriv->FrameAcc -= pAPriv->FramesPerSec;
1234 
1235 		GetYUV(pPPriv);
1236 	    }
1237 	} else
1238 	    if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) {
1239 		StopVideoStream(pPPriv, TRUE);
1240 		RestoreVideoStd(pAPriv);
1241 	    }
1242     }
1243 
1244     for (i = 2; i <= 5; i++) {
1245 	if (pAPriv->Port[i].StopDelay >= 0) {
1246 	    if (!(pAPriv->Port[i].StopDelay--)) {
1247 		FreeBuffers(&pAPriv->Port[i]);
1248 		FreeCookies(&pAPriv->Port[i]);
1249 		pAPriv->TimerUsers &= ~(1 << i);
1250 	    }
1251 	}
1252     }
1253 
1254     if (!pAPriv->pm2p) {
1255 	if (pAPriv->Port[0].StreamOn) {
1256 	    delay = GLINT_READ_REG(VSABase + VSCurrentLine);
1257 
1258 	    if (!(GLINT_READ_REG(VSStatus) & VS_FieldOne0A))
1259 		delay += pAPriv->FrameLines >> 1;
1260 
1261 	    if (delay > (pAPriv->IntLine - 16))
1262 		delay -= pAPriv->FrameLines;
1263 
1264 	    return (((pAPriv->IntLine - delay) * pAPriv->LinePer) + 999999) / 1000000;
1265 	} else if (pAPriv->Port[1].StreamOn) {
1266 	    delay = GLINT_READ_REG(VSBBase + VSCurrentLine);
1267 
1268 	    if (!(GLINT_READ_REG(VSStatus) & VS_FieldOne0B))
1269 		delay += pAPriv->FrameLines >> 1;
1270 
1271 	    if (delay > (pAPriv->IntLine - 16))
1272 		delay -= pAPriv->FrameLines;
1273 
1274 	    return (((pAPriv->IntLine - delay) * pAPriv->LinePer) + 999999) / 1000000;
1275 	}
1276     }
1277 
1278     if (pAPriv->TimerUsers)
1279 	return pAPriv->Instant;
1280 
1281     return 0; /* Cancel */
1282 }
1283 
1284 
1285 /*
1286  *  Video stream (bounce buffer <-> hardware)
1287  */
1288 
1289 static void
StopVideoStream(PortPrivPtr pPPriv,Bool shutdown)1290 StopVideoStream(PortPrivPtr pPPriv, Bool shutdown)
1291 {
1292     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1293     GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn);
1294     int VideoOn;
1295 
1296     pPPriv->StopDelay = -1;
1297 
1298     VideoOn = pPPriv->VideoOn;
1299     pPPriv->VideoOn = VIDEO_OFF;
1300 
1301     if (!pPPriv->StreamOn)
1302 	return;
1303 
1304     if (pAPriv->pm2p) {
1305 	xvipcHandshake(pPPriv, OP_STOP, TRUE);
1306 
1307 	pPPriv->StreamOn = FALSE;
1308 
1309 	if (shutdown)
1310 	    FreeCookies(pPPriv);
1311 
1312 	if (VideoOn > VIDEO_OFF && pGlint->NoAccel)
1313 	    Permedia2Sync(pAPriv->pScrn);
1314 
1315 	return;
1316     }
1317 
1318     if (pPPriv == &pAPriv->Port[0]) {
1319 	int line, eeek = 0;
1320 
1321 	do {
1322 	    if (eeek++ > 1000000) break;
1323 	    line = GLINT_READ_REG(VSABase + VSCurrentLine);
1324 	} while (line > 15);
1325 
1326 	GLINT_WRITE_REG(0, VSABase + VSControl);
1327 
1328 	pAPriv->Port[0].StreamOn = FALSE;
1329 
1330 	usleep(80000);
1331     } else {
1332     	xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, 0x83);
1333 	if (!ColorBars)
1334 	    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2);
1335 
1336 	GLINT_WRITE_REG(0, VSBBase + VSControl);
1337 
1338 	pAPriv->Port[1].StreamOn = FALSE;
1339     }
1340 
1341     if (!pAPriv->Port[0].StreamOn && !pAPriv->Port[1].StreamOn) {
1342 	if (shutdown)
1343 	    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2);
1344 	xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x00);
1345     }
1346 
1347     if (shutdown) {
1348 	FreeBuffers(pPPriv);
1349 	FreeCookies(pPPriv);
1350 
1351 	if (pAPriv->TimerUsers) {
1352 	    pAPriv->TimerUsers &= ~PORTNUM(pPPriv);
1353 	    if (!pAPriv->TimerUsers)
1354 		TimerCancel(pAPriv->Timer);
1355 	}
1356 
1357 	if (VideoOn > VIDEO_OFF && pGlint->NoAccel)
1358 	    Permedia2Sync(pAPriv->pScrn);
1359     }
1360 }
1361 
1362 static Bool
StartVideoStream(PortPrivPtr pPPriv,RegionPtr pRegion)1363 StartVideoStream(PortPrivPtr pPPriv, RegionPtr pRegion)
1364 {
1365     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1366     GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn);
1367 
1368     if (pAPriv->VideoStd < 0)
1369 	return FALSE;
1370 
1371     pPPriv->StopDelay = -1;
1372 
1373     if (pAPriv->pm2p) {
1374 	if (pPPriv == &pAPriv->Port[0]) {
1375 	    if (!RemakePutCookies(pPPriv, pRegion))
1376 		return FALSE;
1377 	    if (pPPriv->StreamOn)
1378 		return TRUE;
1379 	} else {
1380 	    if (!RemakeGetCookies(pPPriv, pRegion))
1381 		return FALSE;
1382 	    if (pPPriv->StreamOn) {
1383 		BlackOut(pPPriv, pRegion);
1384 		return TRUE;
1385 	    }
1386 	}
1387 
1388 	xvipc.a = pPPriv->BuffersRequested;
1389 	xvipc.b = !pPPriv->Attribute[4];
1390 	xvipc.c = 1 + (pPPriv->Attribute[4] & 2);
1391 
1392 	if (!xvipcHandshake(pPPriv, OP_START, TRUE))
1393 		return FALSE;
1394 
1395 	if (pPPriv == &pAPriv->Port[1]) {
1396 	    pPPriv->BufferBase[0] = xvipc.d;
1397 	    BlackOut(pPPriv, pRegion);
1398 	}
1399 
1400 	return pPPriv->StreamOn = TRUE;
1401     } else {
1402 	CARD32 Base = (pPPriv == &pAPriv->Port[0]) ? VSABase : VSBBase;
1403 
1404         if (pPPriv->BuffersAllocated < pPPriv->BuffersRequested) {
1405 	    int height = ((pAPriv->VideoStd == NTSC) ? 512 : 608) >> (!pPPriv->Attribute[4]);
1406 
1407     	    if (!AllocateBuffers(pPPriv, 704, height, 2, pPPriv->BuffersRequested, 0))
1408 		return FALSE;
1409 
1410 	    pPPriv->fw = 704;
1411 	    pPPriv->fh = InputVideoEncodings[pAPriv->VideoStd * 3].height >>
1412 			(!pPPriv->Attribute[4]);
1413 	}
1414 
1415 	if (pPPriv == &pAPriv->Port[0]) {
1416 	    if (!RemakePutCookies(pPPriv, pRegion))
1417 		return FALSE;
1418 	} else {
1419 	    if (!RemakeGetCookies(pPPriv, pRegion))
1420 		return FALSE;
1421 
1422 	    BlackOut(pPPriv, pRegion);
1423 	}
1424 
1425 	if (pPPriv->StreamOn)
1426 	    return TRUE;
1427 
1428 	GLINT_WRITE_REG(pPPriv->BufferBase[0] / 8, Base + VSVideoAddress0);
1429 	if (pPPriv->pFBArea[1])
1430 	    GLINT_WRITE_REG(pPPriv->BufferBase[1] / 8, Base + VSVideoAddress1);
1431 	else
1432 	    GLINT_WRITE_REG(pPPriv->BufferBase[0] / 8, Base + VSVideoAddress1);
1433 	GLINT_WRITE_REG(pPPriv->BufferStride / 8, Base + VSVideoStride);
1434 
1435 	GLINT_WRITE_REG(0, Base + VSCurrentLine);
1436 
1437 	if (pAPriv->VideoStd == NTSC) {
1438 	    GLINT_WRITE_REG(16, Base + VSVideoStartLine);
1439 	    GLINT_WRITE_REG(16 + 240, Base + VSVideoEndLine);
1440 	    GLINT_WRITE_REG(288 + (8 & ~3) * 2, Base + VSVideoStartData);
1441 	    GLINT_WRITE_REG(288 + ((8 & ~3) + 704) * 2, Base + VSVideoEndData);
1442 	} else {
1443 	    GLINT_WRITE_REG(16, Base + VSVideoStartLine);
1444 	    GLINT_WRITE_REG(16 + 288, Base + VSVideoEndLine);
1445 	    GLINT_WRITE_REG(288 + (8 & ~3) * 2, Base + VSVideoStartData);
1446 	    GLINT_WRITE_REG(288 + ((8 & ~3) + 704) * 2, Base + VSVideoEndData);
1447 	}
1448 
1449 	GLINT_WRITE_REG(2, Base + VSVideoAddressHost);
1450 	GLINT_WRITE_REG(0, Base + VSVideoAddressIndex);
1451 
1452 	if (pPPriv == &pAPriv->Port[0]) {
1453 	    int line, eeek = 0;
1454 
1455 	    xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x0D);
1456 
1457 	    do {
1458 		if (eeek++ > 1000000) break;
1459 		line = GLINT_READ_REG(VSABase + VSCurrentLine);
1460 	    } while (line > 15);
1461 
1462 	    GLINT_WRITE_REG(VSA_Video |
1463 			    (pPPriv->Attribute[4] ?
1464 				VSA_CombineFields : VSA_Discard_FieldTwo),
1465 			    VSABase + VSControl);
1466 	    if (ColorBars)
1467 		if (!pAPriv->Port[1].StreamOn) {
1468 		    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, 0x83);
1469 		    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, Enc61[pAPriv->VideoStd]);
1470 		}
1471 	} else {
1472 	    GLINT_WRITE_REG(VSB_Video |
1473 			    (pPPriv->Attribute[4] ? VSB_CombineFields : 0) |
1474 			  /* VSB_GammaCorrect | */
1475 			    (16 << 4) | /* 5:6:5 */
1476 			    (1 << 9) | /* 16 */
1477 			    VSB_RGBOrder, VSBBase + VSControl);
1478 	    xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x0D);
1479 	    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, Enc3A[pPPriv->Plug]);
1480 	    xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, Enc61[pAPriv->VideoStd]);
1481 	}
1482 
1483 	pAPriv->TimerUsers |= 1 << PORTNUM(pPPriv);
1484 	TimerSet(pAPriv->Timer, 0, 80, TimerCallback, pAPriv);
1485 
1486 	return pPPriv->StreamOn = TRUE;
1487     }
1488 
1489     return FALSE;
1490 }
1491 
1492 
1493 /*
1494  *  Xv interface
1495  */
1496 
1497 static int
Permedia2PutVideo(ScrnInfoPtr pScrn,short vid_x,short vid_y,short drw_x,short drw_y,short vid_w,short vid_h,short drw_w,short drw_h,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1498 Permedia2PutVideo(ScrnInfoPtr pScrn,
1499     short vid_x, short vid_y, short drw_x, short drw_y,
1500     short vid_w, short vid_h, short drw_w, short drw_h,
1501     RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1502 {
1503     PortPrivPtr pPPriv = (PortPrivPtr) data;
1504     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1505     int sw, sh;
1506 
1507     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1508 	"PutVideo %d,%d,%d,%d -> %d,%d,%d,%d\n",
1509 	vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h));
1510 
1511     sw = InputVideoEncodings[pAPriv->VideoStd * 3].width;
1512     sh = InputVideoEncodings[pAPriv->VideoStd * 3].height;
1513 
1514     if ((vid_x + vid_w) > sw ||
1515         (vid_y + vid_h) > sh)
1516         return BadValue;
1517 
1518     pPPriv->VideoOn = VIDEO_OFF;
1519 
1520     pPPriv->vx = ((vid_x << 10) * pPPriv->fw) / sw;
1521     pPPriv->vy = ((vid_y << 10) * pPPriv->fh) / sh;
1522     pPPriv->vw = ((vid_w << 10) * pPPriv->fw) / sw;
1523     pPPriv->vh = ((vid_h << 10) * pPPriv->fh) / sh;
1524 
1525     pPPriv->dx = drw_x;
1526     pPPriv->dy = drw_y;
1527     pPPriv->dw = drw_w;
1528     pPPriv->dh = drw_h;
1529 
1530     pPPriv->FrameAcc = pAPriv->FramesPerSec;
1531 
1532     if (!StartVideoStream(pPPriv, clipBoxes))
1533         return XvBadAlloc;
1534 
1535     pPPriv->VideoOn = VIDEO_ON;
1536 
1537     return Success;
1538 }
1539 
1540 static int
Permedia2PutStill(ScrnInfoPtr pScrn,short vid_x,short vid_y,short drw_x,short drw_y,short vid_w,short vid_h,short drw_w,short drw_h,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1541 Permedia2PutStill(ScrnInfoPtr pScrn,
1542     short vid_x, short vid_y, short drw_x, short drw_y,
1543     short vid_w, short vid_h, short drw_w, short drw_h,
1544     RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1545 {
1546     PortPrivPtr pPPriv = (PortPrivPtr) data;
1547     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1548     GLINTPtr pGlint = GLINTPTR(pScrn);
1549     int sw, sh, r = Success;
1550 
1551     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1552 	"PutStill %d,%d,%d,%d -> %d,%d,%d,%d\n",
1553 	vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h));
1554 
1555     sw = InputVideoEncodings[pAPriv->VideoStd * 3].width;
1556     sh = InputVideoEncodings[pAPriv->VideoStd * 3].height;
1557 
1558     if ((vid_x + vid_w) > sw ||
1559         (vid_y + vid_h) > sh)
1560         return BadValue;
1561 
1562     pPPriv->VideoOn = VIDEO_OFF;
1563 
1564     pPPriv->vx = ((vid_x << 10) * pPPriv->fw) / sw;
1565     pPPriv->vy = ((vid_y << 10) * pPPriv->fh) / sh;
1566     pPPriv->vw = ((vid_w << 10) * pPPriv->fw) / sw;
1567     pPPriv->vh = ((vid_h << 10) * pPPriv->fh) / sh;
1568 
1569     pPPriv->dx = drw_x;
1570     pPPriv->dy = drw_y;
1571     pPPriv->dw = drw_w;
1572     pPPriv->dh = drw_h;
1573 
1574     pPPriv->FrameAcc = pAPriv->FramesPerSec;
1575 
1576     if (!StartVideoStream(pPPriv, clipBoxes))
1577         return XvBadAlloc;
1578 
1579     if (pAPriv->pm2p) {
1580 	/* Sleep, not busy wait, until the very next frame is ready.
1581 	   Accept memory requests and other window's update events
1582 	   in the meantime. */
1583 	for (pPPriv->VideoOn = VIDEO_ONE_SHOT; pPPriv->VideoOn;)
1584 	    if (!xvipcHandshake(pPPriv, OP_UPDATE, TRUE)) {
1585 		r = FALSE;
1586 		break;
1587 	    }
1588     } else {
1589         usleep(80000);
1590 
1591         PutYUV(pPPriv, (!pPPriv->pFBArea[1]) ?
1592             pPPriv->BufferBase[0] : pPPriv->BufferBase[1 -
1593 		GLINT_READ_REG(VSABase + VSVideoAddressIndex)], FORMAT_YUYV, 1, 0);
1594     }
1595 
1596     pPPriv->StopDelay = 125;
1597 
1598     return r;
1599 }
1600 
1601 static int
Permedia2GetVideo(ScrnInfoPtr pScrn,short vid_x,short vid_y,short drw_x,short drw_y,short vid_w,short vid_h,short drw_w,short drw_h,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1602 Permedia2GetVideo(ScrnInfoPtr pScrn,
1603     short vid_x, short vid_y, short drw_x, short drw_y,
1604     short vid_w, short vid_h, short drw_w, short drw_h,
1605     RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1606 {
1607     PortPrivPtr pPPriv = (PortPrivPtr) data;
1608     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1609     int sw, sh;
1610 
1611     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1612 	"GetVideo %d,%d,%d,%d <- %d,%d,%d,%d\n",
1613 	vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h));
1614 
1615     sw = InputVideoEncodings[pAPriv->VideoStd * 3].width;
1616     sh = InputVideoEncodings[pAPriv->VideoStd * 3].height;
1617 
1618     if ((vid_x + vid_w) > sw ||
1619         (vid_y + vid_h) > sh) {
1620         return BadValue;
1621     }
1622 
1623     pPPriv->VideoOn = VIDEO_OFF;
1624 
1625     pPPriv->vx = (vid_x * pPPriv->fw) / sw;
1626     pPPriv->vy = (vid_y * pPPriv->fh) / sh;
1627     pPPriv->vw = (vid_w * pPPriv->fw) / sw;
1628     pPPriv->vh = (vid_h * pPPriv->fh) / sh;
1629 
1630     pPPriv->dx = drw_x;
1631     pPPriv->dy = drw_y;
1632     pPPriv->dw = drw_w;
1633     pPPriv->dh = drw_h;
1634 
1635     pPPriv->FrameAcc = pAPriv->FramesPerSec;
1636 
1637     if (!StartVideoStream(pPPriv, clipBoxes)) {
1638         return XvBadAlloc;
1639     }
1640 
1641     GetYUV(pPPriv);
1642 
1643     pPPriv->VideoOn = VIDEO_ON;
1644 
1645     return Success;
1646 }
1647 
1648 static int
Permedia2GetStill(ScrnInfoPtr pScrn,short vid_x,short vid_y,short drw_x,short drw_y,short vid_w,short vid_h,short drw_w,short drw_h,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1649 Permedia2GetStill(ScrnInfoPtr pScrn,
1650     short vid_x, short vid_y, short drw_x, short drw_y,
1651     short vid_w, short vid_h, short drw_w, short drw_h,
1652     RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
1653 {
1654     PortPrivPtr pPPriv = (PortPrivPtr) data;
1655     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1656     int sw, sh;
1657 
1658     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1659 	"GetStill %d,%d,%d,%d <- %d,%d,%d,%d\n",
1660 	vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h));
1661 
1662     sw = InputVideoEncodings[pAPriv->VideoStd * 3].width;
1663     sh = InputVideoEncodings[pAPriv->VideoStd * 3].height;
1664 
1665     if ((vid_x + vid_w) > sw ||
1666         (vid_y + vid_h) > sh)
1667         return BadValue;
1668 
1669     pPPriv->VideoOn = VIDEO_OFF;
1670 
1671     pPPriv->vx = (vid_x * pPPriv->fw) / sw;
1672     pPPriv->vy = (vid_y * pPPriv->fh) / sh;
1673     pPPriv->vw = (vid_w * pPPriv->fw) / sw;
1674     pPPriv->vh = (vid_h * pPPriv->fh) / sh;
1675 
1676     pPPriv->dx = drw_x;
1677     pPPriv->dy = drw_y;
1678     pPPriv->dw = drw_w;
1679     pPPriv->dh = drw_h;
1680 
1681     pPPriv->FrameAcc = pAPriv->FramesPerSec;
1682 
1683     if (!StartVideoStream(pPPriv, clipBoxes))
1684         return XvBadAlloc;
1685 
1686     GetYUV(pPPriv);
1687 
1688     return Success;
1689 }
1690 
1691 static void
CopyYV12(CARD8 * Y,CARD32 * dst,int width,int height,int pitch)1692 CopyYV12(CARD8 *Y, CARD32 *dst, int width, int height, int pitch)
1693 {
1694     int Y_size = width * height;
1695     CARD8 *V = Y + Y_size;
1696     CARD8 *U = V + (Y_size >> 2);
1697     int pad = (pitch >> 2) - (width >> 1);
1698     int x;
1699 
1700     width >>= 1;
1701 
1702     for (height >>= 1; height > 0; height--) {
1703 	for (x = 0; x < width; Y += 2, x++)
1704 	    *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
1705 	dst += pad;
1706 	for (x = 0; x < width; Y += 2, x++)
1707 	    *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
1708 	dst += pad;
1709 	U += width;
1710 	V += width;
1711     }
1712 }
1713 
1714 #if X_BYTE_ORDER == X_BIG_ENDIAN
1715 
1716 static void
CopyYV12_16(CARD8 * Y,CARD32 * dst,int width,int height,int pitch)1717 CopyYV12_16(CARD8 *Y, CARD32 *dst, int width, int height, int pitch)
1718 {
1719     int Y_size = width * height;
1720     CARD8 *V = Y + Y_size;
1721     CARD8 *U = V + (Y_size >> 2);
1722     int pad = (pitch >> 2) - (width >> 1);
1723     int x;
1724 
1725     width >>= 1;
1726 
1727     for (height >>= 1; height > 0; height--) {
1728 	for (x = 0; x < width; Y += 2, x++)
1729 	    *dst++ = Y[1] + (V[x] << 8) + (Y[0] << 16) + (U[x] << 24);
1730 	dst += pad;
1731 	for (x = 0; x < width; Y += 2, x++)
1732 	    *dst++ = Y[1] + (V[x] << 8) + (Y[0] << 16) + (U[x] << 24);
1733 	dst += pad;
1734 	U += width;
1735 	V += width;
1736     }
1737 }
1738 
1739 static void
CopyYV12_8(CARD8 * Y,CARD32 * dst,int width,int height,int pitch)1740 CopyYV12_8(CARD8 *Y, CARD32 *dst, int width, int height, int pitch)
1741 {
1742     int Y_size = width * height;
1743     CARD8 *V = Y + Y_size;
1744     CARD8 *U = V + (Y_size >> 2);
1745     int pad = (pitch >> 2) - (width >> 1);
1746     int x;
1747 
1748     width >>= 1;
1749 
1750     for (height >>= 1; height > 0; height--) {
1751 	for (x = 0; x < width; Y += 2, x++)
1752 	    *dst++ = V[x] + (Y[1] << 8) + (U[x] << 16) + (Y[0] << 24);
1753 	dst += pad;
1754 	for (x = 0; x < width; Y += 2, x++)
1755 	    *dst++ = V[x] + (Y[1] << 8) + (U[x] << 16) + (Y[0] << 24);
1756 	dst += pad;
1757 	U += width;
1758 	V += width;
1759     }
1760 }
1761 
1762 #endif
1763 
1764 static void
CopyFlat(CARD8 * src,CARD8 * dst,int width,int height,int pitch)1765 CopyFlat(CARD8 *src, CARD8 *dst, int width, int height, int pitch)
1766 {
1767     if (width == pitch) {
1768 	memcpy(dst, src, width * height);
1769 	return;
1770     }
1771 
1772     while (height > 0) {
1773 	memcpy(dst, src, width);
1774 	dst += pitch;
1775 	src += width;
1776 	height--;
1777     }
1778 }
1779 
1780 static int
Permedia2PutImage(ScrnInfoPtr pScrn,short src_x,short src_y,short drw_x,short drw_y,short src_w,short src_h,short drw_w,short drw_h,int id,unsigned char * buf,short width,short height,Bool sync,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)1781 Permedia2PutImage(ScrnInfoPtr pScrn,
1782     short src_x, short src_y, short drw_x, short drw_y,
1783     short src_w, short src_h, short drw_w, short drw_h,
1784     int id, unsigned char *buf, short width, short height,
1785     Bool sync, RegionPtr clipBoxes, pointer data,
1786     DrawablePtr pDraw)
1787 {
1788     PortPrivPtr pPPriv = (PortPrivPtr) data;
1789     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1790     GLINTPtr pGlint = GLINTPTR(pScrn);
1791     int i;
1792 
1793     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1794 	"PutImage %d,%d,%d,%d -> %d,%d,%d,%d id=0x%08x buf=%p w=%d h=%d sync=%d\n",
1795 	src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h,
1796 	id, buf, width, height, sync));
1797 
1798     if ((src_x + src_w) > width ||
1799         (src_y + src_h) > height)
1800         return BadValue;
1801 
1802     pPPriv->vx = src_x << 10;
1803     pPPriv->vy = src_y << 10;
1804     pPPriv->vw = src_w << 10;
1805     pPPriv->vh = src_h << 10;
1806 
1807     pPPriv->dx = drw_x;
1808     pPPriv->dy = drw_y;
1809     pPPriv->dw = drw_w;
1810     pPPriv->dh = drw_h;
1811 
1812     if (!RemakePutCookies(pPPriv, clipBoxes))
1813 	return XvBadAlloc;
1814 
1815     if (pPPriv->BuffersAllocated <= 0 ||
1816 	id != pPPriv->Id || /* same bpp */
1817 	width != pPPriv->fw ||
1818 	height != pPPriv->fh)
1819     {
1820 	for (i = 0; i < ENTRIES(ScalerImages); i++)
1821 	    if (id == ScalerImages[i].id)
1822 		break;
1823 
1824 	if (i >= ENTRIES(ScalerImages))
1825 	    return XvBadAlloc;
1826 #if 0
1827 	if (pPPriv->BuffersAllocated <= 0 ||
1828 	    pPPriv->Bpp != ScalerImages[i].bits_per_pixel ||
1829 	    width > pPPriv->fw || height > pPPriv->fw ||
1830 	    pPPriv->fw * pPPriv->fh > width * height * 2)
1831 #else
1832 	if (1)
1833 #endif
1834 	{
1835 	    Permedia2Sync(pScrn);
1836 
1837 	    if (!AllocateBuffers(pPPriv, width, height,
1838 		(ScalerImages[i].bits_per_pixel + 7) >> 3, 1, 0)) {
1839 		pPPriv->Id = 0;
1840 		pPPriv->Bpp = 0;
1841 		pPPriv->fw = 0;
1842 		pPPriv->fh = 0;
1843 
1844 		return XvBadAlloc;
1845 	    }
1846 
1847 	    pPPriv->Id = id;
1848 	    pPPriv->Bpp = ScalerImages[i].bits_per_pixel;
1849 	    pPPriv->fw = width;
1850 	    pPPriv->fh = height;
1851 
1852 	    RemoveableBuffers(pPPriv, TRUE);
1853 	} else
1854 	    Permedia2Sync(pScrn);
1855     } else
1856 	Permedia2Sync(pScrn);
1857 
1858     switch (id) {
1859     case LE4CC('Y','V','1','2'):
1860 	switch(pGlint->HwBpp) {
1861 #if X_BYTE_ORDER == X_BIG_ENDIAN
1862 	case 8:
1863 	case 24:
1864 	    CopyYV12_8(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]),
1865 		width, height, pPPriv->BufferStride);
1866 	    break;
1867 	case 15:
1868 	case 16:
1869 	    CopyYV12_16(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]),
1870 		width, height, pPPriv->BufferStride);
1871 	    break;
1872 #endif
1873 	default:
1874 	    CopyYV12(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]),
1875 		width, height, pPPriv->BufferStride);
1876 	    break;
1877 	}
1878 	PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUYV, 1, 0);
1879 	break;
1880 
1881     case LE4CC('Y','U','Y','2'):
1882 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1883 	    width << 1, height, pPPriv->BufferStride);
1884 	PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUYV, 1, 0);
1885 	break;
1886 
1887     case LE4CC('U','Y','V','Y'):
1888 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1889 	    width << 1, height, pPPriv->BufferStride);
1890 	PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_UYVY, 1, 0);
1891 	break;
1892 
1893     case LE4CC('Y','U','V','A'):
1894 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1895 	    width << 2, height, pPPriv->BufferStride);
1896 	PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUVA, 2, pPPriv->Attribute[7]);
1897 	break;
1898 
1899     case LE4CC('V','U','Y','A'):
1900 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1901 	    width << 2, height, pPPriv->BufferStride);
1902 	PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_VUYA, 2, pPPriv->Attribute[7]);
1903 	break;
1904 
1905     case 0x41: /* RGBA 8:8:8:8 */
1906 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1907 	    width << 2, height, pPPriv->BufferStride);
1908 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB8888, 2, pPPriv->Attribute[7]);
1909 	break;
1910 
1911     case 0x42: /* RGB 5:6:5 */
1912 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1913 	    width << 1, height, pPPriv->BufferStride);
1914 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB565, 1, 0);
1915 	break;
1916 
1917     case 0x43: /* RGB 1:5:5:5 */
1918 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1919 	    width << 1, height, pPPriv->BufferStride);
1920 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB5551, 1, pPPriv->Attribute[7]);
1921 	break;
1922 
1923     case 0x44: /* RGB 4:4:4:4 */
1924 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1925 	    width << 1, height, pPPriv->BufferStride);
1926 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB4444, 1, pPPriv->Attribute[7]);
1927 	break;
1928 
1929     case 0x45: /* RGB 1:2:3:2 */
1930 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1931 	    width, height, pPPriv->BufferStride);
1932 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB2321, 0, pPPriv->Attribute[7]);
1933 	break;
1934 
1935     case 0x46: /* RGB 2:3:3 */
1936 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1937 	    width, height, pPPriv->BufferStride);
1938 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB332, 0, 0);
1939 	break;
1940 
1941     case 0x47: /* BGRA 8:8:8:8 */
1942 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1943 	    width << 2, height, pPPriv->BufferStride);
1944 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR8888, 2, pPPriv->Attribute[7]);
1945 	break;
1946 
1947     case 0x48: /* BGR 5:6:5 */
1948 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1949 	    width << 1, height, pPPriv->BufferStride);
1950 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR565, 1, 0);
1951 	break;
1952 
1953     case 0x49: /* BGR 1:5:5:5 */
1954 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1955 	    width << 1, height, pPPriv->BufferStride);
1956 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR5551, 1, pPPriv->Attribute[7]);
1957 	break;
1958 
1959     case 0x4A: /* BGR 4:4:4:4 */
1960 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1961 	    width << 1, height, pPPriv->BufferStride);
1962 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR4444, 1, pPPriv->Attribute[7]);
1963 	break;
1964 
1965     case 0x4B: /* BGR 1:2:3:2 */
1966 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1967 	    width << 0, height, pPPriv->BufferStride);
1968 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR2321, 0, pPPriv->Attribute[7]);
1969 	break;
1970 
1971     case 0x4C: /* BGR 2:3:3 */
1972 	CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0],
1973 	    width << 0, height, pPPriv->BufferStride);
1974 	PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR332, 0, 0);
1975 	break;
1976 
1977     default:
1978 	return XvBadAlloc;
1979     }
1980 
1981     pPPriv->StopDelay = pAPriv->Delay;
1982 
1983     if (!pAPriv->TimerUsers) {
1984 	pAPriv->TimerUsers |= 1 << PORTNUM(pPPriv);
1985 	TimerSet(pAPriv->Timer, 0, 80, TimerCallback, pAPriv);
1986     }
1987 
1988     if (sync) /* sched_yield? */
1989 	Permedia2Sync(pScrn);
1990 
1991     return Success;
1992 }
1993 
1994 static void
Permedia2StopVideo(ScrnInfoPtr pScrn,pointer data,Bool shutdown)1995 Permedia2StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
1996 {
1997     PortPrivPtr pPPriv = (PortPrivPtr) data;
1998     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
1999     GLINTPtr pGlint = GLINTPTR(pScrn);
2000 
2001     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
2002 	"StopVideo port=%d, shutdown=%d\n", PORTNUM(pPPriv), shutdown));
2003 
2004     if (shutdown) {
2005 	if (PORTNUM(pPPriv) < 2) {
2006 	    StopVideoStream(pPPriv, TRUE);
2007 	    RestoreVideoStd(pAPriv);
2008 	} else {
2009 	    FreeBuffers(pPPriv);
2010 	    FreeCookies(pPPriv);
2011 	    if (pAPriv->TimerUsers) {
2012 		pAPriv->TimerUsers &= ~PORTNUM(pPPriv);
2013 		if (!pAPriv->TimerUsers)
2014 		    TimerCancel(pAPriv->Timer);
2015 	    }
2016 	}
2017     } else {
2018 	pPPriv->VideoOn = VIDEO_OFF;
2019 	pPPriv->StopDelay = 750; /* appx. 30 sec */
2020 
2021 	if (pGlint->NoAccel)
2022 	    Permedia2Sync(pScrn);
2023     }
2024 }
2025 
2026 static void
RestartVideo(PortPrivPtr pPPriv,int old_VideoOn)2027 RestartVideo(PortPrivPtr pPPriv, int old_VideoOn)
2028 {
2029     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
2030     int new_fh;
2031 
2032     if (pPPriv->VideoOn > VIDEO_OFF ||
2033 	pAPriv->VideoStd < 0 /* invalid */)
2034 	return;
2035 
2036     new_fh = InputVideoEncodings[pAPriv->VideoStd * 3].height >>
2037 	(1 - (pPPriv->Attribute[4] & 1));
2038 
2039     if (new_fh != pPPriv->fh) {
2040 	pPPriv->vy = (pPPriv->vy * new_fh) / pPPriv->fh;
2041 	pPPriv->vh = (pPPriv->vh * new_fh) / pPPriv->fh;
2042 
2043 	pPPriv->fh = new_fh;
2044     }
2045 
2046     if (old_VideoOn) {
2047 	if (StartVideoStream(pPPriv, NULL)) {
2048 	    pPPriv->VideoOn = old_VideoOn;
2049 
2050 	    if (pPPriv == &pAPriv->Port[1])
2051 		GetYUV(pPPriv);
2052 	} else {
2053 	    DEBUG(xf86DrvMsgVerb(pAPriv->pScrn->scrnIndex, X_INFO, 4,
2054 		"RestartVideo port=%d suspend\n", PORTNUM(pPPriv)));
2055 	    pPPriv->VideoOn = -old_VideoOn; /* suspend (not off) */
2056 	}
2057     }
2058 }
2059 
2060 static int
Permedia2SetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value,pointer data)2061 Permedia2SetPortAttribute(ScrnInfoPtr pScrn,
2062     Atom attribute, INT32 value, pointer data)
2063 {
2064     PortPrivPtr pPPriv = (PortPrivPtr) data;
2065     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
2066     int old_VideoStd, old_Plug;
2067     int VideoStd = -1, Plug = 0;
2068     int r;
2069 
2070     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
2071 	"SPA attr=%d val=%d port=%d\n",
2072 	attribute, value, PORTNUM(pPPriv)));
2073 
2074     if (attribute == xvFilter) {
2075 	pPPriv->Attribute[5] = !!value;
2076 	return Success;
2077     } else if (attribute == xvAlpha) {
2078 	pPPriv->Attribute[7] = !!value;
2079 	return Success;
2080     }
2081 
2082     if (PORTNUM(pPPriv) >= 2)
2083 	return BadMatch;
2084 
2085     if (attribute == xvInterlace) {
2086 	int old_value = pPPriv->Attribute[4];
2087 
2088 	value %= 3;
2089 
2090 	if (value != old_value) {
2091 	    int old_VideoOn = ABS(pPPriv->VideoOn);
2092 #if 0
2093 	    if (old_VideoOn)
2094 		return XvBadAlloc;
2095 #endif
2096 	    StopVideoStream(pPPriv, FALSE);
2097 	    FreeBuffers(pPPriv);
2098 	    pPPriv->Attribute[4] = value;
2099 	    RestartVideo(pPPriv, old_VideoOn);
2100 
2101 	    if (pPPriv->VideoOn < 0 /* suspended */) {
2102 		pPPriv->Attribute[4] = old_value;
2103 		RestartVideo(pPPriv, old_VideoOn);
2104 		return XvBadAlloc;
2105 	    }
2106 	}
2107 
2108 	return Success;
2109     }
2110 
2111     if (pPPriv == &pAPriv->Port[0]) {
2112 	/*
2113 	 *  Input
2114 	 */
2115 	if (attribute == xvEncoding) {
2116 	    if (value < 0 || value > ENTRIES(InputVideoEncodings))
2117 		return XvBadEncoding;
2118 
2119 	    VideoStd = value / 3;
2120 	    Plug = value % 3;
2121 
2122 	    /* Fall through */
2123 
2124 	} else if (attribute == xvBrightness)
2125 	    return SetAttr(&pAPriv->Port[0], 0, value);
2126 	else if (attribute == xvContrast)
2127 	    return SetAttr(&pAPriv->Port[0], 1, value);
2128    	else if (attribute == xvSaturation)
2129 	    return SetAttr(&pAPriv->Port[0], 2, value);
2130 	else if (attribute == xvHue)
2131 	    return SetAttr(&pAPriv->Port[0], 3, value);
2132     } else {
2133 	/*
2134 	 *  Output
2135 	 */
2136 	if (attribute == xvEncoding) {
2137 	    if (value < 0 || value > ENTRIES(OutputVideoEncodings))
2138 		return XvBadEncoding;
2139 
2140 	    VideoStd = value / 2;
2141 	    Plug = (value % 2) + 1;
2142 
2143 	    /* Fall through */
2144 
2145 	} else if (attribute == xvBkgColor)
2146 	    return SetBkgCol(pPPriv, value);
2147 #if 1
2148 	else if (attribute == xvBrightness ||
2149 		 attribute == xvContrast ||
2150 		 attribute == xvSaturation ||
2151 		 attribute == xvHue)
2152 	    return Success;
2153 #endif
2154     }
2155 
2156     if (attribute != xvEncoding)
2157 	return BadMatch;
2158 
2159     old_VideoStd = pAPriv->VideoStd;
2160     old_Plug = pPPriv->Plug;
2161 
2162 #if 0
2163     if (pAPriv->Port[0].VideoOn ||
2164 	pAPriv->Port[1].VideoOn)
2165 	return XvBadAlloc;
2166 #endif
2167 
2168     if (Plug != old_Plug)
2169 	if ((r = SetPlug(pPPriv, Plug)) != Success)
2170 	    return r;
2171 
2172     if (VideoStd != old_VideoStd) {
2173 	int old_VideoOn0 = ABS(pAPriv->Port[0].VideoOn);
2174 	int old_VideoOn1 = ABS(pAPriv->Port[1].VideoOn);
2175 
2176 	StopVideoStream(&pAPriv->Port[0], FALSE);
2177 	StopVideoStream(&pAPriv->Port[1], FALSE);
2178 
2179 	if (VideoStd == NTSC || pAPriv->VideoStd == NTSC) {
2180 	    FreeBuffers(&pAPriv->Port[0]);
2181 	    FreeBuffers(&pAPriv->Port[1]);
2182 	}
2183 
2184 	if (SetVideoStd(pPPriv, VideoStd) == Success) {
2185 	    RestartVideo(&pAPriv->Port[0], old_VideoOn0);
2186 	    RestartVideo(&pAPriv->Port[1], old_VideoOn1);
2187 	}
2188 
2189 	if (pAPriv->Port[0].VideoOn < 0 ||
2190 	    pAPriv->Port[1].VideoOn < 0 ||
2191 	    VideoStd != pAPriv->VideoStd) {
2192 	    if (SetVideoStd(pPPriv, old_VideoStd) == Success) {
2193 		RestartVideo(&pAPriv->Port[0], old_VideoOn0);
2194 		RestartVideo(&pAPriv->Port[1], old_VideoOn1);
2195 	    }
2196 
2197 	    if (Plug != old_Plug)
2198 		SetPlug(pPPriv, old_Plug);
2199 
2200 	    return XvBadAlloc;
2201 	}
2202     }
2203 
2204     return Success;
2205 }
2206 
2207 static void
RestoreVideoStd(AdaptorPrivPtr pAPriv)2208 RestoreVideoStd(AdaptorPrivPtr pAPriv)
2209 {
2210     if (pAPriv->Port[0].VideoOn && !pAPriv->Port[1].VideoOn &&
2211 	pAPriv->Port[0].VideoStdReq != pAPriv->VideoStd)
2212 	Permedia2SetPortAttribute(pAPriv->pScrn, xvEncoding,
2213 	    pAPriv->Port[0].VideoStdReq * 3 + pAPriv->Port[0].Plug,
2214 	    (pointer) &pAPriv->Port[0]);
2215     else
2216     if (pAPriv->Port[1].VideoOn && !pAPriv->Port[0].VideoOn &&
2217 	pAPriv->Port[1].VideoStdReq != pAPriv->VideoStd)
2218 	Permedia2SetPortAttribute(pAPriv->pScrn, xvEncoding,
2219 	    pAPriv->Port[2].VideoStdReq * 2 + pAPriv->Port[1].Plug - 1,
2220 	    (pointer) &pAPriv->Port[1]);
2221 }
2222 
2223 static int
Permedia2GetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)2224 Permedia2GetPortAttribute(ScrnInfoPtr pScrn,
2225     Atom attribute, INT32 *value, pointer data)
2226 {
2227     PortPrivPtr pPPriv = (PortPrivPtr) data;
2228     AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
2229 
2230     if (PORTNUM(pPPriv) >= 2 &&
2231 	attribute != xvFilter &&
2232 	attribute != xvAlpha)
2233 	return BadMatch;
2234 
2235     if (attribute == xvEncoding) {
2236 	if (pAPriv->VideoStd < 0)
2237 	    return XvBadAlloc;
2238 	else
2239 	    if (pPPriv == &pAPriv->Port[0])
2240 		*value = pAPriv->VideoStd * 3 + pPPriv->Plug;
2241 	    else
2242 		*value = pAPriv->VideoStd * 2 + pPPriv->Plug - 1;
2243     } else if (attribute == xvBrightness)
2244 	*value = pPPriv->Attribute[0];
2245     else if (attribute == xvContrast)
2246 	*value = pPPriv->Attribute[1];
2247     else if (attribute == xvSaturation)
2248 	*value = pPPriv->Attribute[2];
2249     else if (attribute == xvHue)
2250 	*value = pPPriv->Attribute[3];
2251     else if (attribute == xvInterlace)
2252 	*value = pPPriv->Attribute[4];
2253     else if (attribute == xvFilter)
2254 	*value = pPPriv->Attribute[5];
2255     else if (attribute == xvBkgColor)
2256 	*value = pPPriv->Attribute[6];
2257     else if (attribute == xvAlpha)
2258 	*value = pPPriv->Attribute[7];
2259     else
2260 	return BadMatch;
2261 
2262     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
2263 	"GPA attr=%d val=%d port=%d\n",
2264 	attribute, *value, PORTNUM(pPPriv)));
2265 
2266     return Success;
2267 }
2268 
2269 static void
Permedia2QueryBestSize(ScrnInfoPtr pScrn,Bool motion,short vid_w,short vid_h,short drw_w,short drw_h,unsigned int * p_w,unsigned int * p_h,pointer data)2270 Permedia2QueryBestSize(ScrnInfoPtr pScrn, Bool motion,
2271     short vid_w, short vid_h, short drw_w, short drw_h,
2272     unsigned int *p_w, unsigned int *p_h, pointer data)
2273 {
2274     *p_w = drw_w;
2275     *p_h = drw_h;
2276 }
2277 
2278 static int
Permedia2QueryImageAttributes(ScrnInfoPtr pScrn,int id,unsigned short * width,unsigned short * height,int * pitches,int * offsets)2279 Permedia2QueryImageAttributes(ScrnInfoPtr pScrn,
2280     int id, unsigned short *width, unsigned short *height,
2281     int *pitches, int *offsets)
2282 {
2283     int i, pitch;
2284 
2285     *width = CLAMP(*width, 1, 2047);
2286     *height = CLAMP(*height, 1, 2047);
2287 
2288     if (offsets)
2289 	offsets[0] = 0;
2290 
2291     switch (id) {
2292     case LE4CC('Y','V','1','2'): /* Planar YVU 4:2:0 (emulated) */
2293 	*width = CLAMP((*width + 1) & ~1, 2, 2046);
2294 	*height = CLAMP((*height + 1) & ~1, 2, 2046);
2295 
2296 	pitch = *width; /* luma component */
2297 
2298 	if (offsets) {
2299 	    offsets[1] = pitch * *height;
2300 	    offsets[2] = offsets[1] + (offsets[1] >> 2);
2301 	}
2302 
2303 	if (pitches) {
2304 	    pitches[0] = pitch;
2305 	    pitches[1] = pitches[2] = pitch >> 1;
2306 	}
2307 
2308 	return pitch * *height * 3 / 2;
2309 
2310     case LE4CC('Y','U','Y','2'): /* Packed YUYV 4:2:2 */
2311     case LE4CC('U','Y','V','Y'): /* Packed UYVY 4:2:2 */
2312 	*width = CLAMP((*width + 1) & ~1, 2, 2046);
2313 
2314 	pitch = *width * 2;
2315 
2316 	if (pitches)
2317 	    pitches[0] = pitch;
2318 
2319 	return pitch * *height;
2320 
2321     default:
2322 	for (i = 0; i < ENTRIES(ScalerImages); i++)
2323 	    if (ScalerImages[i].id == id)
2324 		break;
2325 
2326 	if (i >= ENTRIES(ScalerImages))
2327 	    break;
2328 
2329 	pitch = *width * (ScalerImages[i].bits_per_pixel >> 3);
2330 
2331 	if (pitches)
2332 	    pitches[0] = pitch;
2333 
2334 	return pitch * *height;
2335     }
2336 
2337     return 0;
2338 }
2339 
2340 static void
RestoreVideo(AdaptorPrivPtr pAPriv)2341 RestoreVideo(AdaptorPrivPtr pAPriv)
2342 {
2343     GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn);
2344 
2345     GLINT_WRITE_REG(pAPriv->dFifoControl, PMFifoControl);
2346     GLINT_WRITE_REG(0, VSABase + VSControl);
2347     GLINT_WRITE_REG(0, VSBBase + VSControl);
2348     usleep(160000);
2349     GLINT_MASK_WRITE_REG(VS_UnitMode_ROM, ~VS_UnitMode_Mask, VSConfiguration);
2350 }
2351 
2352 static void
InitializeVideo(AdaptorPrivPtr pAPriv)2353 InitializeVideo(AdaptorPrivPtr pAPriv)
2354 {
2355     GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn);
2356     int i;
2357 
2358     GLINT_WRITE_REG(0, VSABase + VSControl);
2359     GLINT_WRITE_REG(0, VSBBase + VSControl);
2360 
2361 #if 0
2362     GLINT_MASK_WRITE_REG(0, ~(VSAIntFlag | VSBIntFlag), IntEnable);
2363     GLINT_WRITE_REG(VSAIntFlag | VSBIntFlag, IntFlags); /* Reset */
2364 #endif
2365 
2366     for (i = 0x0018; i <= 0x00B0; i += 8) {
2367         GLINT_WRITE_REG(0, VSABase + i);
2368         GLINT_WRITE_REG(0, VSBBase + i);
2369     }
2370 
2371     GLINT_WRITE_REG((0 << 8) | (132 << 0), VSABase + VSFifoControl);
2372     GLINT_WRITE_REG((0 << 8) | (132 << 0), VSBBase + VSFifoControl);
2373 
2374     GLINT_MASK_WRITE_REG(
2375         VS_UnitMode_AB8 |
2376         VS_GPBusMode_A |
2377      /* VS_HRefPolarityA | */
2378         VS_VRefPolarityA |
2379         VS_VActivePolarityA |
2380      /* VS_UseFieldA | */
2381         VS_FieldPolarityA |
2382      /* VS_FieldEdgeA | */
2383      /* VS_VActiveVBIA | */
2384 	VS_InterlaceA |
2385 	VS_ReverseDataA |
2386 
2387      /* VS_HRefPolarityB | */
2388         VS_VRefPolarityB |
2389         VS_VActivePolarityB |
2390      /* VS_UseFieldB | */
2391         VS_FieldPolarityB |
2392      /* VS_FieldEdgeB | */
2393      /* VS_VActiveVBIB | */
2394         VS_InterlaceB |
2395      /* VS_ColorSpaceB_RGB | */
2396      /* VS_ReverseDataB | */
2397      /* VS_DoubleEdgeB | */
2398         0, ~0x1FFFFE0F, VSConfiguration);
2399 
2400     pAPriv->dFifoControl = GLINT_READ_REG(PMFifoControl);
2401     GLINT_WRITE_REG((12 << 8) | 8, PMFifoControl);
2402 }
2403 
2404 static Bool
xvipcHandshake(PortPrivPtr pPPriv,int op,Bool block)2405 xvipcHandshake(PortPrivPtr pPPriv, int op, Bool block)
2406 {
2407     int r;
2408     int brake = 150;
2409 
2410     xvipc.magic = XVIPC_MAGIC;
2411     xvipc.op = op;
2412     xvipc.block = block;
2413 
2414     if (pPPriv) {
2415 	AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;
2416 
2417 	xvipc.pm2p = pAPriv->pm2p;
2418 	xvipc.pAPriv = pAPriv;
2419 	xvipc.port = PORTNUM(pPPriv);
2420     } else {
2421 	xvipc.pm2p = (void *) -1;
2422 	xvipc.pAPriv = NULL;
2423 	xvipc.port = -1;
2424     }
2425 
2426     for (;;) {
2427 	if (brake-- <= 0)
2428 	    return FALSE; /* I brake for bugs. */
2429 
2430 	DEBUG(xf86MsgVerb(X_INFO, 4,
2431 	    "PM2 XVIPC send op=%d bl=%d po=%d a=%d b=%d c=%d\n",
2432 	    xvipc.op, xvipc.block, xvipc.port, xvipc.a, xvipc.b, xvipc.c));
2433 
2434 	r = ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc);
2435 
2436 	DEBUG(xf86MsgVerb(X_INFO, 4,
2437 	    "PM2 XVIPC recv op=%d bl=%d po=%d a=%d b=%d c=%d err=%d/%d\n",
2438 	    xvipc.op, xvipc.block, xvipc.port, xvipc.a, xvipc.b, xvipc.c, r, errno));
2439 
2440 	switch (xvipc.op) {
2441 	case OP_ALLOC:
2442 	{
2443 	    AdaptorPrivPtr pAPriv = xvipc.pAPriv;
2444 	    ScrnInfoPtr pScrn = pAPriv->pScrn;
2445 	    GLINTPtr pGlint = GLINTPTR(pScrn);
2446 	    FBAreaPtr pFBArea = NULL;
2447 	    LFBAreaPtr pLFBArea;
2448 
2449 	    xvipc.a = -1;
2450 
2451 	    pLFBArea = malloc(sizeof(LFBAreaRec));
2452 
2453 	    if (pLFBArea) {
2454 		pLFBArea->pFBArea = pFBArea =
2455 		    xf86AllocateLinearOffscreenArea(pScrn->pScreen,
2456 		        xvipc.b >> BPPSHIFT(pGlint), 2, NULL, NULL, NULL);
2457 
2458 		if (pFBArea) {
2459 		    /* xvipc.a = pFBArea->linear; */
2460 		    pLFBArea->Linear = xvipc.a =
2461 			((pFBArea->box.y1 * pScrn->displayWidth) +
2462 			    pFBArea->box.x1) << BPPSHIFT(pGlint);
2463 		} else
2464 		    free(pLFBArea);
2465 	    }
2466 
2467 	    /* Report results */
2468 
2469 	    if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) != 0)
2470 		if (pFBArea) {
2471 		    xf86FreeOffscreenArea(pFBArea);
2472 		    free(pLFBArea);
2473 		    pFBArea = NULL;
2474 		}
2475 
2476 	    if (pFBArea) {
2477 		pLFBArea->Next = pAPriv->LFBList;
2478 		pAPriv->LFBList = pLFBArea;
2479 	    }
2480 
2481 	    DEBUG(xf86MsgVerb(X_INFO, 3, "PM2 XVIPC alloc addr=%d=0x%08x pFB=%p\n",
2482 		xvipc.a, xvipc.a, pFBArea));
2483 
2484 	    goto event;
2485 	}
2486 
2487 	case OP_FREE:
2488 	{
2489 	    AdaptorPrivPtr pAPriv = xvipc.pAPriv;
2490 	    LFBAreaPtr pLFBArea, *ppLFBArea;
2491 
2492 	    for (ppLFBArea = &pAPriv->LFBList; (pLFBArea = *ppLFBArea);
2493 		ppLFBArea = &pLFBArea->Next)
2494 		if (pLFBArea->Linear == xvipc.a)
2495 		    break;
2496 
2497 	    if (!pLFBArea)
2498 		xvipc.a = -1;
2499 
2500 	    DEBUG(xf86MsgVerb(X_INFO, 3, "PM2 XVIPC free addr=%d=0x%08x pFB=%p\n",
2501 		xvipc.a, xvipc.a, pLFBArea ? pLFBArea->pFBArea : NULL));
2502 
2503 	    if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) == 0 && pLFBArea) {
2504 		xf86FreeOffscreenArea(pLFBArea->pFBArea);
2505 		*ppLFBArea = pLFBArea->Next;
2506 		free(pLFBArea);
2507 	    }
2508 
2509 	    goto event;
2510 	}
2511 
2512 	case OP_UPDATE:
2513 	{
2514 	    AdaptorPrivPtr pAPriv = xvipc.pAPriv;
2515 	    PortPrivPtr pPPriv;
2516 
2517 	    pPPriv = &pAPriv->Port[0];
2518 
2519 	    if (pPPriv->VideoOn > VIDEO_OFF && xvipc.a > 0) {
2520 	        pPPriv->FrameAcc += pPPriv->FramesPerSec;
2521 	        if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) {
2522 		    pPPriv->FrameAcc -= pAPriv->FramesPerSec;
2523 
2524 		    /* Asynchronous resizing caused by kernel app */
2525 
2526 		    if (xvipc.c != pPPriv->fw ||
2527 		        xvipc.d != pPPriv->fh) {
2528 			pPPriv->vx = (pPPriv->vx * xvipc.c) / pPPriv->fw;
2529 			pPPriv->vw = (pPPriv->vw * xvipc.c) / pPPriv->fw;
2530 			pPPriv->vy = (pPPriv->vy * xvipc.d) / pPPriv->fh;
2531 			pPPriv->vh = (pPPriv->vh * xvipc.d) / pPPriv->fh;
2532 
2533 			pPPriv->fw = xvipc.c;
2534 			pPPriv->fh = xvipc.d;
2535 			pPPriv->BufferPProd = xvipc.e;
2536 
2537 			RemakePutCookies(pPPriv, NULL);
2538 		    }
2539 
2540 		    PutYUV(pPPriv, xvipc.a, FORMAT_YUYV, 1, 0);
2541 
2542 		    if (pPPriv->VideoOn == VIDEO_ONE_SHOT)
2543 			pPPriv->VideoOn = VIDEO_OFF;
2544 		}
2545 	    } else
2546 		if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) {
2547 		    StopVideoStream(pPPriv, TRUE);
2548 		    RestoreVideoStd(pAPriv);
2549 		}
2550 
2551 	    pPPriv = &pAPriv->Port[1];
2552 
2553 	    if (pPPriv->VideoOn > VIDEO_OFF && xvipc.b > 0) {
2554 	        pPPriv->FrameAcc += pPPriv->FramesPerSec;
2555 		if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) {
2556 		    pPPriv->FrameAcc -= pAPriv->FramesPerSec;
2557 
2558 		    pPPriv->BufferBase[0] = xvipc.b;
2559 
2560 		    /* Output is always exclusive, no async resizing */
2561 
2562 		    GetYUV(pPPriv);
2563 
2564 		    if (pPPriv->VideoOn == VIDEO_ONE_SHOT)
2565 			pPPriv->VideoOn = VIDEO_OFF;
2566 		}
2567 	    } else
2568 		if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) {
2569 		    StopVideoStream(pPPriv, TRUE);
2570 		    RestoreVideoStd(pAPriv);
2571 		}
2572 
2573 	    /* Fall through */
2574 	}
2575 
2576 	default:
2577 	event:
2578 	    if (xvipc.op == op)
2579 		return r == 0;
2580 
2581 	    xvipc.op = OP_EVENT;
2582 	    xvipc.block = block;
2583 	}
2584     }
2585 
2586     return TRUE;
2587 }
2588 
2589 static void
Permedia2ReadInput(int fd,pointer unused)2590 Permedia2ReadInput(int fd, pointer unused)
2591 {
2592     xvipcHandshake(NULL, OP_EVENT, FALSE);
2593 }
2594 
2595 static Bool
xvipcOpen(const char * name,ScrnInfoPtr pScrn)2596 xvipcOpen(const char *name, ScrnInfoPtr pScrn)
2597 {
2598     const char *osname;
2599 
2600     if (xvipc_fd >= 0)
2601 	return TRUE;
2602 
2603     xf86GetOS(&osname, NULL, NULL, NULL);
2604 
2605     if (!osname || strcmp(osname, "linux"))
2606 	return FALSE;
2607 
2608     for (;;) {
2609 	DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
2610 	    "XVIPC probing device %s\n", name));
2611 
2612     	if ((xvipc_fd = open(name, O_RDWR /* | O_TRUNC */, 0)) < 0)
2613 	    break;
2614 
2615 	xvipc.magic = XVIPC_MAGIC;
2616 	xvipc.pm2p = (void *) -1;
2617 	xvipc.pAPriv = NULL;
2618 	xvipc.op = OP_CONNECT;
2619 	xvipc.a = 0;
2620 	xvipc.b = 0;
2621 	xvipc.c = 0;
2622 	xvipc.d = 0;
2623 
2624 	if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) < 0 || xvipc.pm2p)
2625 	    break;
2626 
2627 	if (xvipc.c != XVIPC_VERSION) {
2628 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2629 		       "Your Permedia 2 kernel driver %d.%d uses XVIPC protocol "
2630 		       "V.%d while this Xv driver expects V.%d. Please update.\n",
2631 		       xvipc.a, xvipc.b, xvipc.c, XVIPC_VERSION);
2632 	    break;
2633 	}
2634 
2635 	xf86AddInputHandler(xvipc_fd, Permedia2ReadInput, NULL);
2636 
2637 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv driver opened %s\n", name);
2638 
2639 	return TRUE;
2640     }
2641 
2642     if (xvipc_fd >= 0)
2643 	close(xvipc_fd);
2644 
2645     xvipc_fd = -1;
2646 
2647     xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cannot find Permedia 2 kernel driver.\n");
2648 
2649     return FALSE;
2650 }
2651 
2652 static void
DeleteAdaptorPriv(AdaptorPrivPtr pAPriv)2653 DeleteAdaptorPriv(AdaptorPrivPtr pAPriv)
2654 {
2655     int i;
2656 
2657     if (pAPriv->VideoIO) {
2658 	StopVideoStream(&pAPriv->Port[0], TRUE);
2659 	StopVideoStream(&pAPriv->Port[1], TRUE);
2660     }
2661 
2662     for (i = 0; i < 6; i++) {
2663         FreeBuffers(&pAPriv->Port[i]);
2664 	FreeCookies(&pAPriv->Port[i]);
2665     }
2666 
2667     TimerFree(pAPriv->Timer);
2668 
2669     if (pAPriv->VideoIO) {
2670 	if (pAPriv->pm2p)
2671 	    xvipcHandshake(&pAPriv->Port[0], OP_DISCONNECT, TRUE);
2672 	else {
2673 	    xf86DestroyI2CDevRec(&pAPriv->Port[0].I2CDev, FALSE);
2674 	    xf86DestroyI2CDevRec(&pAPriv->Port[1].I2CDev, FALSE);
2675 
2676 	    RestoreVideo(pAPriv);
2677 	}
2678     }
2679 
2680     free(pAPriv);
2681 }
2682 
2683 static AdaptorPrivPtr
NewAdaptorPriv(ScrnInfoPtr pScrn,Bool VideoIO)2684 NewAdaptorPriv(ScrnInfoPtr pScrn, Bool VideoIO)
2685 {
2686     GLINTPtr pGlint = GLINTPTR(pScrn);
2687     AdaptorPrivPtr pAPriv = (AdaptorPrivPtr) calloc(1, sizeof(AdaptorPrivRec));
2688     int i;
2689 
2690     if (!pAPriv)
2691 	return NULL;
2692 
2693     pAPriv->pScrn = pScrn;
2694 
2695     for (i = 0; i < PORTS; i++)
2696 	pAPriv->Port[i].pAdaptor = pAPriv;
2697 
2698     switch (pScrn->depth) {
2699     case 8:
2700         pAPriv->dDitherMode =
2701 	    (0 << 10) |			/* BGR */
2702 	    (1 << 1) |			/* Dither */
2703 	    ((5 & 0x10) << 12) |
2704 	    ((5 & 0x0F) << 2) |		/* 3:3:2f */
2705 	    UNIT_ENABLE;
2706         pAPriv->dAlphaBlendMode =
2707 	    (0 << 13) |
2708 	    ((5 & 0x10) << 12) |
2709 	    ((5 & 0x0F) << 8) |
2710 	    (84 << 1) |			/* Blend (decal) RGB */
2711 	    UNIT_ENABLE;
2712 	pAPriv->dTextureDataFormat =
2713 	    (1 << 4) |			/* No alpha */
2714 	    ((14 & 0x10) << 2) |
2715 	    ((14 & 0x0F) << 0);		/* CI8 */
2716 	break;
2717 
2718     case 15:
2719         pAPriv->dDitherMode =
2720 	    (1 << 10) |			/* RGB */
2721 	    ((1 & 0x10) << 12) |
2722 	    ((1 & 0x0F) << 2) |		/* 5:5:5:1f */
2723 	    UNIT_ENABLE;
2724         pAPriv->dAlphaBlendMode =
2725 	    (1 << 13) |
2726 	    ((1 & 0x10) << 12) |
2727 	    ((1 & 0x0F) << 8) |
2728 	    (84 << 1) |
2729 	    UNIT_ENABLE;
2730 	pAPriv->dTextureDataFormat =
2731     	    (1 << 5) |			/* RGB */
2732 	    (1 << 4) |
2733 	    ((1 & 0x10) << 2) |
2734 	    ((1 & 0x0F) << 0);
2735 	break;
2736 
2737     case 16:
2738         pAPriv->dDitherMode =
2739 	    (1 << 10) |			/* RGB */
2740 	    ((16 & 0x10) << 12) |
2741 	    ((16 & 0x0F) << 2) |	/* 5:6:5f */
2742 	    UNIT_ENABLE;
2743         pAPriv->dAlphaBlendMode =
2744 	    (1 << 13) |
2745 	    ((16 & 0x10) << 12) |
2746 	    ((16 & 0x0F) << 8) |
2747 	    (84 << 1) |
2748 	    UNIT_ENABLE;
2749 	pAPriv->dTextureDataFormat =
2750 	    (1 << 5) |
2751 	    (1 << 4) |
2752 	    ((16 & 0x10) << 2) |
2753 	    ((16 & 0x0F) << 0);
2754 	break;
2755 
2756     case 24:
2757         pAPriv->dDitherMode =
2758 	    (1 << 10) |			/* RGB */
2759 	    ((0 & 0x10) << 12) |
2760 	    ((0 & 0x0F) << 2) |		/* 8:8:8:8 */
2761 	    UNIT_ENABLE;
2762         pAPriv->dAlphaBlendMode =
2763 	    (1 << 13) |
2764 	    ((0 & 0x10) << 12) |
2765 	    ((0 & 0x0F) << 8) |
2766 	    (84 << 1) |
2767 	    UNIT_ENABLE;
2768 	pAPriv->dTextureDataFormat =
2769 	    (1 << 5) |
2770 	    (1 << 4) |
2771 	    ((0 & 0x10) << 2) |
2772 	    ((0 & 0x0F) << 0);
2773 	break;
2774 
2775     default:
2776 	free(pAPriv);
2777 	return NULL;
2778     }
2779 
2780     pAPriv->VideoIO = VideoIO;
2781 
2782     if (VideoIO) {
2783 	if (xvipc_fd >= 0) {
2784 	    /* Initial handshake, take over control of this head */
2785 
2786 	    xvipc.magic = XVIPC_MAGIC;
2787 	    xvipc.pm2p = (void *) -1;		/* Kernel head ID */
2788 	    xvipc.pAPriv = pAPriv;		/* Server head ID */
2789 	    xvipc.op = OP_CONNECT;
2790 
2791 	    xvipc.a = PCI_DEV_BUS(pGlint->PciInfo);
2792 	    xvipc.b = PCI_DEV_DEV(pGlint->PciInfo);
2793 	    xvipc.c = PCI_DEV_FUNC(pGlint->PciInfo);
2794 
2795 	    xvipc.d = pScrn->videoRam << 10;	/* XF86Config overrides probing */
2796 
2797 	    if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) < 0) {
2798 		if (errno == EBUSY)
2799 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2800 			       "Another application already opened the Permedia 2 "
2801 			       "kernel driver for this board. To enable "
2802 			       "shared access please start the server first.\n");
2803 		else
2804 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2805 			       "Failed to initialize kernel backbone "
2806 			       "due to error %d: %s.\n", errno, strerror(errno));
2807 		goto failed;
2808 	    }
2809 
2810 	    pAPriv->pm2p = xvipc.pm2p;
2811 	} else {
2812 	    InitializeVideo(pAPriv);
2813 
2814 	    if (!xf86I2CProbeAddress(pGlint->VSBus, SAA7111_SLAVE_ADDRESS))
2815     		goto failed;
2816 
2817 	    pAPriv->Port[0].I2CDev.DevName = "Decoder SAA 7111A";
2818     	    pAPriv->Port[0].I2CDev.SlaveAddr = SAA7111_SLAVE_ADDRESS;
2819 	    pAPriv->Port[0].I2CDev.pI2CBus = pGlint->VSBus;
2820 
2821 	    if (!xf86I2CDevInit(&pAPriv->Port[0].I2CDev))
2822 		goto failed;
2823 
2824 	    if (!xf86I2CWriteVec(&pAPriv->Port[0].I2CDev, DecInitVec, ENTRIES(DecInitVec) / 2))
2825 		goto failed;
2826 
2827 	    if (!xf86I2CProbeAddress(pGlint->VSBus, SAA7125_SLAVE_ADDRESS))
2828 		goto failed;
2829 
2830 	    pAPriv->Port[1].I2CDev.DevName = "Encoder SAA 7125";
2831 	    pAPriv->Port[1].I2CDev.SlaveAddr = SAA7125_SLAVE_ADDRESS;
2832     	    pAPriv->Port[1].I2CDev.pI2CBus = pGlint->VSBus;
2833 
2834 	    if (!xf86I2CDevInit(&pAPriv->Port[1].I2CDev))
2835 		goto failed;
2836 
2837 	    if (!xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, EncInitVec, ENTRIES(EncInitVec) / 2))
2838 		goto failed;
2839 	}
2840 
2841 	if (SetVideoStd(&pAPriv->Port[0], PAL) != Success ||
2842 	    SetPlug(&pAPriv->Port[0], 0) != Success ||  /* composite */
2843 	    SetPlug(&pAPriv->Port[1], 1) != Success)    /* composite-adaptor */
2844 	    goto failed;
2845 
2846 	pAPriv->Port[1].VideoStdReq = pAPriv->Port[0].VideoStdReq;
2847 
2848 	pAPriv->Port[0].BuffersRequested = 2;
2849 	pAPriv->Port[1].BuffersRequested = 1;
2850 
2851 	for (i = 0; i < 2; i++) {
2852     	    pAPriv->Port[i].fw = 704;
2853     	    pAPriv->Port[i].fh = 576;
2854     	    pAPriv->Port[i].FramesPerSec = 30;
2855     	    pAPriv->Port[i].BufferPProd = partprodPermedia[704 >> 5];
2856 	}
2857 
2858 	SetAttr(&pAPriv->Port[0], 0, 0);	/* Brightness (-1000..+1000) */
2859 	SetAttr(&pAPriv->Port[0], 1, 0);	/* Contrast (-3000..+1000) */
2860 	SetAttr(&pAPriv->Port[0], 2, 0);	/* Color saturation (-3000..+1000) */
2861 	SetAttr(&pAPriv->Port[0], 3, 0);	/* Hue (-1000..+1000) */
2862 
2863 	pAPriv->Port[0].Attribute[4] = 1;	/* Interlaced (0 = not, 1 = yes,
2864 						    2 = double scan 50/60 Hz) */
2865 	pAPriv->Port[0].Attribute[5] = 0;	/* Bilinear Filter (Bool) */
2866 
2867 	pAPriv->Port[1].Attribute[4] = 1;	/* Interlaced (Bool) */
2868 	pAPriv->Port[1].Attribute[5] = 0;	/* Bilinear Filter (Bool) */
2869 
2870 	SetBkgCol(&pAPriv->Port[1], 0x000000);	/* BkgColor 0x00RRGGBB */
2871     } /* VideoIO */
2872 
2873     if (!(pAPriv->Timer = TimerSet(NULL, 0, 0, TimerCallback, pAPriv)))
2874         goto failed;
2875 
2876     for (i = 0; i < PORTS; i++)
2877     	pAPriv->Port[i].StopDelay = -1;
2878 
2879     /* Frontend scaler */
2880 
2881     for (i = 2; i < 6; i++) {
2882 	pAPriv->Port[i].fw = 0;
2883 	pAPriv->Port[i].fh = 0;
2884 	pAPriv->Port[i].BuffersRequested = 1;
2885 	pAPriv->Delay = 125;
2886 	pAPriv->Instant = 1000 / 25;
2887 
2888 	if (!VideoIO || pAPriv->pm2p) {
2889 	    pAPriv->Delay = 5;
2890 	    pAPriv->Instant = 1000;
2891 	}
2892 
2893 	pAPriv->Port[i].Attribute[5] = 0;	/* Bilinear Filter (Bool) */
2894 	pAPriv->Port[i].Attribute[7] = 0;	/* Alpha Enable (Bool) */
2895     }
2896 
2897     return pAPriv;
2898 
2899 failed:
2900 
2901     DeleteAdaptorPriv(pAPriv);
2902 
2903     return NULL;
2904 }
2905 
2906 
2907 /*
2908  *  Glint interface
2909  */
2910 
2911 void
Permedia2VideoEnterVT(ScrnInfoPtr pScrn)2912 Permedia2VideoEnterVT(ScrnInfoPtr pScrn)
2913 {
2914     GLINTPtr pGlint = GLINTPTR(pScrn);
2915     AdaptorPrivPtr pAPriv;
2916 
2917     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv enter VT\n"));
2918 
2919     for (pAPriv = AdaptorPrivList; pAPriv != NULL; pAPriv = pAPriv->Next)
2920 	if (pAPriv->pScrn == pScrn) {
2921 	    if (pAPriv->VideoIO) {
2922 		if (pAPriv->pm2p)
2923 		    xvipcHandshake(&pAPriv->Port[0], OP_ENTER, TRUE);
2924 		else {
2925 		    InitializeVideo(pAPriv);
2926 
2927 		    xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, EncInitVec, ENTRIES(EncInitVec) / 2);
2928 		}
2929 
2930 		SetVideoStd(&pAPriv->Port[0], pAPriv->VideoStd);
2931 		SetPlug(&pAPriv->Port[0], pAPriv->Port[0].Plug);
2932 		SetPlug(&pAPriv->Port[1], pAPriv->Port[1].Plug);
2933 	    }
2934 
2935 	    if (pGlint->NoAccel)
2936 		Permedia2InitializeEngine(pScrn);
2937 
2938 	    break;
2939 	}
2940 }
2941 
2942 void
Permedia2VideoLeaveVT(ScrnInfoPtr pScrn)2943 Permedia2VideoLeaveVT(ScrnInfoPtr pScrn)
2944 {
2945     AdaptorPrivPtr pAPriv;
2946 
2947     for (pAPriv = AdaptorPrivList; pAPriv != NULL; pAPriv = pAPriv->Next)
2948 	if (pAPriv->pScrn == pScrn) {
2949 	    if (pAPriv->VideoIO) {
2950 		StopVideoStream(&pAPriv->Port[0], TRUE);
2951 		StopVideoStream(&pAPriv->Port[1], TRUE);
2952 
2953 		if (pAPriv->pm2p)
2954 		    xvipcHandshake(&pAPriv->Port[0], OP_LEAVE, TRUE);
2955 		else
2956 		    RestoreVideo(pAPriv);
2957 	    }
2958 	    break;
2959 	}
2960 
2961     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Elvis left the building\n"));
2962 }
2963 
2964 void
Permedia2VideoUninit(ScrnInfoPtr pScrn)2965 Permedia2VideoUninit(ScrnInfoPtr pScrn)
2966 {
2967     AdaptorPrivPtr pAPriv, *ppAPriv;
2968 
2969     for (ppAPriv = &AdaptorPrivList; (pAPriv = *ppAPriv); ppAPriv = &(pAPriv->Next))
2970 	if (pAPriv->pScrn == pScrn) {
2971 	    *ppAPriv = pAPriv->Next;
2972 	    DeleteAdaptorPriv(pAPriv);
2973 	    break;
2974 	}
2975 
2976     if (xvipc_fd >= 0) {
2977 	close(xvipc_fd);
2978 	xvipc_fd = -1;
2979     }
2980 
2981     DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv cleanup\n"));
2982 }
2983 
2984 void
Permedia2VideoInit(ScreenPtr pScreen)2985 Permedia2VideoInit(ScreenPtr pScreen)
2986 {
2987     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2988     GLINTPtr pGlint = GLINTPTR(pScrn);
2989     AdaptorPrivPtr pAPriv;
2990     DevUnion Private[PORTS];
2991     XF86VideoAdaptorRec VAR[ADAPTORS];
2992     XF86VideoAdaptorPtr VARPtrs[ADAPTORS];
2993     Bool VideoIO = TRUE;
2994     int i;
2995     /* Glint is still intializing, so pGlint->Options is off-limits. */
2996     OptionInfoPtr VidOpts;
2997 
2998     switch (pGlint->Chipset) {
2999     case PCI_VENDOR_TI_CHIP_PERMEDIA2:
3000     case PCI_VENDOR_3DLABS_CHIP_PERMEDIA2:
3001     case PCI_VENDOR_3DLABS_CHIP_PERMEDIA2V:
3002         break;
3003 
3004     default:
3005         return;
3006     }
3007 
3008     xf86CollectOptions(pScrn, NULL);
3009     /* Process the options */
3010     if (!(VidOpts = malloc(sizeof(pm2Options))))
3011 	return;
3012 
3013     memcpy(VidOpts, pm2Options, sizeof(pm2Options));
3014 
3015     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, VidOpts);
3016     xf86ShowUnusedOptions(pScrn->scrnIndex, VidOpts);
3017 
3018     /* Don't complain about no Xv support unless they asked for Xv support.
3019        Assume they want Xv if OPTION_DEVICE is set, since that's required. */
3020 	if (xf86IsOptionSet(VidOpts, OPTION_DEVICE)) {
3021 	    unsigned int temp;
3022 	    PCI_READ_LONG(pGlint->PciInfo, &temp, PCI_SUBSYSTEM_ID_REG);
3023 	    switch (temp) {
3024 		    case PCI_SUBSYSTEM_ID_WINNER_2000_P2A:
3025 		    case PCI_SUBSYSTEM_ID_WINNER_2000_P2C:
3026 		    case PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2A:
3027 		    case PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2C:
3028 			    break;
3029 		    default:
3030 			    VideoIO = FALSE;
3031 			    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 1, "No Xv vio support for this board\n");
3032 	    }
3033 	}
3034     else
3035 	    /* Assume they don't, even if other options are set. */
3036 	    VideoIO = FALSE;
3037 
3038     if (pGlint->NoAccel && !VideoIO) {
3039 	    free(VidOpts);
3040 	    return;
3041     }
3042 
3043     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, "Initializing Xv driver rev. 4\n");
3044 
3045 	if (VideoIO) {
3046 	    if (!xvipcOpen(xf86GetOptValString(VidOpts, OPTION_DEVICE), pScrn))
3047 		VideoIO = FALSE;
3048     }
3049 
3050     if (!(pAPriv = NewAdaptorPriv(pScrn, VideoIO))) {
3051 	free(VidOpts);
3052 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv driver initialization failed\n");
3053 	return;
3054     }
3055 
3056     if (VideoIO) {
3057 	int n;
3058 
3059 	if (xf86GetOptValInteger(VidOpts, OPTION_IN_BUFFERS, &n))
3060 	    pAPriv->Port[0].BuffersRequested = CLAMP(n, 1, 2);
3061 	if (xf86GetOptValInteger(VidOpts, OPTION_IN_FPS, &n))
3062 	    pAPriv->Port[0].FramesPerSec = CLAMP(n, 1, 30);
3063 
3064 	if (xf86GetOptValInteger(VidOpts, OPTION_OUT_BUFFERS, &n))
3065 	    pAPriv->Port[1].BuffersRequested = 1;
3066 	if (xf86GetOptValInteger(VidOpts, OPTION_OUT_FPS, &n))
3067 	    pAPriv->Port[1].FramesPerSec = CLAMP(n, 1, 30);
3068     }
3069 
3070     if (pGlint->NoAccel) {
3071 	BoxRec AvailFBArea;
3072 
3073 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Xv driver overrides NoAccel option\n");
3074 
3075 	Permedia2InitializeEngine(pScrn);
3076 
3077 	AvailFBArea.x1 = 0;
3078 	AvailFBArea.y1 = 0;
3079 	AvailFBArea.x2 = pScrn->displayWidth;
3080 	AvailFBArea.y2 = pGlint->FbMapSize /
3081 	    (pScrn->displayWidth * pScrn->bitsPerPixel / 8);
3082 
3083 	xf86InitFBManager(pScreen, &AvailFBArea);
3084     }
3085 
3086 #if defined(XFree86LOADER) && 0
3087     if (xf86LoaderCheckSymbol("xf86InitLinearFBManagerRegion")) {
3088 	int last = pGlint->FbMapSize / (pScrn->bitsPerPixel / 8) - 1;
3089 	BoxRec AvailFBArea;
3090 	RegionPtr Region;
3091 
3092 	AvailFBArea.x1 = 0;
3093 	AvailFBArea.y1 = pScrn->virtualY;
3094 	AvailFBArea.x2 = last % pScrn->displayWidth + 1;
3095 	AvailFBArea.y2 = last / pScrn->displayWidth + 1;
3096 
3097 	DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
3098 	    "Using linear FB %d,%d-%d,%d pitch %d (%dk)\n",
3099 	    AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2,
3100 	    pScrn->displayWidth, (((AvailFBArea.y2 - AvailFBArea.y1)
3101 	    * pScrn->displayWidth) << BPPSHIFT(pGlint)) / 1024));
3102 
3103 	Region = xf86LinearFBRegion(pScreen, &AvailFBArea, pScrn->displayWidth);
3104 	xf86InitLinearFBManagerRegion(pScreen, Region);
3105 	REGION_DESTROY(pScreen, Region);
3106     }
3107 #endif
3108 
3109     memset(VAR, 0, sizeof(VAR));
3110 
3111     for (i = 0; i < PORTS; i++)
3112 	Private[i].ptr = (pointer) &pAPriv->Port[i];
3113 
3114     for (i = 0; i < ADAPTORS; i++) {
3115 	VARPtrs[i] = &VAR[i];
3116 	switch (i) {
3117 	case 0:
3118 	    VAR[i].name = "Permedia 2 Video Input";
3119 	    VAR[i].type = XvInputMask | XvWindowMask | XvVideoMask | XvStillMask;
3120 	    VAR[i].nPorts = 1;
3121 	    VAR[i].pPortPrivates = &Private[0];
3122 	    VAR[i].nAttributes	= ENTRIES(InputVideoAttributes);
3123 	    VAR[i].pAttributes	= InputVideoAttributes;
3124 	    VAR[i].nEncodings	= ENTRIES(InputVideoEncodings);
3125 	    VAR[i].pEncodings	= InputVideoEncodings;
3126 	    VAR[i].nFormats	= ENTRIES(InputVideoFormats);
3127 	    VAR[i].pFormats	= InputVideoFormats;
3128 	    break;
3129 
3130 	case 1:
3131 	    VAR[i].name = "Permedia 2 Video Output";
3132 	    VAR[i].type = XvOutputMask | XvWindowMask | XvVideoMask | XvStillMask;
3133 	    VAR[i].nPorts = 1;
3134 	    VAR[i].pPortPrivates = &Private[1];
3135 	    VAR[i].nAttributes	= ENTRIES(OutputVideoAttributes);
3136 	    VAR[i].pAttributes	= OutputVideoAttributes;
3137 	    VAR[i].nEncodings	= ENTRIES(OutputVideoEncodings);
3138 	    VAR[i].pEncodings	= OutputVideoEncodings;
3139 	    VAR[i].nFormats	= ENTRIES(OutputVideoFormats);
3140 	    VAR[i].pFormats	= OutputVideoFormats;
3141 	    break;
3142 
3143 	case 2:
3144 	    VAR[i].name = "Permedia 2 Frontend Scaler";
3145 	    VAR[i].type = XvInputMask | XvWindowMask | XvImageMask;
3146 	    VAR[i].nPorts = 3;
3147 	    VAR[i].pPortPrivates = &Private[2];
3148 	    VAR[i].nAttributes	= ENTRIES(ScalerAttributes);
3149 	    VAR[i].pAttributes	= ScalerAttributes;
3150 	    VAR[i].nEncodings	= ENTRIES(ScalerEncodings);
3151 	    VAR[i].pEncodings	= ScalerEncodings;
3152 	    VAR[i].nFormats	= ENTRIES(ScalerVideoFormats);
3153 	    VAR[i].pFormats	= ScalerVideoFormats;
3154 	    VAR[i].nImages	= ENTRIES(ScalerImages);
3155 	    VAR[i].pImages	= ScalerImages;
3156 	    break;
3157 	}
3158 
3159 	VAR[i].PutVideo = Permedia2PutVideo;
3160 	VAR[i].PutStill = Permedia2PutStill;
3161 	VAR[i].GetVideo = Permedia2GetVideo;
3162 	VAR[i].GetStill = Permedia2GetStill;
3163 	VAR[i].StopVideo = Permedia2StopVideo;
3164 	VAR[i].SetPortAttribute = Permedia2SetPortAttribute;
3165 	VAR[i].GetPortAttribute = Permedia2GetPortAttribute;
3166 	VAR[i].QueryBestSize = Permedia2QueryBestSize;
3167 	VAR[i].PutImage = Permedia2PutImage;
3168 	VAR[i].QueryImageAttributes = Permedia2QueryImageAttributes;
3169     }
3170 
3171     if (VideoIO ? xf86XVScreenInit(pScreen, &VARPtrs[0], 3) :
3172 		  xf86XVScreenInit(pScreen, &VARPtrs[2], 1)) {
3173 	const char *s;
3174 
3175 	xvEncoding	= MAKE_ATOM(XV_ENCODING);
3176 	xvHue		= MAKE_ATOM(XV_HUE);
3177 	xvSaturation	= MAKE_ATOM(XV_SATURATION);
3178 	xvBrightness	= MAKE_ATOM(XV_BRIGHTNESS);
3179 	xvContrast	= MAKE_ATOM(XV_CONTRAST);
3180 	xvInterlace	= MAKE_ATOM(XV_INTERLACE);
3181 	xvFilter	= MAKE_ATOM(XV_FILTER);
3182 	xvBkgColor	= MAKE_ATOM(XV_BKGCOLOR);
3183 	xvAlpha		= MAKE_ATOM(XV_ALPHA);
3184 
3185 	pAPriv->Next = AdaptorPrivList;
3186 	AdaptorPrivList = pAPriv;
3187 
3188 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv frontend scaler enabled\n");
3189 
3190 	if (VideoIO) {
3191 	    if ((s = xf86GetOptValString(VidOpts, OPTION_IN_ENCODING)))
3192 	        for (i = 0; i < ENTRIES(InputVideoEncodings); i++)
3193 		    if (!strncmp(s, InputVideoEncodings[i].name, strlen(s))) {
3194 			Permedia2SetPortAttribute(pScrn, xvEncoding, i, (pointer) &pAPriv->Port[0]);
3195 			break;
3196 		    }
3197 
3198 	    if ((s = xf86GetOptValString(VidOpts, OPTION_OUT_ENCODING)))
3199 		for (i = 0; i < ENTRIES(OutputVideoEncodings); i++)
3200 		    if (!strncmp(s, OutputVideoEncodings[i].name, strlen(s))) {
3201 			Permedia2SetPortAttribute(pScrn, xvEncoding, i, (pointer) &pAPriv->Port[1]);
3202 			break;
3203 		    }
3204 
3205 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv vio driver %senabled\n",
3206 		pAPriv->pm2p ? "with kernel backbone " : "");
3207 	}
3208     } else {
3209 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n");
3210 	DeleteAdaptorPriv(pAPriv);
3211     }
3212 
3213     free(VidOpts);
3214 }
3215