trident_video.c revision 14330f12
1/* 2 * Copyright 1992-2003 by Alan Hourihane, North Wales, UK. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Alan Hourihane, alanh@fairlite.demon.co.uk 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "compiler.h" 32#include "xf86PciInfo.h" 33#include "xf86Pci.h" 34#include "xf86fbman.h" 35#include "regionstr.h" 36 37#include "trident.h" 38#include "trident_regs.h" 39#include <X11/extensions/Xv.h> 40#include "xaa.h" 41#include "xaalocal.h" 42#include "dixstruct.h" 43#include "fourcc.h" 44 45#define OFF_DELAY 800 /* milliseconds */ 46#define FREE_DELAY 60000 47 48#define OFF_TIMER 0x01 49#define FREE_TIMER 0x02 50#define CLIENT_VIDEO_ON 0x04 51 52#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 53 54static XF86VideoAdaptorPtr TRIDENTSetupImageVideo(ScreenPtr); 55static void TRIDENTInitOffscreenImages(ScreenPtr); 56static void TRIDENTStopVideo(ScrnInfoPtr, pointer, Bool); 57static int TRIDENTSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 58static int TRIDENTGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 59static void TRIDENTQueryBestSize(ScrnInfoPtr, Bool, 60 short, short, short, short, unsigned int *, unsigned int *, pointer); 61static int TRIDENTPutImage( ScrnInfoPtr, 62 short, short, short, short, short, short, short, short, 63 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 64 DrawablePtr); 65static int TRIDENTQueryImageAttributes(ScrnInfoPtr, 66 int, unsigned short *, unsigned short *, int *, int *); 67static void TRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time); 68static void tridentSetVideoContrast(TRIDENTPtr pTrident,int value); 69static void tridentSetVideoParameters(TRIDENTPtr pTrident, int brightness, 70 int saturation, int hue); 71void tridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame); 72static void WaitForVBlank(ScrnInfoPtr pScrn); 73 74#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 75 76static Atom xvColorKey, xvSaturation, xvBrightness, xvHUE, xvContrast; 77 78void TRIDENTInitVideo(ScreenPtr pScreen) 79{ 80 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 81 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 82 XF86VideoAdaptorPtr newAdaptor = NULL; 83 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 84 int num_adaptors; 85 86 /* 87 * The following has been tested on: 88 * 89 * 9525 : flags: None 90 * Image985 : flags: None 91 * Cyber9397(DVD) : flags: VID_ZOOM_NOMINI 92 * CyberBlade/i7: flags: VID_ZOOM_INV | VID_ZOOM_MINI 93 * CyberBlade/i1: flags: VID_ZOOM_INV | VID_ZOOM_MINI 94 * CyberBlade/Ai1: flags: VID_ZOOM_INV 95 * Cyber 9540 : flags: VID_ZOOM_INV | VID_SHIFT_4 96 * CyberXPm8 : flags: VID_ZOOM_INV | VID_SHIFT_4 97 * 98 * When you make changes make sure not to break these 99 * Add new chipsets to this list. 100 */ 101 if (pTrident->Chipset >= BLADE3D) { 102 pTrident->videoFlags = VID_ZOOM_INV ; 103 if (pTrident->Chipset <= CYBERBLADEI1D) 104 pTrident->videoFlags |= VID_ZOOM_MINI; 105 else if (pTrident->Chipset < CYBERBLADEAI1 /* verified EE */ 106 || pTrident->Chipset > CYBERBLADEAI1D) 107 pTrident->videoFlags |= VID_OFF_SHIFT_4; 108 } 109 if (pTrident->Chipset == CYBER9397 || pTrident->Chipset == CYBER9397DVD) 110 pTrident->videoFlags = VID_ZOOM_NOMINI; 111 112 if (pTrident->Chipset == CYBER9397DVD || 113 pTrident->Chipset == CYBER9525DVD || 114 (pTrident->Chipset >= BLADE3D && pTrident->Chipset < CYBERBLADEXP4)) 115 pTrident->videoFlags |= VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC; 116 117 newAdaptor = TRIDENTSetupImageVideo(pScreen); 118 TRIDENTInitOffscreenImages(pScreen); 119 120 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 121 122 if(newAdaptor) { 123 if(!num_adaptors) { 124 num_adaptors = 1; 125 adaptors = &newAdaptor; 126 } else { 127 newAdaptors = /* need to free this someplace */ 128 malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 129 if(newAdaptors) { 130 memcpy(newAdaptors, adaptors, num_adaptors * 131 sizeof(XF86VideoAdaptorPtr)); 132 newAdaptors[num_adaptors] = newAdaptor; 133 adaptors = newAdaptors; 134 num_adaptors++; 135 } 136 } 137 } 138 139 if(num_adaptors) 140 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 141 142 if(newAdaptors) 143 free(newAdaptors); 144 145 if (pTrident->videoFlags) 146 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,3, 147 "Trident Video Flags: %s %s %s %s\n", 148 pTrident->videoFlags & VID_ZOOM_INV ? "VID_ZOOM_INV" : "", 149 pTrident->videoFlags & VID_ZOOM_MINI ? "VID_ZOOM_MINI" : "", pTrident->videoFlags & VID_OFF_SHIFT_4 ? "VID_OFF_SHIFT_4" 150 : "", 151 pTrident->videoFlags & VID_ZOOM_NOMINI ? "VID_ZOOM_NOMINI" 152 : ""); 153 154} 155 156/* client libraries expect an encoding */ 157static XF86VideoEncodingRec DummyEncoding[1] = 158{ 159 { 160 0, 161 "XV_IMAGE", 162 1024, 1024, 163 {1, 1} 164 } 165}; 166 167#define NUM_FORMATS 4 168 169static XF86VideoFormatRec Formats[NUM_FORMATS] = 170{ 171 {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 172}; 173 174#define NUM_ATTRIBUTES 5 175 176static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 177{ 178 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 179 {XvSettable | XvGettable, 0, 187, "XV_SATURATION"}, 180 {XvSettable | XvGettable, 0, 0x3F, "XV_BRIGHTNESS"}, 181 {XvSettable | XvGettable, 0, 360 , "XV_HUE"}, 182 {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"} 183}; 184 185#define NUM_IMAGES 3 186 187static XF86ImageRec Images[NUM_IMAGES] = 188{ 189 { 190 0x36315652, 191 XvRGB, 192 LSBFirst, 193 {'R','V','1','6', 194 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 195 16, 196 XvPacked, 197 1, 198 16, 0xF800, 0x07E0, 0x001F, 199 0, 0, 0, 200 0, 0, 0, 201 0, 0, 0, 202 {'R','V','B',0, 203 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}, 204 XvTopToBottom 205 }, 206 XVIMAGE_YV12, 207 XVIMAGE_YUY2 208}; 209 210typedef struct { 211 FBLinearPtr linear; 212 RegionRec clip; 213 CARD32 colorKey; 214 CARD8 Saturation; 215 CARD8 Brightness; 216 CARD16 HUE; 217 INT8 Contrast; 218 CARD32 videoStatus; 219 Time offTime; 220 Time freeTime; 221 int fixFrame; 222} TRIDENTPortPrivRec, *TRIDENTPortPrivPtr; 223 224 225#define GET_PORT_PRIVATE(pScrn) \ 226 (TRIDENTPortPrivPtr)((TRIDENTPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 227 228void TRIDENTResetVideo(ScrnInfoPtr pScrn) 229{ 230 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 231 TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr; 232 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 233 int red, green, blue; 234 int tmp; 235 236 WaitForVBlank(pScrn); 237 OUTW(vgaIOBase + 4, 0x848E); 238 239 if (pTrident->Chipset >= CYBER9388) { 240 OUTW(vgaIOBase + 4, 0x80B9); 241 OUTW(vgaIOBase + 4, 0x00BE); 242 OUTW(0x3C4, 0xC057); 243 OUTW(0x3C4, 0x3420); 244 OUTW(0x3C4, 0x3037); 245 } else { 246 if (pTrident->Chipset >= PROVIDIA9682) { 247 OUTB(0x83C8, 0x57); 248 OUTB(0x83C6, 0xC0); 249 OUTW(vgaIOBase + 4, 0x26BE); 250 } else { 251 OUTB(0x83C8, 0x37); 252 OUTB(0x83C6, 0x01); 253 OUTB(0x83C8, 0x00); 254 OUTB(0x83C6, 0x00); 255 } 256 } 257 258 if (pTrident->Chipset >= BLADEXP) { 259 OUTW(0x3C4, 0x007A); 260 OUTW(0x3C4, 0x007D); 261 } 262 if (pTrident->Chipset == CYBERBLADEXP4) { 263 OUTW(0x3CE, 0x0462); 264 } 265 switch (pScrn->depth) { 266 case 8: 267 VIDEOOUT(pPriv->colorKey, pTrident->keyOffset); 268 VIDEOOUT(0x00, (pTrident->keyOffset + 1)); 269 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 270 VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); 271 VIDEOOUT(0x00, (pTrident->keyOffset + 5)); 272 VIDEOOUT(0x00, (pTrident->keyOffset + 6)); 273 break; 274 default: 275 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 276 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 277 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 278 switch (pScrn->depth) { 279 case 15: 280 tmp = (red << 10) | (green << 5) | (blue); 281 VIDEOOUT((tmp & 0xff), pTrident->keyOffset); 282 VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1)); 283 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 284 VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); 285 VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); 286 VIDEOOUT(0x00, (pTrident->keyOffset + 6)); 287 break; 288 case 16: 289 tmp = (red << 11) | (green << 5) | (blue); 290 VIDEOOUT((tmp & 0xff), pTrident->keyOffset); 291 VIDEOOUT((tmp & 0xff00)>>8, (pTrident->keyOffset + 1)); 292 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 293 VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); 294 VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); 295 VIDEOOUT(0x00, (pTrident->keyOffset + 6)); 296 break; 297 case 24: 298 VIDEOOUT(blue, pTrident->keyOffset); 299 VIDEOOUT(green, (pTrident->keyOffset + 1)); 300 VIDEOOUT(red, (pTrident->keyOffset + 2)); 301 VIDEOOUT(0xFF, (pTrident->keyOffset + 4)); 302 VIDEOOUT(0xFF, (pTrident->keyOffset + 5)); 303 VIDEOOUT(0xFF, (pTrident->keyOffset + 6)); 304 break; 305 } 306 } 307 308 if (pTrident->Chipset >= CYBER9388) { 309 tridentSetVideoContrast(pTrident,pPriv->Contrast); 310 tridentSetVideoParameters(pTrident,pPriv->Brightness,pPriv->Saturation, 311 pPriv->HUE); 312 } 313} 314 315 316static XF86VideoAdaptorPtr 317TRIDENTSetupImageVideo(ScreenPtr pScreen) 318{ 319 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 320 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 321 XF86VideoAdaptorPtr adapt; 322 TRIDENTPortPrivPtr pPriv; 323 324 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 325 sizeof(TRIDENTPortPrivRec) + 326 sizeof(DevUnion)))) 327 return NULL; 328 329 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 330 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 331 adapt->name = "Trident Backend Scaler"; 332 adapt->nEncodings = 1; 333 adapt->pEncodings = DummyEncoding; 334 adapt->nFormats = NUM_FORMATS; 335 adapt->pFormats = Formats; 336 adapt->nPorts = 1; 337 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 338 pPriv = (TRIDENTPortPrivPtr)(&adapt->pPortPrivates[1]); 339 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 340 adapt->pAttributes = Attributes; 341 adapt->nImages = NUM_IMAGES; 342 if (pTrident->Chipset >= CYBER9388) { 343 adapt->nAttributes = NUM_ATTRIBUTES; 344 } else { 345 adapt->nAttributes = 1; /* Just colorkey */ 346 } 347 adapt->pImages = Images; 348 adapt->PutVideo = NULL; 349 adapt->PutStill = NULL; 350 adapt->GetVideo = NULL; 351 adapt->GetStill = NULL; 352 adapt->StopVideo = TRIDENTStopVideo; 353 adapt->SetPortAttribute = TRIDENTSetPortAttribute; 354 adapt->GetPortAttribute = TRIDENTGetPortAttribute; 355 adapt->QueryBestSize = TRIDENTQueryBestSize; 356 adapt->PutImage = TRIDENTPutImage; 357 adapt->QueryImageAttributes = TRIDENTQueryImageAttributes; 358 359 pPriv->colorKey = pTrident->videoKey & ((1 << pScrn->depth) - 1); 360 pPriv->Brightness = 45; 361 pPriv->Saturation = 80; 362 pPriv->Contrast = 4; 363 pPriv->HUE = 0; 364 pPriv->videoStatus = 0; 365 pPriv->fixFrame = 100; 366 367 /* gotta uninit this someplace */ 368 REGION_NULL(pScreen, &pPriv->clip); 369 370 pTrident->adaptor = adapt; 371 372 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 373 374 if (pTrident->Chipset >= CYBER9388) { 375 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 376 xvSaturation = MAKE_ATOM("XV_SATURATION"); 377 xvHUE = MAKE_ATOM("XV_HUE"); 378 xvContrast = MAKE_ATOM("XV_CONTRAST"); 379 } 380 381 if (pTrident->Chipset >= PROVIDIA9682) 382 pTrident->keyOffset = 0x50; 383 else 384 pTrident->keyOffset = 0x30; 385 386 TRIDENTResetVideo(pScrn); 387 388 return adapt; 389} 390 391 392static void 393TRIDENTStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 394{ 395 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 396 TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; 397 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 398 399 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 400 401 if(shutdown) { 402 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 403 WaitForVBlank(pScrn); 404 OUTW(vgaIOBase + 4, 0x848E); 405 OUTW(vgaIOBase + 4, 0x0091); 406 } 407 if(pPriv->linear) { 408 xf86FreeOffscreenLinear(pPriv->linear); 409 pPriv->linear = NULL; 410 } 411 pPriv->videoStatus = 0; 412 } else { 413 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 414 pPriv->videoStatus |= OFF_TIMER; 415 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 416 pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback; 417 } 418 } 419} 420 421#undef PI 422#define PI 3.14159265 423 424static void 425tridentSetVideoContrast(TRIDENTPtr pTrident,int value) 426{ 427 OUTW(0x3C4, (((value & 0x7)|((value & 0x7) << 4)) << 8) | 0xBC); 428} 429 430static void 431tridentSetVideoParameters(TRIDENTPtr pTrident, int brightness, 432 int saturation, int hue) 433{ 434 double dtmp; 435 CARD8 sign, tmp, tmp1; 436 437 if (brightness >= 0x20) 438 brightness -= 0x20; 439 else 440 brightness += 0x20; 441 dtmp = sin((double)hue / 180.0 * PI) * saturation / 12.5; 442 sign = (dtmp < 0) ? 1 << 1 : 0; 443 tmp1 = ((int)fabs(dtmp) >> 4) & 0x1; 444 tmp = brightness << 2 | sign | tmp1; 445 OUTW(0x3C4, tmp << 8 | 0xB1); 446 447 tmp1 = ((int)fabs(dtmp) & 0x7 ) << 5; 448 dtmp = cos((double)hue / 180.0 * PI) * saturation / 12.5; 449 sign = (dtmp < 0) ? 1 << 4 : 0; 450 tmp1 |= (int)fabs(dtmp) & 0xf; 451 tmp = sign | tmp1; 452 OUTW(0x3C4, tmp << 8 | 0xB0); 453} 454 455static int 456TRIDENTSetPortAttribute( 457 ScrnInfoPtr pScrn, 458 Atom attribute, 459 INT32 value, 460 pointer data 461){ 462 TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; 463 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 464 465 if(attribute == xvColorKey) { 466 int red, green, blue; 467 int tmp; 468 pPriv->colorKey = value; 469 switch (pScrn->depth) { 470 case 8: 471 VIDEOOUT(pPriv->colorKey, pTrident->keyOffset); 472 VIDEOOUT(0x00, (pTrident->keyOffset + 1)); 473 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 474 break; 475 default: 476 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 477 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 478 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 479 switch (pScrn->depth) { 480 case 15: 481 tmp = (red << 10) | (green << 5) | (blue); 482 VIDEOOUT((tmp&0xff), pTrident->keyOffset); 483 VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1)); 484 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 485 break; 486 case 16: 487 tmp = (red << 11) | (green << 5) | (blue); 488 VIDEOOUT((tmp&0xff), pTrident->keyOffset); 489 VIDEOOUT((tmp&0xff00)>>8, (pTrident->keyOffset + 1)); 490 VIDEOOUT(0x00, (pTrident->keyOffset + 2)); 491 break; 492 case 24: 493 VIDEOOUT(blue, pTrident->keyOffset); 494 VIDEOOUT(green, (pTrident->keyOffset + 1)); 495 VIDEOOUT(red, (pTrident->keyOffset + 2)); 496 break; 497 } 498 } 499 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 500 } else if (attribute == xvBrightness) { 501 if ((value < 0) || (value > 0x3f)) 502 return BadValue; 503 pPriv->Brightness = value; 504 tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, 505 pPriv->HUE); 506 } else if (attribute == xvSaturation) { 507 if ((value < 0) || (value > 187)) 508 return BadValue; 509 pPriv->Saturation = value; 510 tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, 511 pPriv->HUE); 512 } else if (attribute == xvHUE) { 513 if ((value < 0) || (value > 360)) 514 return BadValue; 515 pPriv->HUE = value; 516 tridentSetVideoParameters(pTrident, pPriv->Brightness, pPriv->Saturation, 517 pPriv->HUE); 518 } else if (attribute == xvContrast) { 519 if ((value < 0) || (value > 7)) 520 return BadValue; 521 pPriv->Contrast = value; 522 tridentSetVideoContrast(pTrident,value); 523 } else 524 return BadMatch; 525 526 return Success; 527} 528 529static int 530TRIDENTGetPortAttribute( 531 ScrnInfoPtr pScrn, 532 Atom attribute, 533 INT32 *value, 534 pointer data 535){ 536 TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; 537 538 if(attribute == xvColorKey) { 539 *value = pPriv->colorKey; 540 } else if(attribute == xvBrightness) { 541 *value = pPriv->Brightness; 542 } else if(attribute == xvSaturation) { 543 *value = pPriv->Saturation; 544 } else if (attribute == xvHUE) { 545 *value = pPriv->HUE; 546 } else if (attribute == xvContrast) { 547 *value = pPriv->Contrast; 548 } else 549 return BadMatch; 550 551 return Success; 552} 553 554static void 555TRIDENTQueryBestSize( 556 ScrnInfoPtr pScrn, 557 Bool motion, 558 short vid_w, short vid_h, 559 short drw_w, short drw_h, 560 unsigned int *p_w, unsigned int *p_h, 561 pointer data 562){ 563 *p_w = drw_w; 564 *p_h = drw_h; 565 566 if(*p_w > 16384) *p_w = 16384; 567} 568 569 570static FBLinearPtr 571TRIDENTAllocateMemory( 572 ScrnInfoPtr pScrn, 573 FBLinearPtr linear, 574 int size 575){ 576 ScreenPtr pScreen; 577 FBLinearPtr new_linear; 578 579 if(linear) { 580 if(linear->size >= size) 581 return linear; 582 583 if(xf86ResizeOffscreenLinear(linear, size)) 584 return linear; 585 586 xf86FreeOffscreenLinear(linear); 587 } 588 589 pScreen = screenInfo.screens[pScrn->scrnIndex]; 590 591 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 592 NULL, NULL, NULL); 593 594 if(!new_linear) { 595 int max_size; 596 597 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 598 PRIORITY_EXTREME); 599 600 if(max_size < size) 601 return NULL; 602 603 xf86PurgeUnlockedOffscreenAreas(pScreen); 604 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 605 NULL, NULL, NULL); 606 } 607 608 return new_linear; 609} 610 611static void 612TRIDENTDisplayVideo( 613 ScrnInfoPtr pScrn, 614 int id, 615 int offset, 616 short width, short height, 617 int pitch, 618 int x1, int y1, int x2, int y2, 619 BoxPtr dstBox, 620 short src_w, short src_h, 621 short drw_w, short drw_h 622){ 623 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 624 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 625 int zoomx1, zoomx2, zoomy1, zoomy2; 626 int tx1,tx2; 627 int ty1,ty2; 628 629 switch(id) { 630 case 0x35315652: /* RGB15 */ 631 case 0x36315652: /* RGB16 */ 632 if (pTrident->Chipset >= CYBER9388) { 633 OUTW(vgaIOBase + 4, 0x22BF); 634 OUTW(vgaIOBase + 4, 0x248F); 635 } else { 636 OUTW(vgaIOBase + 4, 0x118F); 637 } 638 break; 639 case FOURCC_YV12: /* YV12 */ 640 case FOURCC_YUY2: /* YUY2 */ 641 default: 642 if (pTrident->Chipset >= CYBER9388) { 643 OUTW(vgaIOBase + 4, 0x00BF); 644 OUTW(vgaIOBase + 4, 0x208F); 645 } else { 646 OUTW(vgaIOBase + 4, 0x108F); 647 } 648 break; 649 } 650 tx1 = dstBox->x1 + pTrident->hsync; 651 tx2 = dstBox->x2 + pTrident->hsync + pTrident->hsync_rskew; 652 ty1 = dstBox->y1 + pTrident->vsync - 2; 653 ty2 = dstBox->y2 + pTrident->vsync + 2 + pTrident->vsync_bskew; 654 655 OUTW(vgaIOBase + 4, (tx1 & 0xff) <<8 | 0x86); 656 OUTW(vgaIOBase + 4, (tx1 & 0xff00) | 0x87); 657 OUTW(vgaIOBase + 4, (ty1 & 0xff) <<8 | 0x88); 658 OUTW(vgaIOBase + 4, (ty1 & 0xff00) | 0x89); 659 OUTW(vgaIOBase + 4, (tx2 & 0xff) <<8 | 0x8A); 660 OUTW(vgaIOBase + 4, (tx2 & 0xff00) | 0x8B); 661 OUTW(vgaIOBase + 4, (ty2 & 0xff) <<8 | 0x8C); 662 OUTW(vgaIOBase + 4, (ty2 & 0xff00) | 0x8D); 663 664 offset += (x1 >> 15) & ~0x01; 665 666 if (pTrident->videoFlags & VID_OFF_SHIFT_4) 667 offset = offset >> 4; 668 else 669 offset = offset >> 3; 670 671 OUTW(vgaIOBase + 4, (((width<<1) & 0xff)<<8) | 0x90); 672 OUTW(vgaIOBase + 4, ((width<<1) & 0xff00) | 0x91); 673 OUTW(vgaIOBase + 4, ((offset) & 0xff) << 8 | 0x92); 674 OUTW(vgaIOBase + 4, ((offset) & 0xff00) | 0x93); 675 if (pTrident->Chipset >= CYBER9397) { 676 OUTW(vgaIOBase + 4, ((offset) & 0x0f0000) >> 8 | 0x94); 677 } else { 678 OUTW(vgaIOBase + 4, ((offset) & 0x070000) >> 8 | 0x94); 679 } 680 681 /* Horizontal Zoom */ 682 if (pTrident->videoFlags & VID_ZOOM_INV) { 683 if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_w > drw_w) 684 zoomx2 = (int)((float)drw_w/(float)src_w * 1024) 685 | (((int)((float)src_w/(float)drw_w) - 1)&7)<<10 | 0x8000; 686 else 687 zoomx2 = (int)(float)src_w/(float)drw_w * 1024; 688 689 OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); 690 OUTW(vgaIOBase + 4, (zoomx2&0x9f00) | 0x81); 691 } else { 692 if (drw_w == src_w 693 || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_w > drw_w))) { 694 OUTW(vgaIOBase + 4, 0x0080); 695 OUTW(vgaIOBase + 4, 0x0081); 696 } else 697 if (drw_w > src_w) { 698 float z; 699 700 z = (float)((drw_w)/(float)src_w) - 1.0; 701 702 zoomx1 = z; 703 zoomx2 = (z - (int)zoomx1 ) * 1024; 704 705 OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); 706 OUTW(vgaIOBase + 4, (zoomx1&0x0f)<<10 | (zoomx2&0x0300) |0x81); 707 } else { 708 zoomx1 = ((float)drw_w/(float)src_w); 709 zoomx2 = ( ((float)drw_w/(float)src_w) - (int)zoomx1 ) * 1024; 710 OUTW(vgaIOBase + 4, (zoomx2&0xff)<<8 | 0x80); 711 OUTW(vgaIOBase + 4, (zoomx2&0x0300)| 712 (((int)((float)src_w/(float)drw_w)-1)&7)<<10 | 0x8081); 713 } 714 } 715 716 /* Vertical Zoom */ 717 if (pTrident->videoFlags & VID_ZOOM_INV) { 718 if ((pTrident->videoFlags & VID_ZOOM_MINI) && src_h > drw_h) 719 zoomy2 = (int)(( ((float)drw_h/(float)src_h)) * 1024) 720 | (((int)((float)src_h/(float)drw_h)-1)&7)<<10 721 | 0x8000; 722 else 723 zoomy2 = ( ((float)src_h/(float)drw_h)) * 1024; 724 OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); 725 OUTW(vgaIOBase + 4, (zoomy2&0x9f00) | 0x0083); 726 } else { 727 if (drw_h == src_h 728 || ((pTrident->videoFlags & VID_ZOOM_NOMINI) && (src_h > drw_h))) { 729 OUTW(vgaIOBase + 4, 0x0082); 730 OUTW(vgaIOBase + 4, 0x0083); 731 } else 732 if (drw_h > src_h) { 733 float z; 734 735 z = (float)drw_h/(float)src_h - 1; 736 zoomy1 = z; 737 zoomy2 = (z - (int)zoomy1 ) * 1024; 738 739 OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); 740 OUTW(vgaIOBase + 4, (zoomy1&0x0f)<<10 | (zoomy2&0x0300) |0x83); 741 } else { 742 zoomy1 = ((float)drw_h/(float)src_h); 743 zoomy2 = ( ((float)drw_h/(float)src_h) - (int)zoomy1 ) * 1024; 744 OUTW(vgaIOBase + 4, (zoomy2&0xff)<<8 | 0x82); 745 OUTW(vgaIOBase + 4, (zoomy2&0x0300)| 746 (((int)((float)src_h/(float)drw_h)-1)&7)<<10 | 0x8083); 747 } 748 } 749 750 if (pTrident->Chipset >= CYBER9388) { 751 int lb = (width+2) >> 2; 752 753 OUTW(vgaIOBase + 4, ((lb & 0x100)>>1) | 0x0895); 754 OUTW(vgaIOBase + 4, (lb & 0xFF)<<8 | 0x0096); 755 if ((pTrident->videoFlags & VID_DOUBLE_LINEBUFFER_FOR_WIDE_SRC) 756 && (src_w > 384)) { 757 OUTW(0x3C4, 0x0497); /* 2x line buffers */ 758 } else { 759 OUTW(0x3C4, 0x0097); /* 1x line buffers */ 760 } 761 OUTW(vgaIOBase + 4, 0x0097); 762 OUTW(vgaIOBase + 4, 0x00BA); 763 OUTW(vgaIOBase + 4, 0x00BB); 764 OUTW(vgaIOBase + 4, 0xFFBC); 765 OUTW(vgaIOBase + 4, 0xFFBD); 766 OUTW(vgaIOBase + 4, 0x04BE); 767 OUTW(vgaIOBase + 4, 0x948E); 768 } else { 769 770 OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2)) 771 ? (width >> 2) : (width >> 6)) << 8) | 0x95); 772 OUTW(vgaIOBase + 4, ((((id == FOURCC_YV12) || (id == FOURCC_YUY2)) 773 ? ((width+2) >> 2) : ((width+2) >> 6)) << 8) |0x96); 774 775 OUTW(vgaIOBase + 4, 0x948E); 776 OUTB(0x83C8, 0x00); 777 OUTB(0x83C6, 0x95); 778 } 779} 780 781static int 782TRIDENTPutImage( 783 ScrnInfoPtr pScrn, 784 short src_x, short src_y, 785 short drw_x, short drw_y, 786 short src_w, short src_h, 787 short drw_w, short drw_h, 788 int id, unsigned char* buf, 789 short width, short height, 790 Bool sync, 791 RegionPtr clipBoxes, pointer data, 792 DrawablePtr pDraw 793){ 794 TRIDENTPortPrivPtr pPriv = (TRIDENTPortPrivPtr)data; 795 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 796 INT32 x1, x2, y1, y2; 797 unsigned char *dst_start; 798 int new_size, offset, offset2 = 0, offset3 = 0; 799 int srcPitch, srcPitch2 = 0, dstPitch; 800 int top, left, npixels, nlines, bpp; 801 BoxRec dstBox; 802 CARD32 tmp; 803 804 /* Clip */ 805 x1 = src_x; 806 x2 = src_x + src_w; 807 y1 = src_y; 808 y2 = src_y + src_h; 809 810 dstBox.x1 = drw_x; 811 dstBox.x2 = drw_x + drw_w; 812 dstBox.y1 = drw_y; 813 dstBox.y2 = drw_y + drw_h; 814 815 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 816 width, height)) 817 return Success; 818 819 dstBox.x1 -= pScrn->frameX0; 820 dstBox.x2 -= pScrn->frameX0; 821 dstBox.y1 -= pScrn->frameY0; 822 dstBox.y2 -= pScrn->frameY0; 823 824 bpp = pScrn->bitsPerPixel >> 3; 825 826 dstPitch = ((width << 1) + 15) & ~15; 827 new_size = ((dstPitch * height) + bpp - 1) / bpp; 828 switch(id) { 829 case FOURCC_YV12: 830 case FOURCC_I420: 831 srcPitch = (width + 3) & ~3; 832 offset2 = srcPitch * height; 833 srcPitch2 = ((width >> 1) + 3) & ~3; 834 offset3 = (srcPitch2 * (height >> 1)) + offset2; 835 break; 836 case FOURCC_UYVY: 837 case FOURCC_YUY2: 838 default: 839 srcPitch = (width << 1); 840 break; 841 } 842 843 if(!(pPriv->linear = TRIDENTAllocateMemory(pScrn, pPriv->linear, new_size))) 844 return BadAlloc; 845 846 /* copy data */ 847 top = y1 >> 16; 848 left = (x1 >> 16) & ~1; 849 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 850 left <<= 1; 851 852 offset = pPriv->linear->offset * bpp; 853 854 dst_start = pTrident->FbBase + offset + left + (top * dstPitch); 855 856 switch(id) { 857 case FOURCC_YV12: 858 case FOURCC_I420: 859 top &= ~1; 860 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 861 offset2 += tmp; 862 offset3 += tmp; 863 if(id == FOURCC_I420) { 864 tmp = offset2; 865 offset2 = offset3; 866 offset3 = tmp; 867 } 868 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 869 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 870 buf + offset2, buf + offset3, dst_start, 871 srcPitch, srcPitch2, dstPitch, nlines, npixels); 872 break; 873 case FOURCC_UYVY: 874 case FOURCC_YUY2: 875 default: 876 buf += (top * srcPitch) + left; 877 nlines = ((y2 + 0xffff) >> 16) - top; 878 xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 879 break; 880 } 881 882 /* update cliplist */ 883 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 884 /* update cliplist */ 885 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 886 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 887 } 888 889 offset += top * dstPitch; 890 891 /* Fix video position when using doublescan */ 892 if(pScrn->currentMode->Flags & V_DBLSCAN) { 893 dstBox.y1 <<= 1; 894 dstBox.y2 <<= 1; 895 drw_h <<= 1; 896 } 897 898 tridentFixFrame(pScrn,&pPriv->fixFrame); 899 TRIDENTDisplayVideo(pScrn, id, offset, width, height, dstPitch, 900 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 901 902 pPriv->videoStatus = CLIENT_VIDEO_ON; 903 904 pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback; 905 906 return Success; 907} 908 909static int 910TRIDENTQueryImageAttributes( 911 ScrnInfoPtr pScrn, 912 int id, 913 unsigned short *w, unsigned short *h, 914 int *pitches, int *offsets 915){ 916 int size, tmp; 917 918 if(*w > 1024) *w = 1024; 919 if(*h > 1024) *h = 1024; 920 921 *w = (*w + 1) & ~1; 922 if(offsets) offsets[0] = 0; 923 924 switch(id) { 925 case FOURCC_YV12: /* YV12 */ 926 *h = (*h + 1) & ~1; 927 size = (*w + 3) & ~3; 928 if(pitches) pitches[0] = size; 929 size *= *h; 930 if(offsets) offsets[1] = size; 931 tmp = ((*w >> 1) + 3) & ~3; 932 if(pitches) pitches[1] = pitches[2] = tmp; 933 tmp *= (*h >> 1); 934 size += tmp; 935 if(offsets) offsets[2] = size; 936 size += tmp; 937 break; 938 default: /* RGB15, RGB16, YUY2 */ 939 size = *w << 1; 940 if(pitches) pitches[0] = size; 941 size *= *h; 942 break; 943 } 944 945 return size; 946} 947 948/****************** Offscreen stuff ***************/ 949 950typedef struct { 951 FBLinearPtr linear; 952 Bool isOn; 953} OffscreenPrivRec, * OffscreenPrivPtr; 954 955static int 956TRIDENTAllocateSurface( 957 ScrnInfoPtr pScrn, 958 int id, 959 unsigned short w, 960 unsigned short h, 961 XF86SurfacePtr surface 962){ 963 FBLinearPtr linear; 964 int pitch, size, bpp; 965 OffscreenPrivPtr pPriv; 966 967 if((w > 1024) || (h > 1024)) 968 return BadAlloc; 969 970 w = (w + 1) & ~1; 971 pitch = ((w << 1) + 15) & ~15; 972 bpp = pScrn->bitsPerPixel >> 3; 973 size = ((pitch * h) + bpp - 1) / bpp; 974 975 if(!(linear = TRIDENTAllocateMemory(pScrn, NULL, size))) 976 return BadAlloc; 977 978 surface->width = w; 979 surface->height = h; 980 981 if(!(surface->pitches = malloc(sizeof(int)))) { 982 xf86FreeOffscreenLinear(linear); 983 return BadAlloc; 984 } 985 if(!(surface->offsets = malloc(sizeof(int)))) { 986 free(surface->pitches); 987 xf86FreeOffscreenLinear(linear); 988 return BadAlloc; 989 } 990 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 991 free(surface->pitches); 992 free(surface->offsets); 993 xf86FreeOffscreenLinear(linear); 994 return BadAlloc; 995 } 996 997 pPriv->linear = linear; 998 pPriv->isOn = FALSE; 999 1000 surface->pScrn = pScrn; 1001 surface->id = id; 1002 surface->pitches[0] = pitch; 1003 surface->offsets[0] = linear->offset * bpp; 1004 surface->devPrivate.ptr = (pointer)pPriv; 1005 1006 return Success; 1007} 1008 1009static int 1010TRIDENTStopSurface( 1011 XF86SurfacePtr surface 1012){ 1013 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1014 1015 if(pPriv->isOn) { 1016 TRIDENTPtr pTrident = TRIDENTPTR(surface->pScrn); 1017 int vgaIOBase = VGAHWPTR(surface->pScrn)->IOBase; 1018 WaitForVBlank(surface->pScrn); 1019 OUTW(vgaIOBase + 4, 0x848E); 1020 OUTW(vgaIOBase + 4, 0x0091); 1021 pPriv->isOn = FALSE; 1022 } 1023 1024 return Success; 1025} 1026 1027 1028static int 1029TRIDENTFreeSurface( 1030 XF86SurfacePtr surface 1031){ 1032 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1033 1034 if(pPriv->isOn) 1035 TRIDENTStopSurface(surface); 1036 xf86FreeOffscreenLinear(pPriv->linear); 1037 free(surface->pitches); 1038 free(surface->offsets); 1039 free(surface->devPrivate.ptr); 1040 1041 return Success; 1042} 1043 1044static int 1045TRIDENTGetSurfaceAttribute( 1046 ScrnInfoPtr pScrn, 1047 Atom attribute, 1048 INT32 *value 1049){ 1050 return TRIDENTGetPortAttribute(pScrn, attribute, value, 1051 (pointer)(GET_PORT_PRIVATE(pScrn))); 1052} 1053 1054static int 1055TRIDENTSetSurfaceAttribute( 1056 ScrnInfoPtr pScrn, 1057 Atom attribute, 1058 INT32 value 1059){ 1060 return TRIDENTSetPortAttribute(pScrn, attribute, value, 1061 (pointer)(GET_PORT_PRIVATE(pScrn))); 1062} 1063 1064static int 1065TRIDENTDisplaySurface( 1066 XF86SurfacePtr surface, 1067 short src_x, short src_y, 1068 short drw_x, short drw_y, 1069 short src_w, short src_h, 1070 short drw_w, short drw_h, 1071 RegionPtr clipBoxes 1072){ 1073 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1074 ScrnInfoPtr pScrn = surface->pScrn; 1075 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1076 TRIDENTPortPrivPtr portPriv = pTrident->adaptor->pPortPrivates[0].ptr; 1077 INT32 x1, y1, x2, y2; 1078 BoxRec dstBox; 1079 1080 x1 = src_x; 1081 x2 = src_x + src_w; 1082 y1 = src_y; 1083 y2 = src_y + src_h; 1084 1085 dstBox.x1 = drw_x; 1086 dstBox.x2 = drw_x + drw_w; 1087 dstBox.y1 = drw_y; 1088 dstBox.y2 = drw_y + drw_h; 1089 1090 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1091 surface->width, surface->height)) 1092 { 1093 return Success; 1094 } 1095 1096 dstBox.x1 -= pScrn->frameX0; 1097 dstBox.x2 -= pScrn->frameX0; 1098 dstBox.y1 -= pScrn->frameY0; 1099 dstBox.y2 -= pScrn->frameY0; 1100 1101 TRIDENTResetVideo(pScrn); 1102 1103 tridentFixFrame(pScrn,&portPriv->fixFrame); 1104 TRIDENTDisplayVideo(pScrn, surface->id, surface->offsets[0], 1105 surface->width, surface->height, surface->pitches[0], 1106 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1107 1108 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 1109 1110 pPriv->isOn = TRUE; 1111 /* we've prempted the XvImage stream so set its free timer */ 1112 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 1113 REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 1114 UpdateCurrentTime(); 1115 portPriv->videoStatus = FREE_TIMER; 1116 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1117 pTrident->VideoTimerCallback = TRIDENTVideoTimerCallback; 1118 } 1119 1120 return Success; 1121} 1122 1123static void 1124TRIDENTInitOffscreenImages(ScreenPtr pScreen) 1125{ 1126 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1127 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1128 XF86OffscreenImagePtr offscreenImages; 1129 1130 /* need to free this someplace */ 1131 if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 1132 return; 1133 1134 offscreenImages[0].image = &Images[0]; 1135 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1136 VIDEO_CLIP_TO_VIEWPORT; 1137 offscreenImages[0].alloc_surface = TRIDENTAllocateSurface; 1138 offscreenImages[0].free_surface = TRIDENTFreeSurface; 1139 offscreenImages[0].display = TRIDENTDisplaySurface; 1140 offscreenImages[0].stop = TRIDENTStopSurface; 1141 offscreenImages[0].setAttribute = TRIDENTSetSurfaceAttribute; 1142 offscreenImages[0].getAttribute = TRIDENTGetSurfaceAttribute; 1143 offscreenImages[0].max_width = 1024; 1144 offscreenImages[0].max_height = 1024; 1145 if (pTrident->Chipset >= CYBER9388) { 1146 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 1147 } else { 1148 offscreenImages[0].num_attributes = 1; /* just colorkey */ 1149 } 1150 offscreenImages[0].attributes = Attributes; 1151 1152 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1153} 1154 1155static void 1156TRIDENTVideoTimerCallback(ScrnInfoPtr pScrn, Time time) 1157{ 1158 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1159 TRIDENTPortPrivPtr pPriv = pTrident->adaptor->pPortPrivates[0].ptr; 1160 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1161 1162 if(pPriv->videoStatus & TIMER_MASK) { 1163 if(pPriv->videoStatus & OFF_TIMER) { 1164 if(pPriv->offTime < time) { 1165 WaitForVBlank(pScrn); 1166 OUTW(vgaIOBase + 4, 0x848E); 1167 OUTW(vgaIOBase + 4, 0x0091); 1168 pPriv->videoStatus = FREE_TIMER; 1169 pPriv->freeTime = time + FREE_DELAY; 1170 } 1171 } else { /* FREE_TIMER */ 1172 if(pPriv->freeTime < time) { 1173 if(pPriv->linear) { 1174 xf86FreeOffscreenLinear(pPriv->linear); 1175 pPriv->linear = NULL; 1176 } 1177 pPriv->videoStatus = 0; 1178 pTrident->VideoTimerCallback = NULL; 1179 } 1180 } 1181 } else /* shouldn't get here */ 1182 pTrident->VideoTimerCallback = NULL; 1183} 1184 1185 /* Calculate skew offsets for video overlay */ 1186 1187 1188void 1189tridentFixFrame(ScrnInfoPtr pScrn, int *fixFrame) 1190{ 1191 1192 TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 1193 int vgaIOBase = VGAHWPTR(pScrn)->IOBase; 1194 int HTotal, HSyncStart; 1195 int VTotal, VSyncStart; 1196 int h_off = 0; 1197 int v_off = 0; 1198 unsigned char CRTC[0x11]; 1199 unsigned char hcenter, vcenter; 1200 Bool isShadow; 1201 unsigned char shadow = 0; 1202 1203 if ((*fixFrame)++ < 100) 1204 return; 1205 1206 *fixFrame = 0; 1207 1208 OUTB(0x3CE, CyberControl); 1209 isShadow = ((INB(0x3CF) & 0x81) == 0x81); 1210 1211 if (isShadow) 1212 SHADOW_ENABLE(shadow); 1213 1214 OUTB(vgaIOBase + 4, 0x0); 1215 CRTC[0x0] = INB(vgaIOBase + 5); 1216 OUTB(vgaIOBase + 4, 0x4); 1217 CRTC[0x4] = INB(vgaIOBase + 5); 1218 OUTB(vgaIOBase + 4, 0x5); 1219 CRTC[0x5] = INB(vgaIOBase + 5); 1220 OUTB(vgaIOBase + 4, 0x6); 1221 CRTC[0x6] = INB(vgaIOBase + 5); 1222 OUTB(vgaIOBase + 4, 0x7); 1223 CRTC[0x7] = INB(vgaIOBase + 5); 1224 OUTB(vgaIOBase + 4, 0x10); 1225 CRTC[0x10] = INB(vgaIOBase + 5); 1226 OUTB(0x3CE, HorStretch); 1227 hcenter = INB(0x3CF); 1228 OUTB(0x3CE, VertStretch); 1229 vcenter = INB(0x3CF); 1230 1231 HTotal = CRTC[0] << 3; 1232 VTotal = CRTC[6] 1233 | ((CRTC[7] & (1<<0)) << 8) 1234 | ((CRTC[7] & (1<<5)) << 4); 1235 HSyncStart = (CRTC[4] 1236 + ((CRTC[5] >> 5) & 0x3)) << 3; 1237 VSyncStart = CRTC[0x10] 1238 | ((CRTC[7] & (1<<2)) << 6) 1239 | ((CRTC[7] & (1<<7)) << 2); 1240 1241 if (isShadow) { 1242 SHADOW_RESTORE(shadow); 1243 if (pTrident->lcdMode != 0xff) { 1244 if (hcenter & 0x80) { 1245 h_off = (LCD[pTrident->lcdMode].display_x 1246 - pScrn->currentMode->HDisplay) >> 1; 1247 switch (pTrident->Chipset) { 1248 case BLADEXP: 1249 h_off -= 5; 1250 } 1251 } 1252 if (vcenter & 0x80) { 1253 v_off = (LCD[pTrident->lcdMode].display_y 1254 - pScrn->currentMode->VDisplay) >> 1; 1255 } 1256 } 1257 } 1258 1259 pTrident->hsync = HTotal - HSyncStart + 23 + h_off; 1260 pTrident->vsync = VTotal - VSyncStart - 2 + v_off; 1261 pTrident->hsync_rskew = 0; 1262 pTrident->vsync_bskew = 0; 1263 1264 /* 1265 * HACK !! As awful as this is, it appears to be the only way....Sigh! 1266 * We have XvHsync and XvVsync as options now, which adjust 1267 * at the very end of this function. It'll be helpful for now 1268 * and we can get more data on some of these skew values. 1269 */ 1270 switch (pTrident->Chipset) { 1271 case TGUI9680: 1272 /* Furthur tweaking needed */ 1273 pTrident->hsync -= 84; 1274 pTrident->vsync += 2; 1275 break; 1276 case PROVIDIA9682: 1277 /* Furthur tweaking needed */ 1278 pTrident->hsync += 7; 1279 break; 1280 case PROVIDIA9685: 1281 /* Spot on */ 1282 break; 1283 case BLADEXP: 1284 case CYBERBLADEXPAI1: 1285 pTrident->hsync -= 15; 1286 pTrident->hsync_rskew = 3; 1287 break; 1288 case BLADE3D: 1289 if (pScrn->depth == 24) 1290 pTrident->hsync -= 8; 1291 else 1292 pTrident->hsync -= 6; 1293 break; 1294 case CYBERBLADEI7: 1295 case CYBERBLADEI7D: 1296 case CYBERBLADEI1: 1297 case CYBERBLADEI1D: 1298 if (pScrn->depth == 24) 1299 pTrident->hsync -= 7; 1300 else 1301 pTrident->hsync -= 6; 1302 break; 1303 case CYBERBLADEAI1: 1304 pTrident->hsync -= 7; 1305 break; 1306 case CYBERBLADEAI1D: 1307 pTrident->vsync += 2; 1308 pTrident->vsync_bskew = -4; 1309 pTrident->hsync -= 5; 1310 break; 1311 case CYBERBLADEE4: 1312 pTrident->hsync -= 8; 1313 break; 1314 case CYBERBLADEXP4: 1315 pTrident->hsync -= 24; 1316 pTrident->hsync_rskew = -1; 1317 break; 1318 case CYBER9397: 1319 pTrident->hsync -= 1; 1320 pTrident->vsync -= 0; 1321 pTrident->vsync_bskew = 0; 1322 break; 1323 case CYBER9397DVD: 1324 pTrident->hsync_rskew = -1; 1325 pTrident->vsync_bskew = -1; 1326 break; 1327 } 1328 pTrident->hsync+=pTrident->OverrideHsync; 1329 pTrident->vsync+=pTrident->OverrideVsync; 1330 pTrident->hsync_rskew += pTrident->OverrideRskew; 1331 pTrident->vsync_bskew += pTrident->OverrideBskew; 1332} 1333 1334static void 1335WaitForVBlank(ScrnInfoPtr pScrn) 1336{ 1337 register vgaHWPtr hwp = VGAHWPTR(pScrn); 1338 1339 /* We have to wait for one full VBlank to let the video engine start/stop. 1340 * So the first may be waiting for too short a period as it may already 1341 * be part way through the video frame. So we wait a second time to ensure 1342 * full vblank has passed. 1343 * - Alan. 1344 */ 1345#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 1346 if (!xf86IsPc98()) 1347#endif 1348 { 1349 WAITFORVSYNC; 1350 WAITFORVSYNC; 1351 } 1352} 1353