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