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