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