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