trident_video.c revision ff89ac2b
195b296d0Smrg/*
295b296d0Smrg * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
395b296d0Smrg *
495b296d0Smrg * Permission to use, copy, modify, distribute, and sell this software and its
595b296d0Smrg * documentation for any purpose is hereby granted without fee, provided that
695b296d0Smrg * the above copyright notice appear in all copies and that both that
795b296d0Smrg * copyright notice and this permission notice appear in supporting
895b296d0Smrg * documentation, and that the name of Alan Hourihane not be used in
995b296d0Smrg * advertising or publicity pertaining to distribution of the software without
1095b296d0Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1195b296d0Smrg * about the suitability of this software for any purpose.  It is provided
1295b296d0Smrg * "as is" without express or implied warranty.
1395b296d0Smrg *
1495b296d0Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1595b296d0Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1695b296d0Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1795b296d0Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1895b296d0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1995b296d0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2095b296d0Smrg * PERFORMANCE OF THIS SOFTWARE.
2195b296d0Smrg *
2295b296d0Smrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
2395b296d0Smrg */
2495b296d0Smrg
2595b296d0Smrg#ifdef HAVE_CONFIG_H
2695b296d0Smrg#include "config.h"
2795b296d0Smrg#endif
2895b296d0Smrg
2995b296d0Smrg#include "xf86.h"
3095b296d0Smrg#include "xf86_OSproc.h"
3195b296d0Smrg#include "xf86Resources.h"
3295b296d0Smrg#include "compiler.h"
3395b296d0Smrg#include "xf86PciInfo.h"
3495b296d0Smrg#include "xf86Pci.h"
3595b296d0Smrg#include "xf86fbman.h"
3695b296d0Smrg#include "regionstr.h"
3795b296d0Smrg
3895b296d0Smrg#include "trident.h"
3995b296d0Smrg#include "trident_regs.h"
4095b296d0Smrg#include <X11/extensions/Xv.h>
4195b296d0Smrg#include "xaa.h"
4295b296d0Smrg#include "xaalocal.h"
4395b296d0Smrg#include "dixstruct.h"
4495b296d0Smrg#include "fourcc.h"
4595b296d0Smrg
4695b296d0Smrg#define OFF_DELAY 	800  /* milliseconds */
4795b296d0Smrg#define FREE_DELAY 	60000
4895b296d0Smrg
4995b296d0Smrg#define OFF_TIMER 	0x01
5095b296d0Smrg#define FREE_TIMER	0x02
5195b296d0Smrg#define CLIENT_VIDEO_ON	0x04
5295b296d0Smrg
5395b296d0Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
5495b296d0Smrg
5595b296d0Smrgstatic XF86VideoAdaptorPtr TRIDENTSetupImageVideo(ScreenPtr);
5695b296d0Smrgstatic void TRIDENTInitOffscreenImages(ScreenPtr);
5795b296d0Smrgstatic void TRIDENTStopVideo(ScrnInfoPtr, pointer, Bool);
5895b296d0Smrgstatic int TRIDENTSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
5995b296d0Smrgstatic int TRIDENTGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
6095b296d0Smrgstatic void TRIDENTQueryBestSize(ScrnInfoPtr, Bool,
6195b296d0Smrg	short, short, short, short, unsigned int *, unsigned int *, pointer);
6295b296d0Smrgstatic int TRIDENTPutImage( ScrnInfoPtr,
6395b296d0Smrg	short, short, short, short, short, short, short, short,
6495b296d0Smrg	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
6595b296d0Smrg	DrawablePtr);
6695b296d0Smrgstatic int TRIDENTQueryImageAttributes(ScrnInfoPtr,
6795b296d0Smrg	int, unsigned short *, unsigned short *,  int *, int *);
6895b296d0Smrgstatic void TRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
6995b296d0Smrgstatic void tridentSetVideoContrast(TRIDENTPtr pTrident,int value);
7095b296d0Smrgstatic void tridentSetVideoParameters(TRIDENTPtr pTrident, int brightness,
7195b296d0Smrg				      int saturation, int hue);
7295b296d0Smrgvoid tridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame);
7395b296d0Smrgstatic void WaitForVBlank(ScrnInfoPtr pScrn);
7495b296d0Smrg
7595b296d0Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
7695b296d0Smrg
7795b296d0Smrgstatic Atom xvColorKey, xvSaturation, xvBrightness, xvHUE,  xvContrast;
7895b296d0Smrg
7995b296d0Smrgvoid TRIDENTInitVideo(ScreenPtr pScreen)
8095b296d0Smrg{
8195b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
8295b296d0Smrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
8395b296d0Smrg    XF86VideoAdaptorPtr newAdaptor = NULL;
8495b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
8595b296d0Smrg    int num_adaptors;
8695b296d0Smrg
8795b296d0Smrg    /*
8895b296d0Smrg     * The following has been tested on:
8995b296d0Smrg     *
9095b296d0Smrg     * 9525         : flags: None
9195b296d0Smrg     * Image985     : flags: None
9295b296d0Smrg     * Cyber9397(DVD) : flags: VID_ZOOM_NOMINI
9395b296d0Smrg     * CyberBlade/i7: flags: VID_ZOOM_INV | VID_ZOOM_MINI
9495b296d0Smrg     * CyberBlade/i1: flags: VID_ZOOM_INV | VID_ZOOM_MINI
9595b296d0Smrg     * CyberBlade/Ai1: flags: VID_ZOOM_INV
9695b296d0Smrg     * Cyber 9540   : flags: VID_ZOOM_INV | VID_SHIFT_4
9795b296d0Smrg     * CyberXPm8    : flags: VID_ZOOM_INV | VID_SHIFT_4
9895b296d0Smrg     *
9995b296d0Smrg     * When you make changes make sure not to break these
10095b296d0Smrg     * Add new chipsets to this list.
10195b296d0Smrg     */
10295b296d0Smrg    if (pTrident->Chipset >= BLADE3D) {
10395b296d0Smrg       pTrident->videoFlags = VID_ZOOM_INV ;
10495b296d0Smrg       if (pTrident->Chipset <= CYBERBLADEI1D)
10595b296d0Smrg	 pTrident->videoFlags |= VID_ZOOM_MINI;
10695b296d0Smrg       else if (pTrident->Chipset < CYBERBLADEAI1 /* verified EE */
10795b296d0Smrg		|| pTrident->Chipset > CYBERBLADEAI1D)
10895b296d0Smrg	 pTrident->videoFlags |= VID_OFF_SHIFT_4;
10995b296d0Smrg    }
11095b296d0Smrg    if (pTrident->Chipset == CYBER9397 || pTrident->Chipset == CYBER9397DVD)
11195b296d0Smrg	pTrident->videoFlags = VID_ZOOM_NOMINI;
11295b296d0Smrg
11395b296d0Smrg    if (pTrident->Chipset == CYBER9397DVD ||
11495b296d0Smrg	pTrident->Chipset == CYBER9525DVD ||
115ff89ac2bSmrg	(pTrident->Chipset >= BLADE3D && pTrident->Chipset < CYBERBLADEXP4))
11695b296d0Smrg		pTrident->videoFlags |= VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC;
11795b296d0Smrg
11895b296d0Smrg    newAdaptor = TRIDENTSetupImageVideo(pScreen);
11995b296d0Smrg    TRIDENTInitOffscreenImages(pScreen);
12095b296d0Smrg
12195b296d0Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
12295b296d0Smrg
12395b296d0Smrg    if(newAdaptor) {
12495b296d0Smrg	if(!num_adaptors) {
12595b296d0Smrg	    num_adaptors = 1;
12695b296d0Smrg	    adaptors = &newAdaptor;
12795b296d0Smrg	} else {
12895b296d0Smrg	    newAdaptors =  /* need to free this someplace */
12995b296d0Smrg		xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
13095b296d0Smrg	    if(newAdaptors) {
13195b296d0Smrg		memcpy(newAdaptors, adaptors, num_adaptors *
13295b296d0Smrg					sizeof(XF86VideoAdaptorPtr));
13395b296d0Smrg		newAdaptors[num_adaptors] = newAdaptor;
13495b296d0Smrg		adaptors = newAdaptors;
13595b296d0Smrg		num_adaptors++;
13695b296d0Smrg	    }
13795b296d0Smrg	}
13895b296d0Smrg    }
13995b296d0Smrg
14095b296d0Smrg    if(num_adaptors)
14195b296d0Smrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
14295b296d0Smrg
14395b296d0Smrg    if(newAdaptors)
14495b296d0Smrg	xfree(newAdaptors);
14595b296d0Smrg
14695b296d0Smrg    if (pTrident->videoFlags)
14795b296d0Smrg	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,3,
14895b296d0Smrg		       "Trident Video Flags: %s %s %s %s\n",
14995b296d0Smrg		   pTrident->videoFlags & VID_ZOOM_INV ? "VID_ZOOM_INV" : "",
15095b296d0Smrg		   pTrident->videoFlags & VID_ZOOM_MINI ? "VID_ZOOM_MINI" : "",                   pTrident->videoFlags & VID_OFF_SHIFT_4 ? "VID_OFF_SHIFT_4"
15195b296d0Smrg		   : "",
15295b296d0Smrg		   pTrident->videoFlags & VID_ZOOM_NOMINI ? "VID_ZOOM_NOMINI"
15395b296d0Smrg		   : "");
15495b296d0Smrg
15595b296d0Smrg}
15695b296d0Smrg
15795b296d0Smrg/* client libraries expect an encoding */
15895b296d0Smrgstatic XF86VideoEncodingRec DummyEncoding[1] =
15995b296d0Smrg{
16095b296d0Smrg {
16195b296d0Smrg   0,
16295b296d0Smrg   "XV_IMAGE",
16395b296d0Smrg   1024, 1024,
16495b296d0Smrg   {1, 1}
16595b296d0Smrg }
16695b296d0Smrg};
16795b296d0Smrg
16895b296d0Smrg#define NUM_FORMATS 4
16995b296d0Smrg
17095b296d0Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
17195b296d0Smrg{
17295b296d0Smrg  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
17395b296d0Smrg};
17495b296d0Smrg
17595b296d0Smrg#define NUM_ATTRIBUTES 5
17695b296d0Smrg
17795b296d0Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
17895b296d0Smrg{
17995b296d0Smrg    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
18095b296d0Smrg    {XvSettable | XvGettable, 0, 187,           "XV_SATURATION"},
18195b296d0Smrg    {XvSettable | XvGettable, 0, 0x3F,          "XV_BRIGHTNESS"},
18295b296d0Smrg    {XvSettable | XvGettable, 0, 360 ,          "XV_HUE"},
18395b296d0Smrg    {XvSettable | XvGettable, 0, 7,           "XV_CONTRAST"}
18495b296d0Smrg};
18595b296d0Smrg
18695b296d0Smrg#define NUM_IMAGES 3
18795b296d0Smrg
18895b296d0Smrgstatic XF86ImageRec Images[NUM_IMAGES] =
18995b296d0Smrg{
19095b296d0Smrg   {
19195b296d0Smrg	0x36315652,
19295b296d0Smrg        XvRGB,
19395b296d0Smrg	LSBFirst,
19495b296d0Smrg	{'R','V','1','6',
19595b296d0Smrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
19695b296d0Smrg	16,
19795b296d0Smrg	XvPacked,
19895b296d0Smrg	1,
19995b296d0Smrg	16, 0xF800, 0x07E0, 0x001F,
20095b296d0Smrg	0, 0, 0,
20195b296d0Smrg	0, 0, 0,
20295b296d0Smrg	0, 0, 0,
20395b296d0Smrg	{'R','V','B',0,
20495b296d0Smrg	  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
20595b296d0Smrg	XvTopToBottom
20695b296d0Smrg   },
20795b296d0Smrg   XVIMAGE_YV12,
20895b296d0Smrg   XVIMAGE_YUY2
20995b296d0Smrg};
21095b296d0Smrg
21195b296d0Smrgtypedef struct {
21295b296d0Smrg   FBLinearPtr	linear;
21395b296d0Smrg   RegionRec	clip;
21495b296d0Smrg   CARD32	colorKey;
21595b296d0Smrg   CARD8        Saturation;
21695b296d0Smrg   CARD8        Brightness;
21795b296d0Smrg   CARD16       HUE;
21895b296d0Smrg   INT8         Contrast;
21995b296d0Smrg   CARD32	videoStatus;
22095b296d0Smrg   Time		offTime;
22195b296d0Smrg   Time		freeTime;
22295b296d0Smrg   int          fixFrame;
22395b296d0Smrg} TRIDENTPortPrivRec, *TRIDENTPortPrivPtr;
22495b296d0Smrg
22595b296d0Smrg
22695b296d0Smrg#define GET_PORT_PRIVATE(pScrn) \
22795b296d0Smrg   (TRIDENTPortPrivPtr)((TRIDENTPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
22895b296d0Smrg
22995b296d0Smrgvoid TRIDENTResetVideo(ScrnInfoPtr pScrn)
23095b296d0Smrg{
23195b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
23295b296d0Smrg    TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr;
23395b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
23495b296d0Smrg    int red, green, blue;
23595b296d0Smrg    int tmp;
23695b296d0Smrg
23795b296d0Smrg    WaitForVBlank(pScrn);
23895b296d0Smrg    OUTW(vgaIOBase + 4, 0x848E);
23995b296d0Smrg
24095b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
24195b296d0Smrg    	OUTW(vgaIOBase + 4, 0x80B9);
24295b296d0Smrg    	OUTW(vgaIOBase + 4, 0x00BE);
24395b296d0Smrg    	OUTW(0x3C4, 0xC057);
24495b296d0Smrg    	OUTW(0x3C4, 0x3420);
24595b296d0Smrg    	OUTW(0x3C4, 0x3037);
24695b296d0Smrg    } else {
24795b296d0Smrg	if (pTrident->Chipset >= PROVIDIA9682) {
24895b296d0Smrg    	    OUTB(0x83C8, 0x57);
24995b296d0Smrg    	    OUTB(0x83C6, 0xC0);
25095b296d0Smrg    	    OUTW(vgaIOBase + 4, 0x26BE);
25195b296d0Smrg	} else {
25295b296d0Smrg    	    OUTB(0x83C8, 0x37);
25395b296d0Smrg    	    OUTB(0x83C6, 0x01);
25495b296d0Smrg    	    OUTB(0x83C8, 0x00);
25595b296d0Smrg    	    OUTB(0x83C6, 0x00);
25695b296d0Smrg	}
25795b296d0Smrg    }
25895b296d0Smrg
25995b296d0Smrg    if (pTrident->Chipset >= BLADEXP) {
26095b296d0Smrg	OUTW(0x3C4, 0x007A);
26195b296d0Smrg	OUTW(0x3C4, 0x007D);
26295b296d0Smrg    }
263ff89ac2bSmrg    if (pTrident->Chipset == CYBERBLADEXP4) {
264ff89ac2bSmrg    	OUTW(0x3CE, 0x0462);
265ff89ac2bSmrg    }
26695b296d0Smrg    switch (pScrn->depth) {
26795b296d0Smrg    case 8:
26895b296d0Smrg	VIDEOOUT(pPriv->colorKey, pTrident->keyOffset);
26995b296d0Smrg	VIDEOOUT(0x00, (pTrident->keyOffset + 1));
27095b296d0Smrg	VIDEOOUT(0x00, (pTrident->keyOffset + 2));
27195b296d0Smrg	VIDEOOUT(0xFF, (pTrident->keyOffset + 4));
27295b296d0Smrg	VIDEOOUT(0x00, (pTrident->keyOffset + 5));
27395b296d0Smrg	VIDEOOUT(0x00, (pTrident->keyOffset + 6));
27495b296d0Smrg	break;
27595b296d0Smrg    default:
27695b296d0Smrg	red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
27795b296d0Smrg	green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
27895b296d0Smrg	blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
27995b296d0Smrg	switch (pScrn->depth) {
28095b296d0Smrg	case 15:
28195b296d0Smrg	    tmp = (red << 10) | (green << 5) | (blue);
28295b296d0Smrg	    VIDEOOUT((tmp & 0xff), pTrident->keyOffset);
28395b296d0Smrg	    VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1));
28495b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 2));
28595b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 4));
28695b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 5));
28795b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 6));
28895b296d0Smrg	    break;
28995b296d0Smrg	case 16:
29095b296d0Smrg	    tmp = (red << 11) | (green << 5) | (blue);
29195b296d0Smrg	    VIDEOOUT((tmp & 0xff), pTrident->keyOffset);
29295b296d0Smrg	    VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1));
29395b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 2));
29495b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 4));
29595b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 5));
29695b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 6));
29795b296d0Smrg	    break;
29895b296d0Smrg	case 24:
29995b296d0Smrg	    VIDEOOUT(blue, pTrident->keyOffset);
30095b296d0Smrg	    VIDEOOUT(green, (pTrident->keyOffset + 1));
30195b296d0Smrg	    VIDEOOUT(red, (pTrident->keyOffset + 2));
30295b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 4));
30395b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 5));
30495b296d0Smrg	    VIDEOOUT(0xFF, (pTrident->keyOffset + 6));
30595b296d0Smrg	    break;
30695b296d0Smrg	}
30795b296d0Smrg    }
30895b296d0Smrg
30995b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
31095b296d0Smrg    	tridentSetVideoContrast(pTrident,pPriv->Contrast);
31195b296d0Smrg    	tridentSetVideoParameters(pTrident,pPriv->Brightness,pPriv->Saturation,
31295b296d0Smrg                            pPriv->HUE);
31395b296d0Smrg    }
31495b296d0Smrg}
31595b296d0Smrg
31695b296d0Smrg
31795b296d0Smrgstatic XF86VideoAdaptorPtr
31895b296d0SmrgTRIDENTSetupImageVideo(ScreenPtr pScreen)
31995b296d0Smrg{
32095b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
32195b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
32295b296d0Smrg    XF86VideoAdaptorPtr adapt;
32395b296d0Smrg    TRIDENTPortPrivPtr pPriv;
32495b296d0Smrg
32595b296d0Smrg    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
32695b296d0Smrg			    sizeof(TRIDENTPortPrivRec) +
32795b296d0Smrg			    sizeof(DevUnion))))
32895b296d0Smrg	return NULL;
32995b296d0Smrg
33095b296d0Smrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
33195b296d0Smrg    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
33295b296d0Smrg    adapt->name = "Trident Backend Scaler";
33395b296d0Smrg    adapt->nEncodings = 1;
33495b296d0Smrg    adapt->pEncodings = DummyEncoding;
33595b296d0Smrg    adapt->nFormats = NUM_FORMATS;
33695b296d0Smrg    adapt->pFormats = Formats;
33795b296d0Smrg    adapt->nPorts = 1;
33895b296d0Smrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
33995b296d0Smrg    pPriv = (TRIDENTPortPrivPtr)(&adapt->pPortPrivates[1]);
34095b296d0Smrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
34195b296d0Smrg    adapt->pAttributes = Attributes;
34295b296d0Smrg    adapt->nImages = NUM_IMAGES;
34395b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
34495b296d0Smrg    	adapt->nAttributes = NUM_ATTRIBUTES;
34595b296d0Smrg    } else {
34695b296d0Smrg    	adapt->nAttributes = 1; /* Just colorkey */
34795b296d0Smrg    }
34895b296d0Smrg    adapt->pImages = Images;
34995b296d0Smrg    adapt->PutVideo = NULL;
35095b296d0Smrg    adapt->PutStill = NULL;
35195b296d0Smrg    adapt->GetVideo = NULL;
35295b296d0Smrg    adapt->GetStill = NULL;
35395b296d0Smrg    adapt->StopVideo = TRIDENTStopVideo;
35495b296d0Smrg    adapt->SetPortAttribute = TRIDENTSetPortAttribute;
35595b296d0Smrg    adapt->GetPortAttribute = TRIDENTGetPortAttribute;
35695b296d0Smrg    adapt->QueryBestSize = TRIDENTQueryBestSize;
35795b296d0Smrg    adapt->PutImage = TRIDENTPutImage;
35895b296d0Smrg    adapt->QueryImageAttributes = TRIDENTQueryImageAttributes;
35995b296d0Smrg
36095b296d0Smrg    pPriv->colorKey = pTrident->videoKey & ((1 << pScrn->depth) - 1);
36195b296d0Smrg    pPriv->Brightness = 45;
36295b296d0Smrg    pPriv->Saturation = 80;
36395b296d0Smrg    pPriv->Contrast = 4;
36495b296d0Smrg    pPriv->HUE = 0;
36595b296d0Smrg    pPriv->videoStatus = 0;
36695b296d0Smrg    pPriv->fixFrame = 100;
36795b296d0Smrg
36895b296d0Smrg    /* gotta uninit this someplace */
36995b296d0Smrg    REGION_NULL(pScreen, &pPriv->clip);
37095b296d0Smrg
37195b296d0Smrg    pTrident->adaptor = adapt;
37295b296d0Smrg
37395b296d0Smrg    xvColorKey   = MAKE_ATOM("XV_COLORKEY");
37495b296d0Smrg
37595b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
37695b296d0Smrg    	xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
37795b296d0Smrg    	xvSaturation = MAKE_ATOM("XV_SATURATION");
37895b296d0Smrg    	xvHUE        = MAKE_ATOM("XV_HUE");
37995b296d0Smrg    	xvContrast   = MAKE_ATOM("XV_CONTRAST");
38095b296d0Smrg    }
38195b296d0Smrg
38295b296d0Smrg    if (pTrident->Chipset >= PROVIDIA9682)
38395b296d0Smrg	pTrident->keyOffset = 0x50;
38495b296d0Smrg    else
38595b296d0Smrg	pTrident->keyOffset = 0x30;
38695b296d0Smrg
38795b296d0Smrg    TRIDENTResetVideo(pScrn);
38895b296d0Smrg
38995b296d0Smrg    return adapt;
39095b296d0Smrg}
39195b296d0Smrg
39295b296d0Smrg
39395b296d0Smrgstatic void
39495b296d0SmrgTRIDENTStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
39595b296d0Smrg{
39695b296d0Smrg  TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
39795b296d0Smrg  TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data;
39895b296d0Smrg  int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
39995b296d0Smrg
40095b296d0Smrg  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
40195b296d0Smrg
40295b296d0Smrg  if(shutdown) {
40395b296d0Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
40495b296d0Smrg    	WaitForVBlank(pScrn);
40595b296d0Smrg	OUTW(vgaIOBase + 4, 0x848E);
40695b296d0Smrg	OUTW(vgaIOBase + 4, 0x0091);
40795b296d0Smrg     }
40895b296d0Smrg     if(pPriv->linear) {
40995b296d0Smrg	xf86FreeOffscreenLinear(pPriv->linear);
41095b296d0Smrg	pPriv->linear = NULL;
41195b296d0Smrg     }
41295b296d0Smrg     pPriv->videoStatus = 0;
41395b296d0Smrg  } else {
41495b296d0Smrg     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
41595b296d0Smrg	pPriv->videoStatus |= OFF_TIMER;
41695b296d0Smrg	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
41795b296d0Smrg	pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback;
41895b296d0Smrg     }
41995b296d0Smrg  }
42095b296d0Smrg}
42195b296d0Smrg
42295b296d0Smrg#undef PI
42395b296d0Smrg#define PI 3.14159265
42495b296d0Smrg
42595b296d0Smrgstatic void
42695b296d0SmrgtridentSetVideoContrast(TRIDENTPtr pTrident,int value)
42795b296d0Smrg{
42895b296d0Smrg  OUTW(0x3C4, (((value & 0x7)|((value & 0x7) << 4)) << 8) | 0xBC);
42995b296d0Smrg}
43095b296d0Smrg
43195b296d0Smrgstatic void
43295b296d0SmrgtridentSetVideoParameters(TRIDENTPtr pTrident, int brightness,
43395b296d0Smrg			  int saturation, int hue)
43495b296d0Smrg{
43595b296d0Smrg    double dtmp;
43695b296d0Smrg    CARD8 sign, tmp, tmp1;
43795b296d0Smrg
43895b296d0Smrg    if (brightness >= 0x20)
43995b296d0Smrg      brightness -= 0x20;
44095b296d0Smrg    else
44195b296d0Smrg      brightness += 0x20;
44295b296d0Smrg    dtmp = sin((double)hue / 180.0 * PI) * saturation / 12.5;
44395b296d0Smrg    sign = (dtmp < 0) ? 1 << 1 : 0;
44495b296d0Smrg    tmp1 = ((int)fabs(dtmp) >> 4) & 0x1;
44595b296d0Smrg    tmp = brightness << 2 | sign | tmp1;
44695b296d0Smrg    OUTW(0x3C4, tmp << 8 | 0xB1);
44795b296d0Smrg
44895b296d0Smrg    tmp1 = ((int)fabs(dtmp) & 0x7 ) << 5;
44995b296d0Smrg    dtmp = cos((double)hue / 180.0 * PI) * saturation / 12.5;
45095b296d0Smrg    sign = (dtmp < 0) ? 1 << 4 : 0;
45195b296d0Smrg    tmp1 |= (int)fabs(dtmp)  & 0xf;
45295b296d0Smrg    tmp = sign | tmp1;
45395b296d0Smrg    OUTW(0x3C4, tmp << 8 | 0xB0);
45495b296d0Smrg}
45595b296d0Smrg
45695b296d0Smrgstatic int
45795b296d0SmrgTRIDENTSetPortAttribute(
45895b296d0Smrg  ScrnInfoPtr pScrn,
45995b296d0Smrg  Atom attribute,
46095b296d0Smrg  INT32 value,
46195b296d0Smrg  pointer data
46295b296d0Smrg){
46395b296d0Smrg  TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data;
46495b296d0Smrg  TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
46595b296d0Smrg
46695b296d0Smrg  if(attribute == xvColorKey) {
46795b296d0Smrg	int red, green, blue;
46895b296d0Smrg	int tmp;
46995b296d0Smrg	pPriv->colorKey = value;
47095b296d0Smrg	switch (pScrn->depth) {
47195b296d0Smrg	case 8:
47295b296d0Smrg	    VIDEOOUT(pPriv->colorKey, pTrident->keyOffset);
47395b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 1));
47495b296d0Smrg	    VIDEOOUT(0x00, (pTrident->keyOffset + 2));
47595b296d0Smrg	    break;
47695b296d0Smrg	default:
47795b296d0Smrg	    red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
47895b296d0Smrg	    green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
47995b296d0Smrg	    blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
48095b296d0Smrg	    switch (pScrn->depth) {
48195b296d0Smrg	    case 15:
48295b296d0Smrg	    	tmp = (red << 10) | (green << 5) | (blue);
48395b296d0Smrg	    	VIDEOOUT((tmp&0xff), pTrident->keyOffset);
48495b296d0Smrg	    	VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1));
48595b296d0Smrg	    	VIDEOOUT(0x00, (pTrident->keyOffset + 2));
48695b296d0Smrg		break;
48795b296d0Smrg	    case 16:
48895b296d0Smrg	    	tmp = (red << 11) | (green << 5) | (blue);
48995b296d0Smrg	    	VIDEOOUT((tmp&0xff), pTrident->keyOffset);
49095b296d0Smrg	    	VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1));
49195b296d0Smrg	    	VIDEOOUT(0x00, (pTrident->keyOffset + 2));
49295b296d0Smrg		break;
49395b296d0Smrg	    case 24:
49495b296d0Smrg	    	VIDEOOUT(blue, pTrident->keyOffset);
49595b296d0Smrg	    	VIDEOOUT(green, (pTrident->keyOffset + 1));
49695b296d0Smrg	    	VIDEOOUT(red, (pTrident->keyOffset + 2));
49795b296d0Smrg		break;
49895b296d0Smrg	    }
49995b296d0Smrg	}
50095b296d0Smrg	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
50195b296d0Smrg  } else if (attribute == xvBrightness) {
50295b296d0Smrg    if ((value < 0) || (value > 0x3f))
50395b296d0Smrg      return BadValue;
50495b296d0Smrg    pPriv->Brightness = value;
50595b296d0Smrg    tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation,
50695b296d0Smrg			      pPriv->HUE);
50795b296d0Smrg  } else if (attribute == xvSaturation) {
50895b296d0Smrg    if ((value < 0) || (value > 187))
50995b296d0Smrg      return BadValue;
51095b296d0Smrg    pPriv->Saturation = value;
51195b296d0Smrg    tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation,
51295b296d0Smrg			      pPriv->HUE);
51395b296d0Smrg  } else if (attribute == xvHUE) {
51495b296d0Smrg    if ((value < 0) || (value > 360))
51595b296d0Smrg      return BadValue;
51695b296d0Smrg    pPriv->HUE = value;
51795b296d0Smrg    tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation,
51895b296d0Smrg			      pPriv->HUE);
51995b296d0Smrg  } else if (attribute == xvContrast) {
52095b296d0Smrg    if ((value < 0) || (value > 7))
52195b296d0Smrg      return BadValue;
52295b296d0Smrg    pPriv->Contrast = value;
52395b296d0Smrg    tridentSetVideoContrast(pTrident,value);
52495b296d0Smrg  } else
52595b296d0Smrg    return BadMatch;
52695b296d0Smrg
52795b296d0Smrg  return Success;
52895b296d0Smrg}
52995b296d0Smrg
53095b296d0Smrgstatic int
53195b296d0SmrgTRIDENTGetPortAttribute(
53295b296d0Smrg  ScrnInfoPtr pScrn,
53395b296d0Smrg  Atom attribute,
53495b296d0Smrg  INT32 *value,
53595b296d0Smrg  pointer data
53695b296d0Smrg){
53795b296d0Smrg  TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data;
53895b296d0Smrg
53995b296d0Smrg  if(attribute == xvColorKey) {
54095b296d0Smrg	*value = pPriv->colorKey;
54195b296d0Smrg  } else if(attribute == xvBrightness) {
54295b296d0Smrg	*value = pPriv->Brightness;
54395b296d0Smrg  } else if(attribute == xvSaturation) {
54495b296d0Smrg	*value = pPriv->Saturation;
54595b296d0Smrg  } else if (attribute == xvHUE) {
54695b296d0Smrg	*value = pPriv->HUE;
54795b296d0Smrg  } else if (attribute == xvContrast) {
54895b296d0Smrg	*value = pPriv->Contrast;
54995b296d0Smrg  } else
55095b296d0Smrg    return BadMatch;
55195b296d0Smrg
55295b296d0Smrg  return Success;
55395b296d0Smrg}
55495b296d0Smrg
55595b296d0Smrgstatic void
55695b296d0SmrgTRIDENTQueryBestSize(
55795b296d0Smrg  ScrnInfoPtr pScrn,
55895b296d0Smrg  Bool motion,
55995b296d0Smrg  short vid_w, short vid_h,
56095b296d0Smrg  short drw_w, short drw_h,
56195b296d0Smrg  unsigned int *p_w, unsigned int *p_h,
56295b296d0Smrg  pointer data
56395b296d0Smrg){
56495b296d0Smrg  *p_w = drw_w;
56595b296d0Smrg  *p_h = drw_h;
56695b296d0Smrg
56795b296d0Smrg  if(*p_w > 16384) *p_w = 16384;
56895b296d0Smrg}
56995b296d0Smrg
57095b296d0Smrg
57195b296d0Smrgstatic FBLinearPtr
57295b296d0SmrgTRIDENTAllocateMemory(
57395b296d0Smrg   ScrnInfoPtr pScrn,
57495b296d0Smrg   FBLinearPtr linear,
57595b296d0Smrg   int size
57695b296d0Smrg){
57795b296d0Smrg   ScreenPtr pScreen;
57895b296d0Smrg   FBLinearPtr new_linear;
57995b296d0Smrg
58095b296d0Smrg   if(linear) {
58195b296d0Smrg	if(linear->size >= size)
58295b296d0Smrg	   return linear;
58395b296d0Smrg
58495b296d0Smrg        if(xf86ResizeOffscreenLinear(linear, size))
58595b296d0Smrg	   return linear;
58695b296d0Smrg
58795b296d0Smrg	xf86FreeOffscreenLinear(linear);
58895b296d0Smrg   }
58995b296d0Smrg
59095b296d0Smrg   pScreen = screenInfo.screens[pScrn->scrnIndex];
59195b296d0Smrg
59295b296d0Smrg   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
59395b296d0Smrg   						NULL, NULL, NULL);
59495b296d0Smrg
59595b296d0Smrg   if(!new_linear) {
59695b296d0Smrg	int max_size;
59795b296d0Smrg
59895b296d0Smrg	xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
59995b296d0Smrg						PRIORITY_EXTREME);
60095b296d0Smrg
60195b296d0Smrg	if(max_size < size)
60295b296d0Smrg	   return NULL;
60395b296d0Smrg
60495b296d0Smrg	xf86PurgeUnlockedOffscreenAreas(pScreen);
60595b296d0Smrg	new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
60695b296d0Smrg						NULL, NULL, NULL);
60795b296d0Smrg   }
60895b296d0Smrg
60995b296d0Smrg   return new_linear;
61095b296d0Smrg}
61195b296d0Smrg
61295b296d0Smrgstatic void
61395b296d0SmrgTRIDENTDisplayVideo(
61495b296d0Smrg    ScrnInfoPtr pScrn,
61595b296d0Smrg    int id,
61695b296d0Smrg    int offset,
61795b296d0Smrg    short width, short height,
61895b296d0Smrg    int pitch,
61995b296d0Smrg    int x1, int y1, int x2, int y2,
62095b296d0Smrg    BoxPtr dstBox,
62195b296d0Smrg    short src_w, short src_h,
62295b296d0Smrg    short drw_w, short drw_h
62395b296d0Smrg){
62495b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
62595b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
62695b296d0Smrg    int zoomx1, zoomx2, zoomy1, zoomy2;
62795b296d0Smrg    int tx1,tx2;
62895b296d0Smrg    int ty1,ty2;
62995b296d0Smrg
63095b296d0Smrg    switch(id) {
63195b296d0Smrg    case 0x35315652:		/* RGB15 */
63295b296d0Smrg    case 0x36315652:		/* RGB16 */
63395b296d0Smrg	if (pTrident->Chipset >= CYBER9388) {
63495b296d0Smrg    	    OUTW(vgaIOBase + 4, 0x22BF);
63595b296d0Smrg	    OUTW(vgaIOBase + 4, 0x248F);
63695b296d0Smrg	} else {
63795b296d0Smrg    	    OUTW(vgaIOBase + 4, 0x118F);
63895b296d0Smrg	}
63995b296d0Smrg	break;
64095b296d0Smrg    case FOURCC_YV12:		/* YV12 */
64195b296d0Smrg    case FOURCC_YUY2:		/* YUY2 */
64295b296d0Smrg    default:
64395b296d0Smrg	if (pTrident->Chipset >= CYBER9388) {
64495b296d0Smrg    	    OUTW(vgaIOBase + 4, 0x00BF);
64595b296d0Smrg	    OUTW(vgaIOBase + 4, 0x208F);
64695b296d0Smrg	} else {
64795b296d0Smrg    	    OUTW(vgaIOBase + 4, 0x108F);
64895b296d0Smrg	}
64995b296d0Smrg	break;
65095b296d0Smrg    }
65195b296d0Smrg    tx1 = dstBox->x1 + pTrident->hsync;
65295b296d0Smrg    tx2 = dstBox->x2 + pTrident->hsync + pTrident->hsync_rskew;
65395b296d0Smrg    ty1 = dstBox->y1 + pTrident->vsync - 2;
65495b296d0Smrg    ty2 = dstBox->y2 + pTrident->vsync + 2 + pTrident->vsync_bskew;
65595b296d0Smrg
65695b296d0Smrg    OUTW(vgaIOBase + 4, (tx1 & 0xff) <<8 | 0x86);
65795b296d0Smrg    OUTW(vgaIOBase + 4, (tx1 & 0xff00)   | 0x87);
65895b296d0Smrg    OUTW(vgaIOBase + 4, (ty1 & 0xff) <<8 | 0x88);
65995b296d0Smrg    OUTW(vgaIOBase + 4, (ty1 & 0xff00)   | 0x89);
66095b296d0Smrg    OUTW(vgaIOBase + 4, (tx2 & 0xff) <<8 | 0x8A);
66195b296d0Smrg    OUTW(vgaIOBase + 4, (tx2 & 0xff00)   | 0x8B);
66295b296d0Smrg    OUTW(vgaIOBase + 4, (ty2 & 0xff) <<8 | 0x8C);
66395b296d0Smrg    OUTW(vgaIOBase + 4, (ty2 & 0xff00)   | 0x8D);
66495b296d0Smrg
66595b296d0Smrg    offset += (x1 >> 15) & ~0x01;
66695b296d0Smrg
66795b296d0Smrg    if (pTrident->videoFlags & VID_OFF_SHIFT_4)
66895b296d0Smrg        offset = offset >> 4;
66995b296d0Smrg    else
67095b296d0Smrg        offset = offset >> 3;
67195b296d0Smrg
67295b296d0Smrg    OUTW(vgaIOBase + 4, (((width<<1) & 0xff)<<8)   | 0x90);
67395b296d0Smrg    OUTW(vgaIOBase + 4, ((width<<1) & 0xff00)      | 0x91);
67495b296d0Smrg    OUTW(vgaIOBase + 4, ((offset) & 0xff) << 8     | 0x92);
67595b296d0Smrg    OUTW(vgaIOBase + 4, ((offset) & 0xff00)        | 0x93);
67695b296d0Smrg    if (pTrident->Chipset >= CYBER9397) {
67795b296d0Smrg    	OUTW(vgaIOBase + 4, ((offset) & 0x0f0000) >> 8 | 0x94);
67895b296d0Smrg    } else {
67995b296d0Smrg    	OUTW(vgaIOBase + 4, ((offset) & 0x070000) >> 8 | 0x94);
68095b296d0Smrg    }
68195b296d0Smrg
68295b296d0Smrg    /* Horizontal Zoom */
68395b296d0Smrg    if (pTrident->videoFlags & VID_ZOOM_INV) {
68495b296d0Smrg	if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_w > drw_w)
68595b296d0Smrg	    zoomx2 = (int)((float)drw_w/(float)src_w * 1024)
68695b296d0Smrg		| (((int)((float)src_w/(float)drw_w) - 1)&7)<<10 | 0x8000;
68795b296d0Smrg	else
68895b296d0Smrg	    zoomx2 = (int)(float)src_w/(float)drw_w * 1024;
68995b296d0Smrg
69095b296d0Smrg	OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80);
69195b296d0Smrg	OUTW(vgaIOBase + 4, (zoomx2&0x9f00) | 0x81);
69295b296d0Smrg    } else {
69395b296d0Smrg	if (drw_w == src_w
69495b296d0Smrg	    || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_w > drw_w))) {
69595b296d0Smrg	    OUTW(vgaIOBase + 4, 0x0080);
69695b296d0Smrg	    OUTW(vgaIOBase + 4, 0x0081);
69795b296d0Smrg	} else
69895b296d0Smrg	    if (drw_w > src_w) {
69995b296d0Smrg		float z;
70095b296d0Smrg
70195b296d0Smrg		z = (float)((drw_w)/(float)src_w) - 1.0;
70295b296d0Smrg
70395b296d0Smrg		zoomx1 =  z;
70495b296d0Smrg		zoomx2 = (z - (int)zoomx1 ) * 1024;
70595b296d0Smrg
70695b296d0Smrg		OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80);
70795b296d0Smrg		OUTW(vgaIOBase + 4, (zoomx1&0x0f)<<10 | (zoomx2&0x0300) |0x81);
70895b296d0Smrg	    } else {
70995b296d0Smrg		zoomx1 =   ((float)drw_w/(float)src_w);
71095b296d0Smrg		zoomx2 = ( ((float)drw_w/(float)src_w) - (int)zoomx1 ) * 1024;
71195b296d0Smrg		OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 |   0x80);
71295b296d0Smrg		OUTW(vgaIOBase + 4, (zoomx2&0x0300)|
71395b296d0Smrg		     (((int)((float)src_w/(float)drw_w)-1)&7)<<10 | 0x8081);
71495b296d0Smrg	    }
71595b296d0Smrg    }
71695b296d0Smrg
71795b296d0Smrg    /* Vertical Zoom */
71895b296d0Smrg    if (pTrident->videoFlags & VID_ZOOM_INV) {
71995b296d0Smrg	if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_h > drw_h)
72095b296d0Smrg	    zoomy2 = (int)(( ((float)drw_h/(float)src_h)) * 1024)
72195b296d0Smrg		| (((int)((float)src_h/(float)drw_h)-1)&7)<<10
72295b296d0Smrg		| 0x8000;
72395b296d0Smrg	else
72495b296d0Smrg	    zoomy2 = ( ((float)src_h/(float)drw_h)) * 1024;
72595b296d0Smrg	OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82);
72695b296d0Smrg	OUTW(vgaIOBase + 4, (zoomy2&0x9f00) | 0x0083);
72795b296d0Smrg    } else {
72895b296d0Smrg	if (drw_h == src_h
72995b296d0Smrg	    || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_h > drw_h))) {
73095b296d0Smrg	    OUTW(vgaIOBase + 4, 0x0082);
73195b296d0Smrg	    OUTW(vgaIOBase + 4, 0x0083);
73295b296d0Smrg	} else
73395b296d0Smrg	    if (drw_h > src_h) {
73495b296d0Smrg		float z;
73595b296d0Smrg
73695b296d0Smrg		z = (float)drw_h/(float)src_h - 1;
73795b296d0Smrg		zoomy1 =  z;
73895b296d0Smrg		zoomy2 = (z - (int)zoomy1 ) * 1024;
73995b296d0Smrg
74095b296d0Smrg		OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82);
74195b296d0Smrg		OUTW(vgaIOBase + 4, (zoomy1&0x0f)<<10 | (zoomy2&0x0300) |0x83);
74295b296d0Smrg	    } else {
74395b296d0Smrg		zoomy1 =   ((float)drw_h/(float)src_h);
74495b296d0Smrg		zoomy2 = ( ((float)drw_h/(float)src_h) - (int)zoomy1 ) * 1024;
74595b296d0Smrg		OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82);
74695b296d0Smrg		OUTW(vgaIOBase + 4, (zoomy2&0x0300)|
74795b296d0Smrg		     (((int)((float)src_h/(float)drw_h)-1)&7)<<10 | 0x8083);
74895b296d0Smrg	    }
74995b296d0Smrg    }
75095b296d0Smrg
75195b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
75295b296d0Smrg	int lb = (width+2) >> 2;
75395b296d0Smrg
75495b296d0Smrg    	OUTW(vgaIOBase + 4, ((lb & 0x100)>>1) | 0x0895);
75595b296d0Smrg    	OUTW(vgaIOBase + 4,  (lb & 0xFF)<<8   | 0x0096);
75695b296d0Smrg    	if ((pTrident->videoFlags & VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC)
75795b296d0Smrg	      && (src_w > 384)) {
75895b296d0Smrg    	    OUTW(0x3C4, 0x0497); /* 2x line buffers */
75995b296d0Smrg    	} else {
76095b296d0Smrg    	    OUTW(0x3C4, 0x0097); /* 1x line buffers */
76195b296d0Smrg    	}
76295b296d0Smrg    	OUTW(vgaIOBase + 4, 0x0097);
76395b296d0Smrg    	OUTW(vgaIOBase + 4, 0x00BA);
76495b296d0Smrg    	OUTW(vgaIOBase + 4, 0x00BB);
76595b296d0Smrg    	OUTW(vgaIOBase + 4, 0xFFBC);
76695b296d0Smrg    	OUTW(vgaIOBase + 4, 0xFFBD);
76795b296d0Smrg    	OUTW(vgaIOBase + 4, 0x04BE);
76895b296d0Smrg    	OUTW(vgaIOBase + 4, 0x948E);
76995b296d0Smrg    } else {
77095b296d0Smrg
77195b296d0Smrg    	OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2))
77295b296d0Smrg					? (width >> 2) : (width >> 6)) << 8) | 0x95);
77395b296d0Smrg    	OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2))
77495b296d0Smrg				? ((width+2) >> 2) : ((width+2) >> 6)) << 8) |0x96);
77595b296d0Smrg
77695b296d0Smrg    	OUTW(vgaIOBase + 4, 0x948E);
77795b296d0Smrg	OUTB(0x83C8, 0x00);
77895b296d0Smrg	OUTB(0x83C6, 0x95);
77995b296d0Smrg    }
78095b296d0Smrg}
78195b296d0Smrg
78295b296d0Smrgstatic int
78395b296d0SmrgTRIDENTPutImage(
78495b296d0Smrg  ScrnInfoPtr pScrn,
78595b296d0Smrg  short src_x, short src_y,
78695b296d0Smrg  short drw_x, short drw_y,
78795b296d0Smrg  short src_w, short src_h,
78895b296d0Smrg  short drw_w, short drw_h,
78995b296d0Smrg  int id, unsigned char* buf,
79095b296d0Smrg  short width, short height,
79195b296d0Smrg  Bool sync,
79295b296d0Smrg  RegionPtr clipBoxes, pointer data,
79395b296d0Smrg  DrawablePtr pDraw
79495b296d0Smrg){
79595b296d0Smrg   TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data;
79695b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
79795b296d0Smrg   INT32 x1, x2, y1, y2;
79895b296d0Smrg   unsigned char *dst_start;
79995b296d0Smrg   int new_size, offset, offset2 = 0, offset3 = 0;
80095b296d0Smrg   int srcPitch, srcPitch2 = 0, dstPitch;
80195b296d0Smrg   int top, left, npixels, nlines, bpp;
80295b296d0Smrg   BoxRec dstBox;
80395b296d0Smrg   CARD32 tmp;
80495b296d0Smrg
80595b296d0Smrg   /* Clip */
80695b296d0Smrg   x1 = src_x;
80795b296d0Smrg   x2 = src_x + src_w;
80895b296d0Smrg   y1 = src_y;
80995b296d0Smrg   y2 = src_y + src_h;
81095b296d0Smrg
81195b296d0Smrg   dstBox.x1 = drw_x;
81295b296d0Smrg   dstBox.x2 = drw_x + drw_w;
81395b296d0Smrg   dstBox.y1 = drw_y;
81495b296d0Smrg   dstBox.y2 = drw_y + drw_h;
81595b296d0Smrg
81695b296d0Smrg   if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
81795b296d0Smrg								width, height))
81895b296d0Smrg	return Success;
81995b296d0Smrg
82095b296d0Smrg   dstBox.x1 -= pScrn->frameX0;
82195b296d0Smrg   dstBox.x2 -= pScrn->frameX0;
82295b296d0Smrg   dstBox.y1 -= pScrn->frameY0;
82395b296d0Smrg   dstBox.y2 -= pScrn->frameY0;
82495b296d0Smrg
82595b296d0Smrg   bpp = pScrn->bitsPerPixel >> 3;
82695b296d0Smrg
82795b296d0Smrg   dstPitch = ((width << 1) + 15) & ~15;
82895b296d0Smrg   new_size = ((dstPitch * height) + bpp - 1) / bpp;
82995b296d0Smrg   switch(id) {
83095b296d0Smrg   case FOURCC_YV12:
83195b296d0Smrg   case FOURCC_I420:
83295b296d0Smrg	srcPitch = (width + 3) & ~3;
83395b296d0Smrg	offset2 = srcPitch * height;
83495b296d0Smrg	srcPitch2 = ((width >> 1) + 3) & ~3;
83595b296d0Smrg	offset3 = (srcPitch2 * (height >> 1)) + offset2;
83695b296d0Smrg	break;
83795b296d0Smrg   case FOURCC_UYVY:
83895b296d0Smrg   case FOURCC_YUY2:
83995b296d0Smrg   default:
84095b296d0Smrg	srcPitch = (width << 1);
84195b296d0Smrg	break;
84295b296d0Smrg   }
84395b296d0Smrg
84495b296d0Smrg   if(!(pPriv->linear = TRIDENTAllocateMemory(pScrn, pPriv->linear, new_size)))
84595b296d0Smrg	return BadAlloc;
84695b296d0Smrg
84795b296d0Smrg    /* copy data */
84895b296d0Smrg   top = y1 >> 16;
84995b296d0Smrg   left = (x1 >> 16) & ~1;
85095b296d0Smrg   npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
85195b296d0Smrg   left <<= 1;
85295b296d0Smrg
85395b296d0Smrg   offset = pPriv->linear->offset * bpp;
85495b296d0Smrg
85595b296d0Smrg   dst_start = pTrident->FbBase + offset + left + (top * dstPitch);
85695b296d0Smrg
85795b296d0Smrg   switch(id) {
85895b296d0Smrg    case FOURCC_YV12:
85995b296d0Smrg    case FOURCC_I420:
86095b296d0Smrg	top &= ~1;
86195b296d0Smrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
86295b296d0Smrg	offset2 += tmp;
86395b296d0Smrg	offset3 += tmp;
86495b296d0Smrg	if(id == FOURCC_I420) {
86595b296d0Smrg	   tmp = offset2;
86695b296d0Smrg	   offset2 = offset3;
86795b296d0Smrg	   offset3 = tmp;
86895b296d0Smrg	}
86995b296d0Smrg	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
87095b296d0Smrg	xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
87195b296d0Smrg				buf + offset2, buf + offset3, dst_start,
87295b296d0Smrg				srcPitch, srcPitch2, dstPitch, nlines, npixels);
87395b296d0Smrg	break;
87495b296d0Smrg    case FOURCC_UYVY:
87595b296d0Smrg    case FOURCC_YUY2:
87695b296d0Smrg    default:
87795b296d0Smrg	buf += (top * srcPitch) + left;
87895b296d0Smrg	nlines = ((y2 + 0xffff) >> 16) - top;
87995b296d0Smrg	xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
88095b296d0Smrg        break;
88195b296d0Smrg    }
88295b296d0Smrg
88395b296d0Smrg    /* update cliplist */
88495b296d0Smrg    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
88595b296d0Smrg    	/* update cliplist */
88695b296d0Smrg        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
88795b296d0Smrg        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
88895b296d0Smrg    }
88995b296d0Smrg
89095b296d0Smrg    offset += top * dstPitch;
89195b296d0Smrg
892ff89ac2bSmrg    /* Fix video position when using doublescan */
893ff89ac2bSmrg    if(pScrn->currentMode->Flags & V_DBLSCAN) {
894ff89ac2bSmrg	    dstBox.y1 <<= 1;
895ff89ac2bSmrg	    dstBox.y2 <<= 1;
896ff89ac2bSmrg	    drw_h <<= 1;
897ff89ac2bSmrg    }
898ff89ac2bSmrg
89995b296d0Smrg    tridentFixFrame(pScrn,&pPriv->fixFrame);
90095b296d0Smrg    TRIDENTDisplayVideo(pScrn, id, offset, width, height, dstPitch,
90195b296d0Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
90295b296d0Smrg
90395b296d0Smrg    pPriv->videoStatus = CLIENT_VIDEO_ON;
90495b296d0Smrg
90595b296d0Smrg    pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback;
90695b296d0Smrg
90795b296d0Smrg    return Success;
90895b296d0Smrg}
90995b296d0Smrg
91095b296d0Smrgstatic int
91195b296d0SmrgTRIDENTQueryImageAttributes(
91295b296d0Smrg  ScrnInfoPtr pScrn,
91395b296d0Smrg  int id,
91495b296d0Smrg  unsigned short *w, unsigned short *h,
91595b296d0Smrg  int *pitches, int *offsets
91695b296d0Smrg){
91795b296d0Smrg    int size, tmp;
91895b296d0Smrg
91995b296d0Smrg    if(*w > 1024) *w = 1024;
92095b296d0Smrg    if(*h > 1024) *h = 1024;
92195b296d0Smrg
92295b296d0Smrg    *w = (*w + 1) & ~1;
92395b296d0Smrg    if(offsets) offsets[0] = 0;
92495b296d0Smrg
92595b296d0Smrg    switch(id) {
92695b296d0Smrg    case FOURCC_YV12:		/* YV12 */
92795b296d0Smrg	*h = (*h + 1) & ~1;
92895b296d0Smrg	size = (*w + 3) & ~3;
92995b296d0Smrg	if(pitches) pitches[0] = size;
93095b296d0Smrg	size *= *h;
93195b296d0Smrg	if(offsets) offsets[1] = size;
93295b296d0Smrg	tmp = ((*w >> 1) + 3) & ~3;
93395b296d0Smrg	if(pitches) pitches[1] = pitches[2] = tmp;
93495b296d0Smrg	tmp *= (*h >> 1);
93595b296d0Smrg	size += tmp;
93695b296d0Smrg	if(offsets) offsets[2] = size;
93795b296d0Smrg	size += tmp;
93895b296d0Smrg	break;
93995b296d0Smrg    default:			/* RGB15, RGB16, YUY2 */
94095b296d0Smrg	size = *w << 1;
94195b296d0Smrg	if(pitches) pitches[0] = size;
94295b296d0Smrg	size *= *h;
94395b296d0Smrg	break;
94495b296d0Smrg    }
94595b296d0Smrg
94695b296d0Smrg    return size;
94795b296d0Smrg}
94895b296d0Smrg
94995b296d0Smrg/****************** Offscreen stuff ***************/
95095b296d0Smrg
95195b296d0Smrgtypedef struct {
95295b296d0Smrg  FBLinearPtr linear;
95395b296d0Smrg  Bool isOn;
95495b296d0Smrg} OffscreenPrivRec, * OffscreenPrivPtr;
95595b296d0Smrg
95695b296d0Smrgstatic int
95795b296d0SmrgTRIDENTAllocateSurface(
95895b296d0Smrg    ScrnInfoPtr pScrn,
95995b296d0Smrg    int id,
96095b296d0Smrg    unsigned short w,
96195b296d0Smrg    unsigned short h,
96295b296d0Smrg    XF86SurfacePtr surface
96395b296d0Smrg){
96495b296d0Smrg    FBLinearPtr linear;
96595b296d0Smrg    int pitch, size, bpp;
96695b296d0Smrg    OffscreenPrivPtr pPriv;
96795b296d0Smrg
96895b296d0Smrg    if((w > 1024) || (h > 1024))
96995b296d0Smrg	return BadAlloc;
97095b296d0Smrg
97195b296d0Smrg    w = (w + 1) & ~1;
97295b296d0Smrg    pitch = ((w << 1) + 15) & ~15;
97395b296d0Smrg    bpp = pScrn->bitsPerPixel >> 3;
97495b296d0Smrg    size = ((pitch * h) + bpp - 1) / bpp;
97595b296d0Smrg
97695b296d0Smrg    if(!(linear = TRIDENTAllocateMemory(pScrn, NULL, size)))
97795b296d0Smrg	return BadAlloc;
97895b296d0Smrg
97995b296d0Smrg    surface->width = w;
98095b296d0Smrg    surface->height = h;
98195b296d0Smrg
98295b296d0Smrg    if(!(surface->pitches = xalloc(sizeof(int)))) {
98395b296d0Smrg	xf86FreeOffscreenLinear(linear);
98495b296d0Smrg	return BadAlloc;
98595b296d0Smrg    }
98695b296d0Smrg    if(!(surface->offsets = xalloc(sizeof(int)))) {
98795b296d0Smrg	xfree(surface->pitches);
98895b296d0Smrg	xf86FreeOffscreenLinear(linear);
98995b296d0Smrg	return BadAlloc;
99095b296d0Smrg    }
99195b296d0Smrg    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
99295b296d0Smrg	xfree(surface->pitches);
99395b296d0Smrg	xfree(surface->offsets);
99495b296d0Smrg	xf86FreeOffscreenLinear(linear);
99595b296d0Smrg	return BadAlloc;
99695b296d0Smrg    }
99795b296d0Smrg
99895b296d0Smrg    pPriv->linear = linear;
99995b296d0Smrg    pPriv->isOn = FALSE;
100095b296d0Smrg
100195b296d0Smrg    surface->pScrn = pScrn;
100295b296d0Smrg    surface->id = id;
100395b296d0Smrg    surface->pitches[0] = pitch;
100495b296d0Smrg    surface->offsets[0] = linear->offset * bpp;
100595b296d0Smrg    surface->devPrivate.ptr = (pointer)pPriv;
100695b296d0Smrg
100795b296d0Smrg    return Success;
100895b296d0Smrg}
100995b296d0Smrg
101095b296d0Smrgstatic int
101195b296d0SmrgTRIDENTStopSurface(
101295b296d0Smrg    XF86SurfacePtr surface
101395b296d0Smrg){
101495b296d0Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
101595b296d0Smrg
101695b296d0Smrg    if(pPriv->isOn) {
101795b296d0Smrg	TRIDENTPtr pTrident = TRIDENTPTR(surface->pScrn);
101895b296d0Smrg    	int vgaIOBase = VGAHWPTR(surface->pScrn)->IOBase;
101995b296d0Smrg	WaitForVBlank(surface->pScrn);
102095b296d0Smrg 	OUTW(vgaIOBase + 4, 0x848E);
102195b296d0Smrg	OUTW(vgaIOBase + 4, 0x0091);
102295b296d0Smrg	pPriv->isOn = FALSE;
102395b296d0Smrg    }
102495b296d0Smrg
102595b296d0Smrg    return Success;
102695b296d0Smrg}
102795b296d0Smrg
102895b296d0Smrg
102995b296d0Smrgstatic int
103095b296d0SmrgTRIDENTFreeSurface(
103195b296d0Smrg    XF86SurfacePtr surface
103295b296d0Smrg){
103395b296d0Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
103495b296d0Smrg
103595b296d0Smrg    if(pPriv->isOn)
103695b296d0Smrg	TRIDENTStopSurface(surface);
103795b296d0Smrg    xf86FreeOffscreenLinear(pPriv->linear);
103895b296d0Smrg    xfree(surface->pitches);
103995b296d0Smrg    xfree(surface->offsets);
104095b296d0Smrg    xfree(surface->devPrivate.ptr);
104195b296d0Smrg
104295b296d0Smrg    return Success;
104395b296d0Smrg}
104495b296d0Smrg
104595b296d0Smrgstatic int
104695b296d0SmrgTRIDENTGetSurfaceAttribute(
104795b296d0Smrg    ScrnInfoPtr pScrn,
104895b296d0Smrg    Atom attribute,
104995b296d0Smrg    INT32 *value
105095b296d0Smrg){
105195b296d0Smrg    return TRIDENTGetPortAttribute(pScrn, attribute, value,
105295b296d0Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
105395b296d0Smrg}
105495b296d0Smrg
105595b296d0Smrgstatic int
105695b296d0SmrgTRIDENTSetSurfaceAttribute(
105795b296d0Smrg    ScrnInfoPtr pScrn,
105895b296d0Smrg    Atom attribute,
105995b296d0Smrg    INT32 value
106095b296d0Smrg){
106195b296d0Smrg    return TRIDENTSetPortAttribute(pScrn, attribute, value,
106295b296d0Smrg			(pointer)(GET_PORT_PRIVATE(pScrn)));
106395b296d0Smrg}
106495b296d0Smrg
106595b296d0Smrgstatic int
106695b296d0SmrgTRIDENTDisplaySurface(
106795b296d0Smrg    XF86SurfacePtr surface,
106895b296d0Smrg    short src_x, short src_y,
106995b296d0Smrg    short drw_x, short drw_y,
107095b296d0Smrg    short src_w, short src_h,
107195b296d0Smrg    short drw_w, short drw_h,
107295b296d0Smrg    RegionPtr clipBoxes
107395b296d0Smrg){
107495b296d0Smrg    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
107595b296d0Smrg    ScrnInfoPtr pScrn = surface->pScrn;
107695b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
107795b296d0Smrg    TRIDENTPortPrivPtr portPriv = pTrident->adaptor->pPortPrivates[0].ptr;
107895b296d0Smrg    INT32 x1, y1, x2, y2;
107995b296d0Smrg    BoxRec dstBox;
108095b296d0Smrg
108195b296d0Smrg    x1 = src_x;
108295b296d0Smrg    x2 = src_x + src_w;
108395b296d0Smrg    y1 = src_y;
108495b296d0Smrg    y2 = src_y + src_h;
108595b296d0Smrg
108695b296d0Smrg    dstBox.x1 = drw_x;
108795b296d0Smrg    dstBox.x2 = drw_x + drw_w;
108895b296d0Smrg    dstBox.y1 = drw_y;
108995b296d0Smrg    dstBox.y2 = drw_y + drw_h;
109095b296d0Smrg
109195b296d0Smrg    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
109295b296d0Smrg			surface->width, surface->height))
109395b296d0Smrg    {
109495b296d0Smrg	return Success;
109595b296d0Smrg    }
109695b296d0Smrg
109795b296d0Smrg    dstBox.x1 -= pScrn->frameX0;
109895b296d0Smrg    dstBox.x2 -= pScrn->frameX0;
109995b296d0Smrg    dstBox.y1 -= pScrn->frameY0;
110095b296d0Smrg    dstBox.y2 -= pScrn->frameY0;
110195b296d0Smrg
110295b296d0Smrg    TRIDENTResetVideo(pScrn);
110395b296d0Smrg
110495b296d0Smrg    tridentFixFrame(pScrn,&portPriv->fixFrame);
110595b296d0Smrg    TRIDENTDisplayVideo(pScrn, surface->id, surface->offsets[0],
110695b296d0Smrg	     surface->width, surface->height, surface->pitches[0],
110795b296d0Smrg	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
110895b296d0Smrg
110995b296d0Smrg    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
111095b296d0Smrg
111195b296d0Smrg    pPriv->isOn = TRUE;
111295b296d0Smrg    /* we've prempted the XvImage stream so set its free timer */
111395b296d0Smrg    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
111495b296d0Smrg	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
111595b296d0Smrg	UpdateCurrentTime();
111695b296d0Smrg	portPriv->videoStatus = FREE_TIMER;
111795b296d0Smrg	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
111895b296d0Smrg	pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback;
111995b296d0Smrg    }
112095b296d0Smrg
112195b296d0Smrg    return Success;
112295b296d0Smrg}
112395b296d0Smrg
112495b296d0Smrgstatic void
112595b296d0SmrgTRIDENTInitOffscreenImages(ScreenPtr pScreen)
112695b296d0Smrg{
112795b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
112895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
112995b296d0Smrg    XF86OffscreenImagePtr offscreenImages;
113095b296d0Smrg
113195b296d0Smrg    /* need to free this someplace */
113295b296d0Smrg    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
113395b296d0Smrg	return;
113495b296d0Smrg
113595b296d0Smrg    offscreenImages[0].image = &Images[0];
113695b296d0Smrg    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
113795b296d0Smrg			       VIDEO_CLIP_TO_VIEWPORT;
113895b296d0Smrg    offscreenImages[0].alloc_surface = TRIDENTAllocateSurface;
113995b296d0Smrg    offscreenImages[0].free_surface = TRIDENTFreeSurface;
114095b296d0Smrg    offscreenImages[0].display = TRIDENTDisplaySurface;
114195b296d0Smrg    offscreenImages[0].stop = TRIDENTStopSurface;
114295b296d0Smrg    offscreenImages[0].setAttribute = TRIDENTSetSurfaceAttribute;
114395b296d0Smrg    offscreenImages[0].getAttribute = TRIDENTGetSurfaceAttribute;
114495b296d0Smrg    offscreenImages[0].max_width = 1024;
114595b296d0Smrg    offscreenImages[0].max_height = 1024;
114695b296d0Smrg    if (pTrident->Chipset >= CYBER9388) {
114795b296d0Smrg    	offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
114895b296d0Smrg    } else {
114995b296d0Smrg    	offscreenImages[0].num_attributes = 1; /* just colorkey */
115095b296d0Smrg    }
115195b296d0Smrg    offscreenImages[0].attributes = Attributes;
115295b296d0Smrg
115395b296d0Smrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
115495b296d0Smrg}
115595b296d0Smrg
115695b296d0Smrgstatic void
115795b296d0SmrgTRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
115895b296d0Smrg{
115995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
116095b296d0Smrg    TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr;
116195b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
116295b296d0Smrg
116395b296d0Smrg    if(pPriv->videoStatus & TIMER_MASK) {
116495b296d0Smrg	if(pPriv->videoStatus & OFF_TIMER) {
116595b296d0Smrg	    if(pPriv->offTime < time) {
116695b296d0Smrg		WaitForVBlank(pScrn);
116795b296d0Smrg  		OUTW(vgaIOBase + 4, 0x848E);
116895b296d0Smrg		OUTW(vgaIOBase + 4, 0x0091);
116995b296d0Smrg		pPriv->videoStatus = FREE_TIMER;
117095b296d0Smrg		pPriv->freeTime = time + FREE_DELAY;
117195b296d0Smrg	    }
117295b296d0Smrg	} else {  /* FREE_TIMER */
117395b296d0Smrg	    if(pPriv->freeTime < time) {
117495b296d0Smrg		if(pPriv->linear) {
117595b296d0Smrg		   xf86FreeOffscreenLinear(pPriv->linear);
117695b296d0Smrg		   pPriv->linear = NULL;
117795b296d0Smrg		}
117895b296d0Smrg		pPriv->videoStatus = 0;
117995b296d0Smrg	        pTrident->VideoTimerCallback = NULL;
118095b296d0Smrg	    }
118195b296d0Smrg        }
118295b296d0Smrg    } else  /* shouldn't get here */
118395b296d0Smrg	pTrident->VideoTimerCallback = NULL;
118495b296d0Smrg}
118595b296d0Smrg
118695b296d0Smrg    /* Calculate skew offsets for video overlay */
118795b296d0Smrg
118895b296d0Smrg
118995b296d0Smrgvoid
119095b296d0SmrgtridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame)
119195b296d0Smrg{
119295b296d0Smrg
119395b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
119495b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
119595b296d0Smrg    int HTotal, HSyncStart;
119695b296d0Smrg    int VTotal, VSyncStart;
119795b296d0Smrg    int h_off = 0;
119895b296d0Smrg    int v_off = 0;
119995b296d0Smrg    unsigned char CRTC[0x11];
120095b296d0Smrg    unsigned char hcenter, vcenter;
120195b296d0Smrg    Bool isShadow;
120295b296d0Smrg    unsigned char shadow = 0;
120395b296d0Smrg
120495b296d0Smrg    if ((*fixFrame)++ < 100)
120595b296d0Smrg	return;
120695b296d0Smrg
120795b296d0Smrg  *fixFrame = 0;
120895b296d0Smrg
120995b296d0Smrg  OUTB(0x3CE, CyberControl);
121095b296d0Smrg  isShadow = ((INB(0x3CF) & 0x81) == 0x81);
121195b296d0Smrg
121295b296d0Smrg  if (isShadow)
121395b296d0Smrg      SHADOW_ENABLE(shadow);
121495b296d0Smrg
121595b296d0Smrg    OUTB(vgaIOBase + 4, 0x0);
121695b296d0Smrg    CRTC[0x0] = INB(vgaIOBase + 5);
121795b296d0Smrg    OUTB(vgaIOBase + 4, 0x4);
121895b296d0Smrg    CRTC[0x4] = INB(vgaIOBase + 5);
121995b296d0Smrg    OUTB(vgaIOBase + 4, 0x5);
122095b296d0Smrg    CRTC[0x5] = INB(vgaIOBase + 5);
122195b296d0Smrg    OUTB(vgaIOBase + 4, 0x6);
122295b296d0Smrg    CRTC[0x6] = INB(vgaIOBase + 5);
122395b296d0Smrg    OUTB(vgaIOBase + 4, 0x7);
122495b296d0Smrg    CRTC[0x7] = INB(vgaIOBase + 5);
122595b296d0Smrg    OUTB(vgaIOBase + 4, 0x10);
122695b296d0Smrg    CRTC[0x10] = INB(vgaIOBase + 5);
122795b296d0Smrg    OUTB(0x3CE, HorStretch);
122895b296d0Smrg    hcenter = INB(0x3CF);
122995b296d0Smrg    OUTB(0x3CE, VertStretch);
123095b296d0Smrg    vcenter = INB(0x3CF);
123195b296d0Smrg
123295b296d0Smrg    HTotal = CRTC[0] << 3;
123395b296d0Smrg    VTotal = CRTC[6]
123495b296d0Smrg	| ((CRTC[7] & (1<<0)) << 8)
123595b296d0Smrg	| ((CRTC[7] & (1<<5)) << 4);
123695b296d0Smrg    HSyncStart = (CRTC[4]
123795b296d0Smrg		  + ((CRTC[5] >> 5) & 0x3)) << 3;
123895b296d0Smrg    VSyncStart = CRTC[0x10]
123995b296d0Smrg	| ((CRTC[7] & (1<<2)) << 6)
124095b296d0Smrg	| ((CRTC[7] & (1<<7)) << 2);
124195b296d0Smrg
124295b296d0Smrg    if (isShadow) {
124395b296d0Smrg	SHADOW_RESTORE(shadow);
124495b296d0Smrg	if (pTrident->lcdMode != 0xff) {
124595b296d0Smrg	    if (hcenter & 0x80) {
124695b296d0Smrg	    h_off = (LCD[pTrident->lcdMode].display_x
124795b296d0Smrg		     - pScrn->currentMode->HDisplay) >> 1;
124895b296d0Smrg		switch (pTrident->Chipset) {
124995b296d0Smrg		    case BLADEXP:
125095b296d0Smrg			h_off -= 5;
125195b296d0Smrg		}
125295b296d0Smrg	    }
125395b296d0Smrg	    if (vcenter & 0x80) {
125495b296d0Smrg	    v_off = (LCD[pTrident->lcdMode].display_y
125595b296d0Smrg		     - pScrn->currentMode->VDisplay) >> 1;
125695b296d0Smrg	}
125795b296d0Smrg    }
125895b296d0Smrg    }
125995b296d0Smrg
126095b296d0Smrg    pTrident->hsync = HTotal - HSyncStart + 23 + h_off;
126195b296d0Smrg    pTrident->vsync = VTotal - VSyncStart - 2 + v_off;
126295b296d0Smrg    pTrident->hsync_rskew = 0;
126395b296d0Smrg    pTrident->vsync_bskew = 0;
126495b296d0Smrg
126595b296d0Smrg    /*
126695b296d0Smrg     * HACK !! As awful as this is, it appears to be the only way....Sigh!
126795b296d0Smrg     * We have XvHsync and XvVsync as options now, which adjust
126895b296d0Smrg     * at the very end of this function. It'll be helpful for now
126995b296d0Smrg     * and we can get more data on some of these skew values.
127095b296d0Smrg     */
127195b296d0Smrg    switch (pTrident->Chipset) {
127295b296d0Smrg	case TGUI9680:
127395b296d0Smrg	    /* Furthur tweaking needed */
127495b296d0Smrg    	    pTrident->hsync -= 84;
127595b296d0Smrg	    pTrident->vsync += 2;
127695b296d0Smrg	    break;
127795b296d0Smrg	case PROVIDIA9682:
127895b296d0Smrg	    /* Furthur tweaking needed */
127995b296d0Smrg	    pTrident->hsync += 7;
128095b296d0Smrg	    break;
128195b296d0Smrg	case PROVIDIA9685:
128295b296d0Smrg	    /* Spot on */
128395b296d0Smrg	    break;
128495b296d0Smrg        case BLADEXP:
128595b296d0Smrg        case CYBERBLADEXPAI1:
128695b296d0Smrg	    pTrident->hsync -= 15;
128795b296d0Smrg	    pTrident->hsync_rskew = 3;
128895b296d0Smrg	    break;
128995b296d0Smrg	case BLADE3D:
129095b296d0Smrg	    if (pScrn->depth == 24)
129195b296d0Smrg		pTrident->hsync -= 8;
129295b296d0Smrg	    else
129395b296d0Smrg		pTrident->hsync -= 6;
129495b296d0Smrg	    break;
129595b296d0Smrg	case CYBERBLADEI7:
129695b296d0Smrg	case CYBERBLADEI7D:
129795b296d0Smrg	case CYBERBLADEI1:
129895b296d0Smrg	case CYBERBLADEI1D:
129995b296d0Smrg	    if (pScrn->depth == 24)
130095b296d0Smrg		pTrident->hsync -= 7;
130195b296d0Smrg	    else
130295b296d0Smrg		pTrident->hsync -= 6;
130395b296d0Smrg	    break;
130495b296d0Smrg	case CYBERBLADEAI1:
130595b296d0Smrg	    pTrident->hsync -= 7;
130695b296d0Smrg	    break;
130795b296d0Smrg	case CYBERBLADEAI1D:
130895b296d0Smrg	    pTrident->vsync += 2;
130995b296d0Smrg	    pTrident->vsync_bskew = -4;
131095b296d0Smrg	    pTrident->hsync -= 5;
131195b296d0Smrg	    break;
131295b296d0Smrg	case CYBERBLADEE4:
131395b296d0Smrg	    pTrident->hsync -= 8;
131495b296d0Smrg	    break;
1315ff89ac2bSmrg	case CYBERBLADEXP4:
1316ff89ac2bSmrg	    pTrident->hsync -= 24;
1317ff89ac2bSmrg	    pTrident->hsync_rskew = -1;
1318ff89ac2bSmrg	    break;
131995b296d0Smrg	case CYBER9397:
132095b296d0Smrg	    pTrident->hsync -= 1;
132195b296d0Smrg  	    pTrident->vsync -= 0;
132295b296d0Smrg	    pTrident->vsync_bskew = 0;
132395b296d0Smrg	    break;
1324ff89ac2bSmrg	case CYBER9397DVD:
132595b296d0Smrg	    pTrident->hsync_rskew = -1;
132695b296d0Smrg	    pTrident->vsync_bskew = -1;
132795b296d0Smrg	    break;
132895b296d0Smrg    }
132995b296d0Smrg    pTrident->hsync+=pTrident->OverrideHsync;
133095b296d0Smrg    pTrident->vsync+=pTrident->OverrideVsync;
133195b296d0Smrg    pTrident->hsync_rskew += pTrident->OverrideRskew;
133295b296d0Smrg    pTrident->vsync_bskew += pTrident->OverrideBskew;
133395b296d0Smrg}
133495b296d0Smrg
133595b296d0Smrgstatic void
133695b296d0SmrgWaitForVBlank(ScrnInfoPtr pScrn)
133795b296d0Smrg{
133895b296d0Smrg    register vgaHWPtr hwp = VGAHWPTR(pScrn);
133995b296d0Smrg
134095b296d0Smrg    /* We have to wait for one full VBlank to let the video engine start/stop.
134195b296d0Smrg     * So the first may be waiting for too short a period as it may already
134295b296d0Smrg     * be part way through the video frame. So we wait a second time to ensure
134395b296d0Smrg     * full vblank has passed.
134495b296d0Smrg     * - Alan.
134595b296d0Smrg     */
1346ff89ac2bSmrg    if (!xf86IsPc98()) {
1347ff89ac2bSmrg       WAITFORVSYNC;
1348ff89ac2bSmrg       WAITFORVSYNC;
1349ff89ac2bSmrg    }
135095b296d0Smrg}
1351