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